Files
HiveGrid-Wireframes/03 Quellen und Referenzen/hivegrid-cloud/apps/web/app/modules/chat/client/chatRealtimeViewModel.ts
T

57 lines
1.9 KiB
TypeScript

import {
chatConnectionStateLabelKey,
type ChatChannelDetailVM,
type ChatMessageDayGroupVM,
type ChatMessageVM,
type ChatPresenceVM,
} from "@hivegrid/view-models";
import type { ChatRealtimeConnection } from "./chatChannelRealtimeReducer";
export type ChatChannelRealtimeViewOverlay = {
readonly messages: readonly ChatMessageVM[];
readonly messageGroups: readonly ChatMessageDayGroupVM[];
readonly presence: readonly ChatPresenceVM[];
readonly typingLabels: readonly string[];
readonly connection: ChatRealtimeConnection;
};
/** Applies transport-only state to the loader-owned render contract. Repository
* records never cross this boundary. */
export function overlayChatChannelDetailRealtime(vm: ChatChannelDetailVM, overlay: ChatChannelRealtimeViewOverlay): ChatChannelDetailVM {
if (vm.status !== "ready") return vm;
const canRetry = overlay.connection.state === "offline" || overlay.connection.state === "reconnecting";
const composer =
overlay.connection.state === "blocked"
? {
...vm.data.composer,
enabled: false,
disabledReasonKey: "chat.composer.connectionBlocked",
canSend: false,
canAttachFiles: false,
canRecordVoice: false,
canMention: false,
canMarkAsTask: false,
}
: vm.data.composer;
return {
status: "ready",
data: {
...vm.data,
messages: overlay.messages,
messageGroups: overlay.messageGroups,
presence: overlay.presence.map(({ userId, status }) => ({ userId, status })),
typingLabels: overlay.typingLabels,
composer,
connection: {
...vm.data.connection,
state: overlay.connection.state,
stateLabelKey: chatConnectionStateLabelKey(overlay.connection.state),
reconnectAttempt: overlay.connection.reconnectAttempt,
retryAtIso: overlay.connection.retryAtIso,
canRetry,
},
},
};
}