@agimon-ai/doompi-author 0.0.1-alpha.41 → 0.0.1-alpha.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/extensions/web.mjs +189 -295
- package/dist/extensions/web.mjs.map +1 -1
- package/package.json +4 -4
package/dist/extensions/web.mjs
CHANGED
|
@@ -530,11 +530,8 @@ const TERMINAL_REQUEST_STATUSES = /* @__PURE__ */ new Set([
|
|
|
530
530
|
]);
|
|
531
531
|
const EMPTY_SESSION = {
|
|
532
532
|
generation: 0,
|
|
533
|
-
activeTool: "select",
|
|
534
533
|
annotationsByDocument: {},
|
|
535
|
-
|
|
536
|
-
candidateText: "",
|
|
537
|
-
regions: [],
|
|
534
|
+
toolsByDocument: {},
|
|
538
535
|
requests: []
|
|
539
536
|
};
|
|
540
537
|
function normalizeAuthorPath(path) {
|
|
@@ -561,8 +558,19 @@ function authorSessionWorkspace(sessionId) {
|
|
|
561
558
|
if (sessionId === null) return EMPTY_SESSION;
|
|
562
559
|
return authorWorkspace.store.state.sessions[sessionId] ?? EMPTY_SESSION;
|
|
563
560
|
}
|
|
564
|
-
|
|
565
|
-
|
|
561
|
+
const EMPTY_COLLECTION = Object.freeze({
|
|
562
|
+
revision: 0,
|
|
563
|
+
stale: false,
|
|
564
|
+
candidate: void 0,
|
|
565
|
+
candidateText: "",
|
|
566
|
+
annotations: Object.freeze([]),
|
|
567
|
+
updatedAt: 0
|
|
568
|
+
});
|
|
569
|
+
function authorDocumentAnnotations(sessionId, path, state = authorWorkspace.store.state) {
|
|
570
|
+
if (sessionId === null) return EMPTY_COLLECTION;
|
|
571
|
+
const document = state.documents[authorDocumentKey(sessionId, path)];
|
|
572
|
+
const collection = state.sessions[sessionId]?.annotationsByDocument[normalizeAuthorPath(path)];
|
|
573
|
+
return document !== void 0 && collection !== void 0 && !collection.stale && collection.revision === document.version && collection.sourceSha256 === document.sourceSha256 ? collection : EMPTY_COLLECTION;
|
|
566
574
|
}
|
|
567
575
|
function hydrateAuthorAnnotationCollections(records) {
|
|
568
576
|
authorWorkspace.update((state) => {
|
|
@@ -579,8 +587,6 @@ function hydrateAuthorAnnotationCollections(records) {
|
|
|
579
587
|
...record.collection,
|
|
580
588
|
stale
|
|
581
589
|
});
|
|
582
|
-
const visible = session.focusedDocument?.path === path && !stale;
|
|
583
|
-
const annotations = visible ? collection.annotations : session.annotations;
|
|
584
590
|
sessions = {
|
|
585
591
|
...sessions,
|
|
586
592
|
[record.sessionId]: {
|
|
@@ -588,13 +594,7 @@ function hydrateAuthorAnnotationCollections(records) {
|
|
|
588
594
|
annotationsByDocument: {
|
|
589
595
|
...session.annotationsByDocument,
|
|
590
596
|
[path]: collection
|
|
591
|
-
}
|
|
592
|
-
...visible ? {
|
|
593
|
-
annotations,
|
|
594
|
-
regions: annotations,
|
|
595
|
-
candidate: collection.candidate,
|
|
596
|
-
candidateText: collection.candidateText
|
|
597
|
-
} : {}
|
|
597
|
+
}
|
|
598
598
|
}
|
|
599
599
|
};
|
|
600
600
|
}
|
|
@@ -626,32 +626,25 @@ function putAuthorDocument(sessionId, input) {
|
|
|
626
626
|
};
|
|
627
627
|
const session = state.sessions[sessionId];
|
|
628
628
|
let sessions = state.sessions;
|
|
629
|
-
if (sourceChanged && session
|
|
630
|
-
|
|
629
|
+
if (sourceChanged && session !== void 0) {
|
|
630
|
+
const collection = session.annotationsByDocument[path];
|
|
631
|
+
if (collection?.candidate?.thumbnailUrl !== void 0) staleThumbnails.push(collection.candidate.thumbnailUrl);
|
|
632
|
+
staleThumbnails.push(...(collection?.annotations ?? []).flatMap((annotation) => annotation.thumbnailUrl === void 0 ? [] : [annotation.thumbnailUrl]));
|
|
631
633
|
const now = Date.now();
|
|
632
|
-
const
|
|
633
|
-
const staleCollection = staleAuthorCollection(session.annotationsByDocument[path], now);
|
|
634
|
+
const staleCollection = staleAuthorCollection(collection, now);
|
|
634
635
|
sessions = {
|
|
635
636
|
...sessions,
|
|
636
637
|
[sessionId]: {
|
|
637
638
|
...session,
|
|
638
|
-
generation,
|
|
639
|
-
focusedDocument: {
|
|
640
|
-
path,
|
|
641
|
-
generation,
|
|
642
|
-
revision: baselineVersion,
|
|
643
|
-
sourceSha256: input.sourceSha256,
|
|
644
|
-
focusedAt: now
|
|
645
|
-
},
|
|
646
639
|
annotationsByDocument: {
|
|
647
640
|
...session.annotationsByDocument,
|
|
648
641
|
...staleCollection && { [path]: staleCollection }
|
|
649
642
|
},
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
643
|
+
requests: session.requests.map((request) => input.kind !== "story-preview" && request.documentPath === path && [
|
|
644
|
+
"REQUESTED",
|
|
645
|
+
"CHANGING",
|
|
646
|
+
"CHANGED"
|
|
647
|
+
].includes(request.status) ? {
|
|
655
648
|
...request,
|
|
656
649
|
status: "FAILED",
|
|
657
650
|
currentOperation: void 0,
|
|
@@ -660,20 +653,6 @@ function putAuthorDocument(sessionId, input) {
|
|
|
660
653
|
} : request)
|
|
661
654
|
}
|
|
662
655
|
};
|
|
663
|
-
} else if (sourceChanged && session?.annotationsByDocument[path] !== void 0) {
|
|
664
|
-
const collection = session.annotationsByDocument[path];
|
|
665
|
-
if (collection.candidate?.thumbnailUrl !== void 0) staleThumbnails.push(collection.candidate.thumbnailUrl);
|
|
666
|
-
staleThumbnails.push(...collection.annotations.flatMap((annotation) => annotation.thumbnailUrl === void 0 ? [] : [annotation.thumbnailUrl]));
|
|
667
|
-
sessions = {
|
|
668
|
-
...sessions,
|
|
669
|
-
[sessionId]: {
|
|
670
|
-
...session,
|
|
671
|
-
annotationsByDocument: {
|
|
672
|
-
...session.annotationsByDocument,
|
|
673
|
-
[path]: staleAuthorCollection(collection, Date.now())
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
};
|
|
677
656
|
}
|
|
678
657
|
return {
|
|
679
658
|
documents: {
|
|
@@ -687,76 +666,37 @@ function putAuthorDocument(sessionId, input) {
|
|
|
687
666
|
return result;
|
|
688
667
|
}
|
|
689
668
|
/** Claims focus and returns a generation token that makes cleanup race-safe. */
|
|
690
|
-
function focusAuthorDocument(sessionId, path
|
|
691
|
-
const normalized = normalizeAuthorPath(path);
|
|
669
|
+
function focusAuthorDocument(sessionId, path) {
|
|
692
670
|
let generation = 0;
|
|
693
|
-
authorWorkspace.update((state) => {
|
|
694
|
-
const session = state.sessions[sessionId] ?? EMPTY_SESSION;
|
|
695
|
-
generation = session.generation + 1;
|
|
696
|
-
const stored = session.annotationsByDocument[normalized];
|
|
697
|
-
const current = stored !== void 0 && stored.revision === revision && stored.sourceSha256 === sourceSha256 && !stored.stale ? stored : void 0;
|
|
698
|
-
const annotations = current?.annotations ?? [];
|
|
699
|
-
return {
|
|
700
|
-
...state,
|
|
701
|
-
sessions: {
|
|
702
|
-
...state.sessions,
|
|
703
|
-
[sessionId]: {
|
|
704
|
-
...session,
|
|
705
|
-
generation,
|
|
706
|
-
focusedDocument: {
|
|
707
|
-
path: normalized,
|
|
708
|
-
generation,
|
|
709
|
-
revision,
|
|
710
|
-
sourceSha256,
|
|
711
|
-
focusedAt: Date.now()
|
|
712
|
-
},
|
|
713
|
-
annotations,
|
|
714
|
-
regions: annotations,
|
|
715
|
-
candidate: current?.candidate,
|
|
716
|
-
candidateText: current?.candidateText ?? ""
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
};
|
|
720
|
-
});
|
|
721
|
-
return generation;
|
|
722
|
-
}
|
|
723
|
-
function syncAuthorDocumentFocus(sessionId, generation, revision, sourceSha256) {
|
|
724
671
|
updateSession(sessionId, (session) => {
|
|
725
|
-
|
|
726
|
-
if (focused === void 0 || focused.generation !== generation) return session;
|
|
727
|
-
if (focused.revision === revision && focused.sourceSha256 === sourceSha256) return session;
|
|
672
|
+
generation = session.generation + 1;
|
|
728
673
|
return {
|
|
729
674
|
...session,
|
|
675
|
+
generation,
|
|
730
676
|
focusedDocument: {
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
677
|
+
path: normalizeAuthorPath(path),
|
|
678
|
+
generation,
|
|
679
|
+
focusedAt: Date.now()
|
|
734
680
|
}
|
|
735
681
|
};
|
|
736
682
|
});
|
|
683
|
+
return generation;
|
|
737
684
|
}
|
|
738
685
|
function releaseAuthorDocumentFocus(sessionId, generation) {
|
|
739
|
-
updateSession(sessionId, (session) => {
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
focusedDocument: void 0,
|
|
744
|
-
candidate: void 0,
|
|
745
|
-
candidateText: "",
|
|
746
|
-
annotations: [],
|
|
747
|
-
regions: []
|
|
748
|
-
};
|
|
749
|
-
});
|
|
686
|
+
updateSession(sessionId, (session) => session.focusedDocument?.generation === generation ? {
|
|
687
|
+
...session,
|
|
688
|
+
focusedDocument: void 0
|
|
689
|
+
} : session);
|
|
750
690
|
}
|
|
751
|
-
function seekAuthorVideo(sessionId, timeSeconds) {
|
|
752
|
-
const
|
|
753
|
-
const focused =
|
|
754
|
-
if (
|
|
691
|
+
function seekAuthorVideo(sessionId, path, timeSeconds) {
|
|
692
|
+
const normalized = normalizeAuthorPath(path);
|
|
693
|
+
const focused = authorSessionWorkspace(sessionId).focusedDocument;
|
|
694
|
+
if (focused?.path !== normalized || authorDocumentAnnotations(sessionId, normalized).candidate || !Number.isFinite(timeSeconds) || timeSeconds < 0 || authorDocument(sessionId, normalized)?.kind !== "video") return false;
|
|
695
|
+
setAuthorToolMode(sessionId, normalized, "select");
|
|
755
696
|
updateSession(sessionId, (session) => ({
|
|
756
697
|
...session,
|
|
757
|
-
activeTool: "select",
|
|
758
698
|
videoSeekRequest: {
|
|
759
|
-
path:
|
|
699
|
+
path: normalized,
|
|
760
700
|
generation: focused.generation,
|
|
761
701
|
timeSeconds,
|
|
762
702
|
sequence: (session.videoSeekRequest?.sequence ?? 0) + 1
|
|
@@ -764,110 +704,78 @@ function seekAuthorVideo(sessionId, timeSeconds) {
|
|
|
764
704
|
}));
|
|
765
705
|
return true;
|
|
766
706
|
}
|
|
767
|
-
function setAuthorToolMode(sessionId,
|
|
768
|
-
|
|
707
|
+
function setAuthorToolMode(sessionId, path, tool) {
|
|
708
|
+
const normalized = normalizeAuthorPath(path);
|
|
709
|
+
updateSession(sessionId, (session) => ({
|
|
769
710
|
...session,
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
function setAuthorRegionCandidate(sessionId, candidate) {
|
|
774
|
-
let staleThumbnail;
|
|
775
|
-
updateSession(sessionId, (session) => {
|
|
776
|
-
const focused = session.focusedDocument;
|
|
777
|
-
if (candidate !== void 0) {
|
|
778
|
-
if (focused === void 0 || focused.path !== normalizeAuthorPath(candidate.documentPath)) throw new Error("The Author selection does not belong to the focused document.");
|
|
779
|
-
if (focused.revision !== candidate.revision || focused.sourceSha256 !== candidate.sourceSha256) throw new Error("The Author selection is stale for the focused document.");
|
|
711
|
+
toolsByDocument: {
|
|
712
|
+
...session.toolsByDocument,
|
|
713
|
+
[normalized]: tool
|
|
780
714
|
}
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
}, focused.path, { candidate: copied });
|
|
788
|
-
});
|
|
789
|
-
if (staleThumbnail !== void 0 && staleThumbnail !== candidate?.thumbnailUrl) revokeThumbnail(staleThumbnail);
|
|
715
|
+
}));
|
|
716
|
+
}
|
|
717
|
+
function validateCandidate(sessionId, path, candidate) {
|
|
718
|
+
const document = authorDocument(sessionId, path);
|
|
719
|
+
if (document === void 0 || normalizeAuthorPath(candidate.documentPath) !== normalizeAuthorPath(path)) throw new Error("The Author selection does not belong to the document.");
|
|
720
|
+
if (document.version !== candidate.revision || document.sourceSha256 !== candidate.sourceSha256) throw new Error("The Author selection is stale for the document.");
|
|
790
721
|
}
|
|
791
|
-
function
|
|
722
|
+
function setAuthorRegionCandidate(sessionId, path, candidate) {
|
|
723
|
+
if (candidate !== void 0) validateCandidate(sessionId, path, candidate);
|
|
724
|
+
const thumbnail = authorDocumentAnnotations(sessionId, path).candidate?.thumbnailUrl;
|
|
725
|
+
updateCollection(sessionId, path, (collection) => ({
|
|
726
|
+
...collection,
|
|
727
|
+
candidate: candidate && copyCandidate(candidate)
|
|
728
|
+
}));
|
|
729
|
+
if (thumbnail !== void 0 && thumbnail !== candidate?.thumbnailUrl) revokeThumbnail(thumbnail);
|
|
730
|
+
}
|
|
731
|
+
function setAuthorCandidateText(sessionId, path, candidateText) {
|
|
792
732
|
if (new TextEncoder().encode(candidateText).byteLength > 2048) throw new Error("Author candidate text must not exceed 2 KiB.");
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
candidateText
|
|
798
|
-
}, path, { candidateText });
|
|
799
|
-
});
|
|
733
|
+
updateCollection(sessionId, path, (collection) => ({
|
|
734
|
+
...collection,
|
|
735
|
+
candidateText
|
|
736
|
+
}));
|
|
800
737
|
}
|
|
801
|
-
function commitAuthorRegion(sessionId, comment) {
|
|
738
|
+
function commitAuthorRegion(sessionId, path, comment) {
|
|
739
|
+
const candidate = authorDocumentAnnotations(sessionId, path).candidate;
|
|
740
|
+
if (candidate === void 0) throw new Error("Select a document annotation before adding a comment.");
|
|
802
741
|
const id = crypto.randomUUID();
|
|
803
|
-
const session = authorSessionWorkspace(sessionId);
|
|
804
|
-
if (session.candidate === void 0) throw new Error("Select a document annotation before adding a comment.");
|
|
805
742
|
addAuthorRegion(sessionId, {
|
|
806
|
-
...
|
|
743
|
+
...candidate,
|
|
807
744
|
id,
|
|
808
745
|
comment,
|
|
809
746
|
version: 1
|
|
810
747
|
});
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
candidateText: ""
|
|
817
|
-
}, path, {
|
|
818
|
-
candidate: void 0,
|
|
819
|
-
candidateText: ""
|
|
820
|
-
});
|
|
821
|
-
});
|
|
748
|
+
updateCollection(sessionId, path, (collection) => ({
|
|
749
|
+
...collection,
|
|
750
|
+
candidate: void 0,
|
|
751
|
+
candidateText: ""
|
|
752
|
+
}));
|
|
822
753
|
return id;
|
|
823
754
|
}
|
|
824
755
|
function addAuthorRegion(sessionId, region) {
|
|
825
756
|
if (region.comment.trim() === "") throw new Error("Every Author annotation requires a comment.");
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
if (
|
|
829
|
-
if (
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
...session,
|
|
838
|
-
annotations,
|
|
839
|
-
regions: annotations
|
|
840
|
-
}, focused.path, { annotations });
|
|
757
|
+
validateCandidate(sessionId, region.documentPath, region);
|
|
758
|
+
updateCollection(sessionId, region.documentPath, (collection) => {
|
|
759
|
+
if (collection.annotations.length >= 16) throw new Error(`Author requests support at most 16 annotations.`);
|
|
760
|
+
if (collection.annotations.some((candidate) => candidate.id === region.id)) throw new Error(`Author annotation '${region.id}' already exists.`);
|
|
761
|
+
return {
|
|
762
|
+
...collection,
|
|
763
|
+
annotations: [...collection.annotations, copyRegion({
|
|
764
|
+
...region,
|
|
765
|
+
version: region.version ?? 1
|
|
766
|
+
})]
|
|
767
|
+
};
|
|
841
768
|
});
|
|
842
769
|
}
|
|
843
|
-
function removeAuthorRegion(sessionId, regionId, expectedVersion
|
|
770
|
+
function removeAuthorRegion(sessionId, path, regionId, expectedVersion) {
|
|
844
771
|
let thumbnail;
|
|
845
|
-
|
|
846
|
-
const
|
|
847
|
-
if (
|
|
848
|
-
const focused = session.focusedDocument?.path === path;
|
|
849
|
-
const collection = session.annotationsByDocument[path];
|
|
850
|
-
const current = focused ? session.annotations : collection?.annotations;
|
|
851
|
-
if (current === void 0) return session;
|
|
852
|
-
const annotation = current.find((candidate) => candidate.id === regionId);
|
|
853
|
-
if (annotation === void 0 || expectedVersion !== void 0 && (annotation.version ?? 1) !== expectedVersion) return session;
|
|
772
|
+
updateCollection(sessionId, path, (collection) => {
|
|
773
|
+
const annotation = collection.annotations.find((candidate) => candidate.id === regionId);
|
|
774
|
+
if (annotation === void 0 || expectedVersion !== void 0 && (annotation.version ?? 1) !== expectedVersion) return collection;
|
|
854
775
|
thumbnail = annotation.thumbnailUrl;
|
|
855
|
-
const annotations = current.filter((candidate) => candidate.id !== regionId);
|
|
856
|
-
if (focused) return withFocusedCollection({
|
|
857
|
-
...session,
|
|
858
|
-
annotations,
|
|
859
|
-
regions: annotations
|
|
860
|
-
}, path, { annotations });
|
|
861
776
|
return {
|
|
862
|
-
...
|
|
863
|
-
|
|
864
|
-
...session.annotationsByDocument,
|
|
865
|
-
[path]: {
|
|
866
|
-
...collection,
|
|
867
|
-
annotations,
|
|
868
|
-
updatedAt: Date.now()
|
|
869
|
-
}
|
|
870
|
-
}
|
|
777
|
+
...collection,
|
|
778
|
+
annotations: collection.annotations.filter((candidate) => candidate.id !== regionId)
|
|
871
779
|
};
|
|
872
780
|
});
|
|
873
781
|
if (thumbnail !== void 0) revokeThumbnail(thumbnail);
|
|
@@ -1012,9 +920,7 @@ function updateDocument(sessionId, path, update) {
|
|
|
1012
920
|
if (document === void 0) return state;
|
|
1013
921
|
const next = update(document);
|
|
1014
922
|
const session = state.sessions[sessionId];
|
|
1015
|
-
const focused = session?.focusedDocument;
|
|
1016
923
|
const identityChanged = document.version !== next.version || document.sourceSha256 !== next.sourceSha256;
|
|
1017
|
-
const focusedChanged = identityChanged && focused?.path === document.path;
|
|
1018
924
|
const collection = identityChanged ? session?.annotationsByDocument[document.path] : void 0;
|
|
1019
925
|
if (collection !== void 0) {
|
|
1020
926
|
if (collection.candidate?.thumbnailUrl !== void 0) staleThumbnails.push(collection.candidate.thumbnailUrl);
|
|
@@ -1028,18 +934,7 @@ function updateDocument(sessionId, path, update) {
|
|
|
1028
934
|
annotationsByDocument: {
|
|
1029
935
|
...session.annotationsByDocument,
|
|
1030
936
|
...staleCollection && { [document.path]: staleCollection }
|
|
1031
|
-
}
|
|
1032
|
-
...focusedChanged ? {
|
|
1033
|
-
focusedDocument: {
|
|
1034
|
-
...focused,
|
|
1035
|
-
revision: next.version,
|
|
1036
|
-
sourceSha256: next.sourceSha256
|
|
1037
|
-
},
|
|
1038
|
-
candidate: void 0,
|
|
1039
|
-
candidateText: "",
|
|
1040
|
-
annotations: [],
|
|
1041
|
-
regions: []
|
|
1042
|
-
} : {}
|
|
937
|
+
}
|
|
1043
938
|
}
|
|
1044
939
|
} : state.sessions;
|
|
1045
940
|
return {
|
|
@@ -1100,27 +995,31 @@ function staleAuthorCollection(collection, updatedAt) {
|
|
|
1100
995
|
updatedAt
|
|
1101
996
|
};
|
|
1102
997
|
}
|
|
1103
|
-
function
|
|
1104
|
-
const
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
998
|
+
function updateCollection(sessionId, path, update) {
|
|
999
|
+
const normalized = normalizeAuthorPath(path);
|
|
1000
|
+
const document = authorDocument(sessionId, normalized);
|
|
1001
|
+
if (document === void 0) return;
|
|
1002
|
+
updateSession(sessionId, (session) => {
|
|
1003
|
+
const current = authorDocumentAnnotations(sessionId, normalized);
|
|
1004
|
+
const base = current === EMPTY_COLLECTION ? {
|
|
1005
|
+
...EMPTY_COLLECTION,
|
|
1006
|
+
revision: document.version,
|
|
1007
|
+
sourceSha256: document.sourceSha256
|
|
1008
|
+
} : current;
|
|
1009
|
+
const next = update(base);
|
|
1010
|
+
if (next === base) return session;
|
|
1011
|
+
return {
|
|
1012
|
+
...session,
|
|
1013
|
+
annotationsByDocument: {
|
|
1014
|
+
...session.annotationsByDocument,
|
|
1015
|
+
[normalized]: {
|
|
1016
|
+
...next,
|
|
1017
|
+
stale: false,
|
|
1018
|
+
updatedAt: Date.now()
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
};
|
|
1022
|
+
});
|
|
1124
1023
|
}
|
|
1125
1024
|
function boundedHistoryText(value) {
|
|
1126
1025
|
if (value === void 0) return void 0;
|
|
@@ -1346,6 +1245,7 @@ function normalizedAuthorRectangle(bounds, drag) {
|
|
|
1346
1245
|
//#endregion
|
|
1347
1246
|
//#region src/extensions/workspaces/sessions/(frontend)/_lib/authorCapture.ts
|
|
1348
1247
|
const AUTHOR_CAPTURE_MAX_DIMENSION = 1600;
|
|
1248
|
+
const AUTHOR_PACKET_MAX_BYTES = 65536;
|
|
1349
1249
|
const AUTHOR_QUOTE_MAX_BYTES = 4096;
|
|
1350
1250
|
const AUTHOR_REGION_COLORS = [
|
|
1351
1251
|
"#ff5f57",
|
|
@@ -1426,6 +1326,12 @@ function percent(value) {
|
|
|
1426
1326
|
function rectLocation(rect) {
|
|
1427
1327
|
return `x ${percent(rect.x)}, y ${percent(rect.y)}, w ${percent(rect.width)}, h ${percent(rect.height)}`;
|
|
1428
1328
|
}
|
|
1329
|
+
/** Context stays below the host limit even when paths and anchor locations are unusually long. */
|
|
1330
|
+
function authorDocumentContextContent(path, alias, annotations) {
|
|
1331
|
+
const heading = `Author document: ${path}${alias === void 0 ? "" : ` (canvas ${alias})`}`;
|
|
1332
|
+
const drafts = annotations.map((region, index) => `(${index + 1}) ${region.comment.slice(0, 1e3)} [${anchorLocation(region.anchor)}]`);
|
|
1333
|
+
return utf8Prefix([heading, ...drafts.length === 0 ? [] : ["Unsent annotations (not yet submitted):", ...drafts]].join("\n"), AUTHOR_PACKET_MAX_BYTES);
|
|
1334
|
+
}
|
|
1429
1335
|
function anchorLocation(anchor) {
|
|
1430
1336
|
switch (anchor.kind) {
|
|
1431
1337
|
case "text-range": return anchor.startLine === anchor.endLine ? `line ${String(anchor.startLine)}` : `lines ${String(anchor.startLine)}-${String(anchor.endLine)}`;
|
|
@@ -1626,23 +1532,23 @@ function multiRegionCaptureProvider(regions) {
|
|
|
1626
1532
|
}
|
|
1627
1533
|
//#endregion
|
|
1628
1534
|
//#region src/extensions/workspaces/sessions/(frontend)/dock/_components/AuthorRegionDrafts.tsx
|
|
1629
|
-
function AuthorRegionDrafts({ sessionId,
|
|
1535
|
+
function AuthorRegionDrafts({ sessionId, path, drafts }) {
|
|
1630
1536
|
const [error, setError] = useState();
|
|
1631
1537
|
const add = () => {
|
|
1632
1538
|
try {
|
|
1633
|
-
commitAuthorRegion(sessionId,
|
|
1539
|
+
commitAuthorRegion(sessionId, path, drafts.candidateText);
|
|
1634
1540
|
setError(void 0);
|
|
1635
1541
|
} catch (reason) {
|
|
1636
1542
|
setError(reason instanceof Error ? reason.message : String(reason));
|
|
1637
1543
|
}
|
|
1638
1544
|
};
|
|
1639
|
-
if (!
|
|
1640
|
-
const candidateKind =
|
|
1545
|
+
if (!drafts.candidate && drafts.annotations.length === 0) return null;
|
|
1546
|
+
const candidateKind = drafts.candidate?.mode === "point" ? "point" : "region";
|
|
1641
1547
|
return /* @__PURE__ */ jsxs("section", {
|
|
1642
1548
|
className: "space-y-2",
|
|
1643
1549
|
"data-testid": "author-region-drafts",
|
|
1644
1550
|
children: [
|
|
1645
|
-
|
|
1551
|
+
drafts.candidate ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1646
1552
|
/* @__PURE__ */ jsxs("h3", {
|
|
1647
1553
|
className: "text-base font-semibold text-doom-text",
|
|
1648
1554
|
children: ["Current ", candidateKind]
|
|
@@ -1655,18 +1561,18 @@ function AuthorRegionDrafts({ sessionId, workspace }) {
|
|
|
1655
1561
|
" as an unsent annotation."
|
|
1656
1562
|
]
|
|
1657
1563
|
}),
|
|
1658
|
-
|
|
1564
|
+
drafts.candidate.anchor.kind === "video-time-rect" || drafts.candidate.anchor.kind === "video-time-point" ? /* @__PURE__ */ jsxs("p", {
|
|
1659
1565
|
className: "text-base text-doom-dim sm:text-sm",
|
|
1660
1566
|
children: [
|
|
1661
1567
|
"Frame at ",
|
|
1662
|
-
|
|
1568
|
+
drafts.candidate.anchor.timeSeconds.toFixed(3),
|
|
1663
1569
|
"s"
|
|
1664
1570
|
]
|
|
1665
1571
|
}) : null,
|
|
1666
1572
|
/* @__PURE__ */ jsx("textarea", {
|
|
1667
1573
|
"aria-label": "Annotation comment",
|
|
1668
|
-
value:
|
|
1669
|
-
onChange: (event) => setAuthorCandidateText(sessionId, event.target.value),
|
|
1574
|
+
value: drafts.candidateText,
|
|
1575
|
+
onChange: (event) => setAuthorCandidateText(sessionId, path, event.target.value),
|
|
1670
1576
|
placeholder: "What should change here?",
|
|
1671
1577
|
rows: 3,
|
|
1672
1578
|
className: "min-h-11 w-full resize-y rounded border border-doom-border bg-doom-deep p-2 text-lg leading-normal text-doom-text focus:border-doom-red focus:outline-none sm:text-sm"
|
|
@@ -1675,15 +1581,15 @@ function AuthorRegionDrafts({ sessionId, workspace }) {
|
|
|
1675
1581
|
className: "min-h-11 min-w-11 text-base [@media(pointer:fine)]:min-h-8 sm:text-sm",
|
|
1676
1582
|
variant: "outline",
|
|
1677
1583
|
onClick: add,
|
|
1678
|
-
disabled: !
|
|
1584
|
+
disabled: !drafts.candidate || !drafts.candidateText.trim() || drafts.annotations.length >= 16,
|
|
1679
1585
|
children: "add annotation"
|
|
1680
1586
|
}),
|
|
1681
1587
|
/* @__PURE__ */ jsx(Button, {
|
|
1682
1588
|
variant: "ghost",
|
|
1683
1589
|
className: "min-h-11 min-w-11 text-base [@media(pointer:fine)]:min-h-8 sm:text-sm",
|
|
1684
1590
|
onClick: () => {
|
|
1685
|
-
setAuthorRegionCandidate(sessionId, void 0);
|
|
1686
|
-
setAuthorCandidateText(sessionId, "");
|
|
1591
|
+
setAuthorRegionCandidate(sessionId, path, void 0);
|
|
1592
|
+
setAuthorCandidateText(sessionId, path, "");
|
|
1687
1593
|
setError(void 0);
|
|
1688
1594
|
},
|
|
1689
1595
|
children: "Discard annotation"
|
|
@@ -1693,17 +1599,17 @@ function AuthorRegionDrafts({ sessionId, workspace }) {
|
|
|
1693
1599
|
className: "block text-base text-doom-red",
|
|
1694
1600
|
children: error
|
|
1695
1601
|
}) : null,
|
|
1696
|
-
|
|
1602
|
+
drafts.annotations.length > 0 ? /* @__PURE__ */ jsxs("h3", {
|
|
1697
1603
|
className: "text-base font-semibold text-doom-text",
|
|
1698
1604
|
children: [
|
|
1699
1605
|
"Unsent annotations (",
|
|
1700
|
-
|
|
1606
|
+
drafts.annotations.length,
|
|
1701
1607
|
")"
|
|
1702
1608
|
]
|
|
1703
1609
|
}) : null,
|
|
1704
1610
|
/* @__PURE__ */ jsx("ol", {
|
|
1705
1611
|
className: "space-y-2",
|
|
1706
|
-
children:
|
|
1612
|
+
children: drafts.annotations.map((region, index) => /* @__PURE__ */ jsxs("li", {
|
|
1707
1613
|
className: "rounded border border-doom-border bg-doom-panel p-2 text-base leading-normal text-doom-text sm:text-sm",
|
|
1708
1614
|
children: [
|
|
1709
1615
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
@@ -1717,9 +1623,9 @@ function AuthorRegionDrafts({ sessionId, workspace }) {
|
|
|
1717
1623
|
region.anchor.kind === "video-time-rect" || region.anchor.kind === "video-time-point" ? /* @__PURE__ */ jsxs(Button, {
|
|
1718
1624
|
variant: "outline",
|
|
1719
1625
|
className: "min-h-11 min-w-11 text-base [@media(pointer:fine)]:min-h-8 sm:text-sm",
|
|
1720
|
-
disabled:
|
|
1626
|
+
disabled: drafts.candidate !== void 0,
|
|
1721
1627
|
onClick: () => {
|
|
1722
|
-
if (region.anchor.kind === "video-time-rect" || region.anchor.kind === "video-time-point") seekAuthorVideo(sessionId, region.anchor.timeSeconds);
|
|
1628
|
+
if (region.anchor.kind === "video-time-rect" || region.anchor.kind === "video-time-point") seekAuthorVideo(sessionId, path, region.anchor.timeSeconds);
|
|
1723
1629
|
},
|
|
1724
1630
|
children: [
|
|
1725
1631
|
"Go to ",
|
|
@@ -1731,7 +1637,7 @@ function AuthorRegionDrafts({ sessionId, workspace }) {
|
|
|
1731
1637
|
className: "min-h-11 min-w-11 text-base [@media(pointer:fine)]:min-h-8 sm:text-sm",
|
|
1732
1638
|
variant: "ghost",
|
|
1733
1639
|
"aria-label": `Remove annotation ${index + 1}`,
|
|
1734
|
-
onClick: () => removeAuthorRegion(sessionId, region.id),
|
|
1640
|
+
onClick: () => removeAuthorRegion(sessionId, path, region.id),
|
|
1735
1641
|
children: "remove"
|
|
1736
1642
|
})
|
|
1737
1643
|
]
|
|
@@ -1742,7 +1648,7 @@ function AuthorRegionDrafts({ sessionId, workspace }) {
|
|
|
1742
1648
|
}
|
|
1743
1649
|
//#endregion
|
|
1744
1650
|
//#region src/extensions/workspaces/sessions/(frontend)/dock/_components/AuthorFeedbackControls.tsx
|
|
1745
|
-
function AuthorFeedbackControls({ sessionId, document,
|
|
1651
|
+
function AuthorFeedbackControls({ sessionId, document, drafts, submitCapture }) {
|
|
1746
1652
|
const [status, setStatus] = useState();
|
|
1747
1653
|
const [capturing, setCapturing] = useState(false);
|
|
1748
1654
|
return /* @__PURE__ */ jsxs("div", {
|
|
@@ -1750,21 +1656,22 @@ function AuthorFeedbackControls({ sessionId, document, workspace, submitCapture
|
|
|
1750
1656
|
children: [
|
|
1751
1657
|
/* @__PURE__ */ jsx(AuthorRegionDrafts, {
|
|
1752
1658
|
sessionId,
|
|
1753
|
-
|
|
1659
|
+
path: document.path,
|
|
1660
|
+
drafts
|
|
1754
1661
|
}),
|
|
1755
|
-
|
|
1662
|
+
drafts.annotations.length > 0 ? /* @__PURE__ */ jsx(Button, {
|
|
1756
1663
|
className: "min-h-11 min-w-11 w-full text-base [@media(pointer:fine)]:min-h-8 sm:text-sm",
|
|
1757
1664
|
variant: "outline",
|
|
1758
1665
|
"data-testid": "author-attach-capture",
|
|
1759
|
-
disabled: capturing ||
|
|
1666
|
+
disabled: capturing || drafts.candidate !== void 0 || submitCapture === void 0,
|
|
1760
1667
|
onClick: async () => {
|
|
1761
|
-
if (capturing ||
|
|
1668
|
+
if (capturing || drafts.candidate || submitCapture === void 0) return;
|
|
1762
1669
|
setCapturing(true);
|
|
1763
1670
|
setStatus("Submitting annotations…");
|
|
1764
1671
|
try {
|
|
1765
|
-
const packet = createAuthorCapturePacket(crypto.randomUUID(), Date.now(), document,
|
|
1672
|
+
const packet = createAuthorCapturePacket(crypto.randomUUID(), Date.now(), document, drafts.annotations, authorCanvasAlias(sessionId, document.path));
|
|
1766
1673
|
await submitCapture({
|
|
1767
|
-
...await multiRegionCaptureProvider(
|
|
1674
|
+
...await multiRegionCaptureProvider(drafts.annotations).capture(),
|
|
1768
1675
|
context: authorCaptureContext(packet)
|
|
1769
1676
|
});
|
|
1770
1677
|
setStatus("Request submitted. You can keep annotating here.");
|
|
@@ -1774,7 +1681,7 @@ function AuthorFeedbackControls({ sessionId, document, workspace, submitCapture
|
|
|
1774
1681
|
setCapturing(false);
|
|
1775
1682
|
}
|
|
1776
1683
|
},
|
|
1777
|
-
children: capturing ? "Submitting…" : `Submit ${
|
|
1684
|
+
children: capturing ? "Submitting…" : `Submit ${drafts.annotations.length} annotation${drafts.annotations.length === 1 ? "" : "s"}`
|
|
1778
1685
|
}) : null,
|
|
1779
1686
|
submitCapture === void 0 ? /* @__PURE__ */ jsx("output", {
|
|
1780
1687
|
className: "text-sm text-doom-red",
|
|
@@ -1991,10 +1898,10 @@ function AuthorRequestLog({ requests }) {
|
|
|
1991
1898
|
}
|
|
1992
1899
|
//#endregion
|
|
1993
1900
|
//#region src/extensions/workspaces/sessions/(frontend)/dock/_components/AuthorToolPalette.tsx
|
|
1994
|
-
function AuthorToolPalette({ sessionId, kind, activeTool }) {
|
|
1901
|
+
function AuthorToolPalette({ sessionId, path, kind, activeTool }) {
|
|
1995
1902
|
const [error, setError] = useState();
|
|
1996
1903
|
const format = (style) => {
|
|
1997
|
-
const selected =
|
|
1904
|
+
const selected = authorDocumentAnnotations(sessionId, path).candidate;
|
|
1998
1905
|
const document = selected && authorDocument(sessionId, selected.documentPath);
|
|
1999
1906
|
if (!selected || !document || selected.anchor.kind !== "text-range" || selected.revision !== document.version || selected.sourceSha256 !== document.sourceSha256) {
|
|
2000
1907
|
setError("Select text in the document first.");
|
|
@@ -2005,7 +1912,7 @@ function AuthorToolPalette({ sessionId, kind, activeTool }) {
|
|
|
2005
1912
|
const text = content.slice(startOffset, endOffset);
|
|
2006
1913
|
const replacement = style === "Bold" ? `**${text}**` : style === "Link" ? `[${text}](https://)` : text.split("\n").map((line) => `${style === "Heading" ? "## " : "- "}${line}`).join("\n");
|
|
2007
1914
|
reviseAuthorDocument(sessionId, document.path, content.slice(0, startOffset) + replacement + content.slice(endOffset));
|
|
2008
|
-
setAuthorRegionCandidate(sessionId, void 0);
|
|
1915
|
+
setAuthorRegionCandidate(sessionId, path, void 0);
|
|
2009
1916
|
setError(void 0);
|
|
2010
1917
|
};
|
|
2011
1918
|
const tools = [
|
|
@@ -2017,18 +1924,18 @@ function AuthorToolPalette({ sessionId, kind, activeTool }) {
|
|
|
2017
1924
|
].includes(kind) ? [{
|
|
2018
1925
|
label: "Pan",
|
|
2019
1926
|
glyph: "✋",
|
|
2020
|
-
action: () => setAuthorToolMode(sessionId, activeTool === "pan" ? "select" : "pan"),
|
|
1927
|
+
action: () => setAuthorToolMode(sessionId, path, activeTool === "pan" ? "select" : "pan"),
|
|
2021
1928
|
active: activeTool === "pan"
|
|
2022
1929
|
}, {
|
|
2023
1930
|
label: "Draw",
|
|
2024
1931
|
glyph: "✎",
|
|
2025
|
-
action: () => setAuthorToolMode(sessionId, activeTool === "draw" ? "select" : "draw"),
|
|
1932
|
+
action: () => setAuthorToolMode(sessionId, path, activeTool === "draw" ? "select" : "draw"),
|
|
2026
1933
|
active: activeTool === "draw"
|
|
2027
1934
|
}] : [],
|
|
2028
1935
|
{
|
|
2029
1936
|
label: "Region",
|
|
2030
1937
|
glyph: "⌗",
|
|
2031
|
-
action: () => setAuthorToolMode(sessionId, activeTool === "mark" ? "select" : "mark"),
|
|
1938
|
+
action: () => setAuthorToolMode(sessionId, path, activeTool === "mark" ? "select" : "mark"),
|
|
2032
1939
|
active: activeTool === "mark"
|
|
2033
1940
|
},
|
|
2034
1941
|
...kind === "markdown" ? [
|
|
@@ -2056,7 +1963,7 @@ function AuthorToolPalette({ sessionId, kind, activeTool }) {
|
|
|
2056
1963
|
{
|
|
2057
1964
|
label: "Comment",
|
|
2058
1965
|
glyph: "●",
|
|
2059
|
-
action: () => setAuthorToolMode(sessionId, activeTool === "comment" ? "select" : "comment"),
|
|
1966
|
+
action: () => setAuthorToolMode(sessionId, path, activeTool === "comment" ? "select" : "comment"),
|
|
2060
1967
|
active: activeTool === "comment"
|
|
2061
1968
|
}
|
|
2062
1969
|
];
|
|
@@ -2110,7 +2017,8 @@ function AuthorPanel({ sessionId, activeMinorModes, submitCapture, statuses, ren
|
|
|
2110
2017
|
const focused = documents.find((document) => document.path === workspace?.focusedDocument?.path);
|
|
2111
2018
|
const focusedPath = workspace?.focusedDocument?.path;
|
|
2112
2019
|
const requests = (workspace?.requests ?? []).filter((request) => focusedPath === void 0 || request.documentPath === focusedPath);
|
|
2113
|
-
const
|
|
2020
|
+
const drafts = useStore(authorWorkspace.store, (state) => authorDocumentAnnotations(sessionId, focusedPath ?? "", state));
|
|
2021
|
+
const activity = sessionId !== null && focusedPath !== void 0 && requests.some((request) => request.status === "REQUESTED" || request.status === "CHANGING") ? renderSessionActivity?.() ?? null : null;
|
|
2114
2022
|
if (!activeMinorModes?.includes("author")) return null;
|
|
2115
2023
|
return /* @__PURE__ */ jsxs("section", {
|
|
2116
2024
|
"data-testid": "author-panel",
|
|
@@ -2139,8 +2047,9 @@ function AuthorPanel({ sessionId, activeMinorModes, submitCapture, statuses, ren
|
|
|
2139
2047
|
}) : null,
|
|
2140
2048
|
/* @__PURE__ */ jsx(AuthorToolPalette, {
|
|
2141
2049
|
sessionId,
|
|
2050
|
+
path: focused.path,
|
|
2142
2051
|
kind: focused.kind,
|
|
2143
|
-
activeTool: workspace.
|
|
2052
|
+
activeTool: workspace.toolsByDocument[normalizeAuthorPath(focused.path)] ?? "select"
|
|
2144
2053
|
}),
|
|
2145
2054
|
autonomousVoiceGridVisible(statuses) && grid !== void 0 ? /* @__PURE__ */ jsxs("div", {
|
|
2146
2055
|
"data-testid": "author-grid-snapshot",
|
|
@@ -2158,7 +2067,7 @@ function AuthorPanel({ sessionId, activeMinorModes, submitCapture, statuses, ren
|
|
|
2158
2067
|
children: /* @__PURE__ */ jsx(AuthorFeedbackControls, {
|
|
2159
2068
|
sessionId,
|
|
2160
2069
|
document: focused,
|
|
2161
|
-
|
|
2070
|
+
drafts,
|
|
2162
2071
|
submitCapture
|
|
2163
2072
|
}, focused.path)
|
|
2164
2073
|
})
|
|
@@ -3177,11 +3086,11 @@ function AuthorMediaView({ sessionId, document: source, activeTool, displayedReg
|
|
|
3177
3086
|
};
|
|
3178
3087
|
}, [source.mediaUrl]);
|
|
3179
3088
|
const seek = (seconds) => {
|
|
3180
|
-
if (
|
|
3089
|
+
if (authorDocumentAnnotations(sessionId, source.path).candidate || !Number.isFinite(seconds)) return;
|
|
3181
3090
|
const player = video.current;
|
|
3182
3091
|
if (!player) return;
|
|
3183
3092
|
player.pause();
|
|
3184
|
-
setAuthorToolMode(sessionId, "select");
|
|
3093
|
+
setAuthorToolMode(sessionId, source.path, "select");
|
|
3185
3094
|
setSelection(void 0);
|
|
3186
3095
|
if (player.getState().currentTime === seconds) return;
|
|
3187
3096
|
setFrameReady(false);
|
|
@@ -3316,7 +3225,7 @@ function AuthorMediaView({ sessionId, document: source, activeTool, displayedReg
|
|
|
3316
3225
|
if (!blob) throw new Error("Unable to capture selected media.");
|
|
3317
3226
|
if (authorSessionWorkspace(sessionId).focusedDocument?.generation !== focused.generation) return;
|
|
3318
3227
|
thumbnailUrl = URL.createObjectURL(blob);
|
|
3319
|
-
setAuthorRegionCandidate(sessionId, {
|
|
3228
|
+
setAuthorRegionCandidate(sessionId, source.path, {
|
|
3320
3229
|
documentPath: source.path,
|
|
3321
3230
|
revision: source.version,
|
|
3322
3231
|
sourceSha256: source.sourceSha256,
|
|
@@ -3675,14 +3584,14 @@ function AuthorMediaView({ sessionId, document: source, activeTool, displayedReg
|
|
|
3675
3584
|
marking: activeTool === "mark",
|
|
3676
3585
|
onSeek: seek,
|
|
3677
3586
|
onToggle: () => {
|
|
3678
|
-
setAuthorToolMode(sessionId, "select");
|
|
3587
|
+
setAuthorToolMode(sessionId, source.path, "select");
|
|
3679
3588
|
setSelection(void 0);
|
|
3680
3589
|
if (playback.playing) video.current?.pause();
|
|
3681
3590
|
else video.current?.play().catch((reason) => setError(String(reason)));
|
|
3682
3591
|
},
|
|
3683
3592
|
onAnnotate: () => {
|
|
3684
3593
|
video.current?.pause();
|
|
3685
|
-
setAuthorToolMode(sessionId, "mark");
|
|
3594
|
+
setAuthorToolMode(sessionId, source.path, "mark");
|
|
3686
3595
|
}
|
|
3687
3596
|
}) : null,
|
|
3688
3597
|
error ? /* @__PURE__ */ jsx("output", {
|
|
@@ -3763,7 +3672,7 @@ function AuthorStructuredView({ sessionId, document, displayedRegions }) {
|
|
|
3763
3672
|
const bounds = event.currentTarget.getBoundingClientRect();
|
|
3764
3673
|
const slide = Number(fragment.location.match(/(?:slide\s*|slides\/slide)(\d+)/)?.[1]);
|
|
3765
3674
|
if (!cells && !Number.isSafeInteger(slide)) return;
|
|
3766
|
-
setAuthorRegionCandidate(sessionId, {
|
|
3675
|
+
setAuthorRegionCandidate(sessionId, document.path, {
|
|
3767
3676
|
documentPath: document.path,
|
|
3768
3677
|
revision: document.version,
|
|
3769
3678
|
sourceSha256: document.sourceSha256,
|
|
@@ -3851,7 +3760,7 @@ function AuthorTextView({ sessionId, document, preview, displayedRegions }) {
|
|
|
3851
3760
|
const current = authorDocument(sessionId, document.path);
|
|
3852
3761
|
const bounds = host.current?.getBoundingClientRect();
|
|
3853
3762
|
if (!current || !bounds || range.from === range.to) return;
|
|
3854
|
-
setAuthorRegionCandidate(sessionId, {
|
|
3763
|
+
setAuthorRegionCandidate(sessionId, document.path, {
|
|
3855
3764
|
documentPath: current.path,
|
|
3856
3765
|
revision: current.version,
|
|
3857
3766
|
sourceSha256: current.sourceSha256,
|
|
@@ -3884,7 +3793,7 @@ function tabId(path) {
|
|
|
3884
3793
|
}
|
|
3885
3794
|
/** Unsent annotations only. Sent ones live in the request log, not on the canvas. */
|
|
3886
3795
|
function displayedAuthorRegions(workspace) {
|
|
3887
|
-
return (workspace?.
|
|
3796
|
+
return (workspace?.annotations ?? []).map((region, index) => ({
|
|
3888
3797
|
ordinal: index + 1,
|
|
3889
3798
|
region
|
|
3890
3799
|
}));
|
|
@@ -3907,9 +3816,9 @@ function ActiveAuthorDocumentPanel(props) {
|
|
|
3907
3816
|
const alias = useStore(canvasAliases, (state) => props.alias ?? (sessionId === null ? void 0 : state[authorDocumentKey(sessionId, props.path)]));
|
|
3908
3817
|
const loadFailure = useStore(canvasFailures, (state) => sessionId === null ? void 0 : state[authorDocumentKey(sessionId, props.path)]);
|
|
3909
3818
|
const document = useStore(authorWorkspace.store, (state) => sessionId === null ? void 0 : state.documents[authorDocumentKey(sessionId, path)]);
|
|
3910
|
-
const focusGeneration = useRef(void 0);
|
|
3911
3819
|
const workspace = useStore(authorWorkspace.store, (state) => sessionId === null ? void 0 : state.sessions[sessionId]);
|
|
3912
|
-
const
|
|
3820
|
+
const drafts = useStore(authorWorkspace.store, (state) => authorDocumentAnnotations(sessionId, path, state));
|
|
3821
|
+
const activeTool = workspace?.toolsByDocument[normalizeAuthorPath(path)] ?? "select";
|
|
3913
3822
|
const [markdownPreview, setMarkdownPreview] = useState(true);
|
|
3914
3823
|
const [status, setStatus] = useState();
|
|
3915
3824
|
const [previewOpen, setPreviewOpen] = useState(false);
|
|
@@ -3923,25 +3832,10 @@ function ActiveAuthorDocumentPanel(props) {
|
|
|
3923
3832
|
};
|
|
3924
3833
|
const PreviewPanel = (previewSource === void 0 ? void 0 : (props.slotData?.(authorPreviewActionSlot) ?? []).find(({ data }) => data.embeddedPanel !== void 0 && (data.supportsSource === void 0 || data.supportsSource(previewSource))))?.data.embeddedPanel;
|
|
3925
3834
|
useEffect(() => {
|
|
3926
|
-
if (
|
|
3927
|
-
const generation = focusAuthorDocument(sessionId, path
|
|
3928
|
-
focusGeneration.current = generation;
|
|
3835
|
+
if (sessionId === null) return;
|
|
3836
|
+
const generation = focusAuthorDocument(sessionId, path);
|
|
3929
3837
|
return () => releaseAuthorDocumentFocus(sessionId, generation);
|
|
3930
|
-
}, [
|
|
3931
|
-
kind,
|
|
3932
|
-
document?.sourceSha256,
|
|
3933
|
-
path,
|
|
3934
|
-
sessionId
|
|
3935
|
-
]);
|
|
3936
|
-
useEffect(() => {
|
|
3937
|
-
const generation = focusGeneration.current;
|
|
3938
|
-
if (document === void 0 || sessionId === null || generation === void 0) return;
|
|
3939
|
-
syncAuthorDocumentFocus(sessionId, generation, document.version, document.sourceSha256);
|
|
3940
|
-
}, [
|
|
3941
|
-
document?.sourceSha256,
|
|
3942
|
-
document?.version,
|
|
3943
|
-
sessionId
|
|
3944
|
-
]);
|
|
3838
|
+
}, [path, sessionId]);
|
|
3945
3839
|
useEffect(() => {
|
|
3946
3840
|
if (kind === void 0 || sessionId === null || alias === void 0) return;
|
|
3947
3841
|
const profiles = authorProfilesForDocument(sessionId, path, kind);
|
|
@@ -3980,8 +3874,7 @@ function ActiveAuthorDocumentPanel(props) {
|
|
|
3980
3874
|
}
|
|
3981
3875
|
};
|
|
3982
3876
|
const gridVisible = autonomousVoiceGridVisible(statuses);
|
|
3983
|
-
const
|
|
3984
|
-
const displayedRegions = displayedAuthorRegions(focusedWorkspace);
|
|
3877
|
+
const displayedRegions = displayedAuthorRegions(drafts);
|
|
3985
3878
|
const displayedPreviewAnnotations = displayedRegions.flatMap(({ ordinal, region }) => {
|
|
3986
3879
|
if (region.anchor.kind === "story-preview-rect") return [{
|
|
3987
3880
|
ordinal,
|
|
@@ -4012,7 +3905,7 @@ function ActiveAuthorDocumentPanel(props) {
|
|
|
4012
3905
|
document,
|
|
4013
3906
|
activeTool,
|
|
4014
3907
|
displayedRegions,
|
|
4015
|
-
pendingCandidate:
|
|
3908
|
+
pendingCandidate: drafts.candidate !== void 0,
|
|
4016
3909
|
seekRequest: workspace?.videoSeekRequest
|
|
4017
3910
|
}, document.path);
|
|
4018
3911
|
return /* @__PURE__ */ jsxs("section", {
|
|
@@ -4079,7 +3972,7 @@ function ActiveAuthorDocumentPanel(props) {
|
|
|
4079
3972
|
className: "min-h-11 min-w-11 shrink-0",
|
|
4080
3973
|
"aria-label": `${mode} tool`,
|
|
4081
3974
|
"aria-pressed": activeTool === mode,
|
|
4082
|
-
onClick: () => setAuthorToolMode(sessionId, mode),
|
|
3975
|
+
onClick: () => setAuthorToolMode(sessionId, document.path, mode),
|
|
4083
3976
|
children: mode
|
|
4084
3977
|
}, mode))
|
|
4085
3978
|
}) : null,
|
|
@@ -4090,10 +3983,10 @@ function ActiveAuthorDocumentPanel(props) {
|
|
|
4090
3983
|
source: previewSource,
|
|
4091
3984
|
activeTool: activeTool === "crop" ? "select" : activeTool,
|
|
4092
3985
|
displayedAnnotations: displayedPreviewAnnotations,
|
|
4093
|
-
pendingCandidate:
|
|
3986
|
+
pendingCandidate: drafts.candidate !== void 0,
|
|
4094
3987
|
onAnnotationCandidate: (candidate) => {
|
|
4095
3988
|
setAuthorStoryPreview(sessionId, document.path, candidate.preview);
|
|
4096
|
-
setAuthorRegionCandidate(sessionId, {
|
|
3989
|
+
setAuthorRegionCandidate(sessionId, document.path, {
|
|
4097
3990
|
documentPath: document.path,
|
|
4098
3991
|
revision: document.version,
|
|
4099
3992
|
sourceSha256: document.sourceSha256,
|
|
@@ -4120,7 +4013,7 @@ function ActiveAuthorDocumentPanel(props) {
|
|
|
4120
4013
|
visible: gridVisible
|
|
4121
4014
|
})]
|
|
4122
4015
|
}),
|
|
4123
|
-
|
|
4016
|
+
[
|
|
4124
4017
|
"image",
|
|
4125
4018
|
"pdf",
|
|
4126
4019
|
"video",
|
|
@@ -4130,7 +4023,7 @@ function ActiveAuthorDocumentPanel(props) {
|
|
|
4130
4023
|
children: /* @__PURE__ */ jsx(AuthorFeedbackControls, {
|
|
4131
4024
|
sessionId,
|
|
4132
4025
|
document,
|
|
4133
|
-
|
|
4026
|
+
drafts,
|
|
4134
4027
|
submitCapture: props.submitCapture
|
|
4135
4028
|
})
|
|
4136
4029
|
}) : null
|
|
@@ -4153,7 +4046,7 @@ function authorFileTab(path, preferredAlias) {
|
|
|
4153
4046
|
source: "author",
|
|
4154
4047
|
id: documentPath,
|
|
4155
4048
|
label: alias === void 0 ? name : `${alias} · ${name}`,
|
|
4156
|
-
content:
|
|
4049
|
+
content: authorDocumentContextContent(documentPath, alias, authorDocumentAnnotations(sessionId, documentPath).annotations)
|
|
4157
4050
|
};
|
|
4158
4051
|
},
|
|
4159
4052
|
onOpen(sessionId) {
|
|
@@ -4214,6 +4107,7 @@ function authorFileTab(path, preferredAlias) {
|
|
|
4214
4107
|
},
|
|
4215
4108
|
onClose(sessionId) {
|
|
4216
4109
|
const key = authorDocumentKey(sessionId, normalized);
|
|
4110
|
+
setAuthorToolMode(sessionId, canvasPaths.state[key] ?? normalized, "select");
|
|
4217
4111
|
pendingCanvases.get(key)?.abort();
|
|
4218
4112
|
pendingCanvases.delete(key);
|
|
4219
4113
|
const alias = canvasAliases.state[key] ?? preferredAlias;
|
|
@@ -4494,7 +4388,7 @@ function recordAuthorComposerSubmission(submission) {
|
|
|
4494
4388
|
revision: packet.document.revision,
|
|
4495
4389
|
sourceSha256: packet.document.sourceSha256
|
|
4496
4390
|
});
|
|
4497
|
-
for (const region of packet.regions) removeAuthorRegion(submission.sessionId, region.id, region.version ?? 1
|
|
4391
|
+
for (const region of packet.regions) removeAuthorRegion(submission.sessionId, packet.document.path, region.id, region.version ?? 1);
|
|
4498
4392
|
}
|
|
4499
4393
|
}
|
|
4500
4394
|
/** Only the host's correlated execution events may settle a submitted capture. */
|