dsh-codex-subscription 2.5.7 → 2.5.8
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 +588 -183
- package/lib/index.js +1 -1
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -106,7 +106,7 @@ This plugin supports the latest DeepSeek Harness release recorded in its package
|
|
|
106
106
|
2. Paste this package name, with its version, into the **Package name or address** field:
|
|
107
107
|
|
|
108
108
|
```text
|
|
109
|
-
dsh-codex-subscription@2.5.
|
|
109
|
+
dsh-codex-subscription@2.5.8
|
|
110
110
|
```
|
|
111
111
|
|
|
112
112
|
3. Click **Install** and wait for completion. Follow the page instructions; save your work before restarting if requested.
|
|
@@ -139,6 +139,12 @@ dsh --profile headless "Reply with only the word: ok"
|
|
|
139
139
|
|
|
140
140
|
## Inside the plugin
|
|
141
141
|
|
|
142
|
+
<details>
|
|
143
|
+
<summary><b>Interface demo (animation, click to expand)</b>: models, prompts, images, annotation, sketch board, quota and resets</summary>
|
|
144
|
+
<br>
|
|
145
|
+
<p align="center"><img src="docs/assets/readme-demo-en.webp" width="1100" alt="Demo: sign in with ChatGPT, pick a subscription model, ask, generate an image, view and annotate it, continue on the sketch board, and check quota and resets"></p>
|
|
146
|
+
</details>
|
|
147
|
+
|
|
142
148
|
### Everyday controls, right in the composer
|
|
143
149
|
|
|
144
150
|
Choose a model, adjust reasoning, switch speed tiers, and check remaining quota without opening settings for every request.
|
package/README.md
CHANGED
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
2. 在 **包名或地址** 输入框中粘贴下面的包名(已带版本号):
|
|
107
107
|
|
|
108
108
|
```text
|
|
109
|
-
dsh-codex-subscription@2.5.
|
|
109
|
+
dsh-codex-subscription@2.5.8
|
|
110
110
|
```
|
|
111
111
|
|
|
112
112
|
3. 点击 **安装**,等待安装完成;按页面提示操作,需要重启时先保存工作。
|
|
@@ -139,6 +139,12 @@ dsh --profile headless "只回复:ok"
|
|
|
139
139
|
|
|
140
140
|
## 界面一览
|
|
141
141
|
|
|
142
|
+
<details>
|
|
143
|
+
<summary><b>界面演示(动图,点击展开)</b>:选模型、提问、出图、标注、草图、额度与重置</summary>
|
|
144
|
+
<br>
|
|
145
|
+
<p align="center"><img src="docs/assets/readme-demo.webp" width="1100" alt="演示:登录 ChatGPT 选订阅模型、提问、用订阅出图、查看与标注、进入草图、查看额度与重置"></p>
|
|
146
|
+
</details>
|
|
147
|
+
|
|
142
148
|
### 日常操作,留在输入框
|
|
143
149
|
|
|
144
150
|
选模型、调推理档位、切换速度档位,同时查看剩余额度。无需为每次请求打开设置。
|
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,27 @@ 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$6 = /*#__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$5 = /*#__PURE__*/ react.forwardRef(ArrowsPointingOutIcon);
|
|
808
920
|
//#endregion
|
|
809
921
|
//#region node_modules/.pnpm/@heroicons+react@2.2.0_react@18.3.1/node_modules/@heroicons/react/24/outline/esm/ExclamationCircleIcon.js
|
|
810
922
|
function ExclamationCircleIcon({ title, titleId, ...props }, svgRef) {
|
|
@@ -824,7 +936,27 @@ window.__ModuleLoader__.load({
|
|
|
824
936
|
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
937
|
}));
|
|
826
938
|
}
|
|
827
|
-
const ForwardRef$
|
|
939
|
+
const ForwardRef$4 = /*#__PURE__*/ react.forwardRef(ExclamationCircleIcon);
|
|
940
|
+
//#endregion
|
|
941
|
+
//#region node_modules/.pnpm/@heroicons+react@2.2.0_react@18.3.1/node_modules/@heroicons/react/24/outline/esm/PaintBrushIcon.js
|
|
942
|
+
function PaintBrushIcon({ title, titleId, ...props }, svgRef) {
|
|
943
|
+
return /*#__PURE__*/ react.createElement("svg", Object.assign({
|
|
944
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
945
|
+
fill: "none",
|
|
946
|
+
viewBox: "0 0 24 24",
|
|
947
|
+
strokeWidth: 1.5,
|
|
948
|
+
stroke: "currentColor",
|
|
949
|
+
"aria-hidden": "true",
|
|
950
|
+
"data-slot": "icon",
|
|
951
|
+
ref: svgRef,
|
|
952
|
+
"aria-labelledby": titleId
|
|
953
|
+
}, props), title ? /*#__PURE__*/ react.createElement("title", { id: titleId }, title) : null, /*#__PURE__*/ react.createElement("path", {
|
|
954
|
+
strokeLinecap: "round",
|
|
955
|
+
strokeLinejoin: "round",
|
|
956
|
+
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"
|
|
957
|
+
}));
|
|
958
|
+
}
|
|
959
|
+
const ForwardRef$3 = /*#__PURE__*/ react.forwardRef(PaintBrushIcon);
|
|
828
960
|
//#endregion
|
|
829
961
|
//#region node_modules/.pnpm/@heroicons+react@2.2.0_react@18.3.1/node_modules/@heroicons/react/24/outline/esm/PhotoIcon.js
|
|
830
962
|
function PhotoIcon({ title, titleId, ...props }, svgRef) {
|
|
@@ -844,7 +976,27 @@ window.__ModuleLoader__.load({
|
|
|
844
976
|
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
977
|
}));
|
|
846
978
|
}
|
|
847
|
-
const ForwardRef$
|
|
979
|
+
const ForwardRef$2 = /*#__PURE__*/ react.forwardRef(PhotoIcon);
|
|
980
|
+
//#endregion
|
|
981
|
+
//#region node_modules/.pnpm/@heroicons+react@2.2.0_react@18.3.1/node_modules/@heroicons/react/24/outline/esm/ScissorsIcon.js
|
|
982
|
+
function ScissorsIcon({ 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: "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"
|
|
997
|
+
}));
|
|
998
|
+
}
|
|
999
|
+
const ForwardRef$1 = /*#__PURE__*/ react.forwardRef(ScissorsIcon);
|
|
848
1000
|
const ORIGINAL_IMAGE_ID_PATTERN = /^img_[0-9a-f]{32}$/u;
|
|
849
1001
|
const positiveInteger = (value) => Number.isSafeInteger(value) && value > 0;
|
|
850
1002
|
function decodeOriginalImageRef(value) {
|
|
@@ -1032,32 +1184,41 @@ window.__ModuleLoader__.load({
|
|
|
1032
1184
|
errorLabel: t("imageDownloadFailed"),
|
|
1033
1185
|
onInvoke: downloadOriginal
|
|
1034
1186
|
},
|
|
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
|
-
|
|
1187
|
+
actions: !features.imageEditing ? [] : [
|
|
1188
|
+
{
|
|
1189
|
+
id: "continue-editing",
|
|
1190
|
+
label: t("imageEdit"),
|
|
1191
|
+
pendingLabel: t("imageEditPreparing"),
|
|
1192
|
+
errorLabel: t("imageEditFailed"),
|
|
1193
|
+
closeOnSuccess: true,
|
|
1194
|
+
onInvoke: ({ annotations = [] }) => {
|
|
1195
|
+
const imageKey = String(attachment.attachmentId ?? "image").replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
1196
|
+
const sourceName = annotations.length === 0 ? downloadName : `codex-edit-${imageKey}-source.png`;
|
|
1197
|
+
const referenceName = `codex-edit-${imageKey}-annotations.png`;
|
|
1198
|
+
return attachForEdit(src, sourceName, buildImageEditDraft({
|
|
1199
|
+
annotations,
|
|
1200
|
+
translate: t,
|
|
1201
|
+
width: attachment.width,
|
|
1202
|
+
height: attachment.height,
|
|
1203
|
+
sourceName,
|
|
1204
|
+
referenceName
|
|
1205
|
+
}), annotations, referenceName);
|
|
1206
|
+
}
|
|
1207
|
+
},
|
|
1208
|
+
...officialImageTools({
|
|
1209
|
+
src,
|
|
1210
|
+
name: downloadName,
|
|
1211
|
+
t,
|
|
1212
|
+
attachForEdit
|
|
1213
|
+
}),
|
|
1214
|
+
...features.imageSketch && openSketchImage ? [{
|
|
1215
|
+
id: "sketch",
|
|
1216
|
+
label: t("imageToSketch"),
|
|
1217
|
+
pendingLabel: t("imageEditPreparing"),
|
|
1218
|
+
errorLabel: t("imageEditFailed"),
|
|
1219
|
+
onInvoke: () => openSketchImage(src, downloadName)
|
|
1220
|
+
}] : []
|
|
1221
|
+
]
|
|
1061
1222
|
}],
|
|
1062
1223
|
opener: triggerRef.current,
|
|
1063
1224
|
source: "codex-generated",
|
|
@@ -1107,7 +1268,7 @@ window.__ModuleLoader__.load({
|
|
|
1107
1268
|
showOutput ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1108
1269
|
className: "codexImageToolRow",
|
|
1109
1270
|
children: [
|
|
1110
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(!settled ? ForwardRef$
|
|
1271
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(!settled ? ForwardRef$6 : failed ? ForwardRef$4 : ForwardRef$2, {
|
|
1111
1272
|
className: "codexImageToolIcon",
|
|
1112
1273
|
"aria-hidden": "true"
|
|
1113
1274
|
}),
|
|
@@ -5525,6 +5686,21 @@ window.__ModuleLoader__.load({
|
|
|
5525
5686
|
sketchEditableFile: "可编辑草稿",
|
|
5526
5687
|
sketchFormatHint: "PNG 为合并图片;可编辑草稿保留原生笔画,可重新导入(32 MB 内)。",
|
|
5527
5688
|
imageToSketch: "进入草图",
|
|
5689
|
+
imageRemoveBackground: "移除背景",
|
|
5690
|
+
imageRemoveBackgroundPrompt: "移除此图像的背景。保持所有前景主体不变且完整,边缘干净平滑。将背景设为透明。",
|
|
5691
|
+
imageErase: "擦除",
|
|
5692
|
+
imageEraseHint: "在要移除的内容上涂抹",
|
|
5693
|
+
imageErasePrompt: "从第一张图像中移除第二张图像中标记的区域",
|
|
5694
|
+
imageBrushSize: "画笔大小",
|
|
5695
|
+
imageUndo: "撤销",
|
|
5696
|
+
imageSend: "发送",
|
|
5697
|
+
imageResize: "调整大小",
|
|
5698
|
+
imageResizePrompt: "将宽高比设为 {aspectRatio}",
|
|
5699
|
+
imageRatio_square: "正方形",
|
|
5700
|
+
imageRatio_portrait: "竖向",
|
|
5701
|
+
imageRatio_story: "故事版式",
|
|
5702
|
+
imageRatio_landscape: "横向",
|
|
5703
|
+
imageRatio_widescreen: "宽屏",
|
|
5528
5704
|
sketchPictures: "图片",
|
|
5529
5705
|
sketchPictureAdd: "添加",
|
|
5530
5706
|
sketchPictureSelect: "选择图片",
|
|
@@ -6097,6 +6273,21 @@ window.__ModuleLoader__.load({
|
|
|
6097
6273
|
sketchEditableFile: "Editable draft",
|
|
6098
6274
|
sketchFormatHint: "PNG is flattened; editable drafts retain native strokes and can be imported again (up to 32 MB).",
|
|
6099
6275
|
imageToSketch: "Open in sketch",
|
|
6276
|
+
imageRemoveBackground: "Remove background",
|
|
6277
|
+
imageRemoveBackgroundPrompt: "Remove the background from this image. Keep all foreground subjects unchanged and fully intact, with clean, smooth edges. Make the background transparent.",
|
|
6278
|
+
imageErase: "Erase",
|
|
6279
|
+
imageEraseHint: "Brush over what you want to remove",
|
|
6280
|
+
imageErasePrompt: "Remove the area marked in the second image from the first image",
|
|
6281
|
+
imageBrushSize: "Brush size",
|
|
6282
|
+
imageUndo: "Undo",
|
|
6283
|
+
imageSend: "Send",
|
|
6284
|
+
imageResize: "Resize",
|
|
6285
|
+
imageResizePrompt: "Make the aspect ratio {aspectRatio}",
|
|
6286
|
+
imageRatio_square: "Square",
|
|
6287
|
+
imageRatio_portrait: "Portrait",
|
|
6288
|
+
imageRatio_story: "Story",
|
|
6289
|
+
imageRatio_landscape: "Landscape",
|
|
6290
|
+
imageRatio_widescreen: "Widescreen",
|
|
6100
6291
|
sketchPictures: "Images",
|
|
6101
6292
|
sketchPictureAdd: "Add",
|
|
6102
6293
|
sketchPictureSelect: "Select image",
|
|
@@ -6919,6 +7110,9 @@ window.__ModuleLoader__.load({
|
|
|
6919
7110
|
.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
7111
|
.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
7112
|
.dcsiv-hint{display:none}
|
|
7113
|
+
.dcsiv-mask{position:absolute;inset:0;width:100%;height:100%;border-radius:12px;cursor:crosshair;touch-action:none}
|
|
7114
|
+
.dcsiv-tool-icon{width:16px;height:16px;flex:none}.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{background:rgba(255,255,255,.1)}
|
|
7115
|
+
.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}
|
|
6922
7116
|
.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
7117
|
.dcsiv-edit-short{display:none}
|
|
6924
7118
|
@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}}
|
|
@@ -7102,6 +7296,18 @@ window.__ModuleLoader__.load({
|
|
|
7102
7296
|
}
|
|
7103
7297
|
//#endregion
|
|
7104
7298
|
//#region src/subscription-image-viewer.jsx
|
|
7299
|
+
const TOOL_ICONS = {
|
|
7300
|
+
"remove-background": ForwardRef$1,
|
|
7301
|
+
erase: ForwardRef$3,
|
|
7302
|
+
resize: ForwardRef$5
|
|
7303
|
+
};
|
|
7304
|
+
const ToolIcon = ({ id }) => {
|
|
7305
|
+
const Icon = TOOL_ICONS[id];
|
|
7306
|
+
return Icon ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
|
|
7307
|
+
className: "dcsiv-tool-icon",
|
|
7308
|
+
"aria-hidden": "true"
|
|
7309
|
+
}) : null;
|
|
7310
|
+
};
|
|
7105
7311
|
const fill$1 = (value, variables) => Object.entries(variables).reduce((text, [key, replacement]) => text.replaceAll(`{${key}}`, String(replacement)), value);
|
|
7106
7312
|
const clamp = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
7107
7313
|
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,8 +7318,9 @@ window.__ModuleLoader__.load({
|
|
|
7112
7318
|
const noteText = (annotations, t) => annotations.map((annotation, index) => {
|
|
7113
7319
|
return `${fill$1(t("imageAnnotation"), { value: index + 1 })} (${Math.round(annotation.x * 100)}%, ${Math.round(annotation.y * 100)}%): ${annotation.note.trim()}`;
|
|
7114
7320
|
}).filter((line) => !line.endsWith(": ")).join("\n");
|
|
7115
|
-
function ViewerAction({ action, annotations, item, service, revision, t }) {
|
|
7321
|
+
function ViewerAction({ action, annotations, item, service, revision, t, onStartMask }) {
|
|
7116
7322
|
const [state, setState] = (0, react.useState)("idle");
|
|
7323
|
+
const [menu, setMenu] = (0, react.useState)();
|
|
7117
7324
|
const active = (0, react.useRef)(true);
|
|
7118
7325
|
(0, react.useEffect)(() => {
|
|
7119
7326
|
active.current = true;
|
|
@@ -7121,14 +7328,15 @@ window.__ModuleLoader__.load({
|
|
|
7121
7328
|
active.current = false;
|
|
7122
7329
|
};
|
|
7123
7330
|
}, []);
|
|
7124
|
-
const invoke = async () => {
|
|
7331
|
+
const invoke = async (extra = {}) => {
|
|
7125
7332
|
if (state === "pending") return;
|
|
7126
7333
|
setState("pending");
|
|
7127
7334
|
try {
|
|
7128
7335
|
await action.onInvoke({
|
|
7129
7336
|
annotations,
|
|
7130
7337
|
item,
|
|
7131
|
-
src: item.src
|
|
7338
|
+
src: item.src,
|
|
7339
|
+
...extra
|
|
7132
7340
|
});
|
|
7133
7341
|
if (!active.current || service.getSnapshot()?.revision !== revision) return;
|
|
7134
7342
|
setState("idle");
|
|
@@ -7138,6 +7346,62 @@ window.__ModuleLoader__.load({
|
|
|
7138
7346
|
}
|
|
7139
7347
|
};
|
|
7140
7348
|
const label = state === "pending" ? action.pendingLabel : state === "failed" ? action.errorLabel : action.label;
|
|
7349
|
+
if (action.kind === "mask") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
7350
|
+
type: "button",
|
|
7351
|
+
className: "dcsiv-button",
|
|
7352
|
+
onClick: () => onStartMask(action),
|
|
7353
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolIcon, { id: action.id }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7354
|
+
className: "dcsiv-label",
|
|
7355
|
+
children: action.label
|
|
7356
|
+
})]
|
|
7357
|
+
});
|
|
7358
|
+
if (action.kind === "tool") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
7359
|
+
type: "button",
|
|
7360
|
+
className: "dcsiv-button",
|
|
7361
|
+
disabled: state === "pending",
|
|
7362
|
+
onClick: () => {
|
|
7363
|
+
invoke();
|
|
7364
|
+
},
|
|
7365
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolIcon, { id: action.id }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7366
|
+
className: "dcsiv-label",
|
|
7367
|
+
children: label
|
|
7368
|
+
})]
|
|
7369
|
+
});
|
|
7370
|
+
if (action.kind === "choice") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
7371
|
+
type: "button",
|
|
7372
|
+
className: "dcsiv-button",
|
|
7373
|
+
"aria-haspopup": "menu",
|
|
7374
|
+
"aria-expanded": menu !== void 0,
|
|
7375
|
+
disabled: state === "pending",
|
|
7376
|
+
onClick: (event) => {
|
|
7377
|
+
const box = event.currentTarget.getBoundingClientRect();
|
|
7378
|
+
const host = event.currentTarget.closest(".dcsiv-root");
|
|
7379
|
+
setMenu((value) => value === void 0 && host ? {
|
|
7380
|
+
host,
|
|
7381
|
+
style: {
|
|
7382
|
+
left: box.left,
|
|
7383
|
+
bottom: window.innerHeight - box.top + 8
|
|
7384
|
+
}
|
|
7385
|
+
} : void 0);
|
|
7386
|
+
},
|
|
7387
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolIcon, { id: action.id }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7388
|
+
className: "dcsiv-label",
|
|
7389
|
+
children: label
|
|
7390
|
+
})]
|
|
7391
|
+
}), menu ? (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7392
|
+
className: "dcsiv-menu",
|
|
7393
|
+
role: "menu",
|
|
7394
|
+
style: menu.style,
|
|
7395
|
+
children: action.options.map((option) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7396
|
+
type: "button",
|
|
7397
|
+
role: "menuitem",
|
|
7398
|
+
onClick: () => {
|
|
7399
|
+
setMenu(void 0);
|
|
7400
|
+
invoke({ option: option.value });
|
|
7401
|
+
},
|
|
7402
|
+
children: option.label
|
|
7403
|
+
}, option.value))
|
|
7404
|
+
}), menu.host) : null] });
|
|
7141
7405
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
7142
7406
|
type: "button",
|
|
7143
7407
|
className: "dcsiv-button dcsiv-edit-action",
|
|
@@ -7224,6 +7488,12 @@ window.__ModuleLoader__.load({
|
|
|
7224
7488
|
const [selected, setSelected] = (0, react.useState)();
|
|
7225
7489
|
const [focusNote, setFocusNote] = (0, react.useState)();
|
|
7226
7490
|
const [copied, setCopied] = (0, react.useState)(false);
|
|
7491
|
+
const [erasing, setErasing] = (0, react.useState)();
|
|
7492
|
+
const [strokes, setStrokes] = (0, react.useState)([]);
|
|
7493
|
+
const [brush, setBrush] = (0, react.useState)(.05);
|
|
7494
|
+
const [sending, setSending] = (0, react.useState)(false);
|
|
7495
|
+
const drawingRef = (0, react.useRef)(false);
|
|
7496
|
+
const maskRef = (0, react.useRef)(null);
|
|
7227
7497
|
const rootRef = (0, react.useRef)(null);
|
|
7228
7498
|
annotationsByImageRef.current = annotationsByImage;
|
|
7229
7499
|
(0, react.useEffect)(() => {
|
|
@@ -7316,11 +7586,85 @@ window.__ModuleLoader__.load({
|
|
|
7316
7586
|
(0, react.useEffect)(() => {
|
|
7317
7587
|
setAnnotating(false);
|
|
7318
7588
|
setSelected(void 0);
|
|
7589
|
+
setErasing(void 0);
|
|
7590
|
+
setStrokes([]);
|
|
7319
7591
|
}, [
|
|
7320
7592
|
item?.id,
|
|
7321
7593
|
item?.src,
|
|
7322
7594
|
request?.revision
|
|
7323
7595
|
]);
|
|
7596
|
+
(0, react.useEffect)(() => {
|
|
7597
|
+
const canvas = maskRef.current;
|
|
7598
|
+
if (!erasing || canvas === null) return;
|
|
7599
|
+
const context = canvas.getContext("2d");
|
|
7600
|
+
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
7601
|
+
paintEraseStrokes(context, strokes, canvas.width, canvas.height, "rgba(255,59,48,.5)");
|
|
7602
|
+
}, [erasing, strokes]);
|
|
7603
|
+
const strokePoint = (event) => {
|
|
7604
|
+
const bounds = maskRef.current?.getBoundingClientRect();
|
|
7605
|
+
if (bounds === void 0) return void 0;
|
|
7606
|
+
return {
|
|
7607
|
+
x: clamp((event.clientX - bounds.left) / bounds.width, 0, 1),
|
|
7608
|
+
y: clamp((event.clientY - bounds.top) / bounds.height, 0, 1)
|
|
7609
|
+
};
|
|
7610
|
+
};
|
|
7611
|
+
const maskHandlers = {
|
|
7612
|
+
onPointerDown: (event) => {
|
|
7613
|
+
const point = strokePoint(event);
|
|
7614
|
+
if (point === void 0) return;
|
|
7615
|
+
event.stopPropagation();
|
|
7616
|
+
event.currentTarget.setPointerCapture?.(event.pointerId);
|
|
7617
|
+
drawingRef.current = true;
|
|
7618
|
+
setStrokes((current) => [...current, {
|
|
7619
|
+
size: brush / transformRef.current.zoom,
|
|
7620
|
+
points: [point]
|
|
7621
|
+
}]);
|
|
7622
|
+
},
|
|
7623
|
+
onPointerMove: (event) => {
|
|
7624
|
+
if (!drawingRef.current) return;
|
|
7625
|
+
const point = strokePoint(event);
|
|
7626
|
+
if (point === void 0) return;
|
|
7627
|
+
setStrokes((current) => current.length === 0 ? current : [...current.slice(0, -1), {
|
|
7628
|
+
...current.at(-1),
|
|
7629
|
+
points: [...current.at(-1).points, point]
|
|
7630
|
+
}]);
|
|
7631
|
+
},
|
|
7632
|
+
onPointerUp: () => {
|
|
7633
|
+
drawingRef.current = false;
|
|
7634
|
+
},
|
|
7635
|
+
onPointerCancel: () => {
|
|
7636
|
+
drawingRef.current = false;
|
|
7637
|
+
}
|
|
7638
|
+
};
|
|
7639
|
+
const startMask = (action) => {
|
|
7640
|
+
resetGesture();
|
|
7641
|
+
setAnnotating(false);
|
|
7642
|
+
setStrokes([]);
|
|
7643
|
+
setErasing(action);
|
|
7644
|
+
};
|
|
7645
|
+
const sendMask = async () => {
|
|
7646
|
+
const image = imageRef.current;
|
|
7647
|
+
if (!erasing || strokes.length === 0 || image === null || sending) return;
|
|
7648
|
+
setSending(true);
|
|
7649
|
+
try {
|
|
7650
|
+
const canvas = document.createElement("canvas");
|
|
7651
|
+
canvas.width = image.naturalWidth;
|
|
7652
|
+
canvas.height = image.naturalHeight;
|
|
7653
|
+
paintEraseMask(canvas.getContext("2d"), strokes, canvas.width, canvas.height);
|
|
7654
|
+
const mask = await new Promise((resolve, reject) => canvas.toBlob((blob) => blob ? resolve(blob) : reject(/* @__PURE__ */ new Error("Mask")), "image/png"));
|
|
7655
|
+
await erasing.onInvoke({
|
|
7656
|
+
mask,
|
|
7657
|
+
item,
|
|
7658
|
+
src: item.src,
|
|
7659
|
+
annotations: []
|
|
7660
|
+
});
|
|
7661
|
+
setErasing(void 0);
|
|
7662
|
+
setStrokes([]);
|
|
7663
|
+
if (erasing.closeOnSuccess) service.close();
|
|
7664
|
+
} finally {
|
|
7665
|
+
setSending(false);
|
|
7666
|
+
}
|
|
7667
|
+
};
|
|
7324
7668
|
const addAnnotation = (event) => {
|
|
7325
7669
|
if (!annotating || event.target.closest(".dcsiv-annotation")) return;
|
|
7326
7670
|
const bounds = surfaceRef.current?.getBoundingClientRect();
|
|
@@ -7452,7 +7796,8 @@ window.__ModuleLoader__.load({
|
|
|
7452
7796
|
item,
|
|
7453
7797
|
service,
|
|
7454
7798
|
revision: request.revision,
|
|
7455
|
-
t
|
|
7799
|
+
t,
|
|
7800
|
+
onStartMask: startMask
|
|
7456
7801
|
}, `${request.revision}:${index}:${action.id}`))
|
|
7457
7802
|
]
|
|
7458
7803
|
})
|
|
@@ -7466,142 +7811,194 @@ window.__ModuleLoader__.load({
|
|
|
7466
7811
|
}),
|
|
7467
7812
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7468
7813
|
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.
|
|
7814
|
+
children: [
|
|
7815
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("main", {
|
|
7816
|
+
ref: stageRef,
|
|
7817
|
+
className: "dcsiv-stage",
|
|
7818
|
+
"data-dragging": dragging,
|
|
7819
|
+
"data-annotating": annotating || erasing !== void 0,
|
|
7820
|
+
onClick: (event) => {
|
|
7821
|
+
if (event.target === event.currentTarget && !annotating && !erasing && transform.zoom === 1) service.close();
|
|
7822
|
+
},
|
|
7823
|
+
...!annotating && !erasing ? pointerHandlers : {},
|
|
7824
|
+
onDoubleClick: () => {
|
|
7825
|
+
if (transform.zoom === 1) actual();
|
|
7826
|
+
else fit();
|
|
7827
|
+
},
|
|
7828
|
+
children: [
|
|
7829
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7830
|
+
ref: surfaceRef,
|
|
7831
|
+
className: "dcsiv-surface",
|
|
7832
|
+
onClick: addAnnotation,
|
|
7833
|
+
style: { transform: `translate3d(${transform.x}px,${transform.y}px,0) scale(${transform.zoom})` },
|
|
7834
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
7835
|
+
ref: imageRef,
|
|
7836
|
+
className: "dcsiv-image",
|
|
7837
|
+
src: item.src,
|
|
7838
|
+
alt: item.name,
|
|
7839
|
+
draggable: "false",
|
|
7840
|
+
onLoad: () => {
|
|
7841
|
+
measure();
|
|
7842
|
+
}
|
|
7843
|
+
}, `${request.revision}:${item.id}`), erasing ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("canvas", {
|
|
7844
|
+
ref: maskRef,
|
|
7845
|
+
className: "dcsiv-mask",
|
|
7846
|
+
width: imageRef.current?.naturalWidth || 1,
|
|
7847
|
+
height: imageRef.current?.naturalHeight || 1,
|
|
7848
|
+
"aria-label": t("imageEraseHint"),
|
|
7849
|
+
...maskHandlers
|
|
7850
|
+
}) : null]
|
|
7851
|
+
}),
|
|
7852
|
+
annotations.map((annotation, position) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7853
|
+
className: "dcsiv-annotation",
|
|
7854
|
+
"data-x": annotation.x < .38 ? "right" : annotation.x > .62 ? "left" : "center",
|
|
7855
|
+
"data-y": annotation.y < .28 ? "down" : "up",
|
|
7856
|
+
style: annotationPosition(annotation),
|
|
7857
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7858
|
+
type: "button",
|
|
7859
|
+
className: "dcsiv-pin",
|
|
7860
|
+
"data-active": selected === annotation.id,
|
|
7861
|
+
"aria-label": fill$1(t("imageAnnotation"), { value: position + 1 }),
|
|
7862
|
+
onClick: (event) => {
|
|
7863
|
+
event.stopPropagation();
|
|
7864
|
+
const opening = selected !== annotation.id;
|
|
7865
|
+
setSelected(opening ? annotation.id : void 0);
|
|
7866
|
+
if (opening) setFocusNote(annotation.id);
|
|
7867
|
+
},
|
|
7868
|
+
children: position + 1
|
|
7869
|
+
}), selected === annotation.id ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7870
|
+
className: "dcsiv-inline-note",
|
|
7871
|
+
"data-note-id": annotation.id,
|
|
7872
|
+
onClick: (event) => event.stopPropagation(),
|
|
7873
|
+
children: [
|
|
7874
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7875
|
+
className: "dcsiv-inline-index",
|
|
7876
|
+
children: position + 1
|
|
7877
|
+
}),
|
|
7878
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
7879
|
+
value: annotation.note,
|
|
7880
|
+
rows: 1,
|
|
7881
|
+
"aria-label": fill$1(t("imageAnnotation"), { value: position + 1 }),
|
|
7882
|
+
placeholder: t("imageAnnotationPlaceholder"),
|
|
7883
|
+
onChange: (event) => {
|
|
7884
|
+
const note = event.target.value;
|
|
7885
|
+
setAnnotations((current) => current.map((entry) => entry.id === annotation.id ? {
|
|
7886
|
+
...entry,
|
|
7887
|
+
note
|
|
7888
|
+
} : entry));
|
|
7889
|
+
},
|
|
7890
|
+
onKeyDown: (event) => {
|
|
7891
|
+
if (event.key === "Enter" && !event.shiftKey || event.key === "Escape") {
|
|
7892
|
+
event.preventDefault();
|
|
7893
|
+
event.stopPropagation();
|
|
7894
|
+
event.nativeEvent?.stopImmediatePropagation?.();
|
|
7895
|
+
setSelected(void 0);
|
|
7896
|
+
}
|
|
7897
|
+
}
|
|
7898
|
+
}),
|
|
7899
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7900
|
+
type: "button",
|
|
7901
|
+
className: "dcsiv-note-remove",
|
|
7902
|
+
"aria-label": t("imageRemoveAnnotation"),
|
|
7903
|
+
onClick: (event) => {
|
|
7540
7904
|
event.stopPropagation();
|
|
7541
|
-
|
|
7905
|
+
setAnnotations((current) => current.filter((entry) => entry.id !== annotation.id));
|
|
7542
7906
|
setSelected(void 0);
|
|
7543
|
-
}
|
|
7544
|
-
|
|
7545
|
-
|
|
7546
|
-
|
|
7547
|
-
|
|
7548
|
-
|
|
7549
|
-
|
|
7550
|
-
|
|
7551
|
-
|
|
7552
|
-
|
|
7553
|
-
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
|
|
7560
|
-
|
|
7907
|
+
},
|
|
7908
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconCloseOutline16, {})
|
|
7909
|
+
})
|
|
7910
|
+
]
|
|
7911
|
+
}) : null]
|
|
7912
|
+
}, annotation.id)),
|
|
7913
|
+
showCounter ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
7914
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7915
|
+
type: "button",
|
|
7916
|
+
className: "dcsiv-button dcsiv-icon-only dcsiv-nav dcsiv-prev",
|
|
7917
|
+
"aria-label": t("imagePrevious"),
|
|
7918
|
+
onClick: (event) => {
|
|
7919
|
+
event.stopPropagation();
|
|
7920
|
+
setIndex((value) => (value - 1 + request.items.length) % request.items.length);
|
|
7921
|
+
},
|
|
7922
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconChevronLeftOutline14, {})
|
|
7923
|
+
}),
|
|
7924
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7925
|
+
type: "button",
|
|
7926
|
+
className: "dcsiv-button dcsiv-icon-only dcsiv-nav dcsiv-next",
|
|
7927
|
+
"aria-label": t("imageNext"),
|
|
7928
|
+
onClick: (event) => {
|
|
7929
|
+
event.stopPropagation();
|
|
7930
|
+
setIndex((value) => (value + 1) % request.items.length);
|
|
7931
|
+
},
|
|
7932
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconChevronRightOutline14, {})
|
|
7933
|
+
}),
|
|
7934
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
7935
|
+
className: "dcsiv-counter",
|
|
7936
|
+
children: [
|
|
7937
|
+
index + 1,
|
|
7938
|
+
" / ",
|
|
7939
|
+
request.items.length
|
|
7940
|
+
]
|
|
7941
|
+
})
|
|
7942
|
+
] }) : annotating ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7943
|
+
className: "dcsiv-hint",
|
|
7944
|
+
children: t("imageAnnotateHint")
|
|
7945
|
+
}) : transform.zoom === 1 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7946
|
+
className: "dcsiv-hint",
|
|
7947
|
+
children: t("imageZoomHint")
|
|
7948
|
+
}) : null
|
|
7949
|
+
]
|
|
7950
|
+
}),
|
|
7951
|
+
erasing ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7952
|
+
className: "dcsiv-erase-bar",
|
|
7953
|
+
role: "toolbar",
|
|
7954
|
+
"aria-label": t("imageErase"),
|
|
7955
|
+
children: [
|
|
7956
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("imageEraseHint") }),
|
|
7957
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [t("imageBrushSize"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
7958
|
+
type: "range",
|
|
7959
|
+
min: "0.01",
|
|
7960
|
+
max: "0.15",
|
|
7961
|
+
step: "0.01",
|
|
7962
|
+
value: brush,
|
|
7963
|
+
onChange: (event) => setBrush(Number(event.target.value))
|
|
7964
|
+
})] }),
|
|
7561
7965
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7562
7966
|
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, {})
|
|
7967
|
+
className: "dcsiv-button",
|
|
7968
|
+
disabled: strokes.length === 0 || sending,
|
|
7969
|
+
onClick: () => setStrokes((current) => current.slice(0, -1)),
|
|
7970
|
+
children: t("imageUndo")
|
|
7570
7971
|
}),
|
|
7571
7972
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7572
7973
|
type: "button",
|
|
7573
|
-
className: "dcsiv-button
|
|
7574
|
-
|
|
7575
|
-
onClick: (
|
|
7576
|
-
|
|
7577
|
-
|
|
7974
|
+
className: "dcsiv-button",
|
|
7975
|
+
disabled: sending,
|
|
7976
|
+
onClick: () => {
|
|
7977
|
+
setErasing(void 0);
|
|
7978
|
+
setStrokes([]);
|
|
7578
7979
|
},
|
|
7579
|
-
children:
|
|
7980
|
+
children: t("cancel")
|
|
7580
7981
|
}),
|
|
7581
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
7582
|
-
|
|
7583
|
-
|
|
7584
|
-
|
|
7585
|
-
|
|
7586
|
-
|
|
7587
|
-
|
|
7982
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7983
|
+
type: "button",
|
|
7984
|
+
className: "dcsiv-button dcsiv-primary",
|
|
7985
|
+
disabled: strokes.length === 0 || sending,
|
|
7986
|
+
onClick: () => {
|
|
7987
|
+
sendMask();
|
|
7988
|
+
},
|
|
7989
|
+
children: sending ? t("imageEditPreparing") : t("imageSend")
|
|
7588
7990
|
})
|
|
7589
|
-
]
|
|
7590
|
-
|
|
7591
|
-
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
|
|
7597
|
-
|
|
7598
|
-
|
|
7599
|
-
|
|
7600
|
-
onClick: () => {
|
|
7601
|
-
copyNotes();
|
|
7602
|
-
},
|
|
7603
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconCopyOutline16, {}), copied ? t("imageCopied") : t("imageCopyNotes")]
|
|
7604
|
-
}) : null]
|
|
7991
|
+
]
|
|
7992
|
+
}) : null,
|
|
7993
|
+
annotations.some((annotation) => annotation.note.trim() !== "") ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
7994
|
+
type: "button",
|
|
7995
|
+
className: "dcsiv-copy-notes",
|
|
7996
|
+
onClick: () => {
|
|
7997
|
+
copyNotes();
|
|
7998
|
+
},
|
|
7999
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconCopyOutline16, {}), copied ? t("imageCopied") : t("imageCopyNotes")]
|
|
8000
|
+
}) : null
|
|
8001
|
+
]
|
|
7605
8002
|
})
|
|
7606
8003
|
]
|
|
7607
8004
|
});
|
|
@@ -7622,6 +8019,12 @@ window.__ModuleLoader__.load({
|
|
|
7622
8019
|
pendingLabel: typeof action.pendingLabel === "string" && action.pendingLabel !== "" ? action.pendingLabel : action.label,
|
|
7623
8020
|
errorLabel: typeof action.errorLabel === "string" && action.errorLabel !== "" ? action.errorLabel : action.label,
|
|
7624
8021
|
closeOnSuccess: action.closeOnSuccess === true,
|
|
8022
|
+
kind: [
|
|
8023
|
+
"tool",
|
|
8024
|
+
"mask",
|
|
8025
|
+
"choice"
|
|
8026
|
+
].includes(action.kind) ? action.kind : "edit",
|
|
8027
|
+
options: Array.isArray(action.options) ? action.options.filter((option) => typeof option?.value === "string" && typeof option?.label === "string") : [],
|
|
7625
8028
|
onInvoke: action.onInvoke
|
|
7626
8029
|
}];
|
|
7627
8030
|
}) : [];
|
|
@@ -8549,7 +8952,7 @@ window.__ModuleLoader__.load({
|
|
|
8549
8952
|
}
|
|
8550
8953
|
//#endregion
|
|
8551
8954
|
//#region src/version.js
|
|
8552
|
-
const PACKAGE_VERSION = "2.5.
|
|
8955
|
+
const PACKAGE_VERSION = "2.5.8";
|
|
8553
8956
|
//#endregion
|
|
8554
8957
|
//#region src/client-recovery.js
|
|
8555
8958
|
async function recoveryCall(rpc, endpoint, payload = {}, timeoutMs = 1e4) {
|
|
@@ -12161,7 +12564,8 @@ window.__ModuleLoader__.load({
|
|
|
12161
12564
|
imageViewer.close();
|
|
12162
12565
|
liveOpen("sketch", document.activeElement, new File([blob], name || "image.png", { type: blob.type || "image/png" }));
|
|
12163
12566
|
};
|
|
12164
|
-
const attachForEdit = (sessionId) => async (src, filename, draft, annotations = [], referenceName, sourceInDraft = false) => {
|
|
12567
|
+
const attachForEdit = (sessionId) => async (src, filename, draft, annotations = [], referenceName, sourceInDraft = false, extraFiles) => {
|
|
12568
|
+
const tool = Array.isArray(extraFiles);
|
|
12165
12569
|
if (!preference.getSnapshot().imageEditing) throw new Error("Image editing is disabled");
|
|
12166
12570
|
return withComposerSession(sessions, sessionId, async (actx) => {
|
|
12167
12571
|
if (conversation.input?.for === void 0) throw new Error("This DSH version does not provide the image composer bridge");
|
|
@@ -12173,14 +12577,15 @@ window.__ModuleLoader__.load({
|
|
|
12173
12577
|
const reference = await createAnnotatedImageReference(blob, annotations);
|
|
12174
12578
|
files.push(new File([reference], referenceName, { type: "image/png" }));
|
|
12175
12579
|
}
|
|
12580
|
+
if (tool) files.push(...extraFiles);
|
|
12176
12581
|
lifetime.signal.throwIfAborted();
|
|
12177
12582
|
const input = conversation.input.for(actx);
|
|
12178
12583
|
if (!preference.getSnapshot().imageEditing) throw new Error("Image editing is disabled");
|
|
12179
12584
|
if (files.length) attachImageFiles(conversation, input, files, sessionId);
|
|
12180
12585
|
openComposerSession(sessions, ctx.get("uiWorkspace"), sessionId);
|
|
12181
|
-
if (sourceInDraft && !annotations.length) return;
|
|
12586
|
+
if (sourceInDraft && !annotations.length && !tool) return;
|
|
12182
12587
|
if (!input.state.getSnapshot().draft.trim()) input.setDraft(draft);
|
|
12183
|
-
else if (annotations.length) if (!input.state.getSnapshot().occurrences?.length) appendImagePrompt(input, draft);
|
|
12588
|
+
else if (annotations.length || tool) if (!input.state.getSnapshot().occurrences?.length) appendImagePrompt(input, draft);
|
|
12184
12589
|
else input.notify("info", draft);
|
|
12185
12590
|
});
|
|
12186
12591
|
};
|
package/lib/index.js
CHANGED
|
@@ -2049,7 +2049,7 @@ function inheritedOriginalImageRef(session, assetId) {
|
|
|
2049
2049
|
}
|
|
2050
2050
|
//#endregion
|
|
2051
2051
|
//#region src/version.js
|
|
2052
|
-
const PACKAGE_VERSION = "2.5.
|
|
2052
|
+
const PACKAGE_VERSION = "2.5.8";
|
|
2053
2053
|
const USER_AGENT = `dsh-codex-subscription/${PACKAGE_VERSION}`;
|
|
2054
2054
|
//#endregion
|
|
2055
2055
|
//#region src/codex-images.js
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-codex-subscription",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.8",
|
|
4
4
|
"description": "Use ChatGPT and Codex subscriptions in DeepSeek Harness with OAuth, quota, safe resets, web search, images, and Fast mode",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|