@gallop.software/studio 2.3.56 → 2.3.58

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.
@@ -11,7 +11,7 @@
11
11
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
12
12
  }
13
13
  </style>
14
- <script type="module" crossorigin src="/assets/index-CAoLmuAH.js"></script>
14
+ <script type="module" crossorigin src="/assets/index-DiOqdQT0.js"></script>
15
15
  </head>
16
16
  <body>
17
17
  <div id="root"></div>
@@ -1203,13 +1203,13 @@ async function handleSync(request) {
1203
1203
  } catch {
1204
1204
  }
1205
1205
  }
1206
+ await saveMeta(meta);
1206
1207
  pushed.push(imageKey);
1207
1208
  } catch (error) {
1208
1209
  console.error(`Failed to push ${imageKey}:`, error);
1209
1210
  errors.push(`Failed to push: ${imageKey}`);
1210
1211
  }
1211
1212
  }
1212
- await saveMeta(meta);
1213
1213
  for (const folder of sourceFolders) {
1214
1214
  await deleteEmptyFolders(folder);
1215
1215
  }
@@ -1306,6 +1306,7 @@ async function handleUnprocessStream(request) {
1306
1306
  b: entry.b,
1307
1307
  ...entry.c !== void 0 ? { c: entry.c } : {}
1308
1308
  };
1309
+ await saveMeta(meta);
1309
1310
  removed.push(imageKey);
