@rslsp1/fa-app-tools 1.3.5 → 1.3.7

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/index.d.mts CHANGED
@@ -369,6 +369,7 @@ interface ProjectSyncTabProps {
369
369
  hfToken?: string;
370
370
  onHfLoad?: (file: File) => void;
371
371
  onProjectExportBase64?: () => Promise<string>;
372
+ onHfInitialSync?: (onProgress: (done: number, total: number) => void) => Promise<void>;
372
373
  }
373
374
  declare const ProjectSyncTab: React.FC<ProjectSyncTabProps>;
374
375
 
@@ -478,6 +479,6 @@ declare function hfLoadMetadata(token: string): Promise<any[]>;
478
479
  declare function hfUploadImage(base64: string, id: string, token: string, mimeType?: string): Promise<void>;
479
480
  declare function hfLoadImageAsBase64(id: string, token: string): Promise<string | null>;
480
481
 
481
- declare const LIB_VERSION = "1.3.5";
482
+ declare const LIB_VERSION = "1.3.7";
482
483
 
483
484
  export { AvatarArchitectApp, type AvatarArchitectAppProps, CollapsibleCard, CompactDropdown, type ExtractedCharacter, FaToolsBadge, type FlowSdk, GLOBAL_STYLES, type Generation, type HFMetadataEntry, HistoryPanel, InspectPanel, LIB_VERSION, LabBlend, LabCompare, type LabFrame, LabImagePicker, type LabItem, LabLoop, LabRemix, type LabServices, LabsTab, ListView, type MediaItem, MediaLibrary, PillButton, type ProjectMeta, type ProjectSettings, ProjectSyncTab, PromptTab, SectionLabel, type SelectedLabImage, type SelectedTag, SetupPanel, type SyncDiff, TagManagerPanel, type TagOption, type WorkspaceTags, autoLabel, buildBlendInstruction, buildCompareInstruction, buildFallbackPrompt, buildGenerationPrompt, buildImageGenerationOptions, buildLoopInstruction, buildPromptTabPayload, buildReferenceImageMediaIds, buildRemixInstruction, buildScanInstruction, cleanAiResponse, createFlowServices, exportProjectToZip, formatTreeToMarkdown, frameToGeneration, getFormattedTimestamp, getHFToken, groupGenerationsToLabItems, hfDeleteProject, hfDownloadProject, hfListProjects, hfLoadImageAsBase64, hfLoadMetadata, hfLoadTags, hfSaveMetadata, hfSaveTags, hfUploadImage, hfUploadProjectForm, importProjectFromZip, injectXMPMetadata, interpretSdkError, parsePromptFile, parsePromptResponse, setHFToken, useKeyboardNavigation, useOnClickOutside };
package/dist/index.d.ts CHANGED
@@ -369,6 +369,7 @@ interface ProjectSyncTabProps {
369
369
  hfToken?: string;
370
370
  onHfLoad?: (file: File) => void;
371
371
  onProjectExportBase64?: () => Promise<string>;
372
+ onHfInitialSync?: (onProgress: (done: number, total: number) => void) => Promise<void>;
372
373
  }
373
374
  declare const ProjectSyncTab: React.FC<ProjectSyncTabProps>;
374
375
 
@@ -478,6 +479,6 @@ declare function hfLoadMetadata(token: string): Promise<any[]>;
478
479
  declare function hfUploadImage(base64: string, id: string, token: string, mimeType?: string): Promise<void>;
479
480
  declare function hfLoadImageAsBase64(id: string, token: string): Promise<string | null>;
480
481
 
481
- declare const LIB_VERSION = "1.3.5";
482
+ declare const LIB_VERSION = "1.3.7";
482
483
 
