@gallop.software/studio 0.1.111 → 0.1.113

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.
@@ -3242,6 +3242,8 @@ var styles6 = {
3242
3242
  text-overflow: ellipsis;
3243
3243
  margin: 0;
3244
3244
  letter-spacing: -0.01em;
3245
+ direction: rtl;
3246
+ text-align: left;
3245
3247
  `,
3246
3248
  size: css6`
3247
3249
  font-size: ${fontSize.xs};
@@ -3439,7 +3441,7 @@ function GridItem({ item, isSelected, onClick, onOpen, onGenerateThumbnail }) {
3439
3441
  ) : /* @__PURE__ */ jsx6("svg", { css: styles6.fileIcon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" }) })
3440
3442
  ] }),
3441
3443
  /* @__PURE__ */ jsx6("div", { css: styles6.label, children: /* @__PURE__ */ jsx6("div", { css: styles6.labelRow, children: /* @__PURE__ */ jsxs6("div", { css: styles6.labelText, children: [
3442
- /* @__PURE__ */ jsx6("p", { css: styles6.name, title: item.name, children: truncateMiddle(item.name) }),
3444
+ /* @__PURE__ */ jsx6("p", { css: styles6.name, title: item.name, children: item.name }),
3443
3445
  isFolder ? /* @__PURE__ */ jsxs6("p", { css: styles6.size, children: [
3444
3446
  item.fileCount !== void 0 ? `${item.fileCount} files` : "",
3445
3447
  item.fileCount !== void 0 && item.totalSize !== void 0 ? " \xB7 " : "",
@@ -3455,19 +3457,6 @@ function formatFileSize(bytes) {
3455
3457
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
3456
3458
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
3457
3459
  }
3458
- function truncateMiddle(str, maxLength = 36) {
3459
- if (str.length <= maxLength) return str;
3460
- const lastDot = str.lastIndexOf(".");
3461
- const ext = lastDot > 0 ? str.substring(lastDot) : "";
3462
- const name = lastDot > 0 ? str.substring(0, lastDot) : str;
3463
- const availableLength = maxLength - ext.length - 3;
3464
- if (availableLength < 6) {
3465
- return str.substring(0, maxLength - 3) + "...";
3466
- }
3467
- const startLength = Math.ceil(availableLength / 2);
3468
- const endLength = Math.floor(availableLength / 2);
3469
- return name.substring(0, startLength) + "..." + name.substring(name.length - endLength) + ext;
3470
- }
3471
3460
 
3472
3461
  // src/components/StudioFileList.tsx
3473
3462
  import { useState as useState7 } from "react";
@@ -3961,7 +3950,7 @@ function ListRow({ item, isSelected, onClick, onOpen, onGenerateThumbnail }) {
3961
3950
  /* @__PURE__ */ jsx7("svg", { css: styles7.imagesFolderIcon, fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7("path", { d: "M10 4H4a2 2 0 00-2 2v12a2 2 0 002 2h16a2 2 0 002-2V8a2 2 0 00-2-2h-8l-2-2z" }) }),
3962
3951
  /* @__PURE__ */ jsx7("svg", { css: styles7.lockIcon, fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx7("path", { fillRule: "evenodd", d: "M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z", clipRule: "evenodd" }) })
3963
3952
  ] }) : /* @__PURE__ */ jsx7("div", { css: styles7.folderIconWrapper, children: /* @__PURE__ */ jsx7("svg", { css: styles7.folderIcon, fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7("path", { d: "M10 4H4a2 2 0 00-2 2v12a2 2 0 002 2h16a2 2 0 002-2V8a2 2 0 00-2-2h-8l-2-2z" }) }) }) : isImage && item.thumbnail ? /* @__PURE__ */ jsx7("div", { css: styles7.thumbnailWrapper, children: /* @__PURE__ */ jsx7("img", { css: styles7.thumbnail, src: item.thumbnail, alt: item.name, loading: "lazy" }) }) : /* @__PURE__ */ jsx7("div", { css: styles7.thumbnailWrapper, children: /* @__PURE__ */ jsx7("svg", { css: styles7.fileIcon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" }) }) }),
3964
- /* @__PURE__ */ jsx7("span", { css: styles7.name, title: item.name, children: truncateMiddle2(item.name) }),
3953
+ /* @__PURE__ */ jsx7("span", { css: styles7.name, title: item.name, children: truncateMiddle(item.name) }),
3965
3954
  /* @__PURE__ */ jsxs7("div", { css: styles7.actionsCell, children: [
3966
3955
  item.cdnPushed && !item.isRemote && /* @__PURE__ */ jsx7("span", { css: styles7.statusBtn, title: "Pushed to CDN", children: /* @__PURE__ */ jsx7("svg", { css: styles7.cloudIcon, fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7("path", { d: "M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96z" }) }) }),
3967
3956
  item.isRemote && /* @__PURE__ */ jsx7("span", { css: styles7.statusBtn, title: "Remote image", children: /* @__PURE__ */ jsx7("svg", { css: styles7.globeIcon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__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" }) }) }),
@@ -4005,7 +3994,7 @@ function formatFileSize2(bytes) {
4005
3994
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
4006
3995
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
4007
3996
  }
4008
- function truncateMiddle2(str, maxLength = 32) {
3997
+ function truncateMiddle(str, maxLength = 32) {
4009
3998
  if (str.length <= maxLength) return str;
4010
3999
  const lastDot = str.lastIndexOf(".");
4011
4000
  const ext = lastDot > 0 ? str.substring(lastDot) : "";
@@ -4316,12 +4305,14 @@ function StudioDetailView() {
4316
4305
  const { focusedItem, setFocusedItem, triggerRefresh, clearSelection } = useStudio();
4317
4306
  const [showDeleteConfirm, setShowDeleteConfirm] = useState8(false);
4318
4307
  const [showRenameModal, setShowRenameModal] = useState8(false);
4308
+ const [showMoveModal, setShowMoveModal] = useState8(false);
4319
4309
  const [showProcessConfirm, setShowProcessConfirm] = useState8(false);
4320
4310
  const [showR2SetupModal, setShowR2SetupModal] = useState8(false);
4321
4311
  const [processProgress, setProcessProgress] = useState8(null);
4322
4312
  const [alertMessage, setAlertMessage] = useState8(null);
4323
4313
  const [showCopied, setShowCopied] = useState8(false);
4324
4314
  const [pushing, setPushing] = useState8(false);
4315
+ const [moving, setMoving] = useState8(false);
4325
4316
  if (!focusedItem) return null;
4326
4317
  const isImage = isImageFile(focusedItem.name);
4327
4318
  const isVideo = isVideoFile(focusedItem.name);
@@ -4395,6 +4386,62 @@ function StudioDetailView() {
4395
4386
  });
4396
4387
  }
4397
4388
  };
4389
+ const handleMove = async (destination) => {
4390
+ setShowMoveModal(false);
4391
+ setMoving(true);
4392
+ try {
4393
+ const response = await fetch("/api/studio/move", {
4394
+ method: "POST",
4395
+ headers: { "Content-Type": "application/json" },
4396
+ body: JSON.stringify({ paths: [focusedItem.path], destination })
4397
+ });
4398
+ if (!response.body) {
4399
+ throw new Error("No response body");
4400
+ }
4401
+ const reader = response.body.getReader();
4402
+ const decoder = new TextDecoder();
4403
+ let buffer = "";
4404
+ while (true) {
4405
+ const { done, value } = await reader.read();
4406
+ if (done) break;
4407
+ buffer += decoder.decode(value, { stream: true });
4408
+ const lines = buffer.split("\n\n");
4409
+ buffer = lines.pop() || "";
4410
+ for (const line of lines) {
4411
+ if (!line.startsWith("data: ")) continue;
4412
+ try {
4413
+ const data = JSON.parse(line.slice(6));
4414
+ if (data.type === "complete") {
4415
+ if (data.errors > 0 && data.errorMessages?.length > 0) {
4416
+ setAlertMessage({
4417
+ title: "Move Failed",
4418
+ message: data.errorMessages.join("\n")
4419
+ });
4420
+ } else {
4421
+ clearSelection();
4422
+ triggerRefresh();
4423
+ setFocusedItem(null);
4424
+ }
4425
+ } else if (data.type === "error") {
4426
+ setAlertMessage({
4427
+ title: "Move Failed",
4428
+ message: data.message || "Unknown error"
4429
+ });
4430
+ }
4431
+ } catch {
4432
+ }
4433
+ }
4434
+ }
4435
+ } catch (error) {
4436
+ console.error("Move error:", error);
4437
+ setAlertMessage({
4438
+ title: "Move Failed",
4439
+ message: "Failed to move file. Check console for details."
4440
+ });
4441
+ } finally {
4442
+ setMoving(false);
4443
+ }
4444
+ };
4398
4445
  const handleSync = async () => {
4399
4446
  const imageKey = "/" + focusedItem.path.replace(/^public\//, "");
4400
4447
  setPushing(true);
@@ -4536,6 +4583,15 @@ function StudioDetailView() {
4536
4583
  onCancel: () => setShowRenameModal(false)
4537
4584
  }
4538
4585
  ),
4586
+ showMoveModal && /* @__PURE__ */ jsx8(
4587
+ StudioFolderPicker,
4588
+ {
4589
+ selectedItems: /* @__PURE__ */ new Set([focusedItem.path]),
4590
+ currentPath: focusedItem.path.split("/").slice(0, -1).join("/"),
4591
+ onMove: handleMove,
4592
+ onCancel: () => setShowMoveModal(false)
4593
+ }
4594
+ ),
4539
4595
  showProcessConfirm && /* @__PURE__ */ jsx8(
4540
4596
  ConfirmModal,
4541
4597
  {
@@ -4615,6 +4671,18 @@ function StudioDetailView() {
4615
4671
  /* @__PURE__ */ jsx8("svg", { css: styles8.actionIcon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx8("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" }) }),
4616
4672
  "Rename"
4617
4673
  ] }),
4674
+ /* @__PURE__ */ jsxs8(
4675
+ "button",
4676
+ {
4677
+ css: styles8.actionBtn,
4678
+ onClick: () => setShowMoveModal(true),
4679
+ disabled: moving,
4680
+ children: [
4681
+ /* @__PURE__ */ jsx8("svg", { css: styles8.actionIcon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx8("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4" }) }),
4682
+ moving ? "Moving..." : "Move"
4683
+ ]
4684
+ }
4685
+ ),
4618
4686
  /* @__PURE__ */ jsxs8(
4619
4687
  "button",
4620
4688
  {
@@ -5614,4 +5682,4 @@ export {
5614
5682
  StudioUI,
5615
5683
  StudioUI_default as default
5616
5684
  };
5617
- //# sourceMappingURL=StudioUI-XASVLKKZ.mjs.map
5685
+ //# sourceMappingURL=StudioUI-LGRI3HCE.mjs.map