dsh-codex-subscription 2.5.7 → 2.5.9
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/README.en.md +7 -1
- package/README.md +7 -1
- package/lib/client.js +763 -218
- package/lib/index.js +1 -1
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -587,6 +587,88 @@ window.__ModuleLoader__.load({
|
|
|
587
587
|
].join("\n");
|
|
588
588
|
}
|
|
589
589
|
//#endregion
|
|
590
|
+
//#region src/image-official-tools.js
|
|
591
|
+
const IMAGE_ASPECT_RATIOS = Object.freeze([
|
|
592
|
+
["square", "1:1"],
|
|
593
|
+
["portrait", "3:4"],
|
|
594
|
+
["story", "9:16"],
|
|
595
|
+
["landscape", "4:3"],
|
|
596
|
+
["widescreen", "16:9"]
|
|
597
|
+
]);
|
|
598
|
+
/**
|
|
599
|
+
* Build viewer actions for one image.
|
|
600
|
+
* @param {{ src: string, name: string, t: (key: string) => string,
|
|
601
|
+
* attachForEdit: (src: string, name: string, draft: string, annotations?: unknown[], referenceName?: string, sourceInDraft?: boolean, extraFiles?: File[]) => Promise<unknown>,
|
|
602
|
+
* sourceInDraft?: boolean }} options
|
|
603
|
+
*/
|
|
604
|
+
function officialImageTools({ src, name, t, attachForEdit, sourceInDraft = false }) {
|
|
605
|
+
const send = (draft, extraFiles = []) => attachForEdit(src, name, draft, [], void 0, sourceInDraft, extraFiles);
|
|
606
|
+
const base = {
|
|
607
|
+
pendingLabel: t("imageEditPreparing"),
|
|
608
|
+
errorLabel: t("imageEditFailed"),
|
|
609
|
+
closeOnSuccess: true
|
|
610
|
+
};
|
|
611
|
+
return [
|
|
612
|
+
{
|
|
613
|
+
...base,
|
|
614
|
+
id: "remove-background",
|
|
615
|
+
kind: "tool",
|
|
616
|
+
label: t("imageRemoveBackground"),
|
|
617
|
+
onInvoke: () => send(t("imageRemoveBackgroundPrompt"))
|
|
618
|
+
},
|
|
619
|
+
{
|
|
620
|
+
...base,
|
|
621
|
+
id: "erase",
|
|
622
|
+
kind: "mask",
|
|
623
|
+
label: t("imageErase"),
|
|
624
|
+
onInvoke: async ({ mask }) => {
|
|
625
|
+
if (!(mask instanceof Blob)) throw new Error("Mark the area to erase first");
|
|
626
|
+
const maskName = `${String(name).replace(/\.[a-z0-9]+$/iu, "")}-erase-mask.png`;
|
|
627
|
+
return send(t("imageErasePrompt"), [new File([mask], maskName, { type: "image/png" })]);
|
|
628
|
+
}
|
|
629
|
+
},
|
|
630
|
+
{
|
|
631
|
+
...base,
|
|
632
|
+
id: "resize",
|
|
633
|
+
kind: "choice",
|
|
634
|
+
label: t("imageResize"),
|
|
635
|
+
options: IMAGE_ASPECT_RATIOS.map(([id, ratio]) => ({
|
|
636
|
+
value: ratio,
|
|
637
|
+
label: `${t(`imageRatio_${id}`)} ${ratio}`
|
|
638
|
+
})),
|
|
639
|
+
onInvoke: ({ option }) => send(t("imageResizePrompt").replaceAll("{aspectRatio}", option))
|
|
640
|
+
}
|
|
641
|
+
];
|
|
642
|
+
}
|
|
643
|
+
/** Draw relative erase strokes in one color onto a canvas of the given size. */
|
|
644
|
+
function paintEraseStrokes(context, strokes, width, height, color) {
|
|
645
|
+
context.strokeStyle = color;
|
|
646
|
+
context.fillStyle = color;
|
|
647
|
+
context.lineCap = "round";
|
|
648
|
+
context.lineJoin = "round";
|
|
649
|
+
const scale = Math.min(width, height);
|
|
650
|
+
for (const stroke of strokes) {
|
|
651
|
+
const points = stroke.points;
|
|
652
|
+
if (points.length === 0) continue;
|
|
653
|
+
context.lineWidth = stroke.size * scale;
|
|
654
|
+
context.beginPath();
|
|
655
|
+
if (points.length === 1) {
|
|
656
|
+
context.arc(points[0].x * width, points[0].y * height, stroke.size * scale / 2, 0, Math.PI * 2);
|
|
657
|
+
context.fill();
|
|
658
|
+
continue;
|
|
659
|
+
}
|
|
660
|
+
context.moveTo(points[0].x * width, points[0].y * height);
|
|
661
|
+
for (const point of points.slice(1)) context.lineTo(point.x * width, point.y * height);
|
|
662
|
+
context.stroke();
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
/** Codex's erase mask: the marked area white on black, at the image's own resolution. */
|
|
666
|
+
function paintEraseMask(context, strokes, width, height) {
|
|
667
|
+
context.fillStyle = "#000";
|
|
668
|
+
context.fillRect(0, 0, width, height);
|
|
669
|
+
paintEraseStrokes(context, strokes, width, height, "#fff");
|
|
670
|
+
}
|
|
671
|
+
//#endregion
|
|
590
672
|
//#region src/client-image-previews.jsx
|
|
591
673
|
function openPreview(props, item, opener, sourceInDraft = false) {
|
|
592
674
|
const { service, preference, t, attachForEdit } = props;
|
|
@@ -595,25 +677,35 @@ window.__ModuleLoader__.load({
|
|
|
595
677
|
service.open({
|
|
596
678
|
items: [{
|
|
597
679
|
...item,
|
|
598
|
-
actions: settings.imageEditing ? [
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
annotations,
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
680
|
+
actions: settings.imageEditing ? [
|
|
681
|
+
{
|
|
682
|
+
id: "edit",
|
|
683
|
+
label: t("imageEdit"),
|
|
684
|
+
pendingLabel: t("imageEditPreparing"),
|
|
685
|
+
errorLabel: t("imageEditFailed"),
|
|
686
|
+
closeOnSuccess: true,
|
|
687
|
+
onInvoke: ({ annotations }) => attachForEdit(item.src, item.name, buildImageEditDraft({
|
|
688
|
+
annotations,
|
|
689
|
+
translate: t,
|
|
690
|
+
sourceName: item.name,
|
|
691
|
+
referenceName
|
|
692
|
+
}), annotations, referenceName, sourceInDraft)
|
|
693
|
+
},
|
|
694
|
+
...officialImageTools({
|
|
695
|
+
src: item.src,
|
|
696
|
+
name: item.name,
|
|
697
|
+
t,
|
|
698
|
+
attachForEdit,
|
|
699
|
+
sourceInDraft
|
|
700
|
+
}),
|
|
701
|
+
...settings.imageSketch && props.openSketchImage ? [{
|
|
702
|
+
id: "sketch",
|
|
703
|
+
label: t("imageToSketch"),
|
|
704
|
+
pendingLabel: t("imageEditPreparing"),
|
|
705
|
+
errorLabel: t("imageEditFailed"),
|
|
706
|
+
onInvoke: () => props.openSketchImage(item.src, item.name)
|
|
707
|
+
}] : []
|
|
708
|
+
] : []
|
|
617
709
|
}],
|
|
618
710
|
opener,
|
|
619
711
|
source: sourceInDraft ? "codex-draft" : "codex-message",
|
|
@@ -804,7 +896,47 @@ window.__ModuleLoader__.load({
|
|
|
804
896
|
d: "M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99"
|
|
805
897
|
}));
|
|
806
898
|
}
|
|
807
|
-
const ForwardRef$
|
|
899
|
+
const ForwardRef$8 = /*#__PURE__*/ react.forwardRef(ArrowPathIcon);
|
|
900
|
+
//#endregion
|
|
901
|
+
//#region node_modules/.pnpm/@heroicons+react@2.2.0_react@18.3.1/node_modules/@heroicons/react/24/outline/esm/ArrowsPointingOutIcon.js
|
|
902
|
+
function ArrowsPointingOutIcon({ title, titleId, ...props }, svgRef) {
|
|
903
|
+
return /*#__PURE__*/ react.createElement("svg", Object.assign({
|
|
904
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
905
|
+
fill: "none",
|
|
906
|
+
viewBox: "0 0 24 24",
|
|
907
|
+
strokeWidth: 1.5,
|
|
908
|
+
stroke: "currentColor",
|
|
909
|
+
"aria-hidden": "true",
|
|
910
|
+
"data-slot": "icon",
|
|
911
|
+
ref: svgRef,
|
|
912
|
+
"aria-labelledby": titleId
|
|
913
|
+
}, props), title ? /*#__PURE__*/ react.createElement("title", { id: titleId }, title) : null, /*#__PURE__*/ react.createElement("path", {
|
|
914
|
+
strokeLinecap: "round",
|
|
915
|
+
strokeLinejoin: "round",
|
|
916
|
+
d: "M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15"
|
|
917
|
+
}));
|
|
918
|
+
}
|
|
919
|
+
const ForwardRef$7 = /*#__PURE__*/ react.forwardRef(ArrowsPointingOutIcon);
|
|
920
|
+
//#endregion
|
|
921
|
+
//#region node_modules/.pnpm/@heroicons+react@2.2.0_react@18.3.1/node_modules/@heroicons/react/24/outline/esm/ChatBubbleLeftEllipsisIcon.js
|
|
922
|
+
function ChatBubbleLeftEllipsisIcon({ title, titleId, ...props }, svgRef) {
|
|
923
|
+
return /*#__PURE__*/ react.createElement("svg", Object.assign({
|
|
924
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
925
|
+
fill: "none",
|
|
926
|
+
viewBox: "0 0 24 24",
|
|
927
|
+
strokeWidth: 1.5,
|
|
928
|
+
stroke: "currentColor",
|
|
929
|
+
"aria-hidden": "true",
|
|
930
|
+
"data-slot": "icon",
|
|
931
|
+
ref: svgRef,
|
|
932
|
+
"aria-labelledby": titleId
|
|
933
|
+
}, props), title ? /*#__PURE__*/ react.createElement("title", { id: titleId }, title) : null, /*#__PURE__*/ react.createElement("path", {
|
|
934
|
+
strokeLinecap: "round",
|
|
935
|
+
strokeLinejoin: "round",
|
|
936
|
+
d: "M8.625 9.75a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0H8.25m4.125 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0H12m4.125 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0h-.375m-13.5 3.01c0 1.6 1.123 2.994 2.707 3.227 1.087.16 2.185.283 3.293.369V21l4.184-4.183a1.14 1.14 0 0 1 .778-.332 48.294 48.294 0 0 0 5.83-.498c1.585-.233 2.708-1.626 2.708-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0 0 12 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018Z"
|
|
937
|
+
}));
|
|
938
|
+
}
|
|
939
|
+
const ForwardRef$6 = /*#__PURE__*/ react.forwardRef(ChatBubbleLeftEllipsisIcon);
|
|
808
940
|
//#endregion
|
|
809
941
|
//#region node_modules/.pnpm/@heroicons+react@2.2.0_react@18.3.1/node_modules/@heroicons/react/24/outline/esm/ExclamationCircleIcon.js
|
|
810
942
|
function ExclamationCircleIcon({ title, titleId, ...props }, svgRef) {
|
|
@@ -824,7 +956,47 @@ window.__ModuleLoader__.load({
|
|
|
824
956
|
d: "M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z"
|
|
825
957
|
}));
|
|
826
958
|
}
|
|
827
|
-
const ForwardRef$
|
|
959
|
+
const ForwardRef$5 = /*#__PURE__*/ react.forwardRef(ExclamationCircleIcon);
|
|
960
|
+
//#endregion
|
|
961
|
+
//#region node_modules/.pnpm/@heroicons+react@2.2.0_react@18.3.1/node_modules/@heroicons/react/24/outline/esm/PaintBrushIcon.js
|
|
962
|
+
function PaintBrushIcon({ title, titleId, ...props }, svgRef) {
|
|
963
|
+
return /*#__PURE__*/ react.createElement("svg", Object.assign({
|
|
964
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
965
|
+
fill: "none",
|
|
966
|
+
viewBox: "0 0 24 24",
|
|
967
|
+
strokeWidth: 1.5,
|
|
968
|
+
stroke: "currentColor",
|
|
969
|
+
"aria-hidden": "true",
|
|
970
|
+
"data-slot": "icon",
|
|
971
|
+
ref: svgRef,
|
|
972
|
+
"aria-labelledby": titleId
|
|
973
|
+
}, props), title ? /*#__PURE__*/ react.createElement("title", { id: titleId }, title) : null, /*#__PURE__*/ react.createElement("path", {
|
|
974
|
+
strokeLinecap: "round",
|
|
975
|
+
strokeLinejoin: "round",
|
|
976
|
+
d: "M9.53 16.122a3 3 0 0 0-5.78 1.128 2.25 2.25 0 0 1-2.4 2.245 4.5 4.5 0 0 0 8.4-2.245c0-.399-.078-.78-.22-1.128Zm0 0a15.998 15.998 0 0 0 3.388-1.62m-5.043-.025a15.994 15.994 0 0 1 1.622-3.395m3.42 3.42a15.995 15.995 0 0 0 4.764-4.648l3.876-5.814a1.151 1.151 0 0 0-1.597-1.597L14.146 6.32a15.996 15.996 0 0 0-4.649 4.763m3.42 3.42a6.776 6.776 0 0 0-3.42-3.42"
|
|
977
|
+
}));
|
|
978
|
+
}
|
|
979
|
+
const ForwardRef$4 = /*#__PURE__*/ react.forwardRef(PaintBrushIcon);
|
|
980
|
+
//#endregion
|
|
981
|
+
//#region node_modules/.pnpm/@heroicons+react@2.2.0_react@18.3.1/node_modules/@heroicons/react/24/outline/esm/PencilIcon.js
|
|
982
|
+
function PencilIcon({ title, titleId, ...props }, svgRef) {
|
|
983
|
+
return /*#__PURE__*/ react.createElement("svg", Object.assign({
|
|
984
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
985
|
+
fill: "none",
|
|
986
|
+
viewBox: "0 0 24 24",
|
|
987
|
+
strokeWidth: 1.5,
|
|
988
|
+
stroke: "currentColor",
|
|
989
|
+
"aria-hidden": "true",
|
|
990
|
+
"data-slot": "icon",
|
|
991
|
+
ref: svgRef,
|
|
992
|
+
"aria-labelledby": titleId
|
|
993
|
+
}, props), title ? /*#__PURE__*/ react.createElement("title", { id: titleId }, title) : null, /*#__PURE__*/ react.createElement("path", {
|
|
994
|
+
strokeLinecap: "round",
|
|
995
|
+
strokeLinejoin: "round",
|
|
996
|
+
d: "m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125"
|
|
997
|
+
}));
|
|
998
|
+
}
|
|
999
|
+
const ForwardRef$3 = /*#__PURE__*/ react.forwardRef(PencilIcon);
|
|
828
1000
|
//#endregion
|
|
829
1001
|
//#region node_modules/.pnpm/@heroicons+react@2.2.0_react@18.3.1/node_modules/@heroicons/react/24/outline/esm/PhotoIcon.js
|
|
830
1002
|
function PhotoIcon({ title, titleId, ...props }, svgRef) {
|
|
@@ -844,7 +1016,27 @@ window.__ModuleLoader__.load({
|
|
|
844
1016
|
d: "m2.25 15.75 5.159-5.159a2.25 2.25 0 0 1 3.182 0l5.159 5.159m-1.5-1.5 1.409-1.409a2.25 2.25 0 0 1 3.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 0 0 1.5-1.5V6a1.5 1.5 0 0 0-1.5-1.5H3.75A1.5 1.5 0 0 0 2.25 6v12a1.5 1.5 0 0 0 1.5 1.5Zm10.5-11.25h.008v.008h-.008V8.25Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z"
|
|
845
1017
|
}));
|
|
846
1018
|
}
|
|
847
|
-
const ForwardRef$
|
|
1019
|
+
const ForwardRef$2 = /*#__PURE__*/ react.forwardRef(PhotoIcon);
|
|
1020
|
+
//#endregion
|
|
1021
|
+
//#region node_modules/.pnpm/@heroicons+react@2.2.0_react@18.3.1/node_modules/@heroicons/react/24/outline/esm/ScissorsIcon.js
|
|
1022
|
+
function ScissorsIcon({ title, titleId, ...props }, svgRef) {
|
|
1023
|
+
return /*#__PURE__*/ react.createElement("svg", Object.assign({
|
|
1024
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1025
|
+
fill: "none",
|
|
1026
|
+
viewBox: "0 0 24 24",
|
|
1027
|
+
strokeWidth: 1.5,
|
|
1028
|
+
stroke: "currentColor",
|
|
1029
|
+
"aria-hidden": "true",
|
|
1030
|
+
"data-slot": "icon",
|
|
1031
|
+
ref: svgRef,
|
|
1032
|
+
"aria-labelledby": titleId
|
|
1033
|
+
}, props), title ? /*#__PURE__*/ react.createElement("title", { id: titleId }, title) : null, /*#__PURE__*/ react.createElement("path", {
|
|
1034
|
+
strokeLinecap: "round",
|
|
1035
|
+
strokeLinejoin: "round",
|
|
1036
|
+
d: "m7.848 8.25 1.536.887M7.848 8.25a3 3 0 1 1-5.196-3 3 3 0 0 1 5.196 3Zm1.536.887a2.165 2.165 0 0 1 1.083 1.839c.005.351.054.695.14 1.024M9.384 9.137l2.077 1.199M7.848 15.75l1.536-.887m-1.536.887a3 3 0 1 1-5.196 3 3 3 0 0 1 5.196-3Zm1.536-.887a2.165 2.165 0 0 0 1.083-1.838c.005-.352.054-.695.14-1.025m-1.223 2.863 2.077-1.199m0-3.328a4.323 4.323 0 0 1 2.068-1.379l5.325-1.628a4.5 4.5 0 0 1 2.48-.044l.803.215-7.794 4.5m-2.882-1.664A4.33 4.33 0 0 0 10.607 12m3.736 0 7.794 4.5-.802.215a4.5 4.5 0 0 1-2.48-.043l-5.326-1.629a4.324 4.324 0 0 1-2.068-1.379M14.343 12l-2.882 1.664"
|
|
1037
|
+
}));
|
|
1038
|
+
}
|
|
1039
|
+
const ForwardRef$1 = /*#__PURE__*/ react.forwardRef(ScissorsIcon);
|
|
848
1040
|
const ORIGINAL_IMAGE_ID_PATTERN = /^img_[0-9a-f]{32}$/u;
|
|
849
1041
|
const positiveInteger = (value) => Number.isSafeInteger(value) && value > 0;
|
|
850
1042
|
function decodeOriginalImageRef(value) {
|
|
@@ -1032,32 +1224,41 @@ window.__ModuleLoader__.load({
|
|
|
1032
1224
|
errorLabel: t("imageDownloadFailed"),
|
|
1033
1225
|
onInvoke: downloadOriginal
|
|
1034
1226
|
},
|
|
1035
|
-
actions: !features.imageEditing ? [] : [
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1227
|
+
actions: !features.imageEditing ? [] : [
|
|
1228
|
+
{
|
|
1229
|
+
id: "continue-editing",
|
|
1230
|
+
label: t("imageEdit"),
|
|
1231
|
+
pendingLabel: t("imageEditPreparing"),
|
|
1232
|
+
errorLabel: t("imageEditFailed"),
|
|
1233
|
+
closeOnSuccess: true,
|
|
1234
|
+
onInvoke: ({ annotations = [] }) => {
|
|
1235
|
+
const imageKey = String(attachment.attachmentId ?? "image").replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
1236
|
+
const sourceName = annotations.length === 0 ? downloadName : `codex-edit-${imageKey}-source.png`;
|
|
1237
|
+
const referenceName = `codex-edit-${imageKey}-annotations.png`;
|
|
1238
|
+
return attachForEdit(src, sourceName, buildImageEditDraft({
|
|
1239
|
+
annotations,
|
|
1240
|
+
translate: t,
|
|
1241
|
+
width: attachment.width,
|
|
1242
|
+
height: attachment.height,
|
|
1243
|
+
sourceName,
|
|
1244
|
+
referenceName
|
|
1245
|
+
}), annotations, referenceName);
|
|
1246
|
+
}
|
|
1247
|
+
},
|
|
1248
|
+
...officialImageTools({
|
|
1249
|
+
src,
|
|
1250
|
+
name: downloadName,
|
|
1251
|
+
t,
|
|
1252
|
+
attachForEdit
|
|
1253
|
+
}),
|
|
1254
|
+
...features.imageSketch && openSketchImage ? [{
|
|
1255
|
+
id: "sketch",
|
|
1256
|
+
label: t("imageToSketch"),
|
|
1257
|
+
pendingLabel: t("imageEditPreparing"),
|
|
1258
|
+
errorLabel: t("imageEditFailed"),
|
|
1259
|
+
onInvoke: () => openSketchImage(src, downloadName)
|
|
1260
|
+
}] : []
|
|
1261
|
+
]
|
|
1061
1262
|
}],
|
|
1062
1263
|
opener: triggerRef.current,
|
|
1063
1264
|
source: "codex-generated",
|
|
@@ -1107,7 +1308,7 @@ window.__ModuleLoader__.load({
|
|
|
1107
1308
|
showOutput ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1108
1309
|
className: "codexImageToolRow",
|
|
1109
1310
|
children: [
|
|
1110
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(!settled ? ForwardRef$
|
|
1311
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(!settled ? ForwardRef$8 : failed ? ForwardRef$5 : ForwardRef$2, {
|
|
1111
1312
|
className: "codexImageToolIcon",
|
|
1112
1313
|
"aria-hidden": "true"
|
|
1113
1314
|
}),
|
|
@@ -5273,7 +5474,7 @@ window.__ModuleLoader__.load({
|
|
|
5273
5474
|
const IconCopyOutline16 = _deepseek_ai_dsh_client_ui_primitives.IconCopyOutline16 ?? _deepseek_ai_dsh_client_ui_primitives.IconCopyOutlineRegular;
|
|
5274
5475
|
const IconDownloadOutline16 = _deepseek_ai_dsh_client_ui_primitives.IconDownloadOutline16 ?? _deepseek_ai_dsh_client_ui_primitives.IconDownloadOutlineRegular;
|
|
5275
5476
|
const IconEditOutline16 = _deepseek_ai_dsh_client_ui_primitives.IconEditOutline16 ?? _deepseek_ai_dsh_client_ui_primitives.IconEditOutlineRegular;
|
|
5276
|
-
|
|
5477
|
+
_deepseek_ai_dsh_client_ui_primitives.IconFullscreenOutline16 ?? _deepseek_ai_dsh_client_ui_primitives.IconFullscreenOutlineRegular;
|
|
5277
5478
|
//#endregion
|
|
5278
5479
|
//#region src/image-workspace.jsx
|
|
5279
5480
|
function ImageWorkspace(props) {
|
|
@@ -5525,6 +5726,21 @@ window.__ModuleLoader__.load({
|
|
|
5525
5726
|
sketchEditableFile: "可编辑草稿",
|
|
5526
5727
|
sketchFormatHint: "PNG 为合并图片;可编辑草稿保留原生笔画,可重新导入(32 MB 内)。",
|
|
5527
5728
|
imageToSketch: "进入草图",
|
|
5729
|
+
imageRemoveBackground: "移除背景",
|
|
5730
|
+
imageRemoveBackgroundPrompt: "移除此图像的背景。保持所有前景主体不变且完整,边缘干净平滑。将背景设为透明。",
|
|
5731
|
+
imageErase: "擦除",
|
|
5732
|
+
imageEraseHint: "在要移除的内容上涂抹",
|
|
5733
|
+
imageErasePrompt: "从第一张图像中移除第二张图像中标记的区域",
|
|
5734
|
+
imageBrushSize: "画笔大小",
|
|
5735
|
+
imageUndo: "撤销",
|
|
5736
|
+
imageSend: "发送",
|
|
5737
|
+
imageResize: "调整大小",
|
|
5738
|
+
imageResizePrompt: "将宽高比设为 {aspectRatio}",
|
|
5739
|
+
imageRatio_square: "正方形",
|
|
5740
|
+
imageRatio_portrait: "竖向",
|
|
5741
|
+
imageRatio_story: "故事版式",
|
|
5742
|
+
imageRatio_landscape: "横向",
|
|
5743
|
+
imageRatio_widescreen: "宽屏",
|
|
5528
5744
|
sketchPictures: "图片",
|
|
5529
5745
|
sketchPictureAdd: "添加",
|
|
5530
5746
|
sketchPictureSelect: "选择图片",
|
|
@@ -5591,7 +5807,7 @@ window.__ModuleLoader__.load({
|
|
|
5591
5807
|
imageEntryPoints_on: "显示",
|
|
5592
5808
|
imageEntryPoints_off: "隐藏",
|
|
5593
5809
|
imageBrowsing: "图片浏览",
|
|
5594
|
-
imageBrowsingHint: "
|
|
5810
|
+
imageBrowsingHint: "预览粘贴图片与会话图片,可标注、移除背景、擦除、调整大小。",
|
|
5595
5811
|
imageBrowsing_on: "增强",
|
|
5596
5812
|
imageBrowsing_off: "DSH 默认",
|
|
5597
5813
|
imageGroupMixed: "保留原设置",
|
|
@@ -5811,7 +6027,7 @@ window.__ModuleLoader__.load({
|
|
|
5811
6027
|
resetAcknowledgeRequired: "请先确认已了解这次操作可能消耗重置次数。",
|
|
5812
6028
|
resetAccountChanged: "登录账号已变更,请重新开始。",
|
|
5813
6029
|
resetUncertain: "服务端返回结果不确定。请再次确认,插件会复用同一个请求,不会另外发起一次重置。",
|
|
5814
|
-
creditsNote: "
|
|
6030
|
+
creditsNote: "下方的额外 Credits 和额度重置与套餐额度分开计算。",
|
|
5815
6031
|
creditsExpires: "预计 {date} 到期,还剩 {days} 天",
|
|
5816
6032
|
creditsExpiredToday: "今天 {date} 到期",
|
|
5817
6033
|
creditsExpiryEstimate: "(估计:官方公布的 Pro 200 补偿 Credits 到期日,接口未返回,以 ChatGPT 使用情况页为准)",
|
|
@@ -5890,7 +6106,7 @@ window.__ModuleLoader__.load({
|
|
|
5890
6106
|
modelMenuAria: "模型、推理等级、速度与输出详略",
|
|
5891
6107
|
modelLabel: "模型",
|
|
5892
6108
|
effortLabel: "推理等级",
|
|
5893
|
-
providerDefault: "
|
|
6109
|
+
providerDefault: "默认",
|
|
5894
6110
|
selectModel: "选择模型",
|
|
5895
6111
|
modelsLoading: "正在读取模型…",
|
|
5896
6112
|
modelsEmpty: "没有可用模型;请先登录,并确认网络可用。",
|
|
@@ -6097,6 +6313,21 @@ window.__ModuleLoader__.load({
|
|
|
6097
6313
|
sketchEditableFile: "Editable draft",
|
|
6098
6314
|
sketchFormatHint: "PNG is flattened; editable drafts retain native strokes and can be imported again (up to 32 MB).",
|
|
6099
6315
|
imageToSketch: "Open in sketch",
|
|
6316
|
+
imageRemoveBackground: "Remove background",
|
|
6317
|
+
imageRemoveBackgroundPrompt: "Remove the background from this image. Keep all foreground subjects unchanged and fully intact, with clean, smooth edges. Make the background transparent.",
|
|
6318
|
+
imageErase: "Erase",
|
|
6319
|
+
imageEraseHint: "Brush over what you want to remove",
|
|
6320
|
+
imageErasePrompt: "Remove the area marked in the second image from the first image",
|
|
6321
|
+
imageBrushSize: "Brush size",
|
|
6322
|
+
imageUndo: "Undo",
|
|
6323
|
+
imageSend: "Send",
|
|
6324
|
+
imageResize: "Resize",
|
|
6325
|
+
imageResizePrompt: "Make the aspect ratio {aspectRatio}",
|
|
6326
|
+
imageRatio_square: "Square",
|
|
6327
|
+
imageRatio_portrait: "Portrait",
|
|
6328
|
+
imageRatio_story: "Story",
|
|
6329
|
+
imageRatio_landscape: "Landscape",
|
|
6330
|
+
imageRatio_widescreen: "Widescreen",
|
|
6100
6331
|
sketchPictures: "Images",
|
|
6101
6332
|
sketchPictureAdd: "Add",
|
|
6102
6333
|
sketchPictureSelect: "Select image",
|
|
@@ -6163,7 +6394,7 @@ window.__ModuleLoader__.load({
|
|
|
6163
6394
|
imageEntryPoints_on: "Show",
|
|
6164
6395
|
imageEntryPoints_off: "Hide",
|
|
6165
6396
|
imageBrowsing: "Image browsing",
|
|
6166
|
-
imageBrowsingHint: "Preview pasted and conversation images
|
|
6397
|
+
imageBrowsingHint: "Preview pasted and conversation images; annotate, remove the background, erase or resize.",
|
|
6167
6398
|
imageBrowsing_on: "Enhanced",
|
|
6168
6399
|
imageBrowsing_off: "DSH default",
|
|
6169
6400
|
imageGroupMixed: "Keep existing",
|
|
@@ -6383,7 +6614,7 @@ window.__ModuleLoader__.load({
|
|
|
6383
6614
|
resetAcknowledgeRequired: "Confirm that you understand this may consume a reset.",
|
|
6384
6615
|
resetAccountChanged: "The signed-in account changed. Start again.",
|
|
6385
6616
|
resetUncertain: "The server result is uncertain. Confirm again to check the same request; the plugin will not start a separate reset.",
|
|
6386
|
-
creditsNote: "Extra Credits
|
|
6617
|
+
creditsNote: "Extra Credits and quota resets below are counted separately from the plan quota.",
|
|
6387
6618
|
creditsExpires: "Expires {date} ({days} days left)",
|
|
6388
6619
|
creditsExpiredToday: "Expires today ({date})",
|
|
6389
6620
|
creditsExpiryEstimate: "(Estimate: the published expiry of the Pro 200 compensation Credits; the API does not report it, so check ChatGPT usage settings)",
|
|
@@ -6597,7 +6828,7 @@ window.__ModuleLoader__.load({
|
|
|
6597
6828
|
.codexSubscriptionRecover{display:flex;align-items:center;justify-content:space-between;gap:12px}
|
|
6598
6829
|
.codexSubscriptionRecover .codexSubscriptionError{flex:1}
|
|
6599
6830
|
.codexSubscriptionRecover button{flex:0 0 auto}
|
|
6600
|
-
.codexSubscriptionDiagnostics{color:var(--dsw-alias-label-secondary)}
|
|
6831
|
+
.codexSubscriptionDiagnostics{color:var(--dsw-alias-label-secondary)}.codexSubscriptionDiagnostics h3{color:var(--dsw-alias-label-primary)}
|
|
6601
6832
|
.codexSubscriptionDiagnostics ul{margin:0;padding-left:18px;font-size:13px;line-height:20px}
|
|
6602
6833
|
.codexSubscriptionDiagnostics li+li{margin-top:6px}
|
|
6603
6834
|
.codexSubscriptionDiagnostics li strong{font-weight:600;color:var(--dsw-alias-label-primary)}
|
|
@@ -6919,10 +7150,13 @@ window.__ModuleLoader__.load({
|
|
|
6919
7150
|
.dcsiv-inline-note{position:absolute;bottom:34px;box-sizing:border-box;display:grid;width:min(300px,calc(100vw - 40px));grid-template-columns:24px minmax(0,1fr) 24px;align-items:center;gap:7px;padding:7px 8px;border:1px solid rgba(255,255,255,.12);border-radius:18px;background:rgba(32,33,37,.94);box-shadow:0 14px 38px rgba(0,0,0,.38);color:#fff;pointer-events:auto;backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px)}.dcsiv-annotation[data-x=right] .dcsiv-inline-note{left:-8px}.dcsiv-annotation[data-x=left] .dcsiv-inline-note{right:-8px}.dcsiv-annotation[data-x=center] .dcsiv-inline-note{left:50%;transform:translateX(-50%)}.dcsiv-annotation[data-y=down] .dcsiv-inline-note{top:34px;bottom:auto}.dcsiv-inline-note::after{position:absolute;width:9px;height:9px;background:rgba(32,33,37,.94);content:'';transform:rotate(45deg)}.dcsiv-annotation[data-y=up] .dcsiv-inline-note::after{bottom:-5px}.dcsiv-annotation[data-y=down] .dcsiv-inline-note::after{top:-5px}.dcsiv-annotation[data-x=right] .dcsiv-inline-note::after{left:13px}.dcsiv-annotation[data-x=left] .dcsiv-inline-note::after{right:13px}.dcsiv-annotation[data-x=center] .dcsiv-inline-note::after{left:calc(50% - 4px)}.dcsiv-inline-index{display:grid;place-items:center;width:22px;height:22px;border-radius:50%;background:var(--dsw-alias-state-business-primary,#3964fe);color:#fff;font-size:10px;font-weight:700}.dcsiv-inline-note textarea{box-sizing:border-box;width:100%;min-height:24px;max-height:92px;resize:none;overflow:auto;border:0;outline:0;background:transparent;color:#fff;font:inherit;font-size:12px;line-height:18px}.dcsiv-inline-note textarea::placeholder{color:rgba(255,255,255,.44)}.dcsiv-note-remove{display:grid;place-items:center;width:24px;height:24px;padding:0;border:0;border-radius:50%;background:transparent;color:rgba(255,255,255,.68);cursor:pointer}.dcsiv-note-remove:hover{background:rgba(255,255,255,.1);color:#fff}
|
|
6920
7151
|
.dcsiv-nav{position:absolute;top:50%;z-index:4;width:42px;height:42px;padding:0;transform:translateY(-50%);background:rgba(48,49,53,.82);box-shadow:0 8px 24px rgba(0,0,0,.28);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px)}.dcsiv-prev{left:6px}.dcsiv-next{right:6px}.dcsiv-counter{position:absolute;bottom:8px;left:50%;padding:5px 10px;border-radius:999px;background:rgba(38,39,43,.86);color:rgba(255,255,255,.72);font-size:11px;transform:translateX(-50%);backdrop-filter:blur(16px)}
|
|
6921
7152
|
.dcsiv-hint{display:none}
|
|
7153
|
+
.dcsiv-mask{position:absolute;inset:0;width:100%;height:100%;border-radius:12px;cursor:crosshair;touch-action:none}
|
|
7154
|
+
.dcsiv-tool-icon{width:16px;height:16px;flex:none}.dcsiv-icon-button,.dcsiv-download[data-compact="true"]{width:34px;padding:0!important;justify-content:center}.dcsiv-zoom{min-width:52px;font-variant-numeric:tabular-nums}.dcsiv-divider{width:1px;height:18px;margin:0 4px;background:rgba(255,255,255,.14)}.dcsiv-menu{position:fixed;z-index:12;display:flex;flex-direction:column;min-width:150px;padding:6px;border:1px solid rgba(255,255,255,.12);border-radius:12px;background:rgba(32,33,37,.97);box-shadow:0 12px 32px rgba(0,0,0,.4)}.dcsiv-menu button{height:32px;padding:0 10px;border:0;border-radius:8px;background:none;color:rgba(255,255,255,.9);font:inherit;font-size:13px;text-align:left;cursor:pointer}.dcsiv-menu button:hover,.dcsiv-menu button:focus-visible{outline:none;background:rgba(255,255,255,.1)}
|
|
7155
|
+
.dcsiv-erase-bar{position:absolute;left:50%;top:22px;z-index:7;display:flex;align-items:center;gap:10px;padding:6px 8px 6px 14px;transform:translateX(-50%);border:1px solid rgba(255,255,255,.1);border-radius:999px;background:rgba(38,39,43,.92);color:rgba(255,255,255,.86);font-size:12px;white-space:nowrap}.dcsiv-erase-bar label{display:inline-flex;align-items:center;gap:6px}.dcsiv-erase-bar input{width:90px}.dcsiv-primary{background:#fff!important;color:#111!important}.dcsiv-primary[data-state="failed"]{color:#c62828!important}.dcsiv-brush-cursor{position:fixed;z-index:9;pointer-events:none;border:1.5px solid #fff;border-radius:50%;corner-shape:round;box-shadow:0 0 0 1px rgba(0,0,0,.45),inset 0 0 0 1px rgba(0,0,0,.25);transform:translate(-50%,-50%)}@media(pointer:fine){.dcsiv-mask{cursor:none}}.dcsiv-button[data-state="pending"] .dcsiv-tool-icon{animation:dcsiv-pulse 1s ease-in-out infinite}.dcsiv-button[data-state="failed"]{color:#ff8a80!important}@keyframes dcsiv-pulse{50%{opacity:.3}}
|
|
6922
7156
|
.dcsiv-copy-notes{position:absolute;right:20px;bottom:22px;z-index:6;display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 11px;border:1px solid rgba(255,255,255,.1);border-radius:999px;background:rgba(38,39,43,.86);color:rgba(255,255,255,.82);font:inherit;font-size:12px;cursor:pointer;backdrop-filter:blur(16px)}
|
|
6923
7157
|
.dcsiv-edit-short{display:none}
|
|
6924
7158
|
@media(max-width:760px){.dcsiv-actions{flex-wrap:wrap;justify-content:center}.dcsiv-edit-short{display:inline;white-space:normal;max-width:min(280px,calc(100vw - 80px))}.dcsiv-edit-action{height:auto;min-height:32px}.dcsiv-close-floating{top:12px;right:12px;width:40px;height:40px}.dcsiv-workspace{padding:60px 12px 68px}.dcsiv-image{max-width:calc(100vw - 24px);max-height:calc(100vh - 136px)}.dcsiv-topbar{bottom:12px;max-width:calc(100vw - 24px)}.dcsiv-button{padding:0 8px}.dcsiv-button span.dcsiv-label{display:none}.dcsiv-inline-note{width:min(260px,calc(100vw - 40px))}.dcsiv-copy-notes{display:none}}
|
|
6925
|
-
@media(prefers-reduced-motion:reduce){.dcsiv-surface{transition:none}}
|
|
7159
|
+
@media(prefers-reduced-motion:reduce){.dcsiv-surface{transition:none}.dcsiv-tool-icon{animation:none!important}}
|
|
6926
7160
|
`;
|
|
6927
7161
|
//#endregion
|
|
6928
7162
|
//#region src/subscription-image-transform.js
|
|
@@ -7102,6 +7336,20 @@ window.__ModuleLoader__.load({
|
|
|
7102
7336
|
}
|
|
7103
7337
|
//#endregion
|
|
7104
7338
|
//#region src/subscription-image-viewer.jsx
|
|
7339
|
+
const TOOL_ICONS = {
|
|
7340
|
+
"remove-background": ForwardRef$1,
|
|
7341
|
+
erase: ForwardRef$4,
|
|
7342
|
+
resize: ForwardRef$7,
|
|
7343
|
+
sketch: ForwardRef$3,
|
|
7344
|
+
annotate: ForwardRef$6
|
|
7345
|
+
};
|
|
7346
|
+
const ToolIcon = ({ id }) => {
|
|
7347
|
+
const Icon = TOOL_ICONS[id];
|
|
7348
|
+
return Icon ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
|
|
7349
|
+
className: "dcsiv-tool-icon",
|
|
7350
|
+
"aria-hidden": "true"
|
|
7351
|
+
}) : null;
|
|
7352
|
+
};
|
|
7105
7353
|
const fill$1 = (value, variables) => Object.entries(variables).reduce((text, [key, replacement]) => text.replaceAll(`{${key}}`, String(replacement)), value);
|
|
7106
7354
|
const clamp = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
7107
7355
|
const bytesLabel = (bytes) => bytes === void 0 ? void 0 : bytes < 1024 * 1024 ? `${Math.max(.1, bytes / 1024).toLocaleString(void 0, { maximumFractionDigits: 1 })} KB` : `${(bytes / 1024 / 1024).toLocaleString(void 0, { maximumFractionDigits: 1 })} MB`;
|
|
@@ -7112,23 +7360,54 @@ window.__ModuleLoader__.load({
|
|
|
7112
7360
|
const noteText = (annotations, t) => annotations.map((annotation, index) => {
|
|
7113
7361
|
return `${fill$1(t("imageAnnotation"), { value: index + 1 })} (${Math.round(annotation.x * 100)}%, ${Math.round(annotation.y * 100)}%): ${annotation.note.trim()}`;
|
|
7114
7362
|
}).filter((line) => !line.endsWith(": ")).join("\n");
|
|
7115
|
-
function ViewerAction({ action, annotations, item, service, revision, t }) {
|
|
7363
|
+
function ViewerAction({ action, annotations, item, service, revision, t, onStartMask }) {
|
|
7116
7364
|
const [state, setState] = (0, react.useState)("idle");
|
|
7365
|
+
const [menu, setMenu] = (0, react.useState)();
|
|
7117
7366
|
const active = (0, react.useRef)(true);
|
|
7367
|
+
const menuRef = (0, react.useRef)(null);
|
|
7368
|
+
const menuButtonRef = (0, react.useRef)(null);
|
|
7118
7369
|
(0, react.useEffect)(() => {
|
|
7119
7370
|
active.current = true;
|
|
7120
7371
|
return () => {
|
|
7121
7372
|
active.current = false;
|
|
7122
7373
|
};
|
|
7123
7374
|
}, []);
|
|
7124
|
-
|
|
7375
|
+
(0, react.useEffect)(() => {
|
|
7376
|
+
if (menu === void 0) return void 0;
|
|
7377
|
+
menuRef.current?.querySelector("[role=\"menuitem\"]")?.focus();
|
|
7378
|
+
const onKeyDown = (event) => {
|
|
7379
|
+
const items = [...menuRef.current?.querySelectorAll("[role=\"menuitem\"]") ?? []];
|
|
7380
|
+
if (event.key === "Escape") {
|
|
7381
|
+
event.preventDefault();
|
|
7382
|
+
event.stopPropagation();
|
|
7383
|
+
setMenu(void 0);
|
|
7384
|
+
menuButtonRef.current?.focus();
|
|
7385
|
+
} else if ((event.key === "ArrowDown" || event.key === "ArrowUp") && items.length > 0) {
|
|
7386
|
+
event.preventDefault();
|
|
7387
|
+
event.stopPropagation();
|
|
7388
|
+
const step = event.key === "ArrowDown" ? 1 : -1;
|
|
7389
|
+
items[(items.indexOf(document.activeElement) + step + items.length) % items.length].focus();
|
|
7390
|
+
} else if (event.key === "Tab") setMenu(void 0);
|
|
7391
|
+
};
|
|
7392
|
+
const onPointerDown = (event) => {
|
|
7393
|
+
if (!menuRef.current?.contains(event.target) && !menuButtonRef.current?.contains(event.target)) setMenu(void 0);
|
|
7394
|
+
};
|
|
7395
|
+
window.addEventListener("keydown", onKeyDown, true);
|
|
7396
|
+
window.addEventListener("pointerdown", onPointerDown, true);
|
|
7397
|
+
return () => {
|
|
7398
|
+
window.removeEventListener("keydown", onKeyDown, true);
|
|
7399
|
+
window.removeEventListener("pointerdown", onPointerDown, true);
|
|
7400
|
+
};
|
|
7401
|
+
}, [menu]);
|
|
7402
|
+
const invoke = async (extra = {}) => {
|
|
7125
7403
|
if (state === "pending") return;
|
|
7126
7404
|
setState("pending");
|
|
7127
7405
|
try {
|
|
7128
7406
|
await action.onInvoke({
|
|
7129
7407
|
annotations,
|
|
7130
7408
|
item,
|
|
7131
|
-
src: item.src
|
|
7409
|
+
src: item.src,
|
|
7410
|
+
...extra
|
|
7132
7411
|
});
|
|
7133
7412
|
if (!active.current || service.getSnapshot()?.revision !== revision) return;
|
|
7134
7413
|
setState("idle");
|
|
@@ -7138,6 +7417,74 @@ window.__ModuleLoader__.load({
|
|
|
7138
7417
|
}
|
|
7139
7418
|
};
|
|
7140
7419
|
const label = state === "pending" ? action.pendingLabel : state === "failed" ? action.errorLabel : action.label;
|
|
7420
|
+
if (action.kind === "mask") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7421
|
+
type: "button",
|
|
7422
|
+
className: "dcsiv-button dcsiv-icon-button",
|
|
7423
|
+
title: action.label,
|
|
7424
|
+
"aria-label": action.label,
|
|
7425
|
+
onClick: () => onStartMask(action),
|
|
7426
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolIcon, { id: action.id })
|
|
7427
|
+
});
|
|
7428
|
+
if (action.kind === "tool") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7429
|
+
type: "button",
|
|
7430
|
+
className: "dcsiv-button dcsiv-icon-button",
|
|
7431
|
+
title: label,
|
|
7432
|
+
"aria-label": label,
|
|
7433
|
+
"data-state": state,
|
|
7434
|
+
disabled: state === "pending",
|
|
7435
|
+
onClick: () => {
|
|
7436
|
+
invoke();
|
|
7437
|
+
},
|
|
7438
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolIcon, { id: action.id })
|
|
7439
|
+
});
|
|
7440
|
+
if (action.id === "sketch" && state === "idle") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7441
|
+
type: "button",
|
|
7442
|
+
className: "dcsiv-button dcsiv-icon-button",
|
|
7443
|
+
title: action.label,
|
|
7444
|
+
"aria-label": action.label,
|
|
7445
|
+
onClick: () => {
|
|
7446
|
+
invoke();
|
|
7447
|
+
},
|
|
7448
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolIcon, { id: "sketch" })
|
|
7449
|
+
});
|
|
7450
|
+
if (action.kind === "choice") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7451
|
+
ref: menuButtonRef,
|
|
7452
|
+
type: "button",
|
|
7453
|
+
"aria-haspopup": "menu",
|
|
7454
|
+
"aria-expanded": menu !== void 0,
|
|
7455
|
+
"data-state": state,
|
|
7456
|
+
disabled: state === "pending",
|
|
7457
|
+
onClick: (event) => {
|
|
7458
|
+
const box = event.currentTarget.getBoundingClientRect();
|
|
7459
|
+
const host = event.currentTarget.closest(".dcsiv-root");
|
|
7460
|
+
setMenu((value) => value === void 0 && host ? {
|
|
7461
|
+
host,
|
|
7462
|
+
style: {
|
|
7463
|
+
left: box.left,
|
|
7464
|
+
bottom: window.innerHeight - box.top + 8
|
|
7465
|
+
}
|
|
7466
|
+
} : void 0);
|
|
7467
|
+
},
|
|
7468
|
+
className: "dcsiv-button dcsiv-icon-button",
|
|
7469
|
+
title: label,
|
|
7470
|
+
"aria-label": label,
|
|
7471
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolIcon, { id: action.id })
|
|
7472
|
+
}), menu ? (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7473
|
+
ref: menuRef,
|
|
7474
|
+
className: "dcsiv-menu",
|
|
7475
|
+
role: "menu",
|
|
7476
|
+
"aria-label": action.label,
|
|
7477
|
+
style: menu.style,
|
|
7478
|
+
children: action.options.map((option) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7479
|
+
type: "button",
|
|
7480
|
+
role: "menuitem",
|
|
7481
|
+
onClick: () => {
|
|
7482
|
+
setMenu(void 0);
|
|
7483
|
+
invoke({ option: option.value });
|
|
7484
|
+
},
|
|
7485
|
+
children: option.label
|
|
7486
|
+
}, option.value))
|
|
7487
|
+
}), menu.host) : null] });
|
|
7141
7488
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
7142
7489
|
type: "button",
|
|
7143
7490
|
className: "dcsiv-button dcsiv-edit-action",
|
|
@@ -7198,10 +7545,13 @@ window.__ModuleLoader__.load({
|
|
|
7198
7545
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
7199
7546
|
type: "button",
|
|
7200
7547
|
className: "dcsiv-download",
|
|
7548
|
+
"data-compact": state === "idle",
|
|
7549
|
+
title: label,
|
|
7550
|
+
"aria-label": label,
|
|
7201
7551
|
onClick: () => {
|
|
7202
7552
|
invoke();
|
|
7203
7553
|
},
|
|
7204
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconDownloadOutline16, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7554
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconDownloadOutline16, {}), state === "idle" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7205
7555
|
className: "dcsiv-label",
|
|
7206
7556
|
children: state === "pending" ? `${label} ${progress}% · ${t("cancel")}` : label
|
|
7207
7557
|
})]
|
|
@@ -7224,6 +7574,22 @@ window.__ModuleLoader__.load({
|
|
|
7224
7574
|
const [selected, setSelected] = (0, react.useState)();
|
|
7225
7575
|
const [focusNote, setFocusNote] = (0, react.useState)();
|
|
7226
7576
|
const [copied, setCopied] = (0, react.useState)(false);
|
|
7577
|
+
const [erasing, setErasing] = (0, react.useState)();
|
|
7578
|
+
const [strokes, setStrokes] = (0, react.useState)([]);
|
|
7579
|
+
const [brush, setBrush] = (0, react.useState)(.05);
|
|
7580
|
+
const [sending, setSending] = (0, react.useState)(false);
|
|
7581
|
+
const [sendFailed, setSendFailed] = (0, react.useState)(false);
|
|
7582
|
+
const [brushCursor, setBrushCursor] = (0, react.useState)();
|
|
7583
|
+
const eraseRef = (0, react.useRef)({
|
|
7584
|
+
erasing: void 0,
|
|
7585
|
+
sending: false
|
|
7586
|
+
});
|
|
7587
|
+
eraseRef.current = {
|
|
7588
|
+
erasing,
|
|
7589
|
+
sending
|
|
7590
|
+
};
|
|
7591
|
+
const drawingRef = (0, react.useRef)(false);
|
|
7592
|
+
const maskRef = (0, react.useRef)(null);
|
|
7227
7593
|
const rootRef = (0, react.useRef)(null);
|
|
7228
7594
|
annotationsByImageRef.current = annotationsByImage;
|
|
7229
7595
|
(0, react.useEffect)(() => {
|
|
@@ -7253,6 +7619,28 @@ window.__ModuleLoader__.load({
|
|
|
7253
7619
|
document.body.style.overflow = "hidden";
|
|
7254
7620
|
rootRef.current?.focus();
|
|
7255
7621
|
const onKeyDown = (event) => {
|
|
7622
|
+
if (eraseRef.current.erasing !== void 0) {
|
|
7623
|
+
const key = event.key.toLowerCase();
|
|
7624
|
+
if (event.key === "Escape") {
|
|
7625
|
+
event.preventDefault();
|
|
7626
|
+
if (!eraseRef.current.sending) {
|
|
7627
|
+
setErasing(void 0);
|
|
7628
|
+
setStrokes([]);
|
|
7629
|
+
}
|
|
7630
|
+
return;
|
|
7631
|
+
}
|
|
7632
|
+
if ((event.ctrlKey || event.metaKey) && key === "z") {
|
|
7633
|
+
event.preventDefault();
|
|
7634
|
+
if (!eraseRef.current.sending) setStrokes((current) => current.slice(0, -1));
|
|
7635
|
+
return;
|
|
7636
|
+
}
|
|
7637
|
+
if (event.key === "[" || event.key === "]") {
|
|
7638
|
+
event.preventDefault();
|
|
7639
|
+
setBrush((value) => Math.round(clamp(value + (event.key === "]" ? .01 : -.01), .01, .15) * 100) / 100);
|
|
7640
|
+
return;
|
|
7641
|
+
}
|
|
7642
|
+
if (event.key === "ArrowLeft" || event.key === "ArrowRight") return;
|
|
7643
|
+
}
|
|
7256
7644
|
if (event.key === "Escape") {
|
|
7257
7645
|
event.preventDefault();
|
|
7258
7646
|
if (event.target instanceof Element && event.target.closest(".dcsiv-inline-note") !== null) {
|
|
@@ -7316,11 +7704,99 @@ window.__ModuleLoader__.load({
|
|
|
7316
7704
|
(0, react.useEffect)(() => {
|
|
7317
7705
|
setAnnotating(false);
|
|
7318
7706
|
setSelected(void 0);
|
|
7707
|
+
setErasing(void 0);
|
|
7708
|
+
setStrokes([]);
|
|
7319
7709
|
}, [
|
|
7320
7710
|
item?.id,
|
|
7321
7711
|
item?.src,
|
|
7322
7712
|
request?.revision
|
|
7323
7713
|
]);
|
|
7714
|
+
(0, react.useEffect)(() => {
|
|
7715
|
+
const canvas = maskRef.current;
|
|
7716
|
+
if (!erasing || canvas === null) return;
|
|
7717
|
+
const context = canvas.getContext("2d");
|
|
7718
|
+
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
7719
|
+
paintEraseStrokes(context, strokes, canvas.width, canvas.height, "rgba(255,59,48,.5)");
|
|
7720
|
+
}, [erasing, strokes]);
|
|
7721
|
+
const strokePoint = (event) => {
|
|
7722
|
+
const bounds = maskRef.current?.getBoundingClientRect();
|
|
7723
|
+
if (bounds === void 0) return void 0;
|
|
7724
|
+
return {
|
|
7725
|
+
x: clamp((event.clientX - bounds.left) / bounds.width, 0, 1),
|
|
7726
|
+
y: clamp((event.clientY - bounds.top) / bounds.height, 0, 1)
|
|
7727
|
+
};
|
|
7728
|
+
};
|
|
7729
|
+
const maskHandlers = {
|
|
7730
|
+
onPointerDown: (event) => {
|
|
7731
|
+
const point = strokePoint(event);
|
|
7732
|
+
if (point === void 0) return;
|
|
7733
|
+
event.stopPropagation();
|
|
7734
|
+
event.currentTarget.setPointerCapture?.(event.pointerId);
|
|
7735
|
+
drawingRef.current = true;
|
|
7736
|
+
setStrokes((current) => [...current, {
|
|
7737
|
+
size: brush / transformRef.current.zoom,
|
|
7738
|
+
points: [point]
|
|
7739
|
+
}]);
|
|
7740
|
+
},
|
|
7741
|
+
onPointerMove: (event) => {
|
|
7742
|
+
const bounds = maskRef.current?.getBoundingClientRect();
|
|
7743
|
+
if (bounds !== void 0) setBrushCursor({
|
|
7744
|
+
left: event.clientX,
|
|
7745
|
+
top: event.clientY,
|
|
7746
|
+
span: Math.min(bounds.width, bounds.height) / transformRef.current.zoom
|
|
7747
|
+
});
|
|
7748
|
+
if (!drawingRef.current) return;
|
|
7749
|
+
const point = strokePoint(event);
|
|
7750
|
+
if (point === void 0) return;
|
|
7751
|
+
setStrokes((current) => current.length === 0 ? current : [...current.slice(0, -1), {
|
|
7752
|
+
...current.at(-1),
|
|
7753
|
+
points: [...current.at(-1).points, point]
|
|
7754
|
+
}]);
|
|
7755
|
+
},
|
|
7756
|
+
onPointerUp: () => {
|
|
7757
|
+
drawingRef.current = false;
|
|
7758
|
+
},
|
|
7759
|
+
onPointerCancel: () => {
|
|
7760
|
+
drawingRef.current = false;
|
|
7761
|
+
},
|
|
7762
|
+
onPointerLeave: () => {
|
|
7763
|
+
setBrushCursor(void 0);
|
|
7764
|
+
}
|
|
7765
|
+
};
|
|
7766
|
+
const startMask = (action) => {
|
|
7767
|
+
resetGesture();
|
|
7768
|
+
setAnnotating(false);
|
|
7769
|
+
setStrokes([]);
|
|
7770
|
+
setSendFailed(false);
|
|
7771
|
+
setBrushCursor(void 0);
|
|
7772
|
+
setErasing(action);
|
|
7773
|
+
};
|
|
7774
|
+
const sendMask = async () => {
|
|
7775
|
+
const image = imageRef.current;
|
|
7776
|
+
if (!erasing || strokes.length === 0 || image === null || sending) return;
|
|
7777
|
+
setSending(true);
|
|
7778
|
+
setSendFailed(false);
|
|
7779
|
+
try {
|
|
7780
|
+
const canvas = document.createElement("canvas");
|
|
7781
|
+
canvas.width = image.naturalWidth;
|
|
7782
|
+
canvas.height = image.naturalHeight;
|
|
7783
|
+
paintEraseMask(canvas.getContext("2d"), strokes, canvas.width, canvas.height);
|
|
7784
|
+
const mask = await new Promise((resolve, reject) => canvas.toBlob((blob) => blob ? resolve(blob) : reject(/* @__PURE__ */ new Error("Mask")), "image/png"));
|
|
7785
|
+
await erasing.onInvoke({
|
|
7786
|
+
mask,
|
|
7787
|
+
item,
|
|
7788
|
+
src: item.src,
|
|
7789
|
+
annotations: []
|
|
7790
|
+
});
|
|
7791
|
+
setErasing(void 0);
|
|
7792
|
+
setStrokes([]);
|
|
7793
|
+
if (erasing.closeOnSuccess) service.close();
|
|
7794
|
+
} catch {
|
|
7795
|
+
setSendFailed(true);
|
|
7796
|
+
} finally {
|
|
7797
|
+
setSending(false);
|
|
7798
|
+
}
|
|
7799
|
+
};
|
|
7324
7800
|
const addAnnotation = (event) => {
|
|
7325
7801
|
if (!annotating || event.target.closest(".dcsiv-annotation")) return;
|
|
7326
7802
|
const bounds = surfaceRef.current?.getBoundingClientRect();
|
|
@@ -7382,18 +7858,19 @@ window.__ModuleLoader__.load({
|
|
|
7382
7858
|
children: [
|
|
7383
7859
|
request.annotations ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
7384
7860
|
type: "button",
|
|
7385
|
-
className: "dcsiv-button",
|
|
7861
|
+
className: annotating ? "dcsiv-button" : "dcsiv-button dcsiv-icon-button",
|
|
7386
7862
|
"data-active": annotating,
|
|
7863
|
+
title: annotating ? t("imageAnnotateCancel") : t("imageAnnotate"),
|
|
7387
7864
|
"aria-label": annotating ? t("imageAnnotateCancel") : t("imageAnnotate"),
|
|
7388
7865
|
"aria-pressed": annotating,
|
|
7389
7866
|
onClick: () => {
|
|
7390
7867
|
resetGesture();
|
|
7391
7868
|
setAnnotating((value) => !value);
|
|
7392
7869
|
},
|
|
7393
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
7870
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolIcon, { id: "annotate" }), annotating ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7394
7871
|
className: "dcsiv-label",
|
|
7395
|
-
children:
|
|
7396
|
-
})]
|
|
7872
|
+
children: t("imageAnnotateCancel")
|
|
7873
|
+
}) : null]
|
|
7397
7874
|
}) : null,
|
|
7398
7875
|
annotations.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
7399
7876
|
type: "button",
|
|
@@ -7415,32 +7892,27 @@ window.__ModuleLoader__.load({
|
|
|
7415
7892
|
}) : null,
|
|
7416
7893
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
7417
7894
|
type: "button",
|
|
7418
|
-
className: "dcsiv-button",
|
|
7419
|
-
"
|
|
7420
|
-
|
|
7421
|
-
|
|
7422
|
-
|
|
7423
|
-
|
|
7424
|
-
}
|
|
7425
|
-
}),
|
|
7426
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7427
|
-
type: "button",
|
|
7428
|
-
className: "dcsiv-button",
|
|
7429
|
-
onClick: actual,
|
|
7430
|
-
children: t("imageActual")
|
|
7431
|
-
}),
|
|
7432
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
7433
|
-
className: "dcsiv-zoom",
|
|
7895
|
+
className: "dcsiv-button dcsiv-zoom",
|
|
7896
|
+
title: transform.zoom === 1 ? t("imageActual") : t("imageFit"),
|
|
7897
|
+
"aria-label": transform.zoom === 1 ? t("imageActual") : t("imageFit"),
|
|
7898
|
+
onClick: () => {
|
|
7899
|
+
if (transform.zoom === 1) actual();
|
|
7900
|
+
else fit();
|
|
7901
|
+
},
|
|
7434
7902
|
children: [Math.round(transform.zoom * pixelScale * 100), "%"]
|
|
7435
7903
|
}),
|
|
7436
|
-
|
|
7904
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7905
|
+
className: "dcsiv-divider",
|
|
7906
|
+
"aria-hidden": "true"
|
|
7907
|
+
}),
|
|
7908
|
+
item.download === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
7437
7909
|
className: "dcsiv-download",
|
|
7910
|
+
"data-compact": "true",
|
|
7438
7911
|
href: item.src,
|
|
7439
7912
|
download: downloadName(item.name),
|
|
7440
|
-
|
|
7441
|
-
|
|
7442
|
-
|
|
7443
|
-
})]
|
|
7913
|
+
title: t("imageDownload"),
|
|
7914
|
+
"aria-label": t("imageDownload"),
|
|
7915
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconDownloadOutline16, {})
|
|
7444
7916
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ViewerDownload, {
|
|
7445
7917
|
download: item.download,
|
|
7446
7918
|
item,
|
|
@@ -7452,7 +7924,8 @@ window.__ModuleLoader__.load({
|
|
|
7452
7924
|
item,
|
|
7453
7925
|
service,
|
|
7454
7926
|
revision: request.revision,
|
|
7455
|
-
t
|
|
7927
|
+
t,
|
|
7928
|
+
onStartMask: startMask
|
|
7456
7929
|
}, `${request.revision}:${index}:${action.id}`))
|
|
7457
7930
|
]
|
|
7458
7931
|
})
|
|
@@ -7466,142 +7939,205 @@ window.__ModuleLoader__.load({
|
|
|
7466
7939
|
}),
|
|
7467
7940
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7468
7941
|
className: "dcsiv-workspace",
|
|
7469
|
-
children: [
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
|
|
7476
|
-
|
|
7477
|
-
|
|
7478
|
-
|
|
7479
|
-
|
|
7480
|
-
|
|
7481
|
-
|
|
7482
|
-
|
|
7483
|
-
|
|
7484
|
-
|
|
7485
|
-
|
|
7486
|
-
|
|
7487
|
-
|
|
7488
|
-
|
|
7489
|
-
|
|
7490
|
-
|
|
7491
|
-
|
|
7492
|
-
|
|
7493
|
-
|
|
7494
|
-
|
|
7495
|
-
|
|
7496
|
-
|
|
7497
|
-
|
|
7498
|
-
|
|
7499
|
-
|
|
7500
|
-
|
|
7501
|
-
|
|
7502
|
-
|
|
7503
|
-
|
|
7504
|
-
|
|
7505
|
-
|
|
7506
|
-
|
|
7507
|
-
|
|
7508
|
-
|
|
7509
|
-
|
|
7510
|
-
|
|
7511
|
-
|
|
7512
|
-
|
|
7513
|
-
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
-
|
|
7517
|
-
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
|
|
7521
|
-
|
|
7522
|
-
|
|
7523
|
-
|
|
7524
|
-
|
|
7525
|
-
|
|
7526
|
-
|
|
7527
|
-
|
|
7528
|
-
|
|
7529
|
-
|
|
7530
|
-
|
|
7531
|
-
|
|
7532
|
-
|
|
7533
|
-
|
|
7534
|
-
|
|
7535
|
-
|
|
7536
|
-
|
|
7537
|
-
|
|
7538
|
-
|
|
7539
|
-
event.
|
|
7942
|
+
children: [
|
|
7943
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("main", {
|
|
7944
|
+
ref: stageRef,
|
|
7945
|
+
className: "dcsiv-stage",
|
|
7946
|
+
"data-dragging": dragging,
|
|
7947
|
+
"data-annotating": annotating || erasing !== void 0,
|
|
7948
|
+
onClick: (event) => {
|
|
7949
|
+
if (event.target === event.currentTarget && !annotating && !erasing && transform.zoom === 1) service.close();
|
|
7950
|
+
},
|
|
7951
|
+
...!annotating && !erasing ? pointerHandlers : {},
|
|
7952
|
+
onDoubleClick: () => {
|
|
7953
|
+
if (transform.zoom === 1) actual();
|
|
7954
|
+
else fit();
|
|
7955
|
+
},
|
|
7956
|
+
children: [
|
|
7957
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7958
|
+
ref: surfaceRef,
|
|
7959
|
+
className: "dcsiv-surface",
|
|
7960
|
+
onClick: addAnnotation,
|
|
7961
|
+
style: { transform: `translate3d(${transform.x}px,${transform.y}px,0) scale(${transform.zoom})` },
|
|
7962
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
7963
|
+
ref: imageRef,
|
|
7964
|
+
className: "dcsiv-image",
|
|
7965
|
+
src: item.src,
|
|
7966
|
+
alt: item.name,
|
|
7967
|
+
draggable: "false",
|
|
7968
|
+
onLoad: () => {
|
|
7969
|
+
measure();
|
|
7970
|
+
}
|
|
7971
|
+
}, `${request.revision}:${item.id}`), erasing ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("canvas", {
|
|
7972
|
+
ref: maskRef,
|
|
7973
|
+
className: "dcsiv-mask",
|
|
7974
|
+
width: imageRef.current?.naturalWidth || 1,
|
|
7975
|
+
height: imageRef.current?.naturalHeight || 1,
|
|
7976
|
+
"aria-label": t("imageEraseHint"),
|
|
7977
|
+
...maskHandlers
|
|
7978
|
+
}) : null]
|
|
7979
|
+
}),
|
|
7980
|
+
annotations.map((annotation, position) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7981
|
+
className: "dcsiv-annotation",
|
|
7982
|
+
"data-x": annotation.x < .38 ? "right" : annotation.x > .62 ? "left" : "center",
|
|
7983
|
+
"data-y": annotation.y < .28 ? "down" : "up",
|
|
7984
|
+
style: annotationPosition(annotation),
|
|
7985
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7986
|
+
type: "button",
|
|
7987
|
+
className: "dcsiv-pin",
|
|
7988
|
+
"data-active": selected === annotation.id,
|
|
7989
|
+
"aria-label": fill$1(t("imageAnnotation"), { value: position + 1 }),
|
|
7990
|
+
onClick: (event) => {
|
|
7991
|
+
event.stopPropagation();
|
|
7992
|
+
const opening = selected !== annotation.id;
|
|
7993
|
+
setSelected(opening ? annotation.id : void 0);
|
|
7994
|
+
if (opening) setFocusNote(annotation.id);
|
|
7995
|
+
},
|
|
7996
|
+
children: position + 1
|
|
7997
|
+
}), selected === annotation.id ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7998
|
+
className: "dcsiv-inline-note",
|
|
7999
|
+
"data-note-id": annotation.id,
|
|
8000
|
+
onClick: (event) => event.stopPropagation(),
|
|
8001
|
+
children: [
|
|
8002
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8003
|
+
className: "dcsiv-inline-index",
|
|
8004
|
+
children: position + 1
|
|
8005
|
+
}),
|
|
8006
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
8007
|
+
value: annotation.note,
|
|
8008
|
+
rows: 1,
|
|
8009
|
+
"aria-label": fill$1(t("imageAnnotation"), { value: position + 1 }),
|
|
8010
|
+
placeholder: t("imageAnnotationPlaceholder"),
|
|
8011
|
+
onChange: (event) => {
|
|
8012
|
+
const note = event.target.value;
|
|
8013
|
+
setAnnotations((current) => current.map((entry) => entry.id === annotation.id ? {
|
|
8014
|
+
...entry,
|
|
8015
|
+
note
|
|
8016
|
+
} : entry));
|
|
8017
|
+
},
|
|
8018
|
+
onKeyDown: (event) => {
|
|
8019
|
+
if (event.key === "Enter" && !event.shiftKey || event.key === "Escape") {
|
|
8020
|
+
event.preventDefault();
|
|
8021
|
+
event.stopPropagation();
|
|
8022
|
+
event.nativeEvent?.stopImmediatePropagation?.();
|
|
8023
|
+
setSelected(void 0);
|
|
8024
|
+
}
|
|
8025
|
+
}
|
|
8026
|
+
}),
|
|
8027
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
8028
|
+
type: "button",
|
|
8029
|
+
className: "dcsiv-note-remove",
|
|
8030
|
+
"aria-label": t("imageRemoveAnnotation"),
|
|
8031
|
+
onClick: (event) => {
|
|
7540
8032
|
event.stopPropagation();
|
|
7541
|
-
|
|
8033
|
+
setAnnotations((current) => current.filter((entry) => entry.id !== annotation.id));
|
|
7542
8034
|
setSelected(void 0);
|
|
7543
|
-
}
|
|
7544
|
-
|
|
7545
|
-
|
|
7546
|
-
|
|
7547
|
-
|
|
7548
|
-
|
|
7549
|
-
|
|
7550
|
-
|
|
7551
|
-
|
|
7552
|
-
|
|
7553
|
-
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
|
|
7560
|
-
|
|
8035
|
+
},
|
|
8036
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconCloseOutline16, {})
|
|
8037
|
+
})
|
|
8038
|
+
]
|
|
8039
|
+
}) : null]
|
|
8040
|
+
}, annotation.id)),
|
|
8041
|
+
showCounter ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
8042
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
8043
|
+
type: "button",
|
|
8044
|
+
className: "dcsiv-button dcsiv-icon-only dcsiv-nav dcsiv-prev",
|
|
8045
|
+
"aria-label": t("imagePrevious"),
|
|
8046
|
+
onClick: (event) => {
|
|
8047
|
+
event.stopPropagation();
|
|
8048
|
+
setIndex((value) => (value - 1 + request.items.length) % request.items.length);
|
|
8049
|
+
},
|
|
8050
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconChevronLeftOutline14, {})
|
|
8051
|
+
}),
|
|
8052
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
8053
|
+
type: "button",
|
|
8054
|
+
className: "dcsiv-button dcsiv-icon-only dcsiv-nav dcsiv-next",
|
|
8055
|
+
"aria-label": t("imageNext"),
|
|
8056
|
+
onClick: (event) => {
|
|
8057
|
+
event.stopPropagation();
|
|
8058
|
+
setIndex((value) => (value + 1) % request.items.length);
|
|
8059
|
+
},
|
|
8060
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconChevronRightOutline14, {})
|
|
8061
|
+
}),
|
|
8062
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
8063
|
+
className: "dcsiv-counter",
|
|
8064
|
+
children: [
|
|
8065
|
+
index + 1,
|
|
8066
|
+
" / ",
|
|
8067
|
+
request.items.length
|
|
8068
|
+
]
|
|
8069
|
+
})
|
|
8070
|
+
] }) : annotating ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8071
|
+
className: "dcsiv-hint",
|
|
8072
|
+
children: t("imageAnnotateHint")
|
|
8073
|
+
}) : transform.zoom === 1 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8074
|
+
className: "dcsiv-hint",
|
|
8075
|
+
children: t("imageZoomHint")
|
|
8076
|
+
}) : null
|
|
8077
|
+
]
|
|
8078
|
+
}),
|
|
8079
|
+
erasing ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8080
|
+
className: "dcsiv-erase-bar",
|
|
8081
|
+
role: "toolbar",
|
|
8082
|
+
"aria-label": t("imageErase"),
|
|
8083
|
+
children: [
|
|
8084
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("imageEraseHint") }),
|
|
8085
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [t("imageBrushSize"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
8086
|
+
type: "range",
|
|
8087
|
+
min: "0.01",
|
|
8088
|
+
max: "0.15",
|
|
8089
|
+
step: "0.01",
|
|
8090
|
+
value: brush,
|
|
8091
|
+
onChange: (event) => setBrush(Number(event.target.value))
|
|
8092
|
+
})] }),
|
|
7561
8093
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7562
8094
|
type: "button",
|
|
7563
|
-
className: "dcsiv-button
|
|
7564
|
-
|
|
7565
|
-
onClick: (
|
|
7566
|
-
|
|
7567
|
-
setIndex((value) => (value - 1 + request.items.length) % request.items.length);
|
|
7568
|
-
},
|
|
7569
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconChevronLeftOutline14, {})
|
|
8095
|
+
className: "dcsiv-button",
|
|
8096
|
+
disabled: strokes.length === 0 || sending,
|
|
8097
|
+
onClick: () => setStrokes((current) => current.slice(0, -1)),
|
|
8098
|
+
children: t("imageUndo")
|
|
7570
8099
|
}),
|
|
7571
8100
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7572
8101
|
type: "button",
|
|
7573
|
-
className: "dcsiv-button
|
|
7574
|
-
|
|
7575
|
-
onClick: (
|
|
7576
|
-
|
|
7577
|
-
|
|
8102
|
+
className: "dcsiv-button",
|
|
8103
|
+
disabled: sending,
|
|
8104
|
+
onClick: () => {
|
|
8105
|
+
setErasing(void 0);
|
|
8106
|
+
setStrokes([]);
|
|
7578
8107
|
},
|
|
7579
|
-
children:
|
|
8108
|
+
children: t("cancel")
|
|
7580
8109
|
}),
|
|
7581
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
7582
|
-
|
|
7583
|
-
|
|
7584
|
-
|
|
7585
|
-
|
|
7586
|
-
|
|
7587
|
-
|
|
8110
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
8111
|
+
type: "button",
|
|
8112
|
+
className: "dcsiv-button dcsiv-primary",
|
|
8113
|
+
"data-state": sendFailed ? "failed" : void 0,
|
|
8114
|
+
disabled: strokes.length === 0 || sending,
|
|
8115
|
+
onClick: () => {
|
|
8116
|
+
sendMask();
|
|
8117
|
+
},
|
|
8118
|
+
children: sending ? t("imageEditPreparing") : sendFailed ? t("imageEditFailed") : t("imageSend")
|
|
7588
8119
|
})
|
|
7589
|
-
]
|
|
7590
|
-
|
|
7591
|
-
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
|
|
7597
|
-
|
|
7598
|
-
|
|
7599
|
-
|
|
7600
|
-
|
|
7601
|
-
|
|
7602
|
-
|
|
7603
|
-
|
|
7604
|
-
|
|
8120
|
+
]
|
|
8121
|
+
}) : null,
|
|
8122
|
+
erasing && brushCursor ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8123
|
+
className: "dcsiv-brush-cursor",
|
|
8124
|
+
"aria-hidden": "true",
|
|
8125
|
+
style: {
|
|
8126
|
+
left: brushCursor.left,
|
|
8127
|
+
top: brushCursor.top,
|
|
8128
|
+
width: brush * brushCursor.span,
|
|
8129
|
+
height: brush * brushCursor.span
|
|
8130
|
+
}
|
|
8131
|
+
}) : null,
|
|
8132
|
+
annotations.some((annotation) => annotation.note.trim() !== "") ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
8133
|
+
type: "button",
|
|
8134
|
+
className: "dcsiv-copy-notes",
|
|
8135
|
+
onClick: () => {
|
|
8136
|
+
copyNotes();
|
|
8137
|
+
},
|
|
8138
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconCopyOutline16, {}), copied ? t("imageCopied") : t("imageCopyNotes")]
|
|
8139
|
+
}) : null
|
|
8140
|
+
]
|
|
7605
8141
|
})
|
|
7606
8142
|
]
|
|
7607
8143
|
});
|
|
@@ -7622,6 +8158,12 @@ window.__ModuleLoader__.load({
|
|
|
7622
8158
|
pendingLabel: typeof action.pendingLabel === "string" && action.pendingLabel !== "" ? action.pendingLabel : action.label,
|
|
7623
8159
|
errorLabel: typeof action.errorLabel === "string" && action.errorLabel !== "" ? action.errorLabel : action.label,
|
|
7624
8160
|
closeOnSuccess: action.closeOnSuccess === true,
|
|
8161
|
+
kind: [
|
|
8162
|
+
"tool",
|
|
8163
|
+
"mask",
|
|
8164
|
+
"choice"
|
|
8165
|
+
].includes(action.kind) ? action.kind : "edit",
|
|
8166
|
+
options: Array.isArray(action.options) ? action.options.filter((option) => typeof option?.value === "string" && typeof option?.label === "string") : [],
|
|
7625
8167
|
onInvoke: action.onInvoke
|
|
7626
8168
|
}];
|
|
7627
8169
|
}) : [];
|
|
@@ -8549,7 +9091,7 @@ window.__ModuleLoader__.load({
|
|
|
8549
9091
|
}
|
|
8550
9092
|
//#endregion
|
|
8551
9093
|
//#region src/version.js
|
|
8552
|
-
const PACKAGE_VERSION = "2.5.
|
|
9094
|
+
const PACKAGE_VERSION = "2.5.9";
|
|
8553
9095
|
//#endregion
|
|
8554
9096
|
//#region src/client-recovery.js
|
|
8555
9097
|
async function recoveryCall(rpc, endpoint, payload = {}, timeoutMs = 1e4) {
|
|
@@ -11228,6 +11770,7 @@ window.__ModuleLoader__.load({
|
|
|
11228
11770
|
//#endregion
|
|
11229
11771
|
//#region src/client-usage.jsx
|
|
11230
11772
|
const count = (value) => Number(value).toLocaleString();
|
|
11773
|
+
const creditAmount = (value) => Number.isFinite(Number(value)) && String(value).trim() !== "" ? Number(value).toLocaleString(void 0, { maximumFractionDigits: 2 }) : value;
|
|
11231
11774
|
function CreditExpiry({ credits, t }) {
|
|
11232
11775
|
const date = validDate(credits.expiresAt);
|
|
11233
11776
|
if (date === void 0 || credits.unlimited) return null;
|
|
@@ -11630,7 +12173,7 @@ window.__ModuleLoader__.load({
|
|
|
11630
12173
|
children: [
|
|
11631
12174
|
visibleUsage?.credits ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
11632
12175
|
className: "codexSubscriptionCreditBalance",
|
|
11633
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("creditsBalance") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: visibleUsage.credits.unlimited ? t("unlimited") :
|
|
12176
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("creditsBalance") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: visibleUsage.credits.unlimited ? t("unlimited") : visibleUsage.credits.balance == null ? t("unavailable") : `${creditAmount(visibleUsage.credits.balance)} ${t("creditsUnit")}` })]
|
|
11634
12177
|
}) : null,
|
|
11635
12178
|
visibleUsage?.credits ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CreditExpiry, {
|
|
11636
12179
|
credits: visibleUsage.credits,
|
|
@@ -12161,7 +12704,8 @@ window.__ModuleLoader__.load({
|
|
|
12161
12704
|
imageViewer.close();
|
|
12162
12705
|
liveOpen("sketch", document.activeElement, new File([blob], name || "image.png", { type: blob.type || "image/png" }));
|
|
12163
12706
|
};
|
|
12164
|
-
const attachForEdit = (sessionId) => async (src, filename, draft, annotations = [], referenceName, sourceInDraft = false) => {
|
|
12707
|
+
const attachForEdit = (sessionId) => async (src, filename, draft, annotations = [], referenceName, sourceInDraft = false, extraFiles) => {
|
|
12708
|
+
const tool = Array.isArray(extraFiles);
|
|
12165
12709
|
if (!preference.getSnapshot().imageEditing) throw new Error("Image editing is disabled");
|
|
12166
12710
|
return withComposerSession(sessions, sessionId, async (actx) => {
|
|
12167
12711
|
if (conversation.input?.for === void 0) throw new Error("This DSH version does not provide the image composer bridge");
|
|
@@ -12173,14 +12717,15 @@ window.__ModuleLoader__.load({
|
|
|
12173
12717
|
const reference = await createAnnotatedImageReference(blob, annotations);
|
|
12174
12718
|
files.push(new File([reference], referenceName, { type: "image/png" }));
|
|
12175
12719
|
}
|
|
12720
|
+
if (tool) files.push(...extraFiles);
|
|
12176
12721
|
lifetime.signal.throwIfAborted();
|
|
12177
12722
|
const input = conversation.input.for(actx);
|
|
12178
12723
|
if (!preference.getSnapshot().imageEditing) throw new Error("Image editing is disabled");
|
|
12179
12724
|
if (files.length) attachImageFiles(conversation, input, files, sessionId);
|
|
12180
12725
|
openComposerSession(sessions, ctx.get("uiWorkspace"), sessionId);
|
|
12181
|
-
if (sourceInDraft && !annotations.length) return;
|
|
12726
|
+
if (sourceInDraft && !annotations.length && !tool) return;
|
|
12182
12727
|
if (!input.state.getSnapshot().draft.trim()) input.setDraft(draft);
|
|
12183
|
-
else if (annotations.length) if (!input.state.getSnapshot().occurrences?.length) appendImagePrompt(input, draft);
|
|
12728
|
+
else if (annotations.length || tool) if (!input.state.getSnapshot().occurrences?.length) appendImagePrompt(input, draft);
|
|
12184
12729
|
else input.notify("info", draft);
|
|
12185
12730
|
});
|
|
12186
12731
|
};
|