@rslsp1/fa-app-tools 1.2.3 → 1.2.5
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/chunk-UFXDXENC.mjs +218 -0
- package/dist/chunk-UZE44WOR.mjs +99 -0
- package/dist/hfStateService-Y563AT2M.mjs +18 -0
- package/dist/index.d.mts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +451 -124
- package/dist/index.mjs +211 -220
- package/dist/project-O4ORKXY5.mjs +8 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
exportProjectToZip,
|
|
3
|
+
importProjectFromZip,
|
|
4
|
+
injectXMPMetadata
|
|
5
|
+
} from "./chunk-UFXDXENC.mjs";
|
|
6
|
+
import {
|
|
7
|
+
hfDeleteProject,
|
|
8
|
+
hfListProjects,
|
|
9
|
+
hfUploadProject
|
|
10
|
+
} from "./chunk-UZE44WOR.mjs";
|
|
11
|
+
|
|
1
12
|
// src/hooks/useOnClickOutside.ts
|
|
2
13
|
import { useEffect } from "react";
|
|
3
14
|
function useOnClickOutside(ref, handler) {
|
|
@@ -51,217 +62,6 @@ var GLOBAL_STYLES = `
|
|
|
51
62
|
.animate-dropdown { animation: dropdown-enter 0.1s ease-out forwards; }
|
|
52
63
|
`;
|
|
53
64
|
|
|
54
|
-
// src/lib/metadata.ts
|
|
55
|
-
var crcTable = (() => {
|
|
56
|
-
let c;
|
|
57
|
-
const table = new Uint32Array(256);
|
|
58
|
-
for (let n = 0; n < 256; n++) {
|
|
59
|
-
c = n;
|
|
60
|
-
for (let k = 0; k < 8; k++) {
|
|
61
|
-
c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
62
|
-
}
|
|
63
|
-
table[n] = c;
|
|
64
|
-
}
|
|
65
|
-
return table;
|
|
66
|
-
})();
|
|
67
|
-
function calculateCRC(bytes) {
|
|
68
|
-
let crc = 4294967295;
|
|
69
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
70
|
-
crc = crcTable[(crc ^ bytes[i]) & 255] ^ crc >>> 8;
|
|
71
|
-
}
|
|
72
|
-
return (crc ^ 4294967295) >>> 0;
|
|
73
|
-
}
|
|
74
|
-
function indexOfBytes(buffer, search, start = 0) {
|
|
75
|
-
for (let i = start; i <= buffer.length - search.length; i++) {
|
|
76
|
-
let found = true;
|
|
77
|
-
for (let j = 0; j < search.length; j++) {
|
|
78
|
-
if (buffer[i + j] !== search[j]) {
|
|
79
|
-
found = false;
|
|
80
|
-
break;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
if (found) return i;
|
|
84
|
-
}
|
|
85
|
-
return -1;
|
|
86
|
-
}
|
|
87
|
-
function createXMPPacket(prompt, seed, model, id, tags = [], hierarchy) {
|
|
88
|
-
const sanitize = (str) => (str || "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
89
|
-
const escPrompt = sanitize(prompt);
|
|
90
|
-
const escModel = sanitize(model || "AI Model");
|
|
91
|
-
const escHierarchy = sanitize(hierarchy || "");
|
|
92
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
93
|
-
const allTags = [.../* @__PURE__ */ new Set([...tags, "Avatar Architect", escModel])];
|
|
94
|
-
const rdfTags = allTags.map((t) => `<rdf:li>${sanitize(t)}</rdf:li>`).join("");
|
|
95
|
-
const BOM = "\uFEFF";
|
|
96
|
-
return `<?xpacket begin="${BOM}" id="W5M0MpCehiHzreSzNTczkc9d"?>
|
|
97
|
-
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.6-c140">
|
|
98
|
-
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
|
99
|
-
<rdf:Description rdf:about=""
|
|
100
|
-
xmlns:xmp="http://ns.adobe.com/xap/1.0/"
|
|
101
|
-
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
102
|
-
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/"
|
|
103
|
-
xmlns:ai="http://ns.flow.creative/ai/1.0/">
|
|
104
|
-
<dc:format>image/png</dc:format>
|
|
105
|
-
<dc:description><rdf:Alt><rdf:li xml:lang="x-default">${escPrompt}</rdf:li></rdf:Alt></dc:description>
|
|
106
|
-
<dc:subject><rdf:Bag>${rdfTags}</rdf:Bag></dc:subject>
|
|
107
|
-
<photoshop:Instructions>Seed: ${seed} | Model: ${escModel}</photoshop:Instructions>
|
|
108
|
-
<xmp:CreateDate>${timestamp}</xmp:CreateDate>
|
|
109
|
-
<ai:prompt>${escPrompt}</ai:prompt>
|
|
110
|
-
<ai:seed>${seed ?? "0"}</ai:seed>
|
|
111
|
-
<ai:model>${escModel}</ai:model>
|
|
112
|
-
<ai:hierarchy>${escHierarchy}</ai:hierarchy>
|
|
113
|
-
</rdf:Description>
|
|
114
|
-
</rdf:RDF>
|
|
115
|
-
</x:xmpmeta>${" ".repeat(1024)}<?xpacket end="w"?>`;
|
|
116
|
-
}
|
|
117
|
-
function bytesToBase64(bytes) {
|
|
118
|
-
let binary = "";
|
|
119
|
-
const len = bytes.byteLength;
|
|
120
|
-
for (let i = 0; i < len; i++) binary += String.fromCharCode(bytes[i]);
|
|
121
|
-
return btoa(binary);
|
|
122
|
-
}
|
|
123
|
-
function base64ToBytes(base64) {
|
|
124
|
-
const clean = base64.includes(",") ? base64.split(",")[1] : base64.trim();
|
|
125
|
-
try {
|
|
126
|
-
const binary = atob(clean);
|
|
127
|
-
const bytes = new Uint8Array(binary.length);
|
|
128
|
-
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
129
|
-
return bytes;
|
|
130
|
-
} catch (e) {
|
|
131
|
-
return new Uint8Array(0);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
function injectXMPMetadata(base64, prompt, seed, model, id, tags = [], hierarchy) {
|
|
135
|
-
try {
|
|
136
|
-
const bytes = base64ToBytes(base64);
|
|
137
|
-
if (bytes.length < 8 || bytes[0] !== 137 || bytes[1] !== 80) {
|
|
138
|
-
console.warn("Metadaten-Injektion \xFCbersprungen: Datei ist kein PNG.");
|
|
139
|
-
return base64;
|
|
140
|
-
}
|
|
141
|
-
const xmpData = createXMPPacket(prompt, seed, model, id, tags, hierarchy);
|
|
142
|
-
const encoder = new TextEncoder();
|
|
143
|
-
const keyword = encoder.encode("XML:com.adobe.xmp");
|
|
144
|
-
const textBytes = encoder.encode(xmpData);
|
|
145
|
-
const chunkData = new Uint8Array(keyword.length + 5 + textBytes.length);
|
|
146
|
-
chunkData.set(keyword, 0);
|
|
147
|
-
chunkData.set(textBytes, keyword.length + 5);
|
|
148
|
-
const type = encoder.encode("iTXt");
|
|
149
|
-
const crcInput = new Uint8Array(type.length + chunkData.length);
|
|
150
|
-
crcInput.set(type, 0);
|
|
151
|
-
crcInput.set(chunkData, type.length);
|
|
152
|
-
const crc = calculateCRC(crcInput);
|
|
153
|
-
const fullChunk = new Uint8Array(4 + 4 + chunkData.length + 4);
|
|
154
|
-
const view = new DataView(fullChunk.buffer);
|
|
155
|
-
view.setUint32(0, chunkData.length);
|
|
156
|
-
fullChunk.set(type, 4);
|
|
157
|
-
fullChunk.set(chunkData, 8);
|
|
158
|
-
view.setUint32(8 + chunkData.length, crc);
|
|
159
|
-
const IDAT = encoder.encode("IDAT");
|
|
160
|
-
const idatPos = indexOfBytes(bytes, IDAT);
|
|
161
|
-
const insertPos = idatPos !== -1 ? idatPos - 4 : 8;
|
|
162
|
-
const result = new Uint8Array(bytes.length + fullChunk.length);
|
|
163
|
-
result.set(bytes.slice(0, insertPos), 0);
|
|
164
|
-
result.set(fullChunk, insertPos);
|
|
165
|
-
result.set(bytes.slice(insertPos), insertPos + fullChunk.length);
|
|
166
|
-
return bytesToBase64(result);
|
|
167
|
-
} catch (e) {
|
|
168
|
-
console.error("Fehler beim Einbetten der Metadaten:", e);
|
|
169
|
-
return base64;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// src/lib/project.ts
|
|
174
|
-
import JSZip from "jszip";
|
|
175
|
-
function generateMarkdownReport(nodes, history) {
|
|
176
|
-
let md = "# Avatar Architect - Projekt Report\n\n";
|
|
177
|
-
md += `Exportiert: ${(/* @__PURE__ */ new Date()).toLocaleString()}
|
|
178
|
-
|
|
179
|
-
`;
|
|
180
|
-
md += "## Hierarchie\n";
|
|
181
|
-
nodes.forEach((n) => {
|
|
182
|
-
md += `- **${n.data?.label || "Unbenannt"}**
|
|
183
|
-
`;
|
|
184
|
-
});
|
|
185
|
-
md += "\n## Historie der Generationen\n";
|
|
186
|
-
history.forEach((h, i) => {
|
|
187
|
-
md += `### ${i + 1}. Generation (${h.model || "AI"})
|
|
188
|
-
`;
|
|
189
|
-
md += `- **Zeitstempel**: ${new Date(h.timestamp).toLocaleString()}
|
|
190
|
-
`;
|
|
191
|
-
md += `- **Seed**: ${h.seed}
|
|
192
|
-
`;
|
|
193
|
-
md += `- **Prompt**:
|
|
194
|
-
> ${h.prompt}
|
|
195
|
-
|
|
196
|
-
`;
|
|
197
|
-
});
|
|
198
|
-
return md;
|
|
199
|
-
}
|
|
200
|
-
async function exportProjectToZip(nodes, edges, history, galleryItems, settings, workspaceTags, recentLabItemIds) {
|
|
201
|
-
const zip = new JSZip();
|
|
202
|
-
const projectData = {
|
|
203
|
-
nodes,
|
|
204
|
-
edges,
|
|
205
|
-
history: history.map((h) => ({ ...h, base64: void 0 })),
|
|
206
|
-
galleryItems: galleryItems.map((g) => ({ ...g, base64: void 0 })),
|
|
207
|
-
settings,
|
|
208
|
-
workspaceTags: workspaceTags || null,
|
|
209
|
-
recentLabItemIds: recentLabItemIds || [],
|
|
210
|
-
version: "1.3.0"
|
|
211
|
-
};
|
|
212
|
-
zip.file("project.json", JSON.stringify(projectData, null, 2));
|
|
213
|
-
zip.file("projekt_bericht.md", generateMarkdownReport(nodes, history));
|
|
214
|
-
const imgFolder = zip.folder("images");
|
|
215
|
-
if (imgFolder) {
|
|
216
|
-
const allItems = [...history, ...galleryItems];
|
|
217
|
-
for (const item of allItems) {
|
|
218
|
-
if (item.base64) {
|
|
219
|
-
try {
|
|
220
|
-
const cleanB64 = item.base64.includes(",") ? item.base64.split(",")[1] : item.base64;
|
|
221
|
-
const withMeta = injectXMPMetadata(cleanB64, item.prompt || "", item.seed, item.model, item.id, item.tags || []);
|
|
222
|
-
imgFolder.file(`${item.id}.png`, withMeta, { base64: true });
|
|
223
|
-
} catch (e) {
|
|
224
|
-
console.error("Fehler beim Packen eines Bildes:", e);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
const blob = await zip.generateAsync({ type: "blob", compression: "STORE" });
|
|
230
|
-
return blobToBase64(blob);
|
|
231
|
-
}
|
|
232
|
-
async function blobToBase64(blob) {
|
|
233
|
-
return new Promise((resolve, reject) => {
|
|
234
|
-
const reader = new FileReader();
|
|
235
|
-
reader.onloadend = () => {
|
|
236
|
-
const result = reader.result;
|
|
237
|
-
resolve({ base64: result.split(",")[1] });
|
|
238
|
-
};
|
|
239
|
-
reader.onerror = reject;
|
|
240
|
-
reader.readAsDataURL(blob);
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
async function importProjectFromZip(file) {
|
|
244
|
-
const zip = await JSZip.loadAsync(file);
|
|
245
|
-
const jsonStr = await zip.file("project.json")?.async("string");
|
|
246
|
-
if (!jsonStr) throw new Error("Keine project.json gefunden.");
|
|
247
|
-
const data = JSON.parse(jsonStr);
|
|
248
|
-
const imgFolder = zip.folder("images");
|
|
249
|
-
if (imgFolder) {
|
|
250
|
-
const loadImgs = async (items) => {
|
|
251
|
-
if (!items) return [];
|
|
252
|
-
return Promise.all(items.map(async (h) => {
|
|
253
|
-
const imgFile = zip.file(`images/${h.id}.png`);
|
|
254
|
-
if (!imgFile) return h;
|
|
255
|
-
const b64 = await imgFile.async("base64");
|
|
256
|
-
return { ...h, base64: `data:image/png;base64,${b64}` };
|
|
257
|
-
}));
|
|
258
|
-
};
|
|
259
|
-
data.history = await loadImgs(data.history || []);
|
|
260
|
-
data.galleryItems = await loadImgs(data.galleryItems || []);
|
|
261
|
-
}
|
|
262
|
-
return data;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
65
|
// src/lib/aiHelpers.ts
|
|
266
66
|
function buildGenerationPrompt(hierarchyText, mode = "creative") {
|
|
267
67
|
const safe = hierarchyText.length > 2500 ? hierarchyText.slice(0, 2500) + "..." : hierarchyText;
|
|
@@ -664,6 +464,7 @@ var PRESET_URLS = [
|
|
|
664
464
|
var SetupPanel = ({ onWorkspaceImport, buildInfo }) => {
|
|
665
465
|
const workspaceInputRef = useRef2(null);
|
|
666
466
|
const [urlInput, setUrlInput] = useState2("");
|
|
467
|
+
const [tokenInput, setTokenInput] = useState2("");
|
|
667
468
|
const [testStatus, setTestStatus] = useState2("idle");
|
|
668
469
|
const [result, setResult] = useState2(null);
|
|
669
470
|
const [fetchError, setFetchError] = useState2(null);
|
|
@@ -674,7 +475,9 @@ var SetupPanel = ({ onWorkspaceImport, buildInfo }) => {
|
|
|
674
475
|
setFetchError(null);
|
|
675
476
|
const t0 = Date.now();
|
|
676
477
|
try {
|
|
677
|
-
const
|
|
478
|
+
const reqHeaders = {};
|
|
479
|
+
if (tokenInput.trim()) reqHeaders["Authorization"] = `Bearer ${tokenInput.trim()}`;
|
|
480
|
+
const res = await fetch(url.trim(), { headers: reqHeaders });
|
|
678
481
|
const durationMs = Date.now() - t0;
|
|
679
482
|
const contentType = res.headers.get("content-type") || "";
|
|
680
483
|
const headers = {};
|
|
@@ -734,6 +537,16 @@ var SetupPanel = ({ onWorkspaceImport, buildInfo }) => {
|
|
|
734
537
|
},
|
|
735
538
|
u
|
|
736
539
|
)) }),
|
|
540
|
+
/* @__PURE__ */ jsx7(
|
|
541
|
+
"input",
|
|
542
|
+
{
|
|
543
|
+
value: tokenInput,
|
|
544
|
+
onChange: (e) => setTokenInput(e.target.value),
|
|
545
|
+
placeholder: "Bearer Token (optional)",
|
|
546
|
+
type: "password",
|
|
547
|
+
className: "w-full bg-white/5 border border-white/10 rounded-xl px-3 py-2 text-[11px] text-white/60 outline-none focus:border-white/20 placeholder:text-white/20 font-mono"
|
|
548
|
+
}
|
|
549
|
+
),
|
|
737
550
|
/* @__PURE__ */ jsxs5("div", { className: "flex gap-2", children: [
|
|
738
551
|
/* @__PURE__ */ jsx7(
|
|
739
552
|
"input",
|
|
@@ -971,7 +784,7 @@ function ListView({ nodes, edges, onNodeChange, onAddChild, onDeleteNode, onMove
|
|
|
971
784
|
}
|
|
972
785
|
|
|
973
786
|
// src/components/AvatarArchitectApp.tsx
|
|
974
|
-
import { useState as useState14, useCallback, useMemo as useMemo2, useEffect as
|
|
787
|
+
import { useState as useState14, useCallback, useMemo as useMemo2, useEffect as useEffect5, useRef as useRef6 } from "react";
|
|
975
788
|
|
|
976
789
|
// src/components/PromptTab.tsx
|
|
977
790
|
import { useRef as useRef4, useState as useState5 } from "react";
|
|
@@ -1495,7 +1308,7 @@ var PromptTab = ({
|
|
|
1495
1308
|
};
|
|
1496
1309
|
|
|
1497
1310
|
// src/components/ProjectSyncTab.tsx
|
|
1498
|
-
import { useRef as useRef5, useState as useState6 } from "react";
|
|
1311
|
+
import { useRef as useRef5, useState as useState6, useEffect as useEffect4 } from "react";
|
|
1499
1312
|
import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1500
1313
|
var ProjectSyncTab = ({
|
|
1501
1314
|
onProjectExport,
|
|
@@ -1508,7 +1321,10 @@ var ProjectSyncTab = ({
|
|
|
1508
1321
|
onServerDelete,
|
|
1509
1322
|
onRefreshServerProjects,
|
|
1510
1323
|
onComputeSyncDiff,
|
|
1511
|
-
onExecuteSync
|
|
1324
|
+
onExecuteSync,
|
|
1325
|
+
hfToken,
|
|
1326
|
+
onHfLoad,
|
|
1327
|
+
onProjectExportBase64
|
|
1512
1328
|
}) => {
|
|
1513
1329
|
const projectInputRef = useRef5(null);
|
|
1514
1330
|
const workspaceInputRef = useRef5(null);
|
|
@@ -1563,6 +1379,25 @@ var ProjectSyncTab = ({
|
|
|
1563
1379
|
});
|
|
1564
1380
|
};
|
|
1565
1381
|
const isWorking = projectActionState === "working" || projectActionState === "working-full";
|
|
1382
|
+
const [hfProjects, setHfProjects] = useState6([]);
|
|
1383
|
+
const [hfLoading, setHfLoading] = useState6(false);
|
|
1384
|
+
const [hfSaving, setHfSaving] = useState6(false);
|
|
1385
|
+
const [hfError, setHfError] = useState6(null);
|
|
1386
|
+
const [hfSaveName, setHfSaveName] = useState6("");
|
|
1387
|
+
const loadHfProjects = async (token) => {
|
|
1388
|
+
setHfLoading(true);
|
|
1389
|
+
setHfError(null);
|
|
1390
|
+
try {
|
|
1391
|
+
setHfProjects(await hfListProjects(token));
|
|
1392
|
+
} catch (e) {
|
|
1393
|
+
setHfError(e.message);
|
|
1394
|
+
} finally {
|
|
1395
|
+
setHfLoading(false);
|
|
1396
|
+
}
|
|
1397
|
+
};
|
|
1398
|
+
useEffect4(() => {
|
|
1399
|
+
if (hfToken) loadHfProjects(hfToken);
|
|
1400
|
+
}, [hfToken]);
|
|
1566
1401
|
return /* @__PURE__ */ jsx12("div", { className: "absolute inset-0 overflow-y-auto dark-scrollbar", children: /* @__PURE__ */ jsxs10("div", { className: "p-6 flex flex-col gap-8", children: [
|
|
1567
1402
|
(onProjectExport || onProjectImport || onWorkspaceImport) && /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-4", children: [
|
|
1568
1403
|
/* @__PURE__ */ jsx12(SectionLabel, { children: "Projekt-ZIP" }),
|
|
@@ -1653,6 +1488,94 @@ var ProjectSyncTab = ({
|
|
|
1653
1488
|
/* @__PURE__ */ jsx12("button", { onClick: () => onServerDelete?.(p.id), className: "w-8 h-8 flex items-center justify-center text-white/20 active:text-red-400 transition-colors", children: /* @__PURE__ */ jsx12("span", { className: "material-symbols-outlined text-[18px]", children: "delete" }) })
|
|
1654
1489
|
] }, p.id)) })
|
|
1655
1490
|
] }),
|
|
1491
|
+
hfToken && /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-4", children: [
|
|
1492
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between", children: [
|
|
1493
|
+
/* @__PURE__ */ jsx12(SectionLabel, { children: "Hugging Face" }),
|
|
1494
|
+
/* @__PURE__ */ jsx12("button", { onClick: () => loadHfProjects(hfToken), className: "text-white/30 hover:text-white/60 transition", children: /* @__PURE__ */ jsx12("span", { className: `material-symbols-outlined text-[18px]${hfLoading ? " animate-spin" : ""}`, children: "refresh" }) })
|
|
1495
|
+
] }),
|
|
1496
|
+
onProjectExportBase64 && /* @__PURE__ */ jsxs10("div", { className: "flex gap-2", children: [
|
|
1497
|
+
/* @__PURE__ */ jsx12(
|
|
1498
|
+
"input",
|
|
1499
|
+
{
|
|
1500
|
+
type: "text",
|
|
1501
|
+
value: hfSaveName,
|
|
1502
|
+
onChange: (e) => setHfSaveName(e.target.value),
|
|
1503
|
+
placeholder: "Name (optional)",
|
|
1504
|
+
className: "flex-1 bg-white/5 border border-white/10 rounded-xl px-3 text-[12px] text-white/70 outline-none placeholder:text-white/20",
|
|
1505
|
+
style: { height: 40 }
|
|
1506
|
+
}
|
|
1507
|
+
),
|
|
1508
|
+
/* @__PURE__ */ jsx12(
|
|
1509
|
+
PillButton,
|
|
1510
|
+
{
|
|
1511
|
+
variant: "filled",
|
|
1512
|
+
icon: "cloud_upload",
|
|
1513
|
+
loading: hfSaving,
|
|
1514
|
+
onClick: async () => {
|
|
1515
|
+
if (!onProjectExportBase64) return;
|
|
1516
|
+
setHfSaving(true);
|
|
1517
|
+
setHfError(null);
|
|
1518
|
+
try {
|
|
1519
|
+
const base64 = await onProjectExportBase64();
|
|
1520
|
+
const name = hfSaveName.trim() || `project_${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16).replace("T", "_").replace(":", "")}`;
|
|
1521
|
+
await hfUploadProject(base64, name, hfToken);
|
|
1522
|
+
setHfSaveName("");
|
|
1523
|
+
await loadHfProjects(hfToken);
|
|
1524
|
+
} catch (e) {
|
|
1525
|
+
setHfError(e.message);
|
|
1526
|
+
} finally {
|
|
1527
|
+
setHfSaving(false);
|
|
1528
|
+
}
|
|
1529
|
+
},
|
|
1530
|
+
children: "Speichern"
|
|
1531
|
+
}
|
|
1532
|
+
)
|
|
1533
|
+
] }),
|
|
1534
|
+
hfError && /* @__PURE__ */ jsx12("p", { className: "text-[10px] text-red-400 font-mono px-1", children: hfError }),
|
|
1535
|
+
!hfLoading && hfProjects.length === 0 && /* @__PURE__ */ jsx12("p", { className: "text-[10px] text-white/20 px-2", children: "Noch nichts auf HF gespeichert." }),
|
|
1536
|
+
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: [
|
|
1537
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex-1 min-w-0", children: [
|
|
1538
|
+
/* @__PURE__ */ jsx12("p", { className: "text-[11px] text-white/70 font-bold truncate", children: p.name }),
|
|
1539
|
+
/* @__PURE__ */ jsxs10("p", { className: "text-[9px] text-white/25", children: [
|
|
1540
|
+
(p.size / 1024 / 1024).toFixed(1),
|
|
1541
|
+
" MB",
|
|
1542
|
+
p.isLfs ? " \xB7 LFS" : ""
|
|
1543
|
+
] })
|
|
1544
|
+
] }),
|
|
1545
|
+
onHfLoad && /* @__PURE__ */ jsx12(
|
|
1546
|
+
"button",
|
|
1547
|
+
{
|
|
1548
|
+
onClick: async () => {
|
|
1549
|
+
try {
|
|
1550
|
+
const { hfDownloadProject } = await import("./hfStateService-Y563AT2M.mjs");
|
|
1551
|
+
const file = await hfDownloadProject(p.path, hfToken);
|
|
1552
|
+
onHfLoad(file);
|
|
1553
|
+
} catch (e) {
|
|
1554
|
+
setHfError(e.message);
|
|
1555
|
+
}
|
|
1556
|
+
},
|
|
1557
|
+
className: "w-8 h-8 flex items-center justify-center text-white/30 active:text-white transition-colors",
|
|
1558
|
+
children: /* @__PURE__ */ jsx12("span", { className: "material-symbols-outlined text-[18px]", children: "cloud_download" })
|
|
1559
|
+
}
|
|
1560
|
+
),
|
|
1561
|
+
/* @__PURE__ */ jsx12(
|
|
1562
|
+
"button",
|
|
1563
|
+
{
|
|
1564
|
+
onClick: async () => {
|
|
1565
|
+
if (!confirm(`"${p.name}" auf HF l\xF6schen?`)) return;
|
|
1566
|
+
try {
|
|
1567
|
+
await hfDeleteProject(p.path, hfToken);
|
|
1568
|
+
await loadHfProjects(hfToken);
|
|
1569
|
+
} catch (e) {
|
|
1570
|
+
setHfError(e.message);
|
|
1571
|
+
}
|
|
1572
|
+
},
|
|
1573
|
+
className: "w-8 h-8 flex items-center justify-center text-white/20 active:text-red-400 transition-colors",
|
|
1574
|
+
children: /* @__PURE__ */ jsx12("span", { className: "material-symbols-outlined text-[18px]", children: "delete" })
|
|
1575
|
+
}
|
|
1576
|
+
)
|
|
1577
|
+
] }, p.id))
|
|
1578
|
+
] }),
|
|
1656
1579
|
onComputeSyncDiff && onExecuteSync && /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-4", children: [
|
|
1657
1580
|
/* @__PURE__ */ jsx12(SectionLabel, { children: "Sync" }),
|
|
1658
1581
|
(syncState === "idle" || syncState === "computing") && /* @__PURE__ */ jsx12(PillButton, { variant: "outline", icon: "compare_arrows", loading: syncState === "computing", onClick: handleComputeDiff, children: "Diff berechnen" }),
|
|
@@ -2919,7 +2842,7 @@ function TagManagerPanel({ workspaceTags, onTagCreate, onTagUpdate, onTagDelete,
|
|
|
2919
2842
|
// src/components/AvatarArchitectApp.tsx
|
|
2920
2843
|
import { Fragment as Fragment9, jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2921
2844
|
function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onSelectMedia, buildInfo, onFetchServerProjects, onServerSave, onServerLoad, onServerDelete }) {
|
|
2922
|
-
|
|
2845
|
+
useEffect5(() => {
|
|
2923
2846
|
const id = "flow-styles";
|
|
2924
2847
|
if (!document.getElementById(id)) {
|
|
2925
2848
|
const style = document.createElement("style");
|
|
@@ -2937,6 +2860,9 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
2937
2860
|
}
|
|
2938
2861
|
});
|
|
2939
2862
|
const [projectLoaded, setProjectLoaded] = useState14(false);
|
|
2863
|
+
const [hfToken, setHfToken] = useState14("");
|
|
2864
|
+
const [hfTokenInput, setHfTokenInput] = useState14("");
|
|
2865
|
+
const [isLoadingFromHF, setIsLoadingFromHF] = useState14(false);
|
|
2940
2866
|
const wsInputRef = useRef6(null);
|
|
2941
2867
|
const startApp = (choice) => {
|
|
2942
2868
|
try {
|
|
@@ -3439,7 +3365,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
3439
3365
|
setTimeout(() => setProjectActionState("idle"), 4e3);
|
|
3440
3366
|
}
|
|
3441
3367
|
};
|
|
3442
|
-
|
|
3368
|
+
useEffect5(() => {
|
|
3443
3369
|
if (activeTab === "setup" || activeTab === "sync") fetchServerProjects();
|
|
3444
3370
|
}, [activeTab]);
|
|
3445
3371
|
if (isFullscreen && currentResult?.base64) {
|
|
@@ -3537,6 +3463,59 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
3537
3463
|
),
|
|
3538
3464
|
!projectLoaded && /* @__PURE__ */ jsx20("span", { className: "text-white/20 text-[10px] text-center", children: "Baum, Bilder und Einstellungen wiederherstellen" })
|
|
3539
3465
|
] }),
|
|
3466
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex flex-col items-center gap-2 w-full max-w-[280px]", children: [
|
|
3467
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex gap-2 w-full", children: [
|
|
3468
|
+
/* @__PURE__ */ jsx20(
|
|
3469
|
+
"input",
|
|
3470
|
+
{
|
|
3471
|
+
type: "password",
|
|
3472
|
+
value: hfTokenInput,
|
|
3473
|
+
onChange: (e) => setHfTokenInput(e.target.value),
|
|
3474
|
+
onKeyDown: (e) => e.key === "Enter" && hfTokenInput.trim() && setHfToken(hfTokenInput.trim()),
|
|
3475
|
+
placeholder: "HF Token (hf_\u2026)",
|
|
3476
|
+
className: "flex-1 rounded-xl px-3 text-[11px] font-mono outline-none",
|
|
3477
|
+
style: { height: 44, background: "rgba(255,255,255,0.05)", border: "1px solid rgba(255,255,255,0.1)", color: "rgba(255,255,255,0.7)" }
|
|
3478
|
+
}
|
|
3479
|
+
),
|
|
3480
|
+
hfTokenInput.trim() && /* @__PURE__ */ jsx20(
|
|
3481
|
+
"button",
|
|
3482
|
+
{
|
|
3483
|
+
onClick: () => setHfToken(hfTokenInput.trim()),
|
|
3484
|
+
className: "px-3 rounded-xl text-[11px] font-bold text-white",
|
|
3485
|
+
style: { background: "#f59e0b", height: 44 },
|
|
3486
|
+
children: "OK"
|
|
3487
|
+
}
|
|
3488
|
+
)
|
|
3489
|
+
] }),
|
|
3490
|
+
hfToken && /* @__PURE__ */ jsxs18(
|
|
3491
|
+
"button",
|
|
3492
|
+
{
|
|
3493
|
+
disabled: isLoadingFromHF,
|
|
3494
|
+
onClick: async () => {
|
|
3495
|
+
setIsLoadingFromHF(true);
|
|
3496
|
+
try {
|
|
3497
|
+
const { hfListProjects: hfListProjects2, hfDownloadProject } = await import("./hfStateService-Y563AT2M.mjs");
|
|
3498
|
+
const projects = await hfListProjects2(hfToken);
|
|
3499
|
+
if (projects.length > 0) {
|
|
3500
|
+
const file = await hfDownloadProject(projects[0].path, hfToken);
|
|
3501
|
+
await handleProjectImport(file);
|
|
3502
|
+
}
|
|
3503
|
+
} catch (e) {
|
|
3504
|
+
alert("HF Fehler: " + e.message);
|
|
3505
|
+
} finally {
|
|
3506
|
+
setIsLoadingFromHF(false);
|
|
3507
|
+
}
|
|
3508
|
+
},
|
|
3509
|
+
className: "w-full flex items-center justify-center gap-3 rounded-2xl font-bold text-[14px] uppercase tracking-wide text-white active:scale-95 transition-transform disabled:opacity-50",
|
|
3510
|
+
style: { height: 56, background: "#f59e0b" },
|
|
3511
|
+
children: [
|
|
3512
|
+
/* @__PURE__ */ jsx20("span", { className: `material-symbols-outlined text-[22px]${isLoadingFromHF ? " animate-spin" : ""}`, children: isLoadingFromHF ? "sync" : "cloud_download" }),
|
|
3513
|
+
isLoadingFromHF ? "Laden\u2026" : "Von HF laden"
|
|
3514
|
+
]
|
|
3515
|
+
}
|
|
3516
|
+
),
|
|
3517
|
+
hfToken && /* @__PURE__ */ jsx20("span", { className: "text-white/20 text-[10px] text-center", children: "Letzten Stand von Hugging Face laden" })
|
|
3518
|
+
] }),
|
|
3540
3519
|
onFetchServerProjects && /* @__PURE__ */ jsxs18("div", { className: "flex flex-col items-center gap-2 w-full max-w-[280px]", children: [
|
|
3541
3520
|
/* @__PURE__ */ jsxs18(
|
|
3542
3521
|
"button",
|
|
@@ -3829,7 +3808,13 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
3829
3808
|
onServerDelete: onServerDelete ? handleServerDelete : void 0,
|
|
3830
3809
|
onRefreshServerProjects: onFetchServerProjects ? fetchServerProjects : void 0,
|
|
3831
3810
|
onComputeSyncDiff: onFetchServerProjects && onServerLoad && onServerSave ? handleComputeSyncDiff : void 0,
|
|
3832
|
-
onExecuteSync: onFetchServerProjects && onServerLoad && onServerSave ? handleExecuteSync : void 0
|
|
3811
|
+
onExecuteSync: onFetchServerProjects && onServerLoad && onServerSave ? handleExecuteSync : void 0,
|
|
3812
|
+
hfToken: hfToken || void 0,
|
|
3813
|
+
onHfLoad: (f) => handleProjectImport(f),
|
|
3814
|
+
onProjectExportBase64: async () => {
|
|
3815
|
+
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)));
|
|
3816
|
+
return base64;
|
|
3817
|
+
}
|
|
3833
3818
|
}
|
|
3834
3819
|
),
|
|
3835
3820
|
activeTab === "tags" && workspaceTags && /* @__PURE__ */ jsx20(
|
|
@@ -4152,7 +4137,13 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4152
4137
|
onServerDelete: onServerDelete ? handleServerDelete : void 0,
|
|
4153
4138
|
onRefreshServerProjects: onFetchServerProjects ? fetchServerProjects : void 0,
|
|
4154
4139
|
onComputeSyncDiff: onFetchServerProjects && onServerLoad && onServerSave ? handleComputeSyncDiff : void 0,
|
|
4155
|
-
onExecuteSync: onFetchServerProjects && onServerLoad && onServerSave ? handleExecuteSync : void 0
|
|
4140
|
+
onExecuteSync: onFetchServerProjects && onServerLoad && onServerSave ? handleExecuteSync : void 0,
|
|
4141
|
+
hfToken: hfToken || void 0,
|
|
4142
|
+
onHfLoad: (f) => handleProjectImport(f),
|
|
4143
|
+
onProjectExportBase64: async () => {
|
|
4144
|
+
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)));
|
|
4145
|
+
return base64;
|
|
4146
|
+
}
|
|
4156
4147
|
}
|
|
4157
4148
|
)
|
|
4158
4149
|
] })
|
|
@@ -4161,7 +4152,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4161
4152
|
}
|
|
4162
4153
|
|
|
4163
4154
|
// src/index.ts
|
|
4164
|
-
var LIB_VERSION = "1.2.
|
|
4155
|
+
var LIB_VERSION = "1.2.5";
|
|
4165
4156
|
export {
|
|
4166
4157
|
AvatarArchitectApp,
|
|
4167
4158
|
CollapsibleCard,
|