@gallop.software/studio 1.5.0 → 1.5.2

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.
@@ -3120,6 +3120,34 @@ var styles6 = {
3120
3120
  color: #f59e0b;
3121
3121
  transform: translateY(1px);
3122
3122
  `,
3123
+ folderStats: _react3.css`
3124
+ display: flex;
3125
+ align-items: center;
3126
+ gap: 8px;
3127
+ margin-left: auto;
3128
+ padding-left: 8px;
3129
+ `,
3130
+ folderStat: _react3.css`
3131
+ display: flex;
3132
+ align-items: center;
3133
+ gap: 3px;
3134
+ font-size: 11px;
3135
+ color: ${_chunkN6JYTJCBjs.colors.textSecondary};
3136
+ `,
3137
+ folderStatIcon: _react3.css`
3138
+ width: 14px;
3139
+ height: 14px;
3140
+ `,
3141
+ folderStatIconCloud: _react3.css`
3142
+ width: 14px;
3143
+ height: 14px;
3144
+ color: #f59e0b;
3145
+ `,
3146
+ folderStatIconLocal: _react3.css`
3147
+ width: 14px;
3148
+ height: 14px;
3149
+ color: ${_chunkN6JYTJCBjs.colors.textSecondary};
3150
+ `,
3123
3151
  globeIcon: _react3.css`
3124
3152
  width: 18px;
3125
3153
  height: 18px;
@@ -3389,14 +3417,26 @@ function GridItem({ item, isSelected, onClick, onOpen, onGenerateThumbnail }) {
3389
3417
  }
3390
3418
  ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles6.fileIcon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "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" }) })
3391
3419
  ] }),
3392
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles6.label, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles6.labelRow, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.labelText, children: [
3393
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles6.name, title: item.name, children: item.name }),
3394
- isFolder ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "p", { css: styles6.size, children: [
3395
- item.fileCount !== void 0 ? `${item.fileCount} files` : "",
3396
- item.fileCount !== void 0 && item.totalSize !== void 0 ? " \xB7 " : "",
3397
- item.totalSize !== void 0 ? formatFileSize(item.totalSize) : ""
3398
- ] }) : item.size !== void 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles6.size, children: formatFileSize(item.size) })
3399
- ] }) }) })
3420
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles6.label, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.labelRow, children: [
3421
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.labelText, children: [
3422
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles6.name, title: item.name, children: item.name }),
3423
+ isFolder ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "p", { css: styles6.size, children: [
3424
+ item.fileCount !== void 0 ? `${item.fileCount} files` : "",
3425
+ item.fileCount !== void 0 && item.totalSize !== void 0 ? " \xB7 " : "",
3426
+ item.totalSize !== void 0 ? formatFileSize(item.totalSize) : ""
3427
+ ] }) : item.size !== void 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { css: styles6.size, children: formatFileSize(item.size) })
3428
+ ] }),
3429
+ isFolder && (item.localCount || item.cloudCount) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles6.folderStats, children: [
3430
+ item.localCount !== void 0 && item.localCount > 0 && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { css: styles6.folderStat, title: `${item.localCount} local`, children: [
3431
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles6.folderStatIconLocal, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" }) }),
3432
+ item.localCount
3433
+ ] }),
3434
+ item.cloudCount !== void 0 && item.cloudCount > 0 && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { css: styles6.folderStat, title: `${item.cloudCount} in cloud`, children: [
3435
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles6.folderStatIconCloud, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "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" }) }),
3436
+ item.cloudCount
3437
+ ] })
3438
+ ] })
3439
+ ] }) })
3400
3440
  ]
3401
3441
  }
3402
3442
  );
