import { Injectable, signal } from '@angular/core'; import type { Attachment } from '../../domain/models/attachment.model'; @Injectable({ providedIn: 'root' }) export class AttachmentRuntimeStore { readonly updated = signal(0); private attachmentsByMessage = new Map(); private messageRoomIds = new Map(); private originalFiles = new Map(); private cancelledTransfers = new Set(); private pendingRequests = new Map>(); private chunkBuffers = new Map(); private chunkCounts = new Map(); touch(): void { this.updated.set(this.updated() + 1); } getAttachmentsForMessage(messageId: string): Attachment[] { return this.attachmentsByMessage.get(messageId) ?? []; } setAttachmentsForMessage(messageId: string, attachments: Attachment[]): void { if (attachments.length === 0) { this.attachmentsByMessage.delete(messageId); return; } this.attachmentsByMessage.set(messageId, attachments); } hasAttachmentsForMessage(messageId: string): boolean { return this.attachmentsByMessage.has(messageId); } deleteAttachmentsForMessage(messageId: string): void { this.attachmentsByMessage.delete(messageId); } replaceAttachments(nextAttachments: Map): void { this.attachmentsByMessage = nextAttachments; } getAttachmentEntries(): IterableIterator<[string, Attachment[]]> { return this.attachmentsByMessage.entries(); } rememberMessageRoom(messageId: string, roomId: string): void { this.messageRoomIds.set(messageId, roomId); } getMessageRoomId(messageId: string): string | undefined { return this.messageRoomIds.get(messageId); } deleteMessageRoom(messageId: string): void { this.messageRoomIds.delete(messageId); } setOriginalFile(key: string, file: File): void { this.originalFiles.set(key, file); } getOriginalFile(key: string): File | undefined { return this.originalFiles.get(key); } findOriginalFileByFileId(fileId: string): File | null { for (const [key, file] of this.originalFiles) { if (key.endsWith(`:${fileId}`)) { return file; } } return null; } addCancelledTransfer(key: string): void { this.cancelledTransfers.add(key); } hasCancelledTransfer(key: string): boolean { return this.cancelledTransfers.has(key); } deleteCancelledTransfer(key: string): void { this.cancelledTransfers.delete(key); } setPendingRequestPeers(key: string, peers: Set): void { this.pendingRequests.set(key, peers); } getPendingRequestPeers(key: string): Set | undefined { return this.pendingRequests.get(key); } hasPendingRequest(key: string): boolean { return this.pendingRequests.has(key); } deletePendingRequest(key: string): void { this.pendingRequests.delete(key); } setChunkBuffer(key: string, buffer: (ArrayBuffer | undefined)[]): void { this.chunkBuffers.set(key, buffer); } getChunkBuffer(key: string): (ArrayBuffer | undefined)[] | undefined { return this.chunkBuffers.get(key); } deleteChunkBuffer(key: string): void { this.chunkBuffers.delete(key); } setChunkCount(key: string, count: number): void { this.chunkCounts.set(key, count); } getChunkCount(key: string): number | undefined { return this.chunkCounts.get(key); } deleteChunkCount(key: string): void { this.chunkCounts.delete(key); } clearMessageScopedState(messageId: string): void { const scopedPrefix = `${messageId}:`; for (const key of Array.from(this.originalFiles.keys())) { if (key.startsWith(scopedPrefix)) { this.originalFiles.delete(key); } } for (const key of Array.from(this.pendingRequests.keys())) { if (key.startsWith(scopedPrefix)) { this.pendingRequests.delete(key); } } for (const key of Array.from(this.chunkBuffers.keys())) { if (key.startsWith(scopedPrefix)) { this.chunkBuffers.delete(key); } } for (const key of Array.from(this.chunkCounts.keys())) { if (key.startsWith(scopedPrefix)) { this.chunkCounts.delete(key); } } for (const key of Array.from(this.cancelledTransfers)) { if (key.startsWith(scopedPrefix)) { this.cancelledTransfers.delete(key); } } } }