483
484
  export { AvatarArchitectApp, type AvatarArchitectAppProps, CollapsibleCard, CompactDropdown, type ExtractedCharacter, FaToolsBadge, type FlowSdk, GLOBAL_STYLES, type Generation, type HFMetadataEntry, HistoryPanel, InspectPanel, LIB_VERSION, LabBlend, LabCompare, type LabFrame, LabImagePicker, type LabItem, LabLoop, LabRemix, type LabServices, LabsTab, ListView, type MediaItem, MediaLibrary, PillButton, type ProjectMeta, type ProjectSettings, ProjectSyncTab, PromptTab, SectionLabel, type SelectedLabImage, type SelectedTag, SetupPanel, type SyncDiff, TagManagerPanel, type TagOption, type WorkspaceTags, autoLabel, buildBlendInstruction, buildCompareInstruction, buildFallbackPrompt, buildGenerationPrompt, buildImageGenerationOptions, buildLoopInstruction, buildPromptTabPayload, buildReferenceImageMediaIds, buildRemixInstruction, buildScanInstruction, cleanAiResponse, createFlowServices, exportProjectToZip, formatTreeToMarkdown, frameToGeneration, getFormattedTimestamp, getHFToken, groupGenerationsToLabItems, hfDeleteProject, hfDownloadProject, hfListProjects, hfLoadImageAsBase64, hfLoadMetadata, hfLoadTags, hfSaveMetadata, hfSaveTags, hfUploadImage, hfUploadProjectForm, importProjectFromZip, injectXMPMetadata, interpretSdkError, parsePromptFile, parsePromptResponse, setHFToken, useKeyboardNavigation, useOnClickOutside };
package/dist/index.js CHANGED
@@ -1883,7 +1883,8 @@ var ProjectSyncTab = ({
1883
1883
  onExecuteSync,
1884
1884
  hfToken,
1885
1885
  onHfLoad,
1886
- onProjectExportBase64
1886
+ onProjectExportBase64,
1887
+ onHfInitialSync
1887
1888
  }) => {
1888
1889
  const projectInputRef = (0, import_react13.useRef)(null);
1889
1890
  const workspaceInputRef = (0, import_react13.useRef)(null);
@@ -1943,6 +1944,8 @@ var ProjectSyncTab = ({
1943
1944
  const [hfSaving, setHfSaving] = (0, import_react13.useState)(false);
1944
1945
  const [hfError, setHfError] = (0, import_react13.useState)(null);
1945
1946
  const [hfSaveName, setHfSaveName] = (0, import_react13.useState)("");
1947
+ const [hfSyncProgress, setHfSyncProgress] = (0, import_react13.useState)(null);
1948
+ const [hfSyncing, setHfSyncing] = (0, import_react13.useState)(false);
1946
1949
  const loadHfProjects = async (token) => {
1947
1950
  setHfLoading(true);
1948
1951
  setHfError(null);
@@ -2090,6 +2093,38 @@ var ProjectSyncTab = ({
2090
2093
  }
2091
2094
  )
2092
2095
  ] }),
2096
+ onHfInitialSync && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-col gap-2", children: [
2097
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2098
+ PillButton,
2099
+ {
2100
+ variant: "outline",
2101
+ icon: "cloud_sync",
2102
+ loading: hfSyncing,
2103
+ onClick: async () => {
2104
+ setHfSyncing(true);
2105
+ setHfError(null);
2106
+ setHfSyncProgress({ done: 0, total: 0 });
2107
+ try {
2108
+ await onHfInitialSync((done, total) => setHfSyncProgress({ done, total }));
2109
+ setHfSyncProgress(null);
2110
+ } catch (e) {
2111
+ setHfError(e.message);
2112
+ setHfSyncProgress(null);
2113
+ } finally {
2114
+ setHfSyncing(false);
2115
+ }
2116
+ },
2117
+ children: hfSyncing && hfSyncProgress ? `${hfSyncProgress.done} / ${hfSyncProgress.total} Bilder` : "Initial-Sync nach HF"
2118
+ }
2119
+ ),
2120
+ hfSyncing && hfSyncProgress && hfSyncProgress.total > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "w-full h-1 bg-white/10 rounded-full overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2121
+ "div",
2122
+ {
2123
+ className: "h-full bg-blue-400 rounded-full transition-all",
2124
+ style: { width: `${Math.round(hfSyncProgress.done / hfSyncProgress.total * 100)}%` }
2125
+ }
2126
+ ) })
2127
+ ] }),
2093
2128
  hfError && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-[10px] text-red-400 font-mono px-1", children: hfError }),
2094
2129
  !hfLoading && hfProjects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-[10px] text-white/20 px-2", children: "Noch nichts auf HF gespeichert." }),
2095
2130
  hfProjects.map((p) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center gap-2 px-3 py-2 rounded-xl bg-white/5 border border-white/5", children: [
@@ -3924,6 +3959,32 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
3924
3959
  await onServerDelete(id);
3925
3960
  await fetchServerProjects();
3926
3961
  };
