dsh-files-native 0.1.2 → 0.1.3
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/lib/client.js +64 -33
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -125,8 +125,8 @@ function subscribe(fn) {
|
|
|
125
125
|
listeners.delete(fn);
|
|
126
126
|
};
|
|
127
127
|
}
|
|
128
|
-
function
|
|
129
|
-
return items.
|
|
128
|
+
function pendingFor(sessionId) {
|
|
129
|
+
return items.filter((item) => item.sessionId === sessionId);
|
|
130
130
|
}
|
|
131
131
|
function add(sessionId, item) {
|
|
132
132
|
items.push({ ...item, sessionId: item.sessionId || sessionId });
|
|
@@ -344,7 +344,7 @@ function uid() {
|
|
|
344
344
|
}
|
|
345
345
|
async function uploadFile(sessionId, file) {
|
|
346
346
|
const id = uid();
|
|
347
|
-
const
|
|
347
|
+
const pending = {
|
|
348
348
|
id,
|
|
349
349
|
sessionId,
|
|
350
350
|
name: file.name,
|
|
@@ -353,14 +353,14 @@ async function uploadFile(sessionId, file) {
|
|
|
353
353
|
mediaType: file.type || "application/octet-stream",
|
|
354
354
|
status: "uploading"
|
|
355
355
|
};
|
|
356
|
-
add(sessionId,
|
|
356
|
+
add(sessionId, pending);
|
|
357
357
|
const url = `/plugins/file-native/upload?sessionId=${encodeURIComponent(sessionId)}&name=${encodeURIComponent(file.name)}&type=${encodeURIComponent(file.type)}`;
|
|
358
358
|
try {
|
|
359
359
|
const res = await fetch(url, { method: "POST", body: file });
|
|
360
360
|
const body = await res.json();
|
|
361
361
|
if (!res.ok || !body.ok || body.file === void 0) {
|
|
362
362
|
patch(sessionId, id, { status: "error", error: body.error ?? "\u4E0A\u4F20\u5931\u8D25" });
|
|
363
|
-
return { ...
|
|
363
|
+
return { ...pending, status: "error", error: body.error ?? "\u4E0A\u4F20\u5931\u8D25" };
|
|
364
364
|
}
|
|
365
365
|
patch(sessionId, id, {
|
|
366
366
|
status: "done",
|
|
@@ -369,10 +369,10 @@ async function uploadFile(sessionId, file) {
|
|
|
369
369
|
size: body.file.size,
|
|
370
370
|
mediaType: body.file.mediaType
|
|
371
371
|
});
|
|
372
|
-
return { ...
|
|
372
|
+
return { ...pending, ...body.file, status: "done" };
|
|
373
373
|
} catch {
|
|
374
374
|
patch(sessionId, id, { status: "error", error: "\u7F51\u7EDC\u9519\u8BEF" });
|
|
375
|
-
return { ...
|
|
375
|
+
return { ...pending, status: "error", error: "\u7F51\u7EDC\u9519\u8BEF" };
|
|
376
376
|
}
|
|
377
377
|
}
|
|
378
378
|
function intake(sessionId, files, onAddImages) {
|
|
@@ -436,9 +436,10 @@ function ImageTile({ item, onRemove, onOpen }) {
|
|
|
436
436
|
}
|
|
437
437
|
function FileTile({ item, sessionId }) {
|
|
438
438
|
const remove2 = () => {
|
|
439
|
-
|
|
439
|
+
const sid = item.sessionId || sessionId;
|
|
440
|
+
remove(sid, item.id);
|
|
440
441
|
if (item.relPath) {
|
|
441
|
-
void fetch(`/plugins/file-native/remove?sessionId=${encodeURIComponent(
|
|
442
|
+
void fetch(`/plugins/file-native/remove?sessionId=${encodeURIComponent(sid)}&path=${encodeURIComponent(item.relPath)}`, { method: "POST" });
|
|
442
443
|
}
|
|
443
444
|
};
|
|
444
445
|
const meta = item.status === "uploading" ? "\u4E0A\u4F20\u4E2D\u2026" : item.status === "error" ? item.error ?? "\u5931\u8D25" : formatSize(item.size);
|
|
@@ -462,7 +463,7 @@ function FileTile({ item, sessionId }) {
|
|
|
462
463
|
function FileRail(props) {
|
|
463
464
|
ensureStyles();
|
|
464
465
|
const sessionId = String(props.sessionId ?? "");
|
|
465
|
-
const [files, setFiles] = (0, import_react2.useState)(() =>
|
|
466
|
+
const [files, setFiles] = (0, import_react2.useState)(() => pendingFor(sessionId));
|
|
466
467
|
const [, setVersion] = (0, import_react2.useState)(() => version());
|
|
467
468
|
const [preview, setPreview] = (0, import_react2.useState)(null);
|
|
468
469
|
const [edges, setEdges] = (0, import_react2.useState)({ left: false, right: false });
|
|
@@ -470,12 +471,12 @@ function FileRail(props) {
|
|
|
470
471
|
const countRef = (0, import_react2.useRef)(0);
|
|
471
472
|
(0, import_react2.useEffect)(() => {
|
|
472
473
|
const sync = () => {
|
|
473
|
-
setFiles(
|
|
474
|
+
setFiles(pendingFor(sessionId));
|
|
474
475
|
setVersion(version());
|
|
475
476
|
};
|
|
476
477
|
sync();
|
|
477
478
|
return subscribe(sync);
|
|
478
|
-
}, []);
|
|
479
|
+
}, [sessionId]);
|
|
479
480
|
const updateEdges = () => {
|
|
480
481
|
const el = rowRef.current;
|
|
481
482
|
if (el === null) return;
|
|
@@ -483,7 +484,8 @@ function FileRail(props) {
|
|
|
483
484
|
const right = el.scrollLeft < el.scrollWidth - el.clientWidth - 1;
|
|
484
485
|
setEdges((prev) => prev.left === left && prev.right === right ? prev : { left, right });
|
|
485
486
|
};
|
|
486
|
-
const
|
|
487
|
+
const visibleFiles = files.filter((item) => item.sessionId === sessionId);
|
|
488
|
+
const itemCount = props.attachments.length + visibleFiles.length;
|
|
487
489
|
(0, import_react2.useLayoutEffect)(() => {
|
|
488
490
|
const grew = countRef.current !== 0 && itemCount > countRef.current;
|
|
489
491
|
countRef.current = itemCount;
|
|
@@ -519,7 +521,7 @@ function FileRail(props) {
|
|
|
519
521
|
el.scrollBy({ left: direction * Math.max(el.clientWidth - 64, 200), behavior: "smooth" });
|
|
520
522
|
};
|
|
521
523
|
const hasImages = props.attachments.length > 0;
|
|
522
|
-
const hasFiles =
|
|
524
|
+
const hasFiles = visibleFiles.length > 0;
|
|
523
525
|
if (!hasImages && !hasFiles) return null;
|
|
524
526
|
return (0, import_react2.createElement)(
|
|
525
527
|
"div",
|
|
@@ -537,7 +539,7 @@ function FileRail(props) {
|
|
|
537
539
|
onRemove: () => props.onRemoveImage(item.id),
|
|
538
540
|
onOpen: () => setPreview(item)
|
|
539
541
|
})),
|
|
540
|
-
...
|
|
542
|
+
...visibleFiles.map((item) => (0, import_react2.createElement)(FileTile, { key: item.id, item, sessionId }))
|
|
541
543
|
),
|
|
542
544
|
edges.right ? (0, import_react2.createElement)("button", { type: "button", className: "fr-arrow fr-arrow-right", "aria-label": "\u5411\u53F3", onClick: () => page(1) }, (0, import_react2.createElement)(IconChevronRight)) : null
|
|
543
545
|
),
|
|
@@ -581,7 +583,9 @@ var import_react_dom2 = require("react-dom");
|
|
|
581
583
|
var owner = null;
|
|
582
584
|
var lastSessionId = "";
|
|
583
585
|
var dragDepth = 0;
|
|
586
|
+
var generation2 = 0;
|
|
584
587
|
var listeners2 = /* @__PURE__ */ new Set();
|
|
588
|
+
var queuedImages = /* @__PURE__ */ new Map();
|
|
585
589
|
function emit2() {
|
|
586
590
|
for (const fn of [...listeners2]) fn();
|
|
587
591
|
}
|
|
@@ -591,14 +595,42 @@ function subscribeLive(fn) {
|
|
|
591
595
|
listeners2.delete(fn);
|
|
592
596
|
};
|
|
593
597
|
}
|
|
598
|
+
function flushQueuedImages() {
|
|
599
|
+
if (!owner?.onAddImages) return;
|
|
600
|
+
const sid = owner.sessionId;
|
|
601
|
+
const files = (queuedImages.get(sid) ?? []).concat(sid ? queuedImages.get("") ?? [] : []);
|
|
602
|
+
queuedImages.delete(sid);
|
|
603
|
+
if (sid) queuedImages.delete("");
|
|
604
|
+
if (files.length === 0) return;
|
|
605
|
+
owner.onAddImages(files);
|
|
606
|
+
}
|
|
594
607
|
function setLiveOwner(next) {
|
|
608
|
+
generation2 += 1;
|
|
595
609
|
owner = next;
|
|
596
610
|
if (next?.sessionId) lastSessionId = next.sessionId;
|
|
597
611
|
emit2();
|
|
612
|
+
if (next) flushQueuedImages();
|
|
613
|
+
return generation2;
|
|
614
|
+
}
|
|
615
|
+
function clearLiveOwner(token) {
|
|
616
|
+
if (token !== generation2) return;
|
|
617
|
+
owner = null;
|
|
618
|
+
emit2();
|
|
598
619
|
}
|
|
599
620
|
function getLiveOwner() {
|
|
600
621
|
return owner;
|
|
601
622
|
}
|
|
623
|
+
function addImages(sessionId, files) {
|
|
624
|
+
if (files.length === 0) return;
|
|
625
|
+
const sid = sessionId || currentSessionId();
|
|
626
|
+
if (owner?.onAddImages && (!owner.sessionId || owner.sessionId === sid)) {
|
|
627
|
+
owner.onAddImages(files);
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
const key = sid || owner?.sessionId || lastSessionId;
|
|
631
|
+
const prev = queuedImages.get(key) ?? [];
|
|
632
|
+
queuedImages.set(key, prev.concat([...files]));
|
|
633
|
+
}
|
|
602
634
|
function setDragDepth(depth) {
|
|
603
635
|
const next = Math.max(0, depth);
|
|
604
636
|
if (next === dragDepth) return;
|
|
@@ -696,11 +728,9 @@ function PaperclipButton(props) {
|
|
|
696
728
|
const onChange = (event) => {
|
|
697
729
|
const files = Array.from(event.currentTarget.files ?? []);
|
|
698
730
|
event.currentTarget.value = "";
|
|
699
|
-
const
|
|
700
|
-
const sid = String(props.sessionId || live?.sessionId || currentSessionId());
|
|
731
|
+
const sid = String(props.sessionId || currentSessionId());
|
|
701
732
|
if (files.length === 0) return;
|
|
702
|
-
intakeFiles(sid, files,
|
|
703
|
-
}));
|
|
733
|
+
intakeFiles(sid, files, (images) => addImages(sid, images));
|
|
704
734
|
};
|
|
705
735
|
return (0, import_react5.createElement)(
|
|
706
736
|
"span",
|
|
@@ -1035,15 +1065,19 @@ var inject = ["slots"];
|
|
|
1035
1065
|
function RailSlot(props) {
|
|
1036
1066
|
ensureStyles();
|
|
1037
1067
|
const sessionId = resolveSessionId(props);
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1068
|
+
rememberSessionId(sessionId);
|
|
1069
|
+
const tokenRef = (0, import_react8.useRef)(0);
|
|
1070
|
+
(0, import_react8.useLayoutEffect)(() => {
|
|
1071
|
+
tokenRef.current = setLiveOwner({
|
|
1072
|
+
attachments: props.attachments,
|
|
1073
|
+
canAcceptDrop: props.canAcceptDrop,
|
|
1074
|
+
onAddImages: props.onAddImages,
|
|
1075
|
+
onRemoveImage: props.onRemoveImage,
|
|
1076
|
+
sessionId,
|
|
1077
|
+
dropLimits: props.dropLimits
|
|
1078
|
+
});
|
|
1079
|
+
}, [sessionId, props.attachments, props.canAcceptDrop, props.onAddImages, props.onRemoveImage, props.dropLimits]);
|
|
1080
|
+
(0, import_react8.useLayoutEffect)(() => () => clearLiveOwner(tokenRef.current), []);
|
|
1047
1081
|
return null;
|
|
1048
1082
|
}
|
|
1049
1083
|
function PickerSlot(props) {
|
|
@@ -1082,11 +1116,8 @@ function installLiveIntercept() {
|
|
|
1082
1116
|
canAccept: () => true,
|
|
1083
1117
|
onDepth: (depth) => setDragDepth(depth),
|
|
1084
1118
|
onFiles: (files) => {
|
|
1085
|
-
const
|
|
1086
|
-
|
|
1087
|
-
const addImages = live?.onAddImages ?? (() => {
|
|
1088
|
-
});
|
|
1089
|
-
intakeFiles(sessionId, files, addImages);
|
|
1119
|
+
const sessionId = currentSessionId();
|
|
1120
|
+
intakeFiles(sessionId, files, (images) => addImages(sessionId, images));
|
|
1090
1121
|
}
|
|
1091
1122
|
});
|
|
1092
1123
|
}
|