@rslsp1/fa-app-tools 1.3.9 → 1.3.11

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
@@ -479,6 +479,6 @@ declare function hfLoadMetadata(token: string): Promise<any[]>;
479
479
  declare function hfUploadImage(base64: string, id: string, token: string, mimeType?: string): Promise<void>;
480
480
  declare function hfLoadImageAsBase64(id: string, token: string): Promise<string | null>;
481
481
 
482
- declare const LIB_VERSION = "1.3.9";
482
+ declare const LIB_VERSION = "1.3.11";
483
483
 
484
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
@@ -479,6 +479,6 @@ declare function hfLoadMetadata(token: string): Promise<any[]>;
479
479
  declare function hfUploadImage(base64: string, id: string, token: string, mimeType?: string): Promise<void>;
480
480
  declare function hfLoadImageAsBase64(id: string, token: string): Promise<string | null>;
481
481
 
482
- declare const LIB_VERSION = "1.3.9";
482
+ declare const LIB_VERSION = "1.3.11";
483
483
 
484
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
@@ -3747,11 +3747,15 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
3747
3747
  };
3748
3748
  hfUploadImage(base64, genId, hfToken).catch(() => {
3749
3749
  });
3750
- setHfMetadata((prev) => {
3751
- const next = [...prev, entry];
3752
- hfSaveMetadata(next, hfToken).catch(() => {
3753
- });
3754
- return next;
3750
+ hfLoadMetadata(hfToken).then((existing) => {
3751
+ const ids = new Set((existing || []).map((e) => e.id));
3752
+ if (!ids.has(genId)) {
3753
+ const next = [...existing || [], entry];
3754
+ hfSaveMetadata(next, hfToken).catch(() => {
3755
+ });
3756
+ setHfMetadata(next);
3757
+ }
3758
+ }).catch(() => {
3755
3759
  });
3756
3760
  }
3757
3761
  } catch (err) {
@@ -3972,7 +3976,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
3972
3976
  done++;
3973
3977
  onProgress(done, total);
3974
3978
  }
