1import type { PreviewAnnotationPayload } from "@t3tools/contracts";
2
3import type { ComposerFileAttachment, ComposerImageAttachment } from "../../composerDraftStore";
4import { fileContextReference, previewAnnotationContextId } from "../../lib/composerContextRecords";
5
6interface RetainedPreviewAnnotation {
7 annotation: PreviewAnnotationPayload;
8 image: ComposerImageAttachment | undefined;
9}
10
11export interface RetainedAttachmentContextPayloads {
12 files: Map<string, ComposerFileAttachment>;
13 previewAnnotations: Map<string, RetainedPreviewAnnotation>;
14}
15
16export function reconcileAttachmentContextReferences(input: {
17 referencedContextIds: ReadonlySet<string>;
18 files: ReadonlyArray<ComposerFileAttachment>;
19 images: ReadonlyArray<ComposerImageAttachment>;
20 previewAnnotations: ReadonlyArray<PreviewAnnotationPayload>;
21 retained: RetainedAttachmentContextPayloads;
22}): {
23 filesToRemove: string[];
24 filesToRestore: ComposerFileAttachment[];
25 annotationIdsToRemove: string[];
26 annotationsToRestore: RetainedPreviewAnnotation[];
27} {
28 const liveFileContextIds = new Set<string>(
29 input.files.map((file) => fileContextReference(file).contextId),
30 );
31 const filesToRemove: string[] = [];
32 for (const file of input.files) {
33 const contextId = fileContextReference(file).contextId;
34 if (input.referencedContextIds.has(contextId)) continue;
35 input.retained.files.set(contextId, file);
36 filesToRemove.push(file.id);
37 }
38 const filesToRestore = [...input.referencedContextIds].flatMap((contextId) => {
39 if (liveFileContextIds.has(contextId)) return [];
40 const file = input.retained.files.get(contextId);
41 return file ? [file] : [];
42 });
43
44 const imagesById = new Map(input.images.map((image) => [image.id, image]));
45 const liveAnnotationContextIds = new Set<string>(
46 input.previewAnnotations.map((annotation) => previewAnnotationContextId(annotation.id)),
47 );
48 const annotationIdsToRemove: string[] = [];
49 for (const annotation of input.previewAnnotations) {
50 const contextId = previewAnnotationContextId(annotation.id);
51 if (input.referencedContextIds.has(contextId)) continue;
52 input.retained.previewAnnotations.set(contextId, {
53 annotation,
54 image: imagesById.get(annotation.id),
55 });
56 annotationIdsToRemove.push(annotation.id);
57 }
58 const annotationsToRestore = [...input.referencedContextIds].flatMap((contextId) => {
59 if (liveAnnotationContextIds.has(contextId)) return [];
60 const retained = input.retained.previewAnnotations.get(contextId);
61 return retained ? [retained] : [];
62 });
63
64 return { filesToRemove, filesToRestore, annotationIdsToRemove, annotationsToRestore };
65}