3962
+ const handleHfInitialSync = async (onProgress) => {
3963
+ if (!hfToken) return;
3964
+ const gens = galleryItems.filter((g) => g.base64 && g.status === "done");
3965
+ const total = gens.length;
3966
+ onProgress(0, total);
3967
+ let done = 0;
3968
+ for (const gen of gens) {
3969
+ const raw = gen.base64.includes(",") ? gen.base64.split(",")[1] : gen.base64;
3970
+ const mimeType = gen.base64.startsWith("data:image/png") ? "image/png" : "image/jpeg";
3971
+ await hfUploadImage(raw, gen.id, hfToken, mimeType);
3972
+ done++;
3973
+ onProgress(done, total);
3974
+ }
3975
+ const metaEntries = gens.map((g) => ({
3976
+ id: g.id,
3977
+ prompt: g.prompt || void 0,
3978
+ seed: g.seed,
3979
+ model: g.model,
3980
+ tags: g.tags || [],
3981
+ timestamp: g.timestamp,
3982
+ mimeType: g.base64.startsWith("data:image/png") ? "image/png" : "image/jpeg"
3983
+ }));
3984
+ await hfSaveMetadata(metaEntries, hfToken);
3985
+ setHfMetadata(metaEntries);
3986
+ if (workspaceTags) await hfSaveTags(workspaceTags, hfToken);
3987
+ };
3927
3988
  const handleComputeSyncDiff = async () => {
3928
3989
  if (!onFetchServerProjects || !onServerLoad) throw new Error("Server nicht konfiguriert");
3929
3990
  const projects = await onFetchServerProjects();
@@ -3969,8 +4030,30 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
3969
4030
  if (tags?.by_category) setWorkspaceTags(tags);
3970
4031
  }).catch(() => {
3971
4032
  });
3972
- hfLoadMetadata(hfToken).then((entries) => {
3973
- if (Array.isArray(entries)) setHfMetadata(entries);
4033
+ hfLoadMetadata(hfToken).then(async (entries) => {
4034
+ if (!Array.isArray(entries) || entries.length === 0) return;
4035
+ setHfMetadata(entries);
4036
+ const skeletons = entries.map((e) => ({
4037
+ id: e.id,
4038
+ nodeId: e.id,
4039
+ prompt: e.prompt,
4040
+ seed: e.seed,
4041
+ model: e.model,
4042
+ tags: e.tags || [],
4043
+ timestamp: e.timestamp,
4044
+ status: "done"
4045
+ }));
4046
+ setGalleryItems(skeletons);
4047
+ for (const entry of entries) {
4048
+ hfLoadImageAsBase64(entry.id, hfToken).then((b64) => {
4049
+ if (!b64) return;
4050
+ const prefix = `data:${entry.mimeType || "image/jpeg"};base64,`;
4051
+ setGalleryItems((prev) => prev.map(
4052
+ (g) => g.id === entry.id ? { ...g, base64: prefix + b64 } : g
4053
+ ));
4054
+ }).catch(() => {
4055
+ });
4056
+ }
3974
4057
  }).catch(() => {
3975
4058
  });
3976
4059
  }, [hfToken]);
@@ -4436,7 +4519,8 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4436
4519
  onProjectExportBase64: async () => {
4437
4520
  const { base64 } = await exportProjectToZip(nodes, edges, history, galleryItems, { aspectRatio, selectedModel, seed, seedMode }, workspaceTags, recentLabItems.map((i) => i.id));
4438
4521
  return base64;
4439
- }
4522
+ },
4523
+ onHfInitialSync: hfToken ? handleHfInitialSync : void 0
4440
4524
  }
4441
4525
  ),
4442
4526
  activeTab === "tags" && workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
@@ -4765,7 +4849,8 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4765
4849
  onProjectExportBase64: async () => {
4766
4850
  const { base64 } = await Promise.resolve().then(() => (init_project(), project_exports)).then((m) => m.exportProjectToZip(nodes, edges, history, galleryItems, { aspectRatio, selectedModel, seed, seedMode }, workspaceTags, recentLabItems.map((i) => i.id)));
4767
4851
  return base64;
4768
- }
4852
+ },
4853
+ onHfInitialSync: hfToken ? handleHfInitialSync : void 0
4769
4854
  }
4770
4855
  )
4771
4856
  ] })
@@ -4775,7 +4860,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4775
4860
 
4776
4861
  // src/index.ts
