76 lines
2.6 KiB
TypeScript
76 lines
2.6 KiB
TypeScript
import type { Message, Member } from './types';
|
|
import type { RoomMessageResponse } from '@/client/model';
|
|
|
|
export function getDateLabel(isoDate: string): string {
|
|
const date = new Date(isoDate);
|
|
const now = new Date();
|
|
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
|
const yesterday = new Date(today.getTime() - 86400000);
|
|
const msgDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
if (msgDate.getTime() === today.getTime()) return 'Today';
|
|
if (msgDate.getTime() === yesterday.getTime()) return 'Yesterday';
|
|
return date.toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric', year: 'numeric' });
|
|
}
|
|
|
|
export function formatTime(isoDate: string): string {
|
|
return new Date(isoDate).toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' });
|
|
}
|
|
|
|
export function formatRelativeTime(isoDate: string): string {
|
|
const diff = Date.now() - new Date(isoDate).getTime();
|
|
const seconds = Math.floor(diff / 1000);
|
|
if (seconds < 60) return 'just now';
|
|
const minutes = Math.floor(seconds / 60);
|
|
if (minutes < 60) return `${minutes}m ago`;
|
|
const hours = Math.floor(minutes / 60);
|
|
if (hours < 24) return `${hours}h ago`;
|
|
return getDateLabel(isoDate);
|
|
}
|
|
|
|
export function shouldGroup(prev: Message, curr: Message): boolean {
|
|
if (prev.sender_id !== curr.sender_id) return false;
|
|
if (prev.thread || curr.thread) return false;
|
|
if (curr.in_reply_to) return false;
|
|
if (prev.sender_type === 'ai') return false;
|
|
const diff = new Date(curr.send_at).getTime() - new Date(prev.send_at).getTime();
|
|
return diff < 5 * 60 * 1000;
|
|
}
|
|
|
|
export function mapHttpMessage(r: RoomMessageResponse): Message {
|
|
return {
|
|
...r,
|
|
thread: (r as any).thread ?? (r as any).thread_id,
|
|
_localReactions: [],
|
|
is_streaming: false,
|
|
isOptimistic: false,
|
|
isOptimisticError: false,
|
|
thinking_content: (r as any).thinking_content ?? null,
|
|
};
|
|
}
|
|
|
|
export function mapParticipantToMember(p: any, presence?: Member['presence']): Member {
|
|
return {
|
|
uid: p.user,
|
|
username: p.user_info?.username ?? p.user,
|
|
avatar_url: p.user_info?.avatar_url ?? null,
|
|
project_role: p.project_role,
|
|
is_room_owner: p.is_room_owner,
|
|
last_read_seq: p.last_read_seq ?? null,
|
|
do_not_disturb: p.do_not_disturb,
|
|
presence: presence ?? 'offline',
|
|
};
|
|
}
|
|
|
|
export function mapStreamData(data: any): any {
|
|
return {
|
|
message_id: data.message_id ?? data.id,
|
|
content: data.content ?? '',
|
|
seq: data.seq ?? 0,
|
|
chunk_type: data.chunk_type ?? null,
|
|
display_name: data.display_name ?? null,
|
|
done: data.done ?? false,
|
|
thinking_content: data.thinking_content ?? null,
|
|
error: data.error ?? null,
|
|
};
|
|
}
|