@@ -3597,6 +3637,28 @@ var styles7 = {
3597
3637
  color: #f59e0b;
3598
3638
  transform: translateY(1px);
3599
3639
  `,
3640
+ folderStats: _react3.css`
3641
+ display: flex;
3642
+ align-items: center;
3643
+ gap: 8px;
3644
+ `,
3645
+ folderStat: _react3.css`
3646
+ display: flex;
3647
+ align-items: center;
3648
+ gap: 3px;
3649
+ font-size: 12px;
3650
+ color: ${_chunkN6JYTJCBjs.colors.textSecondary};
3651
+ `,
3652
+ folderStatIconCloud: _react3.css`
3653
+ width: 14px;
3654
+ height: 14px;
3655
+ color: #f59e0b;
3656
+ `,
3657
+ folderStatIconLocal: _react3.css`
3658
+ width: 14px;
3659
+ height: 14px;
3660
+ color: ${_chunkN6JYTJCBjs.colors.textSecondary};
3661
+ `,
3600
3662
  globeIcon: _react3.css`
3601
3663
  width: 16px;
3602
3664
  height: 16px;
@@ -3937,7 +3999,21 @@ function ListRow({ item, isSelected, onClick, onOpen, onGenerateThumbnail }) {
3937
3999
  )
3938
4000
  ] })
3939
4001
  ] }) }),