4777
4862
  init_hfStateService();
4778
- var LIB_VERSION = "1.3.5";
4863
+ var LIB_VERSION = "1.3.7";
4779
4864
  // Annotate the CommonJS export names for ESM import in node:
4780
4865
  0 && (module.exports = {
4781
4866
  AvatarArchitectApp,
package/dist/index.mjs CHANGED
@@ -1333,7 +1333,8 @@ var ProjectSyncTab = ({
1333
1333
  onExecuteSync,
1334
1334
  hfToken,
1335
1335
  onHfLoad,
1336
- onProjectExportBase64
1336
+ onProjectExportBase64,
1337
+ onHfInitialSync
1337
1338
  }) => {
1338
1339
  const projectInputRef = useRef5(null);
1339
1340
  const workspaceInputRef = useRef5(null);
@@ -1393,6 +1394,8 @@ var ProjectSyncTab = ({
1393
1394
  const [hfSaving, setHfSaving] = useState6(false);
1394
1395
  const [hfError, setHfError] = useState6(null);
1395
1396
  const [hfSaveName, setHfSaveName] = useState6("");
1397
+ const [hfSyncProgress, setHfSyncProgress] = useState6(null);
1398
+ const [hfSyncing, setHfSyncing] = useState6(false);
1396
1399
  const loadHfProjects = async (token) => {
1397
1400
  setHfLoading(true);
1398
1401
  setHfError(null);
@@ -1540,6 +1543,38 @@ var ProjectSyncTab = ({
1540
1543
  }
1541
1544
  )
1542
1545
  ] }),
1546
+ onHfInitialSync && /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-2", children: [
1547
+ /* @__PURE__ */ jsx12(
1548
+ PillButton,
1549
+ {
1550
+ variant: "outline",
1551
+ icon: "cloud_sync",
1552
+ loading: hfSyncing,
1553
+ onClick: async () => {
1554
+ setHfSyncing(true);
1555
+ setHfError(null);
1556
+ setHfSyncProgress({ done: 0, total: 0 });
1557
+ try {
1558
+ await onHfInitialSync((done, total) => setHfSyncProgress({ done, total }));
1559
+ setHfSyncProgress(null);
1560
+ } catch (e) {
1561
+ setHfError(e.message);
1562
+ setHfSyncProgress(null);
1563
+ } finally {
1564
+ setHfSyncing(false);
1565
+ }
1566
+ },
1567
+ children: hfSyncing && hfSyncProgress ? `${hfSyncProgress.done} / ${hfSyncProgress.total} Bilder` : "Initial-Sync nach HF"
1568
+ }
1569
+ ),
1570
+ hfSyncing && hfSyncProgress && hfSyncProgress.total > 0 && /* @__PURE__ */ jsx12("div", { className: "w-full h-1 bg-white/10 rounded-full overflow-hidden", children: /* @__PURE__ */ jsx12(
1571
+ "div",
1572
+ {
1573
+ className: "h-full bg-blue-400 rounded-full transition-all",
1574
+ style: { width: `${Math.round(hfSyncProgress.done / hfSyncProgress.total * 100)}%` }
1575
+ }
1576
+ ) })
1577
+ ] }),
1543
1578
  hfError && /* @__PURE__ */ jsx12("p", { className: "text-[10px] text-red-400 font-mono px-1", children: hfError }),
1544
1579
  !hfLoading && hfProjects.length === 0 && /* @__PURE__ */ jsx12("p", { className: "text-[10px] text-white/20 px-2", children: "Noch nichts auf HF gespeichert." }),
1545
1580
  hfProjects.map((p) => /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2 px-3 py-2 rounded-xl bg-white/5 border border-white/5", children: [
@@ -3367,6 +3402,32 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
3367
3402
  await onServerDelete(id);
3368
3403
  await fetchServerProjects();
3369
3404
  };
