import { db } from '@/lib/db' import { resolveCasePreviews } from '@/lib/chat/preview' import { extractCaseNumbers, type ChatMessageView } from '@/lib/chat/view' import { listMessages, listReactions, loadReadMarker, type ChatScope } from '@/lib/chat/service' import type { EffectivePermissions } from '@/lib/auth/permissions' /** * Alles, was die Chatansicht beim ersten Rendern braucht. * * Die Vorschaukarten und die Namen werden **hier** aufgelöst, mit den Rechten * des Lesers. Der Strom-Endpunkt tut für nachkommende Nachrichten dasselbe; * die Anzeige selbst löst nie etwas auf. */ export async function loadChatView(p: EffectivePermissions, scope: ChatScope) { const { ort, nachrichten } = await listMessages(p, scope) const scopeId = ort.caseId ?? ort.channelId! const [autoren, vorschauen, reaktionen, lastReadAt, mitglieder] = await Promise.all([ db.user.findMany({ where: { id: { in: [...new Set(nachrichten.map((n) => n.authorId))] } }, select: { id: true, displayName: true }, }), resolveCasePreviews(p, nachrichten.flatMap((n) => extractCaseNumbers(n.body))), listReactions(p, nachrichten.map((n) => n.id)), loadReadMarker(p, ort.caseId ? 'case' : 'channel', scopeId), // Für die Anzeige der Erwähnungen: Benutzername auf Anzeigename. db.user.findMany({ where: { isActive: true }, take: 300, select: { username: true, displayName: true }, }), ]) const nameVon = new Map(autoren.map((a) => [a.id, a.displayName])) const views: ChatMessageView[] = nachrichten.map((nachricht) => { const previews: ChatMessageView['previews'] = {} for (const nummer of extractCaseNumbers(nachricht.body)) { const vorschau = vorschauen.get(nummer) if (vorschau) previews[nummer] = vorschau } return { id: nachricht.id, // Eine zurückgezogene Nachricht kommt ohne Text an. Nicht ausblenden: // gar nicht erst schicken. body: nachricht.withdrawnAt ? '' : nachricht.body, authorId: nachricht.authorId, authorName: nameVon.get(nachricht.authorId) ?? nachricht.authorId, replyToId: nachricht.replyToId, editedAt: nachricht.editedAt?.toISOString() ?? null, withdrawnAt: nachricht.withdrawnAt?.toISOString() ?? null, adoptedEntryId: nachricht.adoptedEntryId, createdAt: nachricht.createdAt.toISOString(), previews, } }) return { ort, scopeId, messages: views, reactions: reaktionen, lastReadAt: lastReadAt?.toISOString() ?? null, mentionNames: Object.fromEntries( mitglieder.map((m) => [m.username.toLowerCase(), m.displayName]), ), } }