3975
- const metaEntries = gens.map((g) => ({
3979
+ const localEntries = gens.map((g) => ({
3976
3980
  id: g.id,
3977
3981
  prompt: g.prompt || void 0,
3978
3982
  seed: g.seed,
@@ -3981,9 +3985,18 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
3981
3985
  timestamp: g.timestamp,
3982
3986
  mimeType: g.base64.startsWith("data:image/png") ? "image/png" : "image/jpeg"
3983
3987
  }));
3984
- await hfSaveMetadata(metaEntries, hfToken);
3985
- setHfMetadata(metaEntries);
3986
- if (workspaceTags) await hfSaveTags(workspaceTags, hfToken);
3988
+ const existingMeta = await hfLoadMetadata(hfToken);
3989
+ const existingIds = new Set((existingMeta || []).map((e) => e.id));
3990
+ const newEntries = localEntries.filter((e) => !existingIds.has(e.id));
3991
+ const mergedMeta = [...existingMeta || [], ...newEntries];
3992
+ await hfSaveMetadata(mergedMeta, hfToken);
3993
+ setHfMetadata(mergedMeta);
3994
+ if (workspaceTags) {
3995
+ const remoteTags = await hfLoadTags(hfToken).catch(() => null);
3996
+ const mergedTags = mergeWorkspaceTags(workspaceTags, remoteTags);
3997
+ await hfSaveTags(mergedTags, hfToken);
3998
+ setWorkspaceTags(mergedTags);
3999
+ }
3987
4000
  };
3988
4001
  const handleComputeSyncDiff = async () => {
3989
4002
  if (!onFetchServerProjects || !onServerLoad) throw new Error("Server nicht konfiguriert");
@@ -4064,12 +4077,31 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4064
4077
  (0, import_react21.useEffect)(() => {
4065
4078
  if (hfToken) loadFromHF(hfToken);
4066
4079
  }, [hfToken]);
4080
+ const mergeWorkspaceTags = (local, remote) => {
4081
+ if (!remote?.by_category) return local;
4082
+ const merged = {};
4083
+ const allCategories = /* @__PURE__ */ new Set([...Object.keys(local.by_category), ...Object.keys(remote.by_category)]);
4084
+ for (const cat of allCategories) {
4085
+ const localTags = local.by_category[cat] || [];
4086
+ const remoteTags = remote.by_category[cat] || [];
4087
+ const localValues = new Set(localTags.map((t) => t.value));
4088
+ const onlyInRemote = remoteTags.filter((t) => !localValues.has(t.value));
4089
+ merged[cat] = [...localTags, ...onlyInRemote];
4090
+ }
4091
+ const all = Object.entries(merged).flatMap(([cat, tags]) => tags.map((t) => ({ ...t, category: cat })));
4092
+ return { by_category: merged, all };
4093
+ };
4067
4094
  (0, import_react21.useEffect)(() => {
4068
4095
  if (!hfToken || !workspaceTags) return;
4069
4096
  if (hfTagSaveTimer.current) clearTimeout(hfTagSaveTimer.current);
4070
- hfTagSaveTimer.current = setTimeout(() => {
4071
- hfSaveTags(workspaceTags, hfToken).catch(() => {
4097
+ hfTagSaveTimer.current = setTimeout(async () => {
4098
+ const remote = await hfLoadTags(hfToken).catch(() => null);
4099
+ const merged = mergeWorkspaceTags(workspaceTags, remote);
4100
+ await hfSaveTags(merged, hfToken).catch(() => {
4072
4101
  });
4102
+ if (Object.values(merged.by_category).some(
4103
+ (tags, i) => tags.length !== Object.values(workspaceTags.by_category)[i]?.length
4104
+ )) setWorkspaceTags(merged);
4073
4105
  }, 1500);
4074
4106
  return () => {
4075
4107
  if (hfTagSaveTimer.current) clearTimeout(hfTagSaveTimer.current);
@@ -4871,7 +4903,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4871
4903
 
4872
4904
  // src/index.ts
4873
4905
  init_hfStateService();
4874
- var LIB_VERSION = "1.3.9";
4906
+ var LIB_VERSION = "1.3.11";
4875
4907
  // Annotate the CommonJS export names for ESM import in node:
4876
4908
  0 && (module.exports = {
4877
4909
  AvatarArchitectApp,
package/dist/index.mjs CHANGED
@@ -3190,11 +3190,15 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
3190
3190
  };
3191
3191
  hfUploadImage(base64, genId, hfToken).catch(() => {
3192
3192
  });
3193
- setHfMetadata((prev) => {
3194
- const next = [...prev, entry];
3195
- hfSaveMetadata(next, hfToken).catch(() => {
3196
- });
3197
- return next;
3193
+ hfLoadMetadata(hfToken).then((existing) => {
3194
+ const ids = new Set((existing || []).map((e) => e.id));
3195
+ if (!ids.has(genId)) {
3196
+ const next = [...existing || [], entry];
3197
+ hfSaveMetadata(next, hfToken).catch(() => {
3198
+ });
3199
+ setHfMetadata(next);
3200
+ }
3201
+ }).catch(() => {
3198
3202
  });
3199
3203
  }
3200
3204
  } catch (err) {
@@ -3415,7 +3419,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
3415
3419
  done++;
3416
3420
  onProgress(done, total);
3417
3421
  }
3418
- const metaEntries = gens.map((g) => ({
3422
+ const localEntries = gens.map((g) => ({
3419
3423
  id: g.id,
3420
3424
  prompt: g.prompt || void 0,
3421
3425
  seed: g.seed,
@@ -3424,9 +3428,18 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
3424
3428
  timestamp: g.timestamp,
3425
3429
  mimeType: g.base64.startsWith("data:image/png") ? "image/png" : "image/jpeg"
3426
3430
  }));
3427
- await hfSaveMetadata(metaEntries, hfToken);
3428
- setHfMetadata(metaEntries);
3429
- if (workspaceTags) await hfSaveTags(workspaceTags, hfToken);
3431
+ const existingMeta = await hfLoadMetadata(hfToken);
3432
+ const existingIds = new Set((existingMeta || []).map((e) => e.id));
3433
+ const newEntries = localEntries.filter((e) => !existingIds.has(e.id));
3434
+ const mergedMeta = [...existingMeta || [], ...newEntries];
3435
+ await hfSaveMetadata(mergedMeta, hfToken);
3436
+ setHfMetadata(mergedMeta);
3437
+ if (workspaceTags) {
3438
+ const remoteTags = await hfLoadTags(hfToken).catch(() => null);
3439
+ const mergedTags = mergeWorkspaceTags(workspaceTags, remoteTags);
3440
+ await hfSaveTags(mergedTags, hfToken);
3441
+ setWorkspaceTags(mergedTags);
3442
+ }
3430
3443
  };
3431
3444
  const handleComputeSyncDiff = async () => {
3432
3445
  if (!onFetchServerProjects || !onServerLoad) throw new Error("Server nicht konfiguriert");
@@ -3507,12 +3520,31 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
3507
3520
  useEffect5(() => {
3508
3521
  if (hfToken) loadFromHF(hfToken);
3509
3522
  }, [hfToken]);
3523
+ const mergeWorkspaceTags = (local, remote) => {
3524
+ if (!remote?.by_category) return local;
3525
+ const merged = {};
3526
+ const allCategories = /* @__PURE__ */ new Set([...Object.keys(local.by_category), ...Object.keys(remote.by_category)]);
3527
+ for (const cat of allCategories) {
3528
+ const localTags = local.by_category[cat] || [];
3529
+ const remoteTags = remote.by_category[cat] || [];
3530
+ const localValues = new Set(localTags.map((t) => t.value));
3531
+ const onlyInRemote = remoteTags.filter((t) => !localValues.has(t.value));
3532
+ merged[cat] = [...localTags, ...onlyInRemote];
3533
+ }
3534
+ const all = Object.entries(merged).flatMap(([cat, tags]) => tags.map((t) => ({ ...t, category: cat })));
3535
+ return { by_category: merged, all };
3536
+ };
3510
3537
  useEffect5(() => {
3511
3538
  if (!hfToken || !workspaceTags) return;
3512
3539
  if (hfTagSaveTimer.current) clearTimeout(hfTagSaveTimer.current);
3513
- hfTagSaveTimer.current = setTimeout(() => {
3514
- hfSaveTags(workspaceTags, hfToken).catch(() => {
3540
+ hfTagSaveTimer.current = setTimeout(async () => {
3541
+ const remote = await hfLoadTags(hfToken).catch(() => null);
3542
+ const merged = mergeWorkspaceTags(workspaceTags, remote);
3543
+ await hfSaveTags(merged, hfToken).catch(() => {
3515
3544
  });
3545
+ if (Object.values(merged.by_category).some(
3546
+ (tags, i) => tags.length !== Object.values(workspaceTags.by_category)[i]?.length
3547
+ )) setWorkspaceTags(merged);
3516
3548
  }, 1500);
3517
3549
  return () => {
3518
3550
  if (hfTagSaveTimer.current) clearTimeout(hfTagSaveTimer.current);
@@ -4313,7 +4345,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4313
4345
  }
4314
4346
 
4315
4347
  // src/index.ts
4316
- var LIB_VERSION = "1.3.9";
4348
+ var LIB_VERSION = "1.3.11";
4317
4349
  export {
4318
4350
  AvatarArchitectApp,
4319
4351
  CollapsibleCard,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rslsp1/fa-app-tools",
3
- "version": "1.3.9",
3
+ "version": "1.3.11",
4
4
  "description": "Shared tools and hooks for Fine Art flow apps",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",