@gallop.software/studio 1.5.4 → 1.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{StudioUI-JNACMWLN.js → StudioUI-2PPNO4QC.js} +162 -24
- package/dist/StudioUI-2PPNO4QC.js.map +1 -0
- package/dist/{StudioUI-NLB3VZAZ.mjs → StudioUI-PERXOBGO.mjs} +153 -15
- package/dist/StudioUI-PERXOBGO.mjs.map +1 -0
- package/dist/handlers/index.js +99 -0
- package/dist/handlers/index.js.map +1 -1
- package/dist/handlers/index.mjs +99 -0
- package/dist/handlers/index.mjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/StudioUI-JNACMWLN.js.map +0 -1
- package/dist/StudioUI-NLB3VZAZ.mjs.map +0 -1
|
@@ -1752,6 +1752,8 @@ function StudioToolbar() {
|
|
|
1752
1752
|
const [syncImageCount, setSyncImageCount] = useState4(0);
|
|
1753
1753
|
const [syncHasRemote, setSyncHasRemote] = useState4(false);
|
|
1754
1754
|
const [syncHasLocal, setSyncHasLocal] = useState4(false);
|
|
1755
|
+
const [showDownloadConfirm, setShowDownloadConfirm] = useState4(false);
|
|
1756
|
+
const [downloadImageCount, setDownloadImageCount] = useState4(0);
|
|
1755
1757
|
const [showProgress, setShowProgress] = useState4(false);
|
|
1756
1758
|
const [progressTitle, setProgressTitle] = useState4("Processing Images");
|
|
1757
1759
|
const [progressState, setProgressState] = useState4({
|
|
@@ -2231,6 +2233,106 @@ function StudioToolbar() {
|
|
|
2231
2233
|
});
|
|
2232
2234
|
}
|
|
2233
2235
|
}, [selectedItems, clearSelection, triggerRefresh]);
|
|
2236
|
+
const handleDownloadClick = useCallback2(async () => {
|
|
2237
|
+
if (selectedItems.size === 0) return;
|
|
2238
|
+
const selectedPaths2 = Array.from(selectedItems);
|
|
2239
|
+
const imageExtensions = ["jpg", "jpeg", "png", "gif", "webp", "svg", "ico", "bmp", "tiff", "tif"];
|
|
2240
|
+
const selectedImagePaths = selectedPaths2.filter((p) => {
|
|
2241
|
+
const ext = p.split(".").pop()?.toLowerCase() || "";
|
|
2242
|
+
return imageExtensions.includes(ext);
|
|
2243
|
+
});
|
|
2244
|
+
if (selectedImagePaths.length === 0) {
|
|
2245
|
+
setAlertMessage({
|
|
2246
|
+
title: "No Images Found",
|
|
2247
|
+
message: "No images found in the selected items."
|
|
2248
|
+
});
|
|
2249
|
+
return;
|
|
2250
|
+
}
|
|
2251
|
+
setDownloadImageCount(selectedImagePaths.length);
|
|
2252
|
+
setShowDownloadConfirm(true);
|
|
2253
|
+
}, [selectedItems]);
|
|
2254
|
+
const handleDownloadConfirm = useCallback2(async () => {
|
|
2255
|
+
setShowDownloadConfirm(false);
|
|
2256
|
+
const selectedPaths2 = Array.from(selectedItems);
|
|
2257
|
+
const imageExtensions = ["jpg", "jpeg", "png", "gif", "webp", "svg", "ico", "bmp", "tiff", "tif"];
|
|
2258
|
+
const selectedImagePaths = selectedPaths2.filter((p) => {
|
|
2259
|
+
const ext = p.split(".").pop()?.toLowerCase() || "";
|
|
2260
|
+
return imageExtensions.includes(ext);
|
|
2261
|
+
});
|
|
2262
|
+
const imageKeys = selectedImagePaths.map((p) => "/" + p.replace(/^public\//, ""));
|
|
2263
|
+
setProgressTitle("Downloading from CDN");
|
|
2264
|
+
setShowProgress(true);
|
|
2265
|
+
setProgressState({
|
|
2266
|
+
current: 0,
|
|
2267
|
+
total: imageKeys.length,
|
|
2268
|
+
percent: 0,
|
|
2269
|
+
status: "processing"
|
|
2270
|
+
});
|
|
2271
|
+
try {
|
|
2272
|
+
const response = await fetch("/api/studio/download-stream", {
|
|
2273
|
+
method: "POST",
|
|
2274
|
+
headers: { "Content-Type": "application/json" },
|
|
2275
|
+
body: JSON.stringify({ imageKeys })
|
|
2276
|
+
});
|
|
2277
|
+
if (!response.ok || !response.body) {
|
|
2278
|
+
throw new Error("Download request failed");
|
|
2279
|
+
}
|
|
2280
|
+
const reader = response.body.getReader();
|
|
2281
|
+
const decoder = new TextDecoder();
|
|
2282
|
+
let buffer = "";
|
|
2283
|
+
while (true) {
|
|
2284
|
+
const { done, value } = await reader.read();
|
|
2285
|
+
if (done) break;
|
|
2286
|
+
buffer += decoder.decode(value, { stream: true });
|
|
2287
|
+
const lines = buffer.split("\n");
|
|
2288
|
+
buffer = lines.pop() || "";
|
|
2289
|
+
for (const line of lines) {
|
|
2290
|
+
if (line.startsWith("data: ")) {
|
|
2291
|
+
try {
|
|
2292
|
+
const data = JSON.parse(line.slice(6));
|
|
2293
|
+
if (data.type === "progress") {
|
|
2294
|
+
setProgressState({
|
|
2295
|
+
current: data.current,
|
|
2296
|
+
total: data.total,
|
|
2297
|
+
percent: Math.round(data.current / data.total * 100),
|
|
2298
|
+
status: "processing",
|
|
2299
|
+
message: data.message
|
|
2300
|
+
});
|
|
2301
|
+
} else if (data.type === "complete") {
|
|
2302
|
+
setProgressState({
|
|
2303
|
+
current: data.total || imageKeys.length,
|
|
2304
|
+
total: data.total || imageKeys.length,
|
|
2305
|
+
percent: 100,
|
|
2306
|
+
status: "complete",
|
|
2307
|
+
message: data.message
|
|
2308
|
+
});
|
|
2309
|
+
} else if (data.type === "error") {
|
|
2310
|
+
setProgressState({
|
|
2311
|
+
current: 0,
|
|
2312
|
+
total: 0,
|
|
2313
|
+
percent: 0,
|
|
2314
|
+
status: "error",
|
|
2315
|
+
message: data.message
|
|
2316
|
+
});
|
|
2317
|
+
}
|
|
2318
|
+
} catch {
|
|
2319
|
+
}
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
clearSelection();
|
|
2324
|
+
triggerRefresh();
|
|
2325
|
+
} catch (error) {
|
|
2326
|
+
console.error("Download error:", error);
|
|
2327
|
+
setProgressState({
|
|
2328
|
+
current: 0,
|
|
2329
|
+
total: 0,
|
|
2330
|
+
percent: 0,
|
|
2331
|
+
status: "error",
|
|
2332
|
+
message: "Failed to download from CDN."
|
|
2333
|
+
});
|
|
2334
|
+
}
|
|
2335
|
+
}, [selectedItems, clearSelection, triggerRefresh]);
|
|
2234
2336
|
const handleCreateFolder = useCallback2(async (folderName) => {
|
|
2235
2337
|
setShowNewFolderModal(false);
|
|
2236
2338
|
try {
|
|
@@ -2349,6 +2451,10 @@ function StudioToolbar() {
|
|
|
2349
2451
|
const item = fileItems.find((f) => f.path === path);
|
|
2350
2452
|
return item && item.cdnPushed && !item.isRemote;
|
|
2351
2453
|
});
|
|
2454
|
+
const allR2Selection = hasSelection && Array.from(selectedItems).every((path) => {
|
|
2455
|
+
const item = fileItems.find((f) => f.path === path);
|
|
2456
|
+
return item && item.type === "file" && item.cdnPushed && !item.isRemote;
|
|
2457
|
+
});
|
|
2352
2458
|
const selectedPaths = Array.from(selectedItems);
|
|
2353
2459
|
const singleFolderSelected = selectedPaths.length === 1 && !selectedPaths[0].includes(".");
|
|
2354
2460
|
const selectedFolderPath = singleFolderSelected ? selectedPaths[0] : null;
|
|
@@ -2395,6 +2501,16 @@ function StudioToolbar() {
|
|
|
2395
2501
|
onCancel: () => setShowSyncConfirm(false)
|
|
2396
2502
|
}
|
|
2397
2503
|
),
|
|
2504
|
+
showDownloadConfirm && /* @__PURE__ */ jsx5(
|
|
2505
|
+
ConfirmModal,
|
|
2506
|
+
{
|
|
2507
|
+
title: "Download from CDN",
|
|
2508
|
+
message: `Download ${downloadImageCount} image${downloadImageCount !== 1 ? "s" : ""} from Cloudflare R2 to local storage? Images will be removed from the CDN.`,
|
|
2509
|
+
confirmLabel: "Download",
|
|
2510
|
+
onConfirm: handleDownloadConfirm,
|
|
2511
|
+
onCancel: () => setShowDownloadConfirm(false)
|
|
2512
|
+
}
|
|
2513
|
+
),
|
|
2398
2514
|
showProgress && /* @__PURE__ */ jsx5(
|
|
2399
2515
|
ProgressModal,
|
|
2400
2516
|
{
|
|
@@ -2550,7 +2666,18 @@ function StudioToolbar() {
|
|
|
2550
2666
|
]
|
|
2551
2667
|
}
|
|
2552
2668
|
),
|
|
2553
|
-
/* @__PURE__ */ jsxs5(
|
|
2669
|
+
allR2Selection ? /* @__PURE__ */ jsxs5(
|
|
2670
|
+
"button",
|
|
2671
|
+
{
|
|
2672
|
+
css: styles5.btn,
|
|
2673
|
+
onClick: handleDownloadClick,
|
|
2674
|
+
disabled: !hasSelection,
|
|
2675
|
+
children: [
|
|
2676
|
+
/* @__PURE__ */ jsx5(CloudDownloadIcon, {}),
|
|
2677
|
+
"Download"
|
|
2678
|
+
]
|
|
2679
|
+
}
|
|
2680
|
+
) : /* @__PURE__ */ jsxs5(
|
|
2554
2681
|
"button",
|
|
2555
2682
|
{
|
|
2556
2683
|
css: styles5.btn,
|
|
@@ -2649,6 +2776,9 @@ function MoveIcon() {
|
|
|
2649
2776
|
function CloudIcon() {
|
|
2650
2777
|
return /* @__PURE__ */ jsx5("svg", { css: styles5.icon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" }) });
|
|
2651
2778
|
}
|
|
2779
|
+
function CloudDownloadIcon() {
|
|
2780
|
+
return /* @__PURE__ */ jsx5("svg", { css: styles5.icon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M9 19l3 3m0 0l3-3m-3 3V10" }) });
|
|
2781
|
+
}
|
|
2652
2782
|
function GridIcon() {
|
|
2653
2783
|
return /* @__PURE__ */ jsx5("svg", { css: styles5.icon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z" }) });
|
|
2654
2784
|
}
|
|
@@ -3163,11 +3293,18 @@ var styles6 = {
|
|
|
3163
3293
|
storedLabel: css6`
|
|
3164
3294
|
display: flex;
|
|
3165
3295
|
align-items: center;
|
|
3166
|
-
gap: 4px;
|
|
3167
|
-
font-size: ${fontSize.xs};
|
|
3168
|
-
color: #f59e0b;
|
|
3169
3296
|
margin: 2px 0 0 0;
|
|
3170
3297
|
`,
|
|
3298
|
+
storedIconCloud: css6`
|
|
3299
|
+
width: 16px;
|
|
3300
|
+
height: 16px;
|
|
3301
|
+
color: #f59e0b;
|
|
3302
|
+
`,
|
|
3303
|
+
storedIconRemote: css6`
|
|
3304
|
+
width: 16px;
|
|
3305
|
+
height: 16px;
|
|
3306
|
+
color: #ef4444;
|
|
3307
|
+
`,
|
|
3171
3308
|
globeIcon: css6`
|
|
3172
3309
|
width: 18px;
|
|
3173
3310
|
height: 18px;
|
|
@@ -3454,10 +3591,7 @@ function GridItem({ item, isSelected, onClick, onOpen, onGenerateThumbnail }) {
|
|
|
3454
3591
|
item.fileCount,
|
|
3455
3592
|
" files"
|
|
3456
3593
|
] })
|
|
3457
|
-
] }) : item.cdnPushed ? /* @__PURE__ */
|
|
3458
|
-
/* @__PURE__ */ jsx6("svg", { css: item.isRemote ? styles6.folderStatIconRemote : styles6.folderStatIconCloud, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: item.isRemote ? /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" }) : /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z" }) }),
|
|
3459
|
-
"stored"
|
|
3460
|
-
] }) : item.size !== void 0 && /* @__PURE__ */ jsx6("p", { css: styles6.size, children: formatFileSize(item.size) })
|
|
3594
|
+
] }) : item.cdnPushed ? /* @__PURE__ */ jsx6("p", { css: styles6.storedLabel, children: /* @__PURE__ */ jsx6("svg", { css: item.isRemote ? styles6.storedIconRemote : styles6.storedIconCloud, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: item.isRemote ? /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" }) : /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z" }) }) }) : item.size !== void 0 && /* @__PURE__ */ jsx6("p", { css: styles6.size, children: formatFileSize(item.size) })
|
|
3461
3595
|
] }) }) })
|
|
3462
3596
|
]
|
|
3463
3597
|
}
|
|
@@ -3697,10 +3831,17 @@ var styles7 = {
|
|
|
3697
3831
|
storedLabel: css7`
|
|
3698
3832
|
display: flex;
|
|
3699
3833
|
align-items: center;
|
|
3700
|
-
|
|
3701
|
-
|
|
3834
|
+
`,
|
|
3835
|
+
storedIconCloud: css7`
|
|
3836
|
+
width: 16px;
|
|
3837
|
+
height: 16px;
|
|
3702
3838
|
color: #f59e0b;
|
|
3703
3839
|
`,
|
|
3840
|
+
storedIconRemote: css7`
|
|
3841
|
+
width: 16px;
|
|
3842
|
+
height: 16px;
|
|
3843
|
+
color: #ef4444;
|
|
3844
|
+
`,
|
|
3704
3845
|
globeIcon: css7`
|
|
3705
3846
|
width: 16px;
|
|
3706
3847
|
height: 16px;
|
|
@@ -4057,10 +4198,7 @@ function ListRow({ item, isSelected, onClick, onOpen, onGenerateThumbnail }) {
|
|
|
4057
4198
|
" files"
|
|
4058
4199
|
] }),
|
|
4059
4200
|
!item.localCount && !item.cloudCount && !item.remoteCount && item.fileCount === void 0 && "--"
|
|
4060
|
-
] }) : item.cdnPushed ? /* @__PURE__ */
|
|
4061
|
-
/* @__PURE__ */ jsx7("svg", { css: item.isRemote ? styles7.folderStatIconRemote : styles7.folderStatIconCloud, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: item.isRemote ? /* @__PURE__ */ jsx7("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" }) : /* @__PURE__ */ jsx7("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z" }) }),
|
|
4062
|
-
"stored"
|
|
4063
|
-
] }) : item.size !== void 0 ? formatFileSize2(item.size) : "--" }),
|
|
4201
|
+
] }) : item.cdnPushed ? /* @__PURE__ */ jsx7("span", { css: styles7.storedLabel, children: /* @__PURE__ */ jsx7("svg", { css: item.isRemote ? styles7.storedIconRemote : styles7.storedIconCloud, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: item.isRemote ? /* @__PURE__ */ jsx7("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" }) : /* @__PURE__ */ jsx7("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z" }) }) }) : item.size !== void 0 ? formatFileSize2(item.size) : "--" }),
|
|
4064
4202
|
/* @__PURE__ */ jsx7("td", { css: [styles7.td, styles7.meta], children: isFolder ? item.totalSize !== void 0 ? formatFileSize2(item.totalSize) : "--" : item.dimensions ? `${item.dimensions.width}x${item.dimensions.height}` : "--" }),
|
|
4065
4203
|
/* @__PURE__ */ jsx7("td", { css: styles7.td, children: item.cdnPushed ? item.isRemote ? /* @__PURE__ */ jsx7("span", { css: styles7.cdnBadgeRemote, children: "Remote" }) : /* @__PURE__ */ jsxs7("span", { css: styles7.cdnBadge, children: [
|
|
4066
4204
|
/* @__PURE__ */ jsx7("svg", { css: styles7.cdnIcon, fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx7("path", { fillRule: "evenodd", d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z", clipRule: "evenodd" }) }),
|
|
@@ -6344,4 +6482,4 @@ export {
|
|
|
6344
6482
|
StudioUI,
|
|
6345
6483
|
StudioUI_default as default
|
|
6346
6484
|
};
|
|
6347
|
-
//# sourceMappingURL=StudioUI-
|
|
6485
|
+
//# sourceMappingURL=StudioUI-PERXOBGO.mjs.map
|