3940
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "td", { css: [styles7.td, styles7.meta], children: isFolder ? item.fileCount !== void 0 ? `${item.fileCount} files` : "--" : item.size !== void 0 ? formatFileSize2(item.size) : "--" }),
4002
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "td", { css: [styles7.td, styles7.meta], children: isFolder ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles7.folderStats, children: [
4003
+ item.localCount !== void 0 && item.localCount > 0 && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { css: styles7.folderStat, title: `${item.localCount} local`, children: [
4004
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles7.folderStatIconLocal, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" }) }),
4005
+ item.localCount
4006
+ ] }),
4007
+ item.cloudCount !== void 0 && item.cloudCount > 0 && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { css: styles7.folderStat, title: `${item.cloudCount} in cloud`, children: [
4008
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles7.folderStatIconCloud, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "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" }) }),
4009
+ item.cloudCount
4010
+ ] }),
4011
+ !item.localCount && !item.cloudCount && item.fileCount !== void 0 && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { children: [
4012
+ item.fileCount,
4013
+ " files"
4014
+ ] }),
4015
+ !item.localCount && !item.cloudCount && item.fileCount === void 0 && "--"
4016
+ ] }) : item.size !== void 0 ? formatFileSize2(item.size) : "--" }),
3941
4017
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "td", { css: [styles7.td, styles7.meta], children: isFolder ? item.totalSize !== void 0 ? formatFileSize2(item.totalSize) : "--" : item.dimensions ? `${item.dimensions.width}x${item.dimensions.height}` : "--" }),
3942
4018
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "td", { css: styles7.td, children: item.cdnPushed ? item.isRemote ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { css: styles7.cdnBadgeRemote, children: "Remote" }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { css: styles7.cdnBadge, children: [
3943
4019
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles7.cdnIcon, fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "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" }) }),
@@ -4282,7 +4358,14 @@ function StudioDetailView() {
4282
4358
  const [showR2SetupModal, setShowR2SetupModal] = _react.useState.call(void 0, false);
4283
4359
  const [alertMessage, setAlertMessage] = _react.useState.call(void 0, null);
4284
4360
  const [showCopied, setShowCopied] = _react.useState.call(void 0, false);
4285
- const [generatingFavicon, setGeneratingFavicon] = _react.useState.call(void 0, false);
4361
+ const [showFaviconProgress, setShowFaviconProgress] = _react.useState.call(void 0, false);
4362
+ const [faviconProgress, setFaviconProgress] = _react.useState.call(void 0, {
4363
+ current: 0,
4364
+ total: 3,
4365
+ percent: 0,
4366
+ status: "processing",
4367
+ message: "Generating favicons..."
4368
+ });
4286
4369
  const isActionInProgress = actionState.showProgress;
4287
4370
  const isFaviconSource = focusedItem ? focusedItem.name.toLowerCase() === "favicon.png" || focusedItem.name.toLowerCase() === "favicon.jpg" : false;
4288
4371
  if (!focusedItem) return null;
@@ -4333,7 +4416,14 @@ function StudioDetailView() {
4333
4416
  };
4334
4417
  const handleGenerateFavicons = async () => {
4335
4418
  if (!focusedItem) return;
4336
- setGeneratingFavicon(true);
4419
+ setShowFaviconProgress(true);
4420
+ setFaviconProgress({
4421
+ current: 0,
4422
+ total: 3,
4423
+ percent: 0,
4424
+ status: "processing",
4425
+ message: "Generating favicons..."
4426
+ });
4337
4427
  try {
4338
4428
  const response = await fetch("/api/studio/generate-favicon", {
4339
4429
  method: "POST",
@@ -4342,26 +4432,74 @@ function StudioDetailView() {
4342
4432
  imagePath: "/" + focusedItem.path.replace(/^public\//, "")
4343
4433
  })
4344
4434
  });
4345
- const data = await response.json();
4346
- if (response.ok && data.success) {
4347
- setAlertMessage({
4348
- title: "Favicons Generated",
4349
- message: data.message + " Files saved to src/app/"
4350
- });
4351
- } else {
4352
- setAlertMessage({
4353
- title: "Generation Failed",
4354
- message: data.error || data.message || "Failed to generate favicons"
4435
+ if (!response.ok) {
4436
+ const error = await response.json();
4437
+ setFaviconProgress({
4438
+ current: 0,
4439
+ total: 3,
4440
+ percent: 0,
4441
+ status: "error",
4442
+ message: error.error || "Failed to generate favicons"
4355
4443
  });
4444
+ return;
4445
+ }
4446
+ const reader = _optionalChain([response, 'access', _42 => _42.body, 'optionalAccess', _43 => _43.getReader, 'call', _44 => _44()]);
4447
+ const decoder = new TextDecoder();
4448
+ if (reader) {
4449
+ let buffer = "";
4450
+ while (true) {
4451
+ const { done, value } = await reader.read();
4452
+ if (done) break;
4453
+ buffer += decoder.decode(value, { stream: true });
4454
+ const lines = buffer.split("\n");
4455
+ buffer = lines.pop() || "";
4456
+ for (const line of lines) {
4457
+ if (line.startsWith("data: ")) {
4458
+ try {
4459
+ const data = JSON.parse(line.slice(6));
4460
+ if (data.type === "start") {
4461
+ setFaviconProgress((prev) => ({
4462
+ ...prev,
4463
+ total: data.total
4464
+ }));
4465
+ } else if (data.type === "progress") {
4466
+ setFaviconProgress({
4467
+ current: data.current,
4468
+ total: data.total,
4469
+ percent: data.percent,
4470
+ status: "processing",
4471
+ message: data.message
4472
+ });
4473
+ } else if (data.type === "complete") {
4474
+ setFaviconProgress({
4475
+ current: data.processed,
4476
+ total: data.processed,
4477
+ percent: 100,
4478
+ status: data.errors > 0 ? "error" : "complete",
4479
+ message: data.message
4480
+ });
4481
+ } else if (data.type === "error") {
4482
+ setFaviconProgress((prev) => ({
4483
+ ...prev,
4484
+ status: "error",
4485
+ message: data.message
4486
+ }));
4487
+ }
4488
+ } catch (e4) {
4489
+ }
4490
+ }
4491
+ }
4492
+ }
4356
4493
  }
4357
4494
  } catch (error) {
4358
4495
  console.error("Favicon generation error:", error);
4359
- setAlertMessage({
4360
- title: "Generation Failed",
4496
+ setFaviconProgress({
4497
+ current: 0,
4498
+ total: 3,
4499
+ percent: 0,
4500
+ status: "error",
4361
4501
  message: "An error occurred while generating favicons"
4362
4502
  });
4363
- } finally {
4364
- setGeneratingFavicon(false);
4365
4503
  }
4366
4504
  };
4367
4505
  const renderMedia = () => {
@@ -4404,6 +4542,14 @@ function StudioDetailView() {
4404
4542
  onCancel: () => setShowRenameModal(false)
4405
4543
  }
4406
4544
  ),
4545
+ showFaviconProgress && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4546
+ ProgressModal,
4547
+ {
4548
+ title: "Generating Favicons",
4549
+ progress: faviconProgress,
4550
+ onClose: () => setShowFaviconProgress(false)
4551
+ }
4552
+ ),
4407
4553
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { css: styles8.overlay, onClick: handleClose, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles8.container, onClick: (e) => e.stopPropagation(), children: [
4408
4554
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles8.main, children: [
4409
4555
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { css: styles8.headerButtons, children: [
@@ -4515,10 +4661,10 @@ function StudioDetailView() {
4515
4661
  {
4516
4662
  css: styles8.actionBtn,
4517
4663
  onClick: handleGenerateFavicons,
4518
- disabled: generatingFavicon || focusedItem.isProtected,
4664
+ disabled: showFaviconProgress || focusedItem.isProtected,
4519
4665
  children: [
4520
4666
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { css: styles8.actionIcon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z" }) }),
4521
- generatingFavicon ? "Generating..." : "Generate Favicons"
4667
+ "Generate Favicons"
4522
4668
  ]
4523
4669
  }
4524
4670
  ),
@@ -5261,7 +5407,7 @@ function useStudioActions({
5261
5407
  });
5262
5408
  return;
5263
5409
  }
5264
- const reader = _optionalChain([response, 'access', _42 => _42.body, 'optionalAccess', _43 => _43.getReader, 'call', _44 => _44()]);
5410
+ const reader = _optionalChain([response, 'access', _45 => _45.body, 'optionalAccess', _46 => _46.getReader, 'call', _47 => _47()]);
5265
5411
  const decoder = new TextDecoder();
5266
5412
  if (reader) {
5267
5413
  let buffer = "";
@@ -5291,7 +5437,7 @@ function useStudioActions({
5291
5437
  status: "complete",
5292
5438
  message: `Moved ${data.moved} file${data.moved !== 1 ? "s" : ""}${data.errors > 0 ? `, ${data.errors} error${data.errors !== 1 ? "s" : ""}` : ""}`
5293
5439
  }));
5294
- if (data.errors > 0 && _optionalChain([data, 'access', _45 => _45.errorMessages, 'optionalAccess', _46 => _46.length]) > 0) {
5440
+ if (data.errors > 0 && _optionalChain([data, 'access', _48 => _48.errorMessages, 'optionalAccess', _49 => _49.length]) > 0) {
5295
5441
  showError("Move Failed", data.errorMessages.join("\n"));
5296
5442
  }
5297
5443
  clearSelection();
@@ -5304,7 +5450,7 @@ function useStudioActions({
5304
5450
  message: data.message || "Unknown error"
5305
5451
  }));
5306
5452
  }
5307
- } catch (e4) {
5453
+ } catch (e5) {
5308
5454
  }
5309
5455
  }
5310
5456
  }
@@ -5419,7 +5565,7 @@ function useStudioActions({
5419
5565
  });
5420
5566
  return;
5421
5567
  }
5422
- const reader = _optionalChain([response, 'access', _47 => _47.body, 'optionalAccess', _48 => _48.getReader, 'call', _49 => _49()]);
5568
+ const reader = _optionalChain([response, 'access', _50 => _50.body, 'optionalAccess', _51 => _51.getReader, 'call', _52 => _52()]);
5423
5569
  const decoder = new TextDecoder();
5424
5570
  if (reader) {
5425
5571
  let buffer = "";
@@ -5468,7 +5614,7 @@ function useStudioActions({
5468
5614
  message: data.message
5469
5615
  }));
5470
5616
  }
5471
- } catch (e5) {
5617
+ } catch (e6) {
5472
5618
  }
5473
5619
  }
5474
5620
  }
@@ -5508,7 +5654,7 @@ function useStudioActions({
5508
5654
  setProgressState((prev) => ({
5509
5655
  ...prev,
5510
5656
  orphanedFiles: void 0,
5511
- message: _optionalChain([prev, 'access', _50 => _50.message, 'optionalAccess', _51 => _51.replace, 'call', _52 => _52(/Found \d+ orphaned thumbnail\(s\).*/, "Orphaned thumbnails deleted.")])
5657
+ message: _optionalChain([prev, 'access', _53 => _53.message, 'optionalAccess', _54 => _54.replace, 'call', _55 => _55(/Found \d+ orphaned thumbnail\(s\).*/, "Orphaned thumbnails deleted.")])
5512
5658
  }));
5513
5659
  triggerRefresh();
5514
5660
  } else {
@@ -6151,4 +6297,4 @@ var StudioUI_default = StudioUI;
6151
6297
 
6152
6298
 
6153
6299
  exports.StudioUI = StudioUI; exports.default = StudioUI_default;
6154
- //# sourceMappingURL=StudioUI-MZENRXN3.js.map
6300
+ //# sourceMappingURL=StudioUI-2UVUYHHA.js.map