3405
+ const handleHfInitialSync = async (onProgress) => {
3406
+ if (!hfToken) return;
3407
+ const gens = galleryItems.filter((g) => g.base64 && g.status === "done");
3408
+ const total = gens.length;
3409
+ onProgress(0, total);
3410
+ let done = 0;
3411
+ for (const gen of gens) {
3412
+ const raw = gen.base64.includes(",") ? gen.base64.split(",")[1] : gen.base64;
3413
+ const mimeType = gen.base64.startsWith("data:image/png") ? "image/png" : "image/jpeg";
3414
+ await hfUploadImage(raw, gen.id, hfToken, mimeType);
3415
+ done++;
3416
+ onProgress(done, total);
3417
+ }
3418
+ const metaEntries = gens.map((g) => ({
3419
+ id: g.id,
3420
+ prompt: g.prompt || void 0,
3421
+ seed: g.seed,
3422
+ model: g.model,
3423
+ tags: g.tags || [],
3424
+ timestamp: g.timestamp,
3425
+ mimeType: g.base64.startsWith("data:image/png") ? "image/png" : "image/jpeg"
3426
+ }));
3427
+ await hfSaveMetadata(metaEntries, hfToken);
3428
+ setHfMetadata(metaEntries);
3429
+ if (workspaceTags) await hfSaveTags(workspaceTags, hfToken);
3430
+ };
3370
3431
  const handleComputeSyncDiff = async () => {
3371
3432
  if (!onFetchServerProjects || !onServerLoad) throw new Error("Server nicht konfiguriert");
3372
3433
  const projects = await onFetchServerProjects();
@@ -3412,8 +3473,30 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
3412
3473
  if (tags?.by_category) setWorkspaceTags(tags);
3413
3474
  }).catch(() => {
3414
3475
  });
3415
- hfLoadMetadata(hfToken).then((entries) => {
3416
- if (Array.isArray(entries)) setHfMetadata(entries);
3476
+ hfLoadMetadata(hfToken).then(async (entries) => {
3477
+ if (!Array.isArray(entries) || entries.length === 0) return;
3478
+ setHfMetadata(entries);
3479
+ const skeletons = entries.map((e) => ({
3480
+ id: e.id,
3481
+ nodeId: e.id,
3482
+ prompt: e.prompt,
3483
+ seed: e.seed,
3484
+ model: e.model,
3485
+ tags: e.tags || [],
3486
+ timestamp: e.timestamp,
3487
+ status: "done"
3488
+ }));
3489
+ setGalleryItems(skeletons);
3490
+ for (const entry of entries) {
3491
+ hfLoadImageAsBase64(entry.id, hfToken).then((b64) => {
3492
+ if (!b64) return;
3493
+ const prefix = `data:${entry.mimeType || "image/jpeg"};base64,`;
3494
+ setGalleryItems((prev) => prev.map(
3495
+ (g) => g.id === entry.id ? { ...g, base64: prefix + b64 } : g
3496
+ ));
3497
+ }).catch(() => {
3498
+ });
3499
+ }
3417
3500
  }).catch(() => {
3418
3501
  });
3419
3502
  }, [hfToken]);
@@ -3879,7 +3962,8 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
3879
3962
  onProjectExportBase64: async () => {
3880
3963
  const { base64 } = await exportProjectToZip(nodes, edges, history, galleryItems, { aspectRatio, selectedModel, seed, seedMode }, workspaceTags, recentLabItems.map((i) => i.id));
3881
3964
  return base64;
3882
- }
3965
+ },
3966
+ onHfInitialSync: hfToken ? handleHfInitialSync : void 0
3883
3967
  }
3884
3968
  ),
3885
3969
  activeTab === "tags" && workspaceTags && /* @__PURE__ */ jsx20(
@@ -4208,7 +4292,8 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4208
4292
  onProjectExportBase64: async () => {
4209
4293
  const { base64 } = await import("./project-O4ORKXY5.mjs").then((m) => m.exportProjectToZip(nodes, edges, history, galleryItems, { aspectRatio, selectedModel, seed, seedMode }, workspaceTags, recentLabItems.map((i) => i.id)));
4210
4294
  return base64;
4211
- }
4295
+ },
4296
+ onHfInitialSync: hfToken ? handleHfInitialSync : void 0
4212
4297
  }
4213
4298
  )
4214
4299
  ] })
@@ -4217,7 +4302,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4217
4302
  }
4218
4303
 
4219
4304
  // src/index.ts
4220
- var LIB_VERSION = "1.3.5";
4305
+ var LIB_VERSION = "1.3.7";
4221
4306
  export {
4222
4307
  AvatarArchitectApp,
4223
4308
  CollapsibleCard,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rslsp1/fa-app-tools",
3
- "version": "1.3.5",
3
+ "version": "1.3.7",
4
4
  "description": "Shared tools and hooks for Fine Art flow apps",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",