| 1 | import type { PreviewAnnotationPayload } from "@t3tools/contracts"; |
| 2 | |
| 3 | import type { ComposerFileAttachment, ComposerImageAttachment } from "../../composerDraftStore"; |
| 4 | import { fileContextReference, previewAnnotationContextId } from "../../lib/composerContextRecords"; |
| 5 | |
| 6 | interface RetainedPreviewAnnotation { |
| 7 | annotation: PreviewAnnotationPayload; |
| 8 | image: ComposerImageAttachment | undefined; |
| 9 | } |
| 10 | |
| 11 | export interface RetainedAttachmentContextPayloads { |
| 12 | files: Map<string, ComposerFileAttachment>; |
| 13 | previewAnnotations: Map<string, RetainedPreviewAnnotation>; |
| 14 | } |
| 15 | |
| 16 | export 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 | } |