Files
glchat/web/src/lib/presence.ts
T

54 lines
2.0 KiB
TypeScript
Raw Normal View History

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);
}
}