d02ef7527a
Аватар нельзя было показать в списке друзей: файл без комнаты был доступен только загрузившему. Добавлено назначение файла (`files.purpose`: attachment | avatar | banner, миграция 00006): аватары и баннеры отдаются любому авторизованному пользователю, вложения по-прежнему проверяются по правам комнаты, а непривязанные загрузки остаются приватными.
54 lines
2.0 KiB
TypeScript
54 lines
2.0 KiB
TypeScript
import type { UserStatus } from '@/api/types';
|
||
import { DEFAULT_TIMEZONE } from '@/lib/timezones';
|
||
|
||
/**
|
||
* Присутствие в разделе друзей.
|
||
*
|
||
* Цвета точки статуса отличаются от панели пользователя (там «не беспокоить»
|
||
* красный, как в Discord): в списке друзей `dnd` — серый, а `invisible` —
|
||
* тёмно-голубой. У других пользователей «невидимка» приходит как `offline`,
|
||
* поэтому тёмно-голубой виден только у себя.
|
||
*/
|
||
export const presenceDotClass: Record<UserStatus, string> = {
|
||
online: 'bg-success',
|
||
offline: 'bg-danger',
|
||
idle: 'bg-warning',
|
||
dnd: 'bg-fg-muted',
|
||
invisible: 'bg-info',
|
||
};
|
||
|
||
/**
|
||
* Время последнего входа в часовом поясе пользователя из настроек
|
||
* (`user.timezone`, по умолчанию Москва).
|
||
*
|
||
* Возвращает `null`, если дата не пришла или не разбирается: вызывающий код
|
||
* показывает «Не в сети давно».
|
||
*/
|
||
export function formatLastSeen(
|
||
lastSeenAt: string | undefined,
|
||
timezone: string | undefined,
|
||
locale: string,
|
||
): string | null {
|
||
if (lastSeenAt === undefined || lastSeenAt === '') {
|
||
return null;
|
||
}
|
||
const date = new Date(lastSeenAt);
|
||
if (Number.isNaN(date.getTime())) {
|
||
return null;
|
||
}
|
||
try {
|
||
return new Intl.DateTimeFormat(locale, {
|
||
dateStyle: 'short',
|
||
timeStyle: 'short',
|
||
timeZone: timezone === undefined || timezone === '' ? DEFAULT_TIMEZONE : timezone,
|
||
}).format(date);
|
||
} catch {
|
||
// Неизвестный пояс (например, устаревшее значение в настройках) — МСК.
|
||
return new Intl.DateTimeFormat(locale, {
|
||
dateStyle: 'short',
|
||
timeStyle: 'short',
|
||
timeZone: DEFAULT_TIMEZONE,
|
||
}).format(date);
|
||
}
|
||
}
|