1310
1311
  sendEvent({
1311
1312
  type: "progress",
@@ -1468,6 +1469,7 @@ async function handleReprocessStream(request) {
1468
1469
  }
1469
1470
  meta[imageKey] = updatedEntry;
1470
1471
  }
1472
+ await saveMeta(meta);
1471
1473
  processed.push(imageKey);
1472
1474
  sendEvent({
1473
1475
  type: "progress",
@@ -1594,6 +1596,7 @@ async function handleDownloadStream(request) {
1594
1596
  entry.lg = processedEntry.lg;
1595
1597
  entry.f = processedEntry.f;
1596
1598
  }
1599
+ await saveMeta(meta);
1597
1600
  downloaded.push(imageKey);
1598
1601
  sendEvent({
1599
1602
  type: "progress",
@@ -1748,6 +1751,7 @@ async function handlePushUpdatesStream(request) {
1748
1751
  }
1749
1752
  await fs6.unlink(localPath);
1750
1753
  delete entry.u;
1754
+ await saveMeta(meta);
1751
1755
  pushed.push(key);
1752
1756
  sendEvent({
1753
1757
  type: "progress",
@@ -2138,7 +2142,7 @@ async function handleRename(request) {
2138
2142
  return jsonResponse({ error: "An item with this name already exists" }, { status: 400 });
2139
2143
  } catch {
2140
2144
  }
2141
- if (isInOurR2 && !hasLocalFile && isImage) {
2145
+ if (isInOurR2 && !hasLocalFile) {
2142
2146
  await moveInCdn(oldKey, newKey, hasThumbnails);
2143
2147
  delete meta[oldKey];
2144
2148
  meta[newKey] = entry;
@@ -2297,11 +2301,17 @@ async function handleRenameStream(request) {
2297
2301
  }
2298
2302
  sendEvent({ type: "progress", current: 1, total, renamed: 1, message: "Renamed folder" });
2299
2303
  let renamed = 1;
2304
+ const handleRenameCancel = async () => {
2305
+ await saveMeta(meta);
2306
+ await deleteEmptyFolders(absoluteOldPath);
2307
+ const oldThumbFolder2 = path7.join(getPublicPath("/images"), oldRelativePath);
2308
+ await deleteEmptyFolders(oldThumbFolder2);
2309
+ sendEvent({ type: "complete", renamed, newPath, cancelled: true });
2310
+ controller.close();
2311
+ };
2300
2312
  for (const item of itemsToUpdate) {
2301
2313
  if (isCancelled()) {
2302
- await saveMeta(meta);
2303
- sendEvent({ type: "complete", renamed, newPath, cancelled: true });
2304
- controller.close();
2314
+ await handleRenameCancel();
2305
2315
  return;
2306
2316
  }
2307
2317
  const { oldKey: oldKey2, newKey: newKey2, entry: entry2 } = item;
@@ -2326,6 +2336,7 @@ async function handleRenameStream(request) {
2326
2336
  }
2327
2337
  delete meta[oldKey2];
2328
2338
  meta[newKey2] = entry2;
2339
+ await saveMeta(meta);
2329
2340
  renamed++;
2330
2341
  sendEvent({
2331
2342
  type: "progress",
@@ -2335,7 +2346,6 @@ async function handleRenameStream(request) {
2335
2346
  message: `Renamed ${path7.basename(newKey2)}`
2336
2347
  });
2337
2348
  }
2338
- await saveMeta(meta);
2339
2349
  await deleteEmptyFolders(absoluteOldPath);
2340
2350
  const oldThumbFolder = path7.join(getPublicPath("/images"), oldRelativePath);
2341
2351
  await deleteEmptyFolders(oldThumbFolder);
@@ -2351,7 +2361,7 @@ async function handleRenameStream(request) {
2351
2361
  const isInOurR2 = isInCloud && fileCdnUrl === publicUrl;
2352
2362
  const hasThumbnails = entry ? isProcessed(entry) : false;
2353
2363
  sendEvent({ type: "start", total: 1, message: "Renaming file..." });
2354
- if (isInOurR2 && !hasLocalItem && isImagePath) {
2364
+ if (isInOurR2 && !hasLocalItem) {
2355
2365
  await moveInCdn(oldKey, newKey, hasThumbnails);
2356
2366
  delete meta[oldKey];
2357
2367
  if (entry) meta[newKey] = entry;
@@ -2508,18 +2518,26 @@ async function handleMoveStream(request) {
2508
2518
  }
2509
2519
  sendEvent({ type: "start", total: totalFiles });
2510
2520
  let processedFiles = 0;
2521
+ let filesMoved = 0;
2522
+ const handleCancel = async () => {
2523
+ await saveMeta(meta);
2524
+ for (const folder of sourceFolders) {
2525
+ await deleteEmptyFolders(folder);
2526
+ }
2527
+ await deleteEmptyFolders(absoluteDestination);
2528
+ sendEvent({ type: "complete", moved: filesMoved, errors: errors.length, errorMessages: errors, cancelled: true });
2529
+ controller.close();
2530
+ };
2511
2531
  for (const expandedItem of expandedItems) {
2512
2532
  if (isCancelled()) {
2513
- sendEvent({ type: "complete", moved: moved.length, errors: errors.length, errorMessages: errors, cancelled: true });
2514
- controller.close();
2533
+ await handleCancel();
2515
2534
  return;
2516
2535
  }
2517
2536
  const { itemPath, safePath, itemName, oldKey, newKey, newAbsolutePath, isVirtualFolder, virtualFolderItems } = expandedItem;
2518
2537
  if (isVirtualFolder && virtualFolderItems) {
2519
2538
  for (const vItem of virtualFolderItems) {
2520
2539
  if (isCancelled()) {
2521
- sendEvent({ type: "complete", moved: moved.length, errors: errors.length, errorMessages: errors, cancelled: true });
2522
- controller.close();
2540
+ await handleCancel();
2523
2541
  return;
2524
2542
  }
2525
2543
  const itemEntry = vItem.entry;
@@ -2532,21 +2550,26 @@ async function handleMoveStream(request) {
2532
2550
  try {
2533
2551
  await moveInCdn(vItem.oldKey, vItem.newKey, itemHasThumbnails);
2534
2552
  vItemMoved = true;
2553
+ filesMoved++;
2535
2554
  } catch (err) {
2536
2555
  console.error(`Failed to move cloud item ${vItem.oldKey}:`, err);
2537
2556
  delete meta[vItem.oldKey];
2557
+ await saveMeta(meta);
2538
2558
  }
2539
2559
  }
2540
2560
  if (vItemMoved) {
2541
2561
  delete meta[vItem.oldKey];
2542
2562
  meta[vItem.newKey] = itemEntry;
2563
+ await saveMeta(meta);
2564
+ const oldAbsPath = getPublicPath(vItem.oldKey);
2565
+ sourceFolders.add(path7.dirname(oldAbsPath));
2543
2566
  }
2544
2567
  processedFiles++;
2545
2568
  sendEvent({
2546
2569
  type: "progress",
2547
2570
  current: processedFiles,
2548
2571
  total: totalFiles,
2549
- moved: moved.length,
2572
+ moved: filesMoved,
2550
2573
  percent: Math.round(processedFiles / totalFiles * 100),
2551
2574
  currentFile: path7.basename(vItem.newKey)
2552
2575
  });
@@ -2555,6 +2578,8 @@ async function handleMoveStream(request) {
2555
2578
  await deleteEmptyFolders(newFolderPath);
2556
2579
  const newThumbFolder = path7.join(getPublicPath("images"), newKey.slice(1));
2557
2580
  await deleteEmptyFolders(newThumbFolder);
2581
+ const oldFolderPath = getPublicPath(oldKey);
2582
+ sourceFolders.add(oldFolderPath);
2558
2583
  moved.push(itemPath);
2559
2584
  continue;
2560
2585
  }
@@ -2581,7 +2606,7 @@ async function handleMoveStream(request) {
2581
2606
  try {
2582
2607
  const sourceFolder = path7.dirname(getWorkspacePath(safePath));
2583
2608
  sourceFolders.add(sourceFolder);
2584
- if (isRemote && isImage) {
2609
+ if (isRemote) {
2585
2610
  const remoteUrl = `${fileCdnUrl}${oldKey}`;
2586
2611
  const buffer = await downloadFromRemoteUrl(remoteUrl);
2587
2612
  await fs7.mkdir(path7.dirname(newAbsolutePath), { recursive: true });
@@ -2592,29 +2617,33 @@ async function handleMoveStream(request) {
2592
2617
  };
2593
2618
  delete meta[oldKey];
2594
2619
  meta[newKey] = newEntry;
2620
+ await saveMeta(meta);
2595
2621
  moved.push(itemPath);
2622
+ filesMoved++;
2596
2623
  processedFiles++;
2597
2624
  sendEvent({
2598
2625
  type: "progress",
2599
2626
  current: processedFiles,
2600
2627
  total: totalFiles,
2601
- moved: moved.length,
2628
+ moved: filesMoved,
2602
2629
  percent: Math.round(processedFiles / totalFiles * 100),
2603
2630
  currentFile: itemName
2604
2631
  });
2605
- } else if (isPushedToR2 && isImage) {
2632
+ } else if (isPushedToR2) {
2606
2633
  await moveInCdn(oldKey, newKey, hasProcessedThumbnails);
2607
2634
  delete meta[oldKey];
2608
2635
  if (entry) {
2609
2636
  meta[newKey] = entry;
2610
2637
  }
2638
+ await saveMeta(meta);
2611
2639
  moved.push(itemPath);
2640
+ filesMoved++;
2612
2641
  processedFiles++;
2613
2642
  sendEvent({
2614
2643
  type: "progress",
2615
2644
  current: processedFiles,
2616
2645
  total: totalFiles,
2617
- moved: moved.length,
2646
+ moved: filesMoved,
2618
2647
  percent: Math.round(processedFiles / totalFiles * 100),
2619
2648
  currentFile: itemName
2620
2649
  });
@@ -2627,7 +2656,7 @@ async function handleMoveStream(request) {
2627
2656
  type: "progress",
2628
2657
  current: processedFiles,
2629
2658
  total: totalFiles,
2630
- moved: moved.length,
2659
+ moved: filesMoved,
2631
2660
  percent: Math.round(processedFiles / totalFiles * 100),
2632
2661
  currentFile: itemName
2633
2662
  });
@@ -2642,7 +2671,7 @@ async function handleMoveStream(request) {
2642
2671
  type: "progress",
2643
2672
  current: processedFiles,
2644
2673
  total: totalFiles,
2645
- moved: moved.length,
2674
+ moved: filesMoved,
2646
2675
  percent: Math.round(processedFiles / totalFiles * 100),
2647
2676
  currentFile: itemName
2648
2677
  });
@@ -2656,7 +2685,7 @@ async function handleMoveStream(request) {
2656
2685
  type: "progress",
2657
2686
  current: processedFiles,
2658
2687
  total: totalFiles,
2659
- moved: moved.length,
2688
+ moved: filesMoved,
2660
2689
  percent: Math.round(processedFiles / totalFiles * 100),
2661
2690
  currentFile: itemName
2662
2691
  });
@@ -2694,17 +2723,19 @@ async function handleMoveStream(request) {
2694
2723
  }
2695
2724
  delete meta[oldKey];
2696
2725
  meta[newKey] = entry;
2726
+ await saveMeta(meta);
2697
2727
  }
2728
+ moved.push(itemPath);
2729
+ filesMoved++;
2698
2730
  processedFiles++;
2699
2731
  sendEvent({
2700
2732
  type: "progress",
2701
2733
  current: processedFiles,
2702
2734
  total: totalFiles,
2703
- moved: moved.length,
2735
+ moved: filesMoved,
2704
2736
  percent: Math.round(processedFiles / totalFiles * 100),
2705
2737
  currentFile: itemName
2706
2738
  });
2707
- moved.push(itemPath);
2708
2739
  } else if (stats.isDirectory()) {
2709
2740
  const oldPrefix = oldKey + "/";
2710
2741
  const newPrefix = newKey + "/";
@@ -2739,9 +2770,7 @@ async function handleMoveStream(request) {
2739
2770
  }
2740
2771
  for (const localFile of localFiles) {
2741
2772
  if (isCancelled()) {
2742
- await saveMeta(meta);
2743
- sendEvent({ type: "complete", moved: moved.length, errors: errors.length, errorMessages: errors, cancelled: true });
2744
- controller.close();
2773
+ await handleCancel();
2745
2774
  return;
2746
2775
  }
2747
2776
  const fileOldPath = path7.join(absolutePath, localFile.relativePath);
@@ -2752,6 +2781,7 @@ async function handleMoveStream(request) {
2752
2781
  sourceFolders.add(path7.dirname(fileOldPath));
2753
2782
  await fs7.mkdir(path7.dirname(fileNewPath), { recursive: true });
2754
2783
  await fs7.rename(fileOldPath, fileNewPath);
2784
+ filesMoved++;
2755
2785
  if (localFile.isImage && fileEntry) {
2756
2786
  const oldThumbPaths = getAllThumbnailPaths(fileOldKey);
2757
2787
  const newThumbPaths = getAllThumbnailPaths(fileNewKey);
@@ -2775,22 +2805,21 @@ async function handleMoveStream(request) {
2775
2805
  }
2776
2806
  delete meta[fileOldKey];
2777
2807
  meta[fileNewKey] = fileEntry;
2808
+ await saveMeta(meta);
2778
2809
  }
2779
2810
  processedFiles++;
2780
2811
  sendEvent({
2781
2812
  type: "progress",
2782
2813
  current: processedFiles,
2783
2814
  total: totalFiles,
2784
- moved: moved.length,
2815
+ moved: filesMoved,
2785
2816
  percent: Math.round(processedFiles / totalFiles * 100),
2786
2817
  currentFile: path7.basename(localFile.relativePath)
2787
2818
  });
2788
2819
  }
2789
2820
  for (const cloudFile of cloudOnlyFiles) {
2790
2821
  if (isCancelled()) {
2791
- await saveMeta(meta);
2792
- sendEvent({ type: "complete", moved: moved.length, errors: errors.length, errorMessages: errors, cancelled: true });
2793
- controller.close();
2822
+ await handleCancel();
2794
2823
  return;
2795
2824
  }
2796
2825
  const cloudEntry = cloudFile.entry;
@@ -2803,21 +2832,24 @@ async function handleMoveStream(request) {
2803
2832
  try {
2804
2833
  await moveInCdn(cloudFile.oldKey, cloudFile.newKey, cloudHasThumbs);
2805
2834
  cloudFileMoved = true;
2835
+ filesMoved++;
2806
2836
  } catch (err) {
2807
2837
  console.error(`Failed to move cloud file ${cloudFile.oldKey}:`, err);
2808
2838
  delete meta[cloudFile.oldKey];
2839
+ await saveMeta(meta);
2809
2840
  }
2810
2841
  }
2811
2842
  if (cloudFileMoved) {
2812
2843
  delete meta[cloudFile.oldKey];
2813
2844
  meta[cloudFile.newKey] = cloudEntry;
2845
+ await saveMeta(meta);
2814
2846
  }
2815
2847
  processedFiles++;
2816
2848
  sendEvent({
2817
2849
  type: "progress",
2818
2850
  current: processedFiles,
2819
2851
  total: totalFiles,
2820
- moved: moved.length,
2852
+ moved: filesMoved,
2821
2853
  percent: Math.round(processedFiles / totalFiles * 100),
2822
2854
  currentFile: path7.basename(cloudFile.newKey)
2823
2855
  });
@@ -2837,7 +2869,7 @@ async function handleMoveStream(request) {
2837
2869
  type: "progress",
2838
2870
  current: processedFiles,
2839
2871
  total: totalFiles,
2840
- moved: moved.length,
2872
+ moved: filesMoved,
2841
2873
  percent: Math.round(processedFiles / totalFiles * 100),
2842
2874
  currentFile: itemName
2843
2875
  });
@@ -2850,7 +2882,7 @@ async function handleMoveStream(request) {
2850
2882
  await deleteEmptyFolders(absoluteDestination);
2851
2883
  sendEvent({
2852
2884
  type: "complete",
2853
- moved: moved.length,
2885
+ moved: filesMoved,
2854
2886
  errors: errors.length,
2855
2887
  errorMessages: errors
2856
2888
  });
@@ -3002,6 +3034,9 @@ async function handleScanStream() {
3002
3034
  }
3003
3035
  existingKeys.add(imageKey);
3004
3036
  added.push(imageKey);
3037
+ if (added.length % 10 === 0) {
3038
+ await saveMeta(meta);
3039
+ }
3005
3040
  } catch (error) {
3006
3041
  console.error(`Failed to process ${relativePath}:`, error);
3007
3042
  errors.push(relativePath);
@@ -3452,6 +3487,9 @@ async function handleGenerateFavicon(request) {
3452
3487
  // src/server/index.ts
3453
3488
  var __filename = fileURLToPath(import.meta.url);
3454
3489
  var __dirname = dirname(__filename);
3490
+ var packageJsonPath = resolve(__dirname, "../../package.json");
3491
+ var packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
3492
+ var version = packageJson.version;
3455
3493
  function isPortAvailable(port) {
3456
3494
  return new Promise((resolve2) => {
3457
3495
  const server = createServer();
@@ -3542,10 +3580,11 @@ async function startServer(options) {
3542
3580
  }
3543
3581
  });
3544
3582
  app.use(express.static(clientDir));
3583
+ const title = `Gallop - Studio (${version})`;
3545
3584
  app.listen(port, () => {
3546
3585
  console.log(`
3547
3586
  \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510
3548
- \u2502 Studio - Media Manager \u2502
3587
+ \u2502 ${title.padEnd(34)}\u2502
3549
3588
  \u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524
3550
3589
  \u2502 Workspace: ${workspace.length > 24 ? "..." + workspace.slice(-21) : workspace.padEnd(24)}\u2502
3551
3590
  \u2502 URL: http://localhost:${port} \u2502