@rslsp1/fa-app-tools 1.3.18 → 2.0.13
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-WCFXXLKN.mjs +409 -0
- package/dist/hfStateService-6YYT6ATO.mjs +54 -0
- package/dist/index.d.mts +103 -9
- package/dist/index.d.ts +103 -9
- package/dist/index.js +1514 -557
- package/dist/index.mjs +1277 -511
- package/package.json +5 -4
- package/dist/chunk-X6S5BP36.mjs +0 -232
- package/dist/hfStateService-B62RV5K3.mjs +0 -32
package/dist/index.js
CHANGED
|
@@ -259,13 +259,28 @@ var init_project = __esm({
|
|
|
259
259
|
}
|
|
260
260
|
});
|
|
261
261
|
|
|
262
|
+
// src/lib/hfEventTypes.ts
|
|
263
|
+
var CURRENT_EVENT_VERSION;
|
|
264
|
+
var init_hfEventTypes = __esm({
|
|
265
|
+
"src/lib/hfEventTypes.ts"() {
|
|
266
|
+
"use strict";
|
|
267
|
+
CURRENT_EVENT_VERSION = { major: 1, minor: 0 };
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
|
|
262
271
|
// src/lib/hfStateService.ts
|
|
263
272
|
var hfStateService_exports = {};
|
|
264
273
|
__export(hfStateService_exports, {
|
|
265
274
|
HF_TOKEN_KEY: () => HF_TOKEN_KEY,
|
|
266
275
|
getHFToken: () => getHFToken,
|
|
276
|
+
getSessionClientId: () => getSessionClientId,
|
|
277
|
+
hfBatchArchive: () => hfBatchArchive,
|
|
278
|
+
hfBootstrapFromLegacy: () => hfBootstrapFromLegacy,
|
|
267
279
|
hfDeleteProject: () => hfDeleteProject,
|
|
280
|
+
hfDownloadBinaryByPath: () => hfDownloadBinaryByPath,
|
|
281
|
+
hfDownloadJsonByPath: () => hfDownloadJsonByPath,
|
|
268
282
|
hfDownloadProject: () => hfDownloadProject,
|
|
283
|
+
hfListDir: () => hfListDir,
|
|
269
284
|
hfListProjects: () => hfListProjects,
|
|
270
285
|
hfLoadImageAsBase64: () => hfLoadImageAsBase64,
|
|
271
286
|
hfLoadMetadata: () => hfLoadMetadata,
|
|
@@ -275,7 +290,12 @@ __export(hfStateService_exports, {
|
|
|
275
290
|
hfUploadImage: () => hfUploadImage,
|
|
276
291
|
hfUploadProject: () => hfUploadProject,
|
|
277
292
|
hfUploadProjectForm: () => hfUploadProjectForm,
|
|
278
|
-
|
|
293
|
+
hfUploadSmallFile: () => hfUploadSmallFile,
|
|
294
|
+
loadHFState: () => loadHFState,
|
|
295
|
+
loadPendingEvents: () => loadPendingEvents,
|
|
296
|
+
setHFToken: () => setHFToken,
|
|
297
|
+
tsFromEventPath: () => tsFromEventPath,
|
|
298
|
+
writeHFEvent: () => writeHFEvent
|
|
279
299
|
});
|
|
280
300
|
function getHFToken() {
|
|
281
301
|
try {
|
|
@@ -290,6 +310,177 @@ function setHFToken(token) {
|
|
|
290
310
|
} catch {
|
|
291
311
|
}
|
|
292
312
|
}
|
|
313
|
+
function treeUrl(namespace, subdir = "") {
|
|
314
|
+
const parts = [namespace.replace(/\/$/, ""), subdir].filter(Boolean).join("/");
|
|
315
|
+
return `${HF_BASE}/api/datasets/${HF_REPO}/tree/main${parts ? "/" + parts : ""}`;
|
|
316
|
+
}
|
|
317
|
+
async function hfListDir(namespace, subdir, token) {
|
|
318
|
+
const res = await fetch(treeUrl(namespace, subdir), {
|
|
319
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
320
|
+
});
|
|
321
|
+
if (res.status === 404) return [];
|
|
322
|
+
if (!res.ok) throw new Error(`HF list failed: ${res.status} ${res.statusText}`);
|
|
323
|
+
return res.json();
|
|
324
|
+
}
|
|
325
|
+
async function hfDownloadJsonByPath(repoPath, token) {
|
|
326
|
+
const res = await fetch(
|
|
327
|
+
`${HF_BASE}/datasets/${HF_REPO}/resolve/main/${repoPath}?download=true`,
|
|
328
|
+
{ headers: { Authorization: `Bearer ${token}` } }
|
|
329
|
+
);
|
|
330
|
+
if (!res.ok) throw new Error(`HF download failed: ${res.status}`);
|
|
331
|
+
return res.json();
|
|
332
|
+
}
|
|
333
|
+
async function hfDownloadBinaryByPath(repoPath, token) {
|
|
334
|
+
const res = await fetch(
|
|
335
|
+
`${HF_BASE}/datasets/${HF_REPO}/resolve/main/${repoPath}?download=true`,
|
|
336
|
+
{ headers: { Authorization: `Bearer ${token}` } }
|
|
337
|
+
);
|
|
338
|
+
if (!res.ok) throw new Error(`HF download binary failed: ${res.status}`);
|
|
339
|
+
return new Uint8Array(await res.arrayBuffer());
|
|
340
|
+
}
|
|
341
|
+
async function hfUploadSmallFile(repoPath, content, token, summary = `Update ${repoPath}`) {
|
|
342
|
+
const bytes = new TextEncoder().encode(content);
|
|
343
|
+
let binary = "";
|
|
344
|
+
bytes.forEach((b) => binary += String.fromCharCode(b));
|
|
345
|
+
const b64 = btoa(binary);
|
|
346
|
+
const res = await fetch(`${HF_BASE}/api/datasets/${HF_REPO}/commit/main`, {
|
|
347
|
+
method: "POST",
|
|
348
|
+
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/x-ndjson" },
|
|
349
|
+
body: [
|
|
350
|
+
JSON.stringify({ key: "header", value: { summary, description: "" } }),
|
|
351
|
+
JSON.stringify({ key: "file", value: { path: repoPath, encoding: "base64", content: b64 } })
|
|
352
|
+
].join("\n")
|
|
353
|
+
});
|
|
354
|
+
if (!res.ok) {
|
|
355
|
+
const err = await res.text().catch(() => "");
|
|
356
|
+
throw new Error(`HF upload failed: ${res.status} \u2014 ${err.slice(0, 200)}`);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
async function hfBatchArchive(moves, token, summary) {
|
|
360
|
+
const lines = [
|
|
361
|
+
JSON.stringify({ key: "header", value: { summary, description: "" } }),
|
|
362
|
+
...moves.flatMap(({ from, to, content }) => {
|
|
363
|
+
const bytes = new TextEncoder().encode(content);
|
|
364
|
+
let binary = "";
|
|
365
|
+
bytes.forEach((b) => binary += String.fromCharCode(b));
|
|
366
|
+
return [
|
|
367
|
+
JSON.stringify({ key: "file", value: { path: to, encoding: "base64", content: btoa(binary) } }),
|
|
368
|
+
JSON.stringify({ key: "deletedFile", value: { path: from } })
|
|
369
|
+
];
|
|
370
|
+
})
|
|
371
|
+
];
|
|
372
|
+
const res = await fetch(`${HF_BASE}/api/datasets/${HF_REPO}/commit/main`, {
|
|
373
|
+
method: "POST",
|
|
374
|
+
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/x-ndjson" },
|
|
375
|
+
body: lines.join("\n")
|
|
376
|
+
});
|
|
377
|
+
if (!res.ok) {
|
|
378
|
+
const err = await res.text().catch(() => "");
|
|
379
|
+
throw new Error(`HF batch archive failed: ${res.status} \u2014 ${err.slice(0, 200)}`);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
function tsFromEventPath(repoPath) {
|
|
383
|
+
const filename = repoPath.split("/").pop() || "";
|
|
384
|
+
const iso = filename.replace(/_[^_]+\.json$/, "").replace(/-/g, (m, i) => i > 7 ? ":" : m);
|
|
385
|
+
const ts = Date.parse(iso.replace(/T(\d{2}):(\d{2}):(\d{2})\.(\d{3})Z/, "T$1:$2:$3.$4Z"));
|
|
386
|
+
return isNaN(ts) ? 0 : ts;
|
|
387
|
+
}
|
|
388
|
+
async function loadHFState(namespace, token) {
|
|
389
|
+
const files = await hfListDir(namespace, "", token);
|
|
390
|
+
const stateFiles = files.filter((f) => f.type === "file" && /state-[\dT\-]+Z\.zip$/.test(f.path.split("/").pop() || "")).sort((a, b) => b.path.localeCompare(a.path));
|
|
391
|
+
if (!stateFiles.length) return null;
|
|
392
|
+
const zipBytes = await hfDownloadBinaryByPath(stateFiles[0].path, token);
|
|
393
|
+
const zip = await import_jszip2.default.loadAsync(zipBytes);
|
|
394
|
+
const [metadataStr, tagsStr, metaStr] = await Promise.all([
|
|
395
|
+
zip.file("metadata.json")?.async("string"),
|
|
396
|
+
zip.file("tags.json")?.async("string"),
|
|
397
|
+
zip.file("state_meta.json")?.async("string")
|
|
398
|
+
]);
|
|
399
|
+
if (!metadataStr || !tagsStr || !metaStr) throw new Error("state.zip: fehlende Pflicht-Dateien");
|
|
400
|
+
return {
|
|
401
|
+
metadata: JSON.parse(metadataStr),
|
|
402
|
+
tags: JSON.parse(tagsStr),
|
|
403
|
+
meta: JSON.parse(metaStr)
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
async function loadPendingEvents(namespace, token, sinceTs) {
|
|
407
|
+
const files = await hfListDir(namespace, "events", token);
|
|
408
|
+
const pending = files.filter((f) => f.type === "file" && tsFromEventPath(f.path) > sinceTs).sort((a, b) => a.path.localeCompare(b.path));
|
|
409
|
+
const events = await Promise.all(
|
|
410
|
+
pending.map((f) => hfDownloadJsonByPath(f.path, token))
|
|
411
|
+
);
|
|
412
|
+
return events;
|
|
413
|
+
}
|
|
414
|
+
function getSessionClientId() {
|
|
415
|
+
return SESSION_CLIENT_ID;
|
|
416
|
+
}
|
|
417
|
+
function tsToFilename(ts) {
|
|
418
|
+
return new Date(ts).toISOString().replace(/:/g, "-").replace(".", "-");
|
|
419
|
+
}
|
|
420
|
+
async function writeHFEvent(namespace, token, type, payload, prevTs) {
|
|
421
|
+
const ts = Date.now();
|
|
422
|
+
const uuid = crypto.randomUUID().slice(0, 8);
|
|
423
|
+
const event = {
|
|
424
|
+
v: CURRENT_EVENT_VERSION,
|
|
425
|
+
type,
|
|
426
|
+
ts,
|
|
427
|
+
prevTs,
|
|
428
|
+
clientId: SESSION_CLIENT_ID,
|
|
429
|
+
payload
|
|
430
|
+
};
|
|
431
|
+
const filename = `${tsToFilename(ts)}_${uuid}.json`;
|
|
432
|
+
const repoPath = `${namespace}events/${filename}`;
|
|
433
|
+
await hfUploadSmallFile(repoPath, JSON.stringify(event, null, 2), token, `Event: ${type}`);
|
|
434
|
+
return event;
|
|
435
|
+
}
|
|
436
|
+
async function hfBootstrapFromLegacy(namespace, token, onProgress) {
|
|
437
|
+
const log = (msg) => {
|
|
438
|
+
if (onProgress) onProgress(msg);
|
|
439
|
+
};
|
|
440
|
+
log("Lese tags.json \u2026");
|
|
441
|
+
const tags = await fetch(
|
|
442
|
+
`${HF_BASE}/datasets/${HF_REPO}/resolve/main/tags.json?download=true`,
|
|
443
|
+
{ headers: { Authorization: `Bearer ${token}` } }
|
|
444
|
+
).then((r) => r.ok ? r.json() : null).catch(() => null);
|
|
445
|
+
log("Lese metadata.json \u2026");
|
|
446
|
+
const metadata = await fetch(
|
|
447
|
+
`${HF_BASE}/datasets/${HF_REPO}/resolve/main/metadata.json?download=true`,
|
|
448
|
+
{ headers: { Authorization: `Bearer ${token}` } }
|
|
449
|
+
).then((r) => r.ok ? r.json() : []).catch(() => []);
|
|
450
|
+
const snapshot = {
|
|
451
|
+
metadata: Array.isArray(metadata) ? metadata : [],
|
|
452
|
+
tags: tags?.by_category ? tags : { by_category: {}, all: [] },
|
|
453
|
+
meta: { consolidatedAt: Date.now(), version: 1 }
|
|
454
|
+
};
|
|
455
|
+
log(`Erstelle state.zip (${snapshot.metadata.length} Bilder, ${snapshot.tags.all?.length ?? 0} Tags) \u2026`);
|
|
456
|
+
const zip = new import_jszip2.default();
|
|
457
|
+
zip.file("metadata.json", JSON.stringify(snapshot.metadata, null, 2));
|
|
458
|
+
zip.file("tags.json", JSON.stringify(snapshot.tags, null, 2));
|
|
459
|
+
zip.file("state_meta.json", JSON.stringify(snapshot.meta, null, 2));
|
|
460
|
+
const zipBytes = await zip.generateAsync({ type: "uint8array", compression: "DEFLATE" });
|
|
461
|
+
const ts = snapshot.meta.consolidatedAt;
|
|
462
|
+
const stateFilename = `state-${new Date(ts).toISOString().replace(/:/g, "-").replace(".", "-")}.zip`;
|
|
463
|
+
const repoPath = `${namespace}${stateFilename}`;
|
|
464
|
+
let binary = "";
|
|
465
|
+
zipBytes.forEach((b) => {
|
|
466
|
+
binary += String.fromCharCode(b);
|
|
467
|
+
});
|
|
468
|
+
const b64 = btoa(binary);
|
|
469
|
+
log("Lade state.zip hoch \u2026");
|
|
470
|
+
const commitRes = await fetch(`${HF_BASE}/api/datasets/${HF_REPO}/commit/main`, {
|
|
471
|
+
method: "POST",
|
|
472
|
+
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/x-ndjson" },
|
|
473
|
+
body: [
|
|
474
|
+
JSON.stringify({ key: "header", value: { summary: `Bootstrap: initialer State aus Legacy-Daten`, description: "" } }),
|
|
475
|
+
JSON.stringify({ key: "file", value: { path: repoPath, encoding: "base64", content: b64 } })
|
|
476
|
+
].join("\n")
|
|
477
|
+
});
|
|
478
|
+
if (!commitRes.ok) {
|
|
479
|
+
const err = await commitRes.text().catch(() => "");
|
|
480
|
+
throw new Error(`HF commit failed: ${commitRes.status} \u2014 ${err.slice(0, 300)}`);
|
|
481
|
+
}
|
|
482
|
+
log(`Fertig \u2014 ${stateFilename}`);
|
|
483
|
+
}
|
|
293
484
|
async function hfListProjects(token) {
|
|
294
485
|
const res = await fetch(`${HF_BASE}/api/datasets/${HF_REPO}/tree/main`, {
|
|
295
486
|
headers: { Authorization: `Bearer ${token}` }
|
|
@@ -333,7 +524,6 @@ async function hfUploadProject(zipBase64, name, token) {
|
|
|
333
524
|
if (!preRes.ok) throw new Error(`HF preupload failed: ${preRes.status} ${preRes.statusText}`);
|
|
334
525
|
const preData = await preRes.json();
|
|
335
526
|
const fileInfo = preData.files?.[0];
|
|
336
|
-
const debugInfo = JSON.stringify({ uploadMode: fileInfo?.uploadMode, hasUploadUrl: !!fileInfo?.uploadUrl, hasVerifyUrl: !!fileInfo?.verifyUrl, headerKeys: Object.keys(fileInfo?.header || {}), verifyHeaderKeys: Object.keys(fileInfo?.verifyHeader || {}) });
|
|
337
527
|
if (!fileInfo?.uploadMode) throw new Error(`HF preupload kein fileInfo: ${JSON.stringify(preData)}`);
|
|
338
528
|
if (fileInfo.uploadMode === "lfs" && fileInfo.uploadUrl) {
|
|
339
529
|
let uploadStatus = 0;
|
|
@@ -379,21 +569,8 @@ async function hfUploadProject(zipBase64, name, token) {
|
|
|
379
569
|
}
|
|
380
570
|
return { id: filename.replace(/\.zip$/, ""), name: filename.replace(/\.zip$/, ""), path: filename, size, isLfs: true };
|
|
381
571
|
}
|
|
382
|
-
async function hfUploadProjectForm(
|
|
383
|
-
|
|
384
|
-
const binary = atob(zipBase64);
|
|
385
|
-
const bytes = new Uint8Array(binary.length);
|
|
386
|
-
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
387
|
-
const blob = new Blob([bytes], { type: "application/zip" });
|
|
388
|
-
const { uploadFile } = await import("@huggingface/hub");
|
|
389
|
-
await uploadFile({
|
|
390
|
-
repo: { type: "dataset", name: HF_REPO },
|
|
391
|
-
credentials: { accessToken: token },
|
|
392
|
-
file: { path: filename, content: blob },
|
|
393
|
-
branch: "main",
|
|
394
|
-
commitTitle: `Upload ${filename}`
|
|
395
|
-
});
|
|
396
|
-
return { id: filename.replace(/\.zip$/, ""), name: filename.replace(/\.zip$/, ""), path: filename, size: bytes.length, isLfs: true };
|
|
572
|
+
async function hfUploadProjectForm(_zipBase64, _name, _token) {
|
|
573
|
+
throw new Error("hfUploadProjectForm is deprecated. Use hfUploadProject instead.");
|
|
397
574
|
}
|
|
398
575
|
async function hfDeleteProject(path, token) {
|
|
399
576
|
const res = await fetch(`${HF_BASE}/api/datasets/${HF_REPO}/commit/main`, {
|
|
@@ -406,16 +583,8 @@ async function hfDeleteProject(path, token) {
|
|
|
406
583
|
});
|
|
407
584
|
if (!res.ok) throw new Error(`HF delete failed: ${res.status} ${res.statusText}`);
|
|
408
585
|
}
|
|
409
|
-
async function hfSaveTags(
|
|
410
|
-
|
|
411
|
-
const { uploadFile } = await import("@huggingface/hub");
|
|
412
|
-
await uploadFile({
|
|
413
|
-
repo: { type: "dataset", name: HF_REPO },
|
|
414
|
-
credentials: { accessToken: token },
|
|
415
|
-
file: { path: "tags.json", content },
|
|
416
|
-
branch: "main",
|
|
417
|
-
commitTitle: "Auto-sync tags"
|
|
418
|
-
});
|
|
586
|
+
async function hfSaveTags(_workspaceTags, _token) {
|
|
587
|
+
throw new Error("hfSaveTags is deprecated. Use writeHFEvent instead.");
|
|
419
588
|
}
|
|
420
589
|
async function hfLoadTags(token) {
|
|
421
590
|
try {
|
|
@@ -429,16 +598,8 @@ async function hfLoadTags(token) {
|
|
|
429
598
|
return null;
|
|
430
599
|
}
|
|
431
600
|
}
|
|
432
|
-
async function hfSaveMetadata(
|
|
433
|
-
|
|
434
|
-
const { uploadFile } = await import("@huggingface/hub");
|
|
435
|
-
await uploadFile({
|
|
436
|
-
repo: { type: "dataset", name: HF_REPO },
|
|
437
|
-
credentials: { accessToken: token },
|
|
438
|
-
file: { path: "metadata.json", content },
|
|
439
|
-
branch: "main",
|
|
440
|
-
commitTitle: "Auto-sync metadata"
|
|
441
|
-
});
|
|
601
|
+
async function hfSaveMetadata(_entries, _token) {
|
|
602
|
+
throw new Error("hfSaveMetadata is deprecated. Use writeHFEvent instead.");
|
|
442
603
|
}
|
|
443
604
|
async function hfLoadMetadata(token) {
|
|
444
605
|
try {
|
|
@@ -457,14 +618,32 @@ async function hfUploadImage(base64, id, token, mimeType = "image/jpeg") {
|
|
|
457
618
|
const binary = atob(base64);
|
|
458
619
|
const bytes = new Uint8Array(binary.length);
|
|
459
620
|
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
460
|
-
const
|
|
461
|
-
const
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
621
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", bytes);
|
|
622
|
+
const oid = Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
623
|
+
const size = bytes.length;
|
|
624
|
+
const filename = `images/${id}.${ext}`;
|
|
625
|
+
const preRes = await fetch(`${HF_BASE}/api/datasets/${HF_REPO}/preupload/main`, {
|
|
626
|
+
method: "POST",
|
|
627
|
+
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
|
|
628
|
+
body: JSON.stringify({ files: [{ path: filename, size }] })
|
|
629
|
+
});
|
|
630
|
+
if (!preRes.ok) throw new Error(`HF preupload failed: ${preRes.status}`);
|
|
631
|
+
const preData = await preRes.json();
|
|
632
|
+
const fileInfo = preData.files?.[0];
|
|
633
|
+
if (fileInfo?.uploadUrl) {
|
|
634
|
+
await fetch(fileInfo.uploadUrl, {
|
|
635
|
+
method: "PUT",
|
|
636
|
+
headers: { "Content-Type": mimeType, ...fileInfo.header || {} },
|
|
637
|
+
body: bytes
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
await fetch(`${HF_BASE}/api/datasets/${HF_REPO}/commit/main`, {
|
|
641
|
+
method: "POST",
|
|
642
|
+
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/x-ndjson" },
|
|
643
|
+
body: [
|
|
644
|
+
JSON.stringify({ key: "header", value: { summary: `Add image ${id}`, description: "" } }),
|
|
645
|
+
JSON.stringify({ key: "lfsFile", value: { path: filename, algo: "sha256", oid, size } })
|
|
646
|
+
].join("\n")
|
|
468
647
|
});
|
|
469
648
|
}
|
|
470
649
|
async function hfLoadImageAsBase64(id, token) {
|
|
@@ -488,13 +667,16 @@ async function hfLoadImageAsBase64(id, token) {
|
|
|
488
667
|
}
|
|
489
668
|
return null;
|
|
490
669
|
}
|
|
491
|
-
var HF_BASE, HF_REPO, HF_TOKEN_KEY;
|
|
670
|
+
var import_jszip2, HF_BASE, HF_REPO, HF_TOKEN_KEY, SESSION_CLIENT_ID;
|
|
492
671
|
var init_hfStateService = __esm({
|
|
493
672
|
"src/lib/hfStateService.ts"() {
|
|
494
673
|
"use strict";
|
|
674
|
+
import_jszip2 = __toESM(require("jszip"));
|
|
675
|
+
init_hfEventTypes();
|
|
495
676
|
HF_BASE = "https://huggingface.co";
|
|
496
677
|
HF_REPO = "RolandSch/fa-app-state";
|
|
497
678
|
HF_TOKEN_KEY = "hf-token";
|
|
679
|
+
SESSION_CLIENT_ID = `client-${crypto.randomUUID().slice(0, 8)}`;
|
|
498
680
|
}
|
|
499
681
|
});
|
|
500
682
|
|
|
@@ -524,9 +706,12 @@ __export(index_exports, {
|
|
|
524
706
|
SectionLabel: () => SectionLabel,
|
|
525
707
|
SetupPanel: () => SetupPanel,
|
|
526
708
|
TagManagerPanel: () => TagManagerPanel,
|
|
709
|
+
applyEvent: () => applyEvent,
|
|
710
|
+
applyEvents: () => applyEvents,
|
|
527
711
|
autoLabel: () => autoLabel,
|
|
528
712
|
buildBlendInstruction: () => buildBlendInstruction,
|
|
529
713
|
buildCompareInstruction: () => buildCompareInstruction,
|
|
714
|
+
buildDag: () => buildDag,
|
|
530
715
|
buildFallbackPrompt: () => buildFallbackPrompt,
|
|
531
716
|
buildGenerationPrompt: () => buildGenerationPrompt,
|
|
532
717
|
buildImageGenerationOptions: () => buildImageGenerationOptions,
|
|
@@ -538,29 +723,38 @@ __export(index_exports, {
|
|
|
538
723
|
cleanAiResponse: () => cleanAiResponse,
|
|
539
724
|
createFlowServices: () => createFlowServices,
|
|
540
725
|
exportProjectToZip: () => exportProjectToZip,
|
|
726
|
+
findForks: () => findForks,
|
|
727
|
+
findTips: () => findTips,
|
|
541
728
|
formatTreeToMarkdown: () => formatTreeToMarkdown,
|
|
542
729
|
frameToGeneration: () => frameToGeneration,
|
|
543
730
|
getFormattedTimestamp: () => getFormattedTimestamp,
|
|
544
731
|
getHFToken: () => getHFToken,
|
|
732
|
+
getSessionClientId: () => getSessionClientId,
|
|
545
733
|
groupGenerationsToLabItems: () => groupGenerationsToLabItems,
|
|
734
|
+
hfBatchArchive: () => hfBatchArchive,
|
|
735
|
+
hfBootstrapFromLegacy: () => hfBootstrapFromLegacy,
|
|
546
736
|
hfDeleteProject: () => hfDeleteProject,
|
|
547
737
|
hfDownloadProject: () => hfDownloadProject,
|
|
738
|
+
hfListDir: () => hfListDir,
|
|
548
739
|
hfListProjects: () => hfListProjects,
|
|
549
740
|
hfLoadImageAsBase64: () => hfLoadImageAsBase64,
|
|
550
|
-
hfLoadMetadata: () => hfLoadMetadata,
|
|
551
|
-
hfLoadTags: () => hfLoadTags,
|
|
552
|
-
hfSaveMetadata: () => hfSaveMetadata,
|
|
553
|
-
hfSaveTags: () => hfSaveTags,
|
|
554
741
|
hfUploadImage: () => hfUploadImage,
|
|
555
742
|
hfUploadProjectForm: () => hfUploadProjectForm,
|
|
743
|
+
hfUploadSmallFile: () => hfUploadSmallFile,
|
|
556
744
|
importProjectFromZip: () => importProjectFromZip,
|
|
557
745
|
injectXMPMetadata: () => injectXMPMetadata,
|
|
558
746
|
interpretSdkError: () => interpretSdkError,
|
|
747
|
+
loadHFState: () => loadHFState,
|
|
748
|
+
loadPendingEvents: () => loadPendingEvents,
|
|
559
749
|
parsePromptFile: () => parsePromptFile,
|
|
560
750
|
parsePromptResponse: () => parsePromptResponse,
|
|
561
751
|
setHFToken: () => setHFToken,
|
|
752
|
+
topoSort: () => topoSort,
|
|
753
|
+
tsFromEventPath: () => tsFromEventPath,
|
|
754
|
+
useHFState: () => useHFState,
|
|
562
755
|
useKeyboardNavigation: () => useKeyboardNavigation,
|
|
563
|
-
useOnClickOutside: () => useOnClickOutside
|
|
756
|
+
useOnClickOutside: () => useOnClickOutside,
|
|
757
|
+
writeHFEvent: () => writeHFEvent
|
|
564
758
|
});
|
|
565
759
|
module.exports = __toCommonJS(index_exports);
|
|
566
760
|
|
|
@@ -1343,7 +1537,7 @@ function ListView({ nodes, edges, onNodeChange, onAddChild, onDeleteNode, onMove
|
|
|
1343
1537
|
}
|
|
1344
1538
|
|
|
1345
1539
|
// src/components/AvatarArchitectApp.tsx
|
|
1346
|
-
var
|
|
1540
|
+
var import_react23 = require("react");
|
|
1347
1541
|
|
|
1348
1542
|
// src/components/PromptTab.tsx
|
|
1349
1543
|
var import_react12 = require("react");
|
|
@@ -1871,6 +2065,7 @@ var import_react13 = require("react");
|
|
|
1871
2065
|
init_hfStateService();
|
|
1872
2066
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1873
2067
|
var ProjectSyncTab = ({
|
|
2068
|
+
topSlot,
|
|
1874
2069
|
onProjectExport,
|
|
1875
2070
|
onProjectImport,
|
|
1876
2071
|
onWorkspaceImport,
|
|
@@ -1962,6 +2157,7 @@ var ProjectSyncTab = ({
|
|
|
1962
2157
|
if (hfToken) loadHfProjects(hfToken);
|
|
1963
2158
|
}, [hfToken]);
|
|
1964
2159
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "absolute inset-0 overflow-y-auto dark-scrollbar", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "p-6 flex flex-col gap-8", children: [
|
|
2160
|
+
topSlot && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { children: topSlot }),
|
|
1965
2161
|
(onProjectExport || onProjectImport || onWorkspaceImport) && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-col gap-4", children: [
|
|
1966
2162
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SectionLabel, { children: "Projekt-ZIP" }),
|
|
1967
2163
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
@@ -2370,14 +2566,255 @@ function toPromptImages(images) {
|
|
|
2370
2566
|
// src/components/AvatarArchitectApp.tsx
|
|
2371
2567
|
init_hfStateService();
|
|
2372
2568
|
|
|
2569
|
+
// src/hooks/useHFState.ts
|
|
2570
|
+
var import_react14 = require("react");
|
|
2571
|
+
init_hfStateService();
|
|
2572
|
+
|
|
2573
|
+
// src/lib/hfReducer.ts
|
|
2574
|
+
function applyEvent(state, event) {
|
|
2575
|
+
if (event.v.major > 1) return state;
|
|
2576
|
+
switch (event.type) {
|
|
2577
|
+
case "image_added": {
|
|
2578
|
+
const p = event.payload;
|
|
2579
|
+
if (state.metadata.some((m) => m.id === p.id)) return state;
|
|
2580
|
+
return { ...state, metadata: [...state.metadata, p] };
|
|
2581
|
+
}
|
|
2582
|
+
case "tag_upserted": {
|
|
2583
|
+
const p = event.payload;
|
|
2584
|
+
const tags = state.tags;
|
|
2585
|
+
const cat = tags.by_category[p.category] || [];
|
|
2586
|
+
const existing = cat.find((t) => t.value === p.value);
|
|
2587
|
+
const updated = { label: p.label, value: p.value, is_user_created: p.is_user_created, is_deleted: p.is_deleted };
|
|
2588
|
+
const newCat = existing ? cat.map((t) => t.value === p.value ? { ...t, ...updated } : t) : [...cat, updated];
|
|
2589
|
+
const newAll = tags.all.some((t) => t.value === p.value && t.category === p.category) ? tags.all.map((t) => t.value === p.value && t.category === p.category ? { ...t, ...updated, category: p.category } : t) : [...tags.all, { ...updated, category: p.category }];
|
|
2590
|
+
return { ...state, tags: { by_category: { ...tags.by_category, [p.category]: newCat }, all: newAll } };
|
|
2591
|
+
}
|
|
2592
|
+
case "metadata_updated": {
|
|
2593
|
+
const p = event.payload;
|
|
2594
|
+
return {
|
|
2595
|
+
...state,
|
|
2596
|
+
metadata: state.metadata.map((m) => m.id === p.id ? { ...m, ...p.delta } : m)
|
|
2597
|
+
};
|
|
2598
|
+
}
|
|
2599
|
+
default:
|
|
2600
|
+
return state;
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2603
|
+
function applyEvents(state, events) {
|
|
2604
|
+
return events.reduce(applyEvent, state);
|
|
2605
|
+
}
|
|
2606
|
+
|
|
2607
|
+
// src/lib/hfDag.ts
|
|
2608
|
+
function buildDag(events) {
|
|
2609
|
+
const dag = /* @__PURE__ */ new Map();
|
|
2610
|
+
for (const event of events) {
|
|
2611
|
+
dag.set(event.ts, { event, children: [] });
|
|
2612
|
+
}
|
|
2613
|
+
for (const event of events) {
|
|
2614
|
+
for (const parent of event.prevTs) {
|
|
2615
|
+
const node = dag.get(parent);
|
|
2616
|
+
if (node && !node.children.includes(event.ts)) {
|
|
2617
|
+
node.children.push(event.ts);
|
|
2618
|
+
}
|
|
2619
|
+
}
|
|
2620
|
+
}
|
|
2621
|
+
return dag;
|
|
2622
|
+
}
|
|
2623
|
+
function findTips(dag) {
|
|
2624
|
+
return [...dag.values()].filter((n) => n.children.length === 0).map((n) => n.event.ts);
|
|
2625
|
+
}
|
|
2626
|
+
function findForks(dag) {
|
|
2627
|
+
const forks = [];
|
|
2628
|
+
for (const [ts, node] of dag) {
|
|
2629
|
+
if (node.children.length > 1) {
|
|
2630
|
+
forks.push({ parentTs: ts, childTs: node.children });
|
|
2631
|
+
}
|
|
2632
|
+
}
|
|
2633
|
+
return forks;
|
|
2634
|
+
}
|
|
2635
|
+
function topoSort(events) {
|
|
2636
|
+
if (!events.length) return [];
|
|
2637
|
+
const inDegree = /* @__PURE__ */ new Map();
|
|
2638
|
+
const children = /* @__PURE__ */ new Map();
|
|
2639
|
+
const tsSet = new Set(events.map((e) => e.ts));
|
|
2640
|
+
for (const e of events) {
|
|
2641
|
+
inDegree.set(e.ts, 0);
|
|
2642
|
+
children.set(e.ts, []);
|
|
2643
|
+
}
|
|
2644
|
+
for (const e of events) {
|
|
2645
|
+
for (const p of e.prevTs) {
|
|
2646
|
+
if (tsSet.has(p)) {
|
|
2647
|
+
children.get(p).push(e.ts);
|
|
2648
|
+
inDegree.set(e.ts, (inDegree.get(e.ts) || 0) + 1);
|
|
2649
|
+
}
|
|
2650
|
+
}
|
|
2651
|
+
}
|
|
2652
|
+
const queue = events.filter((e) => (inDegree.get(e.ts) || 0) === 0).sort((a, b) => a.ts - b.ts);
|
|
2653
|
+
const result = [];
|
|
2654
|
+
const byTs = new Map(events.map((e) => [e.ts, e]));
|
|
2655
|
+
while (queue.length) {
|
|
2656
|
+
const node = queue.shift();
|
|
2657
|
+
result.push(node);
|
|
2658
|
+
for (const childTs of children.get(node.ts) || []) {
|
|
2659
|
+
const newDeg = (inDegree.get(childTs) || 0) - 1;
|
|
2660
|
+
inDegree.set(childTs, newDeg);
|
|
2661
|
+
if (newDeg === 0) {
|
|
2662
|
+
const child = byTs.get(childTs);
|
|
2663
|
+
const insertAt = queue.findIndex((q) => q.ts > child.ts);
|
|
2664
|
+
if (insertAt === -1) queue.push(child);
|
|
2665
|
+
else queue.splice(insertAt, 0, child);
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
return result;
|
|
2670
|
+
}
|
|
2671
|
+
|
|
2672
|
+
// src/hooks/useHFState.ts
|
|
2673
|
+
var OFFLINE_BUFFER_KEY = "hf-offline-buffer";
|
|
2674
|
+
var POLL_INTERVAL_MS = 3e4;
|
|
2675
|
+
function readOfflineBuffer() {
|
|
2676
|
+
try {
|
|
2677
|
+
return JSON.parse(localStorage.getItem(OFFLINE_BUFFER_KEY) || "[]");
|
|
2678
|
+
} catch {
|
|
2679
|
+
return [];
|
|
2680
|
+
}
|
|
2681
|
+
}
|
|
2682
|
+
function writeOfflineBuffer(events) {
|
|
2683
|
+
try {
|
|
2684
|
+
localStorage.setItem(OFFLINE_BUFFER_KEY, JSON.stringify(events));
|
|
2685
|
+
} catch {
|
|
2686
|
+
}
|
|
2687
|
+
}
|
|
2688
|
+
function useHFState(token, namespace) {
|
|
2689
|
+
const [state, setState] = (0, import_react14.useState)(null);
|
|
2690
|
+
const [isLoading, setIsLoading] = (0, import_react14.useState)(false);
|
|
2691
|
+
const [error, setError] = (0, import_react14.useState)(null);
|
|
2692
|
+
const [eventCount, setEventCount] = (0, import_react14.useState)(0);
|
|
2693
|
+
const [forks, setForks] = (0, import_react14.useState)([]);
|
|
2694
|
+
const [pendingBufferCount, setPendingBufferCount] = (0, import_react14.useState)(readOfflineBuffer().length);
|
|
2695
|
+
const [lastEventTs, setLastEventTs] = (0, import_react14.useState)(0);
|
|
2696
|
+
const [hasStateZip, setHasStateZip] = (0, import_react14.useState)(false);
|
|
2697
|
+
const knownEventPaths = (0, import_react14.useRef)(/* @__PURE__ */ new Set());
|
|
2698
|
+
const allEventsRef = (0, import_react14.useRef)([]);
|
|
2699
|
+
const applyNewEvents = (0, import_react14.useCallback)((snapshot, newEvents) => {
|
|
2700
|
+
if (!newEvents.length && allEventsRef.current.length === 0) {
|
|
2701
|
+
setEventCount(0);
|
|
2702
|
+
return snapshot;
|
|
2703
|
+
}
|
|
2704
|
+
const sorted = topoSort([...allEventsRef.current, ...newEvents]);
|
|
2705
|
+
allEventsRef.current = sorted;
|
|
2706
|
+
const afterConsolidation = sorted.filter((e) => e.ts > snapshot.meta.consolidatedAt);
|
|
2707
|
+
const dag = buildDag(afterConsolidation);
|
|
2708
|
+
setForks(findForks(dag));
|
|
2709
|
+
setEventCount(afterConsolidation.length);
|
|
2710
|
+
if (afterConsolidation.length) setLastEventTs(Math.max(...afterConsolidation.map((e) => e.ts)));
|
|
2711
|
+
return applyEvents(snapshot, afterConsolidation);
|
|
2712
|
+
}, []);
|
|
2713
|
+
const loadFull = (0, import_react14.useCallback)(async () => {
|
|
2714
|
+
if (!token || !namespace) return;
|
|
2715
|
+
setIsLoading(true);
|
|
2716
|
+
setError(null);
|
|
2717
|
+
try {
|
|
2718
|
+
const snapshot = await loadHFState(namespace, token);
|
|
2719
|
+
setHasStateZip(snapshot !== null);
|
|
2720
|
+
const base = snapshot ?? {
|
|
2721
|
+
metadata: [],
|
|
2722
|
+
tags: { by_category: {}, all: [] },
|
|
2723
|
+
meta: { consolidatedAt: 0, version: 1 }
|
|
2724
|
+
};
|
|
2725
|
+
const events = await loadPendingEvents(namespace, token, base.meta.consolidatedAt);
|
|
2726
|
+
events.forEach((e) => knownEventPaths.current.add(`${e.ts}_${e.clientId}`));
|
|
2727
|
+
allEventsRef.current = [];
|
|
2728
|
+
const finalState = applyNewEvents(base, events);
|
|
2729
|
+
setState(finalState);
|
|
2730
|
+
const buffer = readOfflineBuffer();
|
|
2731
|
+
if (buffer.length) {
|
|
2732
|
+
for (const evt of buffer) {
|
|
2733
|
+
await writeHFEvent(namespace, token, evt.type, evt.payload, evt.prevTs).catch(() => {
|
|
2734
|
+
});
|
|
2735
|
+
}
|
|
2736
|
+
writeOfflineBuffer([]);
|
|
2737
|
+
setPendingBufferCount(0);
|
|
2738
|
+
const freshEvents = await loadPendingEvents(namespace, token, base.meta.consolidatedAt);
|
|
2739
|
+
freshEvents.forEach((e) => knownEventPaths.current.add(`${e.ts}_${e.clientId}`));
|
|
2740
|
+
setState((prev) => prev ? applyNewEvents(base, freshEvents) : prev);
|
|
2741
|
+
}
|
|
2742
|
+
} catch (e) {
|
|
2743
|
+
setError(e.message);
|
|
2744
|
+
} finally {
|
|
2745
|
+
setIsLoading(false);
|
|
2746
|
+
}
|
|
2747
|
+
}, [token, namespace, applyNewEvents]);
|
|
2748
|
+
const pollNew = (0, import_react14.useCallback)(async () => {
|
|
2749
|
+
if (!token || !namespace || !state) return;
|
|
2750
|
+
try {
|
|
2751
|
+
const events = await loadPendingEvents(namespace, token, state.meta.consolidatedAt);
|
|
2752
|
+
const newEvents = events.filter((e) => !knownEventPaths.current.has(`${e.ts}_${e.clientId}`));
|
|
2753
|
+
if (!newEvents.length) return;
|
|
2754
|
+
newEvents.forEach((e) => knownEventPaths.current.add(`${e.ts}_${e.clientId}`));
|
|
2755
|
+
setState((prev) => prev ? applyNewEvents(prev, newEvents) : prev);
|
|
2756
|
+
} catch {
|
|
2757
|
+
}
|
|
2758
|
+
}, [token, namespace, state, applyNewEvents]);
|
|
2759
|
+
(0, import_react14.useEffect)(() => {
|
|
2760
|
+
if (token && namespace) loadFull();
|
|
2761
|
+
}, [token, namespace]);
|
|
2762
|
+
(0, import_react14.useEffect)(() => {
|
|
2763
|
+
if (!token || !namespace) return;
|
|
2764
|
+
const id = setInterval(pollNew, POLL_INTERVAL_MS);
|
|
2765
|
+
return () => clearInterval(id);
|
|
2766
|
+
}, [token, namespace, pollNew]);
|
|
2767
|
+
const writeEvent2 = (0, import_react14.useCallback)(async (type, payload) => {
|
|
2768
|
+
const prevTs = lastEventTs ? [lastEventTs] : [state?.meta.consolidatedAt ?? 0];
|
|
2769
|
+
console.log("[HF] writeEvent called:", { type, namespace, tokenOk: !!token, prevTs });
|
|
2770
|
+
await pollNew();
|
|
2771
|
+
try {
|
|
2772
|
+
console.log("[HF] writeHFEvent start, path will be:", `${namespace}events/...`);
|
|
2773
|
+
const event = await writeHFEvent(namespace, token, type, payload, prevTs);
|
|
2774
|
+
console.log("[HF] writeHFEvent success:", event.ts);
|
|
2775
|
+
knownEventPaths.current.add(`${event.ts}_${event.clientId}`);
|
|
2776
|
+
setState((prev) => prev ? applyNewEvents(prev, [event]) : prev);
|
|
2777
|
+
setLastEventTs(event.ts);
|
|
2778
|
+
await pollNew();
|
|
2779
|
+
} catch (e) {
|
|
2780
|
+
console.error("[HF] writeHFEvent FAILED, going to offline buffer:", e);
|
|
2781
|
+
const buffer = readOfflineBuffer();
|
|
2782
|
+
const offline = {
|
|
2783
|
+
v: { major: 1, minor: 0 },
|
|
2784
|
+
type,
|
|
2785
|
+
ts: Date.now(),
|
|
2786
|
+
prevTs,
|
|
2787
|
+
clientId: getSessionClientId(),
|
|
2788
|
+
payload
|
|
2789
|
+
};
|
|
2790
|
+
writeOfflineBuffer([...buffer, offline]);
|
|
2791
|
+
setPendingBufferCount(buffer.length + 1);
|
|
2792
|
+
setState((prev) => prev ? applyNewEvents(prev, [offline]) : prev);
|
|
2793
|
+
}
|
|
2794
|
+
}, [namespace, token, lastEventTs, state, pollNew, applyNewEvents]);
|
|
2795
|
+
return {
|
|
2796
|
+
state,
|
|
2797
|
+
isLoading,
|
|
2798
|
+
error,
|
|
2799
|
+
pendingBufferCount,
|
|
2800
|
+
eventCount,
|
|
2801
|
+
forks,
|
|
2802
|
+
writeEvent: writeEvent2,
|
|
2803
|
+
refresh: loadFull,
|
|
2804
|
+
lastEventTs,
|
|
2805
|
+
allEvents: allEventsRef.current,
|
|
2806
|
+
hasStateZip
|
|
2807
|
+
};
|
|
2808
|
+
}
|
|
2809
|
+
|
|
2373
2810
|
// src/components/labs/LabsTab.tsx
|
|
2374
|
-
var
|
|
2811
|
+
var import_react20 = require("react");
|
|
2375
2812
|
|
|
2376
2813
|
// src/components/labs/LabRemix.tsx
|
|
2377
|
-
var
|
|
2814
|
+
var import_react16 = require("react");
|
|
2378
2815
|
|
|
2379
2816
|
// src/components/labs/LabImagePicker.tsx
|
|
2380
|
-
var
|
|
2817
|
+
var import_react15 = require("react");
|
|
2381
2818
|
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
2382
2819
|
var LabImagePicker = ({
|
|
2383
2820
|
availableItems,
|
|
@@ -2386,8 +2823,8 @@ var LabImagePicker = ({
|
|
|
2386
2823
|
onClose,
|
|
2387
2824
|
title = "Bild w\xE4hlen"
|
|
2388
2825
|
}) => {
|
|
2389
|
-
const [search, setSearch] = (0,
|
|
2390
|
-
const [drillItem, setDrillItem] = (0,
|
|
2826
|
+
const [search, setSearch] = (0, import_react15.useState)("");
|
|
2827
|
+
const [drillItem, setDrillItem] = (0, import_react15.useState)(null);
|
|
2391
2828
|
const filtered = availableItems.filter(
|
|
2392
2829
|
(item) => !search || item.prompt.toLowerCase().includes(search.toLowerCase())
|
|
2393
2830
|
);
|
|
@@ -2489,13 +2926,13 @@ var LabImagePicker = ({
|
|
|
2489
2926
|
// src/components/labs/LabRemix.tsx
|
|
2490
2927
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
2491
2928
|
var LabRemix = ({ services, onResult }) => {
|
|
2492
|
-
const [showPicker, setShowPicker] = (0,
|
|
2493
|
-
const [selected, setSelected] = (0,
|
|
2494
|
-
const [instruction, setInstruction] = (0,
|
|
2495
|
-
const [generatedPrompt, setGeneratedPrompt] = (0,
|
|
2496
|
-
const [resultImage, setResultImage] = (0,
|
|
2497
|
-
const [isGeneratingPrompt, setIsGeneratingPrompt] = (0,
|
|
2498
|
-
const [isGeneratingImage, setIsGeneratingImage] = (0,
|
|
2929
|
+
const [showPicker, setShowPicker] = (0, import_react16.useState)(false);
|
|
2930
|
+
const [selected, setSelected] = (0, import_react16.useState)(null);
|
|
2931
|
+
const [instruction, setInstruction] = (0, import_react16.useState)("");
|
|
2932
|
+
const [generatedPrompt, setGeneratedPrompt] = (0, import_react16.useState)("");
|
|
2933
|
+
const [resultImage, setResultImage] = (0, import_react16.useState)(null);
|
|
2934
|
+
const [isGeneratingPrompt, setIsGeneratingPrompt] = (0, import_react16.useState)(false);
|
|
2935
|
+
const [isGeneratingImage, setIsGeneratingImage] = (0, import_react16.useState)(false);
|
|
2499
2936
|
const handleSelectImage = (item, frame) => {
|
|
2500
2937
|
services.onItemUsed(item);
|
|
2501
2938
|
setSelected({
|
|
@@ -2678,16 +3115,16 @@ var LabRemix = ({ services, onResult }) => {
|
|
|
2678
3115
|
};
|
|
2679
3116
|
|
|
2680
3117
|
// src/components/labs/LabBlend.tsx
|
|
2681
|
-
var
|
|
3118
|
+
var import_react17 = require("react");
|
|
2682
3119
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
2683
3120
|
var LabBlend = ({ services, onResult }) => {
|
|
2684
|
-
const [showPickerFor, setShowPickerFor] = (0,
|
|
2685
|
-
const [selectedImages, setSelectedImages] = (0,
|
|
2686
|
-
const [instruction, setInstruction] = (0,
|
|
2687
|
-
const [generatedPrompt, setGeneratedPrompt] = (0,
|
|
2688
|
-
const [resultImage, setResultImage] = (0,
|
|
2689
|
-
const [isGeneratingPrompt, setIsGeneratingPrompt] = (0,
|
|
2690
|
-
const [isGeneratingImage, setIsGeneratingImage] = (0,
|
|
3121
|
+
const [showPickerFor, setShowPickerFor] = (0, import_react17.useState)(null);
|
|
3122
|
+
const [selectedImages, setSelectedImages] = (0, import_react17.useState)([]);
|
|
3123
|
+
const [instruction, setInstruction] = (0, import_react17.useState)("");
|
|
3124
|
+
const [generatedPrompt, setGeneratedPrompt] = (0, import_react17.useState)("");
|
|
3125
|
+
const [resultImage, setResultImage] = (0, import_react17.useState)(null);
|
|
3126
|
+
const [isGeneratingPrompt, setIsGeneratingPrompt] = (0, import_react17.useState)(false);
|
|
3127
|
+
const [isGeneratingImage, setIsGeneratingImage] = (0, import_react17.useState)(false);
|
|
2691
3128
|
const handleSelectImage = (index, item, frame) => {
|
|
2692
3129
|
services.onItemUsed(item);
|
|
2693
3130
|
const newImg = {
|
|
@@ -2874,17 +3311,17 @@ var LabBlend = ({ services, onResult }) => {
|
|
|
2874
3311
|
};
|
|
2875
3312
|
|
|
2876
3313
|
// src/components/labs/LabCompare.tsx
|
|
2877
|
-
var
|
|
3314
|
+
var import_react18 = require("react");
|
|
2878
3315
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
2879
3316
|
var LabCompare = ({ services, onResult }) => {
|
|
2880
|
-
const [showPickerFor, setShowPickerFor] = (0,
|
|
2881
|
-
const [selectedImages, setSelectedImages] = (0,
|
|
2882
|
-
const [instruction, setInstruction] = (0,
|
|
2883
|
-
const [analysis, setAnalysis] = (0,
|
|
2884
|
-
const [generatedPrompt, setGeneratedPrompt] = (0,
|
|
2885
|
-
const [resultImage, setResultImage] = (0,
|
|
2886
|
-
const [isAnalyzing, setIsAnalyzing] = (0,
|
|
2887
|
-
const [isGeneratingImage, setIsGeneratingImage] = (0,
|
|
3317
|
+
const [showPickerFor, setShowPickerFor] = (0, import_react18.useState)(null);
|
|
3318
|
+
const [selectedImages, setSelectedImages] = (0, import_react18.useState)([]);
|
|
3319
|
+
const [instruction, setInstruction] = (0, import_react18.useState)("");
|
|
3320
|
+
const [analysis, setAnalysis] = (0, import_react18.useState)("");
|
|
3321
|
+
const [generatedPrompt, setGeneratedPrompt] = (0, import_react18.useState)("");
|
|
3322
|
+
const [resultImage, setResultImage] = (0, import_react18.useState)(null);
|
|
3323
|
+
const [isAnalyzing, setIsAnalyzing] = (0, import_react18.useState)(false);
|
|
3324
|
+
const [isGeneratingImage, setIsGeneratingImage] = (0, import_react18.useState)(false);
|
|
2888
3325
|
const handleSelectImage = (index, item, frame) => {
|
|
2889
3326
|
services.onItemUsed(item);
|
|
2890
3327
|
const newImg = {
|
|
@@ -3047,14 +3484,14 @@ var LabCompare = ({ services, onResult }) => {
|
|
|
3047
3484
|
};
|
|
3048
3485
|
|
|
3049
3486
|
// src/components/labs/LabLoop.tsx
|
|
3050
|
-
var
|
|
3487
|
+
var import_react19 = require("react");
|
|
3051
3488
|
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
3052
3489
|
var LabLoop = ({ services, onResult }) => {
|
|
3053
|
-
const [rounds, setRounds] = (0,
|
|
3054
|
-
const [currentInstruction, setCurrentInstruction] = (0,
|
|
3055
|
-
const [showPickerForRound, setShowPickerForRound] = (0,
|
|
3056
|
-
const [pendingImages, setPendingImages] = (0,
|
|
3057
|
-
const [isGenerating, setIsGenerating] = (0,
|
|
3490
|
+
const [rounds, setRounds] = (0, import_react19.useState)([]);
|
|
3491
|
+
const [currentInstruction, setCurrentInstruction] = (0, import_react19.useState)("");
|
|
3492
|
+
const [showPickerForRound, setShowPickerForRound] = (0, import_react19.useState)(null);
|
|
3493
|
+
const [pendingImages, setPendingImages] = (0, import_react19.useState)([]);
|
|
3494
|
+
const [isGenerating, setIsGenerating] = (0, import_react19.useState)(false);
|
|
3058
3495
|
const currentPrompt = rounds.length > 0 ? rounds[rounds.length - 1].prompt : "";
|
|
3059
3496
|
const handleAddImage = (item, frame) => {
|
|
3060
3497
|
services.onItemUsed(item);
|
|
@@ -3218,7 +3655,7 @@ var TABS = [
|
|
|
3218
3655
|
{ key: "loop", label: "Loop", icon: "loop" }
|
|
3219
3656
|
];
|
|
3220
3657
|
var LabsTab = ({ services, onResult }) => {
|
|
3221
|
-
const [activeTab, setActiveTab] = (0,
|
|
3658
|
+
const [activeTab, setActiveTab] = (0, import_react20.useState)("remix");
|
|
3222
3659
|
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex flex-col h-full overflow-hidden", children: [
|
|
3223
3660
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex border-b border-white/5 shrink-0", children: TABS.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
3224
3661
|
"button",
|
|
@@ -3242,19 +3679,19 @@ var LabsTab = ({ services, onResult }) => {
|
|
|
3242
3679
|
};
|
|
3243
3680
|
|
|
3244
3681
|
// src/components/TagManagerPanel.tsx
|
|
3245
|
-
var
|
|
3682
|
+
var import_react21 = require("react");
|
|
3246
3683
|
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
3247
3684
|
function TagManagerPanel({ workspaceTags, onTagCreate, onTagUpdate, onTagDelete, onTagReorder, onTagMove }) {
|
|
3248
3685
|
const categories = Object.keys(workspaceTags.by_category).filter(
|
|
3249
3686
|
(cat) => (workspaceTags.by_category[cat] || []).some((t) => !t.is_deleted)
|
|
3250
3687
|
);
|
|
3251
|
-
const [selectedCategory, setSelectedCategory] = (0,
|
|
3688
|
+
const [selectedCategory, setSelectedCategory] = (0, import_react21.useState)(categories[0] || "");
|
|
3252
3689
|
const effectiveCategory = categories.includes(selectedCategory) ? selectedCategory : categories[0] || "";
|
|
3253
|
-
const [editingLabel, setEditingLabel] = (0,
|
|
3254
|
-
const [editState, setEditState] = (0,
|
|
3255
|
-
const [newTag, setNewTag] = (0,
|
|
3256
|
-
const [movingLabel, setMovingLabel] = (0,
|
|
3257
|
-
const [moveTarget, setMoveTarget] = (0,
|
|
3690
|
+
const [editingLabel, setEditingLabel] = (0, import_react21.useState)(null);
|
|
3691
|
+
const [editState, setEditState] = (0, import_react21.useState)({ label: "", value: "" });
|
|
3692
|
+
const [newTag, setNewTag] = (0, import_react21.useState)({ label: "", value: "" });
|
|
3693
|
+
const [movingLabel, setMovingLabel] = (0, import_react21.useState)(null);
|
|
3694
|
+
const [moveTarget, setMoveTarget] = (0, import_react21.useState)("");
|
|
3258
3695
|
const tags = (workspaceTags.by_category[effectiveCategory] || []).filter((t) => !t.is_deleted);
|
|
3259
3696
|
const otherCategories = categories.filter((c) => c !== effectiveCategory);
|
|
3260
3697
|
const startEdit = (tag) => {
|
|
@@ -3449,10 +3886,449 @@ function TagManagerPanel({ workspaceTags, onTagCreate, onTagUpdate, onTagDelete,
|
|
|
3449
3886
|
] });
|
|
3450
3887
|
}
|
|
3451
3888
|
|
|
3452
|
-
// src/components/
|
|
3889
|
+
// src/components/HFTestTab.tsx
|
|
3890
|
+
var import_react22 = require("react");
|
|
3453
3891
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
3454
|
-
|
|
3455
|
-
|
|
3892
|
+
var HF_BASE2 = "https://huggingface.co";
|
|
3893
|
+
var HF_REPO2 = "RolandSch/fa-app-state";
|
|
3894
|
+
var TEST_DIR = "test";
|
|
3895
|
+
async function doFetch(label, url, init = {}) {
|
|
3896
|
+
const rawHeaders = init.headers || {};
|
|
3897
|
+
const sanitized = Object.fromEntries(
|
|
3898
|
+
Object.entries(rawHeaders).map(
|
|
3899
|
+
([k, v]) => k.toLowerCase() === "authorization" ? [k, v.replace(/Bearer\s+\S+/, (m) => "Bearer " + m.slice(7, 14) + "***")] : [k, v]
|
|
3900
|
+
)
|
|
3901
|
+
);
|
|
3902
|
+
const s = {
|
|
3903
|
+
label,
|
|
3904
|
+
method: init.method || "GET",
|
|
3905
|
+
url,
|
|
3906
|
+
reqHeaders: sanitized,
|
|
3907
|
+
reqBody: init.body ? typeof init.body === "string" ? init.body.length > 800 ? init.body.slice(0, 800) + "\n\u2026[truncated]" : init.body : "[binary data]" : void 0
|
|
3908
|
+
};
|
|
3909
|
+
const t0 = Date.now();
|
|
3910
|
+
try {
|
|
3911
|
+
const r = await fetch(url, init);
|
|
3912
|
+
s.durationMs = Date.now() - t0;
|
|
3913
|
+
s.resStatus = r.status;
|
|
3914
|
+
s.resStatusText = r.statusText;
|
|
3915
|
+
const body = await r.text().catch(() => "");
|
|
3916
|
+
s.resBody = body.length > 3e3 ? body.slice(0, 3e3) + "\n\u2026[truncated]" : body;
|
|
3917
|
+
s.ok = r.ok;
|
|
3918
|
+
} catch (e) {
|
|
3919
|
+
s.durationMs = Date.now() - t0;
|
|
3920
|
+
s.error = String(e?.message ?? e);
|
|
3921
|
+
s.ok = false;
|
|
3922
|
+
}
|
|
3923
|
+
return s;
|
|
3924
|
+
}
|
|
3925
|
+
function toBase64(bytes) {
|
|
3926
|
+
let bin = "";
|
|
3927
|
+
bytes.forEach((b) => bin += String.fromCharCode(b));
|
|
3928
|
+
return btoa(bin);
|
|
3929
|
+
}
|
|
3930
|
+
async function sha256hex(bytes) {
|
|
3931
|
+
const buf = await crypto.subtle.digest("SHA-256", bytes);
|
|
3932
|
+
return Array.from(new Uint8Array(buf)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
3933
|
+
}
|
|
3934
|
+
function b64ToBytes(b64) {
|
|
3935
|
+
const raw = b64.includes(",") ? b64.split(",")[1] : b64;
|
|
3936
|
+
const bin = atob(raw);
|
|
3937
|
+
const bytes = new Uint8Array(bin.length);
|
|
3938
|
+
for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
|
|
3939
|
+
return bytes;
|
|
3940
|
+
}
|
|
3941
|
+
function rawB64(dataUrl) {
|
|
3942
|
+
return dataUrl.includes(",") ? dataUrl.split(",")[1] : dataUrl;
|
|
3943
|
+
}
|
|
3944
|
+
async function uploadDirect(token, path, b64content) {
|
|
3945
|
+
const ndjson = [
|
|
3946
|
+
JSON.stringify({ key: "header", value: { summary: `HF Test: upload ${path}`, description: "" } }),
|
|
3947
|
+
JSON.stringify({ key: "file", value: { path, encoding: "base64", content: b64content } })
|
|
3948
|
+
].join("\n");
|
|
3949
|
+
return [await doFetch(
|
|
3950
|
+
"POST commit (direct, kein LFS)",
|
|
3951
|
+
`${HF_BASE2}/api/datasets/${HF_REPO2}/commit/main`,
|
|
3952
|
+
{ method: "POST", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/x-ndjson" }, body: ndjson }
|
|
3953
|
+
)];
|
|
3954
|
+
}
|
|
3955
|
+
async function uploadLFS(token, path, bytes) {
|
|
3956
|
+
const oid = await sha256hex(bytes);
|
|
3957
|
+
const size = bytes.length;
|
|
3958
|
+
const sample = toBase64(bytes.slice(0, 512));
|
|
3959
|
+
const steps = [];
|
|
3960
|
+
const pre = await doFetch("Preupload (LFS-URL anfordern)", `${HF_BASE2}/api/datasets/${HF_REPO2}/preupload/main`, {
|
|
3961
|
+
method: "POST",
|
|
3962
|
+
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
|
|
3963
|
+
body: JSON.stringify({ files: [{ path, size, sample }] })
|
|
3964
|
+
});
|
|
3965
|
+
steps.push(pre);
|
|
3966
|
+
if (!pre.ok) return steps;
|
|
3967
|
+
let fi;
|
|
3968
|
+
try {
|
|
3969
|
+
fi = JSON.parse(pre.resBody || "{}").files?.[0];
|
|
3970
|
+
} catch {
|
|
3971
|
+
}
|
|
3972
|
+
if (!fi) {
|
|
3973
|
+
steps.push({ label: "Parse", method: "-", url: "-", reqHeaders: {}, resBody: "Kein files[0] in preupload response", ok: false });
|
|
3974
|
+
return steps;
|
|
3975
|
+
}
|
|
3976
|
+
if (fi.uploadMode === "lfs" && fi.uploadUrl) {
|
|
3977
|
+
const up = await doFetch("PUT to LFS upload URL", fi.uploadUrl, {
|
|
3978
|
+
method: "PUT",
|
|
3979
|
+
headers: { "Content-Type": "application/octet-stream", ...fi.header || {} },
|
|
3980
|
+
body: bytes
|
|
3981
|
+
});
|
|
3982
|
+
steps.push(up);
|
|
3983
|
+
if (!up.ok) return steps;
|
|
3984
|
+
if (fi.verifyUrl) {
|
|
3985
|
+
const ver = await doFetch("POST LFS verify", fi.verifyUrl, {
|
|
3986
|
+
method: "POST",
|
|
3987
|
+
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", ...fi.verifyHeader || {} },
|
|
3988
|
+
body: JSON.stringify({ oid, size })
|
|
3989
|
+
});
|
|
3990
|
+
steps.push(ver);
|
|
3991
|
+
if (!ver.ok) return steps;
|
|
3992
|
+
}
|
|
3993
|
+
} else {
|
|
3994
|
+
steps.push({ label: "Info", method: "-", url: "-", reqHeaders: {}, resBody: `uploadMode="${fi.uploadMode}" \xB7 uploadUrl: ${fi.uploadUrl ? "ja" : "nein"} \u2192 ${!fi.uploadUrl ? "bereits in LFS (Deduplizierung)" : "kein LFS n\xF6tig"}`, ok: true });
|
|
3995
|
+
}
|
|
3996
|
+
const ndjson = [
|
|
3997
|
+
JSON.stringify({ key: "header", value: { summary: `HF Test: LFS commit ${path}`, description: "" } }),
|
|
3998
|
+
JSON.stringify({ key: "lfsFile", value: { path, algo: "sha256", oid, size } })
|
|
3999
|
+
].join("\n");
|
|
4000
|
+
steps.push(await doFetch("Commit (lfsFile reference)", `${HF_BASE2}/api/datasets/${HF_REPO2}/commit/main`, {
|
|
4001
|
+
method: "POST",
|
|
4002
|
+
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/x-ndjson" },
|
|
4003
|
+
body: ndjson
|
|
4004
|
+
}));
|
|
4005
|
+
return steps;
|
|
4006
|
+
}
|
|
4007
|
+
async function uploadViaHubLib(token, path, bytes, mimeType) {
|
|
4008
|
+
const s = { label: "uploadFile() via @huggingface/hub", method: "import()+call", url: "@huggingface/hub", reqHeaders: {} };
|
|
4009
|
+
const t0 = Date.now();
|
|
4010
|
+
try {
|
|
4011
|
+
const { uploadFile } = await import(
|
|
4012
|
+
/* @vite-ignore */
|
|
4013
|
+
"@huggingface/hub"
|
|
4014
|
+
);
|
|
4015
|
+
await uploadFile({
|
|
4016
|
+
repo: { type: "dataset", name: HF_REPO2 },
|
|
4017
|
+
credentials: { accessToken: token },
|
|
4018
|
+
file: { path, content: new Blob([bytes], { type: mimeType }) },
|
|
4019
|
+
branch: "main",
|
|
4020
|
+
commitTitle: `HF Test: hub lib upload ${path}`
|
|
4021
|
+
});
|
|
4022
|
+
s.durationMs = Date.now() - t0;
|
|
4023
|
+
s.resBody = "SUCCESS";
|
|
4024
|
+
s.ok = true;
|
|
4025
|
+
} catch (e) {
|
|
4026
|
+
s.durationMs = Date.now() - t0;
|
|
4027
|
+
s.error = String(e?.message ?? e);
|
|
4028
|
+
s.ok = false;
|
|
4029
|
+
}
|
|
4030
|
+
return [s];
|
|
4031
|
+
}
|
|
4032
|
+
async function uploadViaCdnLib(token, path, bytes, mimeType) {
|
|
4033
|
+
const s = { label: "uploadFile() via esm.sh/@huggingface/hub", method: "import()+call", url: "https://esm.sh/@huggingface/hub", reqHeaders: {} };
|
|
4034
|
+
const t0 = Date.now();
|
|
4035
|
+
try {
|
|
4036
|
+
const { uploadFile } = await import(
|
|
4037
|
+
/* @vite-ignore */
|
|
4038
|
+
"https://esm.sh/@huggingface/hub"
|
|
4039
|
+
);
|
|
4040
|
+
await uploadFile({
|
|
4041
|
+
repo: { type: "dataset", name: HF_REPO2 },
|
|
4042
|
+
credentials: { accessToken: token },
|
|
4043
|
+
file: { path, content: new Blob([bytes], { type: mimeType }) },
|
|
4044
|
+
branch: "main",
|
|
4045
|
+
commitTitle: `HF Test: CDN hub lib upload ${path}`
|
|
4046
|
+
});
|
|
4047
|
+
s.durationMs = Date.now() - t0;
|
|
4048
|
+
s.resBody = "SUCCESS";
|
|
4049
|
+
s.ok = true;
|
|
4050
|
+
} catch (e) {
|
|
4051
|
+
s.durationMs = Date.now() - t0;
|
|
4052
|
+
s.error = String(e?.message ?? e);
|
|
4053
|
+
s.ok = false;
|
|
4054
|
+
}
|
|
4055
|
+
return [s];
|
|
4056
|
+
}
|
|
4057
|
+
async function writeEvent(token, namespace) {
|
|
4058
|
+
const ns = namespace.endsWith("/") ? namespace : namespace ? namespace + "/" : "";
|
|
4059
|
+
const ts = Date.now();
|
|
4060
|
+
const uuid = crypto.randomUUID().slice(0, 8);
|
|
4061
|
+
const isoTs = new Date(ts).toISOString().replace(/:/g, "-").replace(".", "-");
|
|
4062
|
+
const eventPath = `${ns}${TEST_DIR}/events/${isoTs}_${uuid}.json`;
|
|
4063
|
+
const event = JSON.stringify({ v: { major: 1, minor: 0 }, type: "probe", ts, prevTs: [], clientId: "hf-test-tab", payload: { test: true } }, null, 2);
|
|
4064
|
+
const b64 = toBase64(new TextEncoder().encode(event));
|
|
4065
|
+
const ndjson = [
|
|
4066
|
+
JSON.stringify({ key: "header", value: { summary: "HF Test: write event", description: "" } }),
|
|
4067
|
+
JSON.stringify({ key: "file", value: { path: eventPath, encoding: "base64", content: b64 } })
|
|
4068
|
+
].join("\n");
|
|
4069
|
+
return [await doFetch(
|
|
4070
|
+
`Event \u2192 ${eventPath}`,
|
|
4071
|
+
`${HF_BASE2}/api/datasets/${HF_REPO2}/commit/main`,
|
|
4072
|
+
{ method: "POST", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/x-ndjson" }, body: ndjson }
|
|
4073
|
+
)];
|
|
4074
|
+
}
|
|
4075
|
+
function tryFmt(s) {
|
|
4076
|
+
try {
|
|
4077
|
+
return JSON.stringify(JSON.parse(s), null, 2);
|
|
4078
|
+
} catch {
|
|
4079
|
+
return s;
|
|
4080
|
+
}
|
|
4081
|
+
}
|
|
4082
|
+
function CopyBtn({ text }) {
|
|
4083
|
+
const [done, setDone] = (0, import_react22.useState)(false);
|
|
4084
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
4085
|
+
"button",
|
|
4086
|
+
{
|
|
4087
|
+
onClick: () => {
|
|
4088
|
+
navigator.clipboard?.writeText(text).catch(() => {
|
|
4089
|
+
});
|
|
4090
|
+
setDone(true);
|
|
4091
|
+
setTimeout(() => setDone(false), 1500);
|
|
4092
|
+
},
|
|
4093
|
+
style: { background: "none", border: "1px solid rgba(255,255,255,0.15)", borderRadius: 5, color: done ? "#4ade80" : "rgba(255,255,255,0.45)", fontSize: 10, padding: "3px 8px", cursor: "pointer", fontFamily: "inherit", display: "flex", alignItems: "center", gap: 3 },
|
|
4094
|
+
children: [
|
|
4095
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: done ? "check" : "content_copy" }),
|
|
4096
|
+
done ? "Kopiert" : "Copy"
|
|
4097
|
+
]
|
|
4098
|
+
}
|
|
4099
|
+
);
|
|
4100
|
+
}
|
|
4101
|
+
function StepView({ step }) {
|
|
4102
|
+
const isSpecial = step.method === "-" || step.method === "import()" || step.method === "import()+call";
|
|
4103
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { marginBottom: 6, background: "rgba(0,0,0,0.3)", borderRadius: 7, padding: "7px 9px", border: `1px solid ${step.ok === false ? "rgba(248,113,113,0.2)" : "rgba(255,255,255,0.05)"}` }, children: [
|
|
4104
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6, marginBottom: 4 }, children: [
|
|
4105
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { style: { fontSize: 11, fontWeight: 700, color: step.ok === false ? "#f87171" : "#4ade80" }, children: step.ok === false ? "\u2717" : "\u2713" }),
|
|
4106
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { style: { fontSize: 11, fontWeight: 600, color: "rgba(255,255,255,0.7)", flex: 1 }, children: step.label }),
|
|
4107
|
+
step.durationMs !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { style: { fontSize: 10, color: "rgba(255,255,255,0.3)" }, children: [
|
|
4108
|
+
step.durationMs,
|
|
4109
|
+
"ms"
|
|
4110
|
+
] }),
|
|
4111
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(CopyBtn, { text: JSON.stringify(step, null, 2) })
|
|
4112
|
+
] }),
|
|
4113
|
+
!isSpecial && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { marginBottom: 5 }, children: [
|
|
4114
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { fontSize: 10, color: "rgba(255,255,255,0.25)", marginBottom: 2 }, children: [
|
|
4115
|
+
"\u2192 ",
|
|
4116
|
+
step.method,
|
|
4117
|
+
" ",
|
|
4118
|
+
step.url
|
|
4119
|
+
] }),
|
|
4120
|
+
Object.keys(step.reqHeaders).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("pre", { style: { fontSize: 9, color: "rgba(255,255,255,0.35)", margin: "2px 0", padding: "3px 5px", background: "rgba(255,255,255,0.03)", borderRadius: 3, whiteSpace: "pre-wrap", wordBreak: "break-all", maxHeight: 60, overflow: "auto" }, children: Object.entries(step.reqHeaders).map(([k, v]) => `${k}: ${v}`).join("\n") }),
|
|
4121
|
+
step.reqBody && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("pre", { style: { fontSize: 9, color: "rgba(255,255,255,0.35)", margin: "2px 0", padding: "3px 5px", background: "rgba(255,255,255,0.03)", borderRadius: 3, whiteSpace: "pre-wrap", wordBreak: "break-all", maxHeight: 80, overflow: "auto" }, children: step.reqBody })
|
|
4122
|
+
] }),
|
|
4123
|
+
step.error && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("pre", { style: { fontSize: 11, color: "#f87171", margin: 0, padding: "3px 5px", background: "rgba(248,113,113,0.05)", borderRadius: 3, whiteSpace: "pre-wrap", wordBreak: "break-all" }, children: step.error }),
|
|
4124
|
+
!step.error && (step.resStatus !== void 0 || step.resBody) && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { children: [
|
|
4125
|
+
step.resStatus !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { fontSize: 11, fontWeight: 700, color: (step.resStatus || 0) < 300 ? "#4ade80" : "#f87171", marginBottom: 3 }, children: [
|
|
4126
|
+
"\u2190 ",
|
|
4127
|
+
step.resStatus,
|
|
4128
|
+
" ",
|
|
4129
|
+
step.resStatusText
|
|
4130
|
+
] }),
|
|
4131
|
+
step.resBody && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("pre", { style: { fontSize: 9, color: "rgba(255,255,255,0.55)", margin: 0, padding: "3px 5px", background: "rgba(255,255,255,0.03)", borderRadius: 3, whiteSpace: "pre-wrap", wordBreak: "break-all", maxHeight: 180, overflow: "auto" }, children: tryFmt(step.resBody) })
|
|
4132
|
+
] })
|
|
4133
|
+
] });
|
|
4134
|
+
}
|
|
4135
|
+
function TestCard({
|
|
4136
|
+
id,
|
|
4137
|
+
label,
|
|
4138
|
+
icon,
|
|
4139
|
+
desc,
|
|
4140
|
+
disabled,
|
|
4141
|
+
state,
|
|
4142
|
+
onRun,
|
|
4143
|
+
expanded,
|
|
4144
|
+
onToggle
|
|
4145
|
+
}) {
|
|
4146
|
+
const hasResult = state && state.status !== "idle";
|
|
4147
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { marginBottom: 8, background: "rgba(255,255,255,0.03)", borderRadius: 10, border: `1px solid ${state?.status === "ok" ? "rgba(74,222,128,0.15)" : state?.status === "error" ? "rgba(248,113,113,0.15)" : "rgba(255,255,255,0.07)"}`, overflow: "hidden" }, children: [
|
|
4148
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8, padding: "9px 10px" }, children: [
|
|
4149
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18, color: state?.status === "ok" ? "#4ade80" : state?.status === "error" ? "#f87171" : state?.status === "running" ? "#60a5fa" : "rgba(255,255,255,0.35)", flexShrink: 0 }, children: state?.status === "ok" ? "check_circle" : state?.status === "error" ? "error" : state?.status === "running" ? "hourglass_top" : icon }),
|
|
4150
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
4151
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { fontSize: 13, fontWeight: 700, color: "#fff" }, children: label }),
|
|
4152
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { fontSize: 10, color: "rgba(255,255,255,0.3)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: desc })
|
|
4153
|
+
] }),
|
|
4154
|
+
hasResult && state?.status !== "running" && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { onClick: onToggle, style: { background: "none", border: "none", color: "rgba(255,255,255,0.3)", cursor: "pointer", padding: 2, lineHeight: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: expanded ? "expand_less" : "expand_more" }) }),
|
|
4155
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
4156
|
+
"button",
|
|
4157
|
+
{
|
|
4158
|
+
onClick: onRun,
|
|
4159
|
+
disabled,
|
|
4160
|
+
style: { background: disabled ? "transparent" : "#0284c7", border: "1px solid rgba(255,255,255,0.1)", borderRadius: 6, color: "#fff", fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.05em", padding: "5px 10px", cursor: disabled ? "default" : "pointer", opacity: disabled ? 0.35 : 1, fontFamily: "inherit", flexShrink: 0 },
|
|
4161
|
+
children: state?.status === "running" ? "\u2026" : "Run"
|
|
4162
|
+
}
|
|
4163
|
+
)
|
|
4164
|
+
] }),
|
|
4165
|
+
hasResult && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { borderTop: "1px solid rgba(255,255,255,0.05)" }, children: [
|
|
4166
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { padding: "4px 10px 5px", display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
4167
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { style: { fontSize: 11, fontWeight: 700, color: state.status === "ok" ? "#4ade80" : "#f87171" }, children: state.status === "ok" ? "\u2713 OK" : state.status === "running" ? "\u2026" : "\u2717 Fehler" }),
|
|
4168
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { style: { fontSize: 10, color: "rgba(255,255,255,0.3)" }, children: [
|
|
4169
|
+
state.totalMs,
|
|
4170
|
+
"ms \xB7 ",
|
|
4171
|
+
state.steps.length,
|
|
4172
|
+
" Step",
|
|
4173
|
+
state.steps.length !== 1 ? "s" : ""
|
|
4174
|
+
] }),
|
|
4175
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { flex: 1 } }),
|
|
4176
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(CopyBtn, { text: JSON.stringify(state, null, 2) })
|
|
4177
|
+
] }),
|
|
4178
|
+
expanded && state.steps.map((step, i) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { padding: "0 10px 4px" }, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(StepView, { step }) }, i))
|
|
4179
|
+
] })
|
|
4180
|
+
] });
|
|
4181
|
+
}
|
|
4182
|
+
function HFTestTab({ token, namespace, galleryItems }) {
|
|
4183
|
+
const [selected, setSelected] = (0, import_react22.useState)(null);
|
|
4184
|
+
const [results, setResults] = (0, import_react22.useState)({});
|
|
4185
|
+
const [expanded, setExpanded] = (0, import_react22.useState)({});
|
|
4186
|
+
const withResults = galleryItems.filter((g) => g.base64 && g.status === "done");
|
|
4187
|
+
const setRunning = (id) => setResults((r) => ({ ...r, [id]: { status: "running", steps: [], totalMs: 0 } }));
|
|
4188
|
+
const setDone = (id, steps, t0) => {
|
|
4189
|
+
const ok = steps.length > 0 && steps.every((s) => s.ok !== false);
|
|
4190
|
+
setResults((r) => ({ ...r, [id]: { status: ok ? "ok" : "error", steps, totalMs: Date.now() - t0 } }));
|
|
4191
|
+
setExpanded((e) => ({ ...e, [id]: true }));
|
|
4192
|
+
};
|
|
4193
|
+
const run = async (id) => {
|
|
4194
|
+
const isImgTest = id !== "event";
|
|
4195
|
+
if (isImgTest && !selected?.base64) return;
|
|
4196
|
+
setRunning(id);
|
|
4197
|
+
const t0 = Date.now();
|
|
4198
|
+
let steps = [];
|
|
4199
|
+
try {
|
|
4200
|
+
if (isImgTest) {
|
|
4201
|
+
const bytes = b64ToBytes(selected.base64);
|
|
4202
|
+
const imgPath = `${TEST_DIR}/${selected.id}.jpg`;
|
|
4203
|
+
switch (id) {
|
|
4204
|
+
case "img-direct":
|
|
4205
|
+
steps = await uploadDirect(token, imgPath, rawB64(selected.base64));
|
|
4206
|
+
break;
|
|
4207
|
+
case "img-lfs":
|
|
4208
|
+
steps = await uploadLFS(token, imgPath, bytes);
|
|
4209
|
+
break;
|
|
4210
|
+
case "img-hub":
|
|
4211
|
+
steps = await uploadViaHubLib(token, imgPath, bytes, "image/jpeg");
|
|
4212
|
+
break;
|
|
4213
|
+
case "img-cdn":
|
|
4214
|
+
steps = await uploadViaCdnLib(token, imgPath, bytes, "image/jpeg");
|
|
4215
|
+
break;
|
|
4216
|
+
}
|
|
4217
|
+
} else {
|
|
4218
|
+
steps = await writeEvent(token, namespace);
|
|
4219
|
+
}
|
|
4220
|
+
} catch (e) {
|
|
4221
|
+
steps = [{ label: "Unexpected error", method: "-", url: "-", reqHeaders: {}, error: String(e?.message ?? e), ok: false }];
|
|
4222
|
+
}
|
|
4223
|
+
setDone(id, steps, t0);
|
|
4224
|
+
};
|
|
4225
|
+
const noToken = !token;
|
|
4226
|
+
const noImg = !selected;
|
|
4227
|
+
const imgTests = [
|
|
4228
|
+
{ id: "img-direct", label: "Upload Direct", icon: "upload_file", desc: "POST commit + file+base64 (kein LFS)" },
|
|
4229
|
+
{ id: "img-lfs", label: "Upload LFS", icon: "cloud_upload", desc: "preupload \u2192 PUT LFS \u2192 verify \u2192 commit" },
|
|
4230
|
+
{ id: "img-hub", label: "Upload hub lib", icon: "package_2", desc: "uploadFile() via @huggingface/hub" },
|
|
4231
|
+
{ id: "img-cdn", label: "Upload CDN lib", icon: "language", desc: "uploadFile() via esm.sh hub lib" }
|
|
4232
|
+
];
|
|
4233
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { display: "flex", flexDirection: "column", height: "100%", overflowY: "auto", padding: "12px 10px 80px", boxSizing: "border-box", fontFamily: "inherit" }, children: [
|
|
4234
|
+
noToken && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { marginBottom: 10, padding: "8px 12px", background: "rgba(248,113,113,0.08)", borderRadius: 8, border: "1px solid rgba(248,113,113,0.2)", fontSize: 12, color: "#f87171" }, children: "Kein HF-Token geladen \u2014 bitte zuerst Token im Sync-Tab eingeben." }),
|
|
4235
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { marginBottom: 14 }, children: [
|
|
4236
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { fontSize: 10, fontWeight: 700, color: "rgba(255,255,255,0.3)", textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 8 }, children: [
|
|
4237
|
+
"Bild ausw\xE4hlen (",
|
|
4238
|
+
withResults.length,
|
|
4239
|
+
" verf\xFCgbar)"
|
|
4240
|
+
] }),
|
|
4241
|
+
withResults.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { fontSize: 12, color: "rgba(255,255,255,0.3)", fontStyle: "italic" }, children: "Noch keine Bilder in der Galerie. Generiere zuerst ein Bild oder lade von HF." }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 6 }, children: withResults.slice(0, 12).map((g) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
4242
|
+
"button",
|
|
4243
|
+
{
|
|
4244
|
+
onClick: () => setSelected(g),
|
|
4245
|
+
style: { padding: 0, border: `2px solid ${selected?.id === g.id ? "#0284c7" : "transparent"}`, borderRadius: 6, cursor: "pointer", overflow: "hidden", background: "none", lineHeight: 0 },
|
|
4246
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
4247
|
+
"img",
|
|
4248
|
+
{
|
|
4249
|
+
src: g.base64,
|
|
4250
|
+
alt: g.prompt || g.id,
|
|
4251
|
+
style: { width: "100%", aspectRatio: "1", objectFit: "cover", display: "block", borderRadius: 4 }
|
|
4252
|
+
}
|
|
4253
|
+
)
|
|
4254
|
+
},
|
|
4255
|
+
g.id
|
|
4256
|
+
)) }),
|
|
4257
|
+
selected && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { marginTop: 10, display: "flex", gap: 10, alignItems: "flex-start" }, children: [
|
|
4258
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
4259
|
+
"img",
|
|
4260
|
+
{
|
|
4261
|
+
src: selected.base64,
|
|
4262
|
+
style: { width: 80, height: 80, objectFit: "cover", borderRadius: 8, border: "1px solid rgba(255,255,255,0.1)", flexShrink: 0 }
|
|
4263
|
+
}
|
|
4264
|
+
),
|
|
4265
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
4266
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { fontSize: 11, fontWeight: 700, color: "rgba(255,255,255,0.7)", marginBottom: 2 }, children: "Ausgew\xE4hlt" }),
|
|
4267
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { fontSize: 10, color: "rgba(255,255,255,0.3)", wordBreak: "break-all" }, children: [
|
|
4268
|
+
"ID: ",
|
|
4269
|
+
selected.id
|
|
4270
|
+
] }),
|
|
4271
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { fontSize: 10, color: "rgba(255,255,255,0.3)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", marginTop: 2 }, children: [
|
|
4272
|
+
"Ziel: test/",
|
|
4273
|
+
selected.id,
|
|
4274
|
+
".jpg"
|
|
4275
|
+
] }),
|
|
4276
|
+
selected.prompt && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { fontSize: 10, color: "rgba(255,255,255,0.25)", marginTop: 2, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: selected.prompt })
|
|
4277
|
+
] })
|
|
4278
|
+
] })
|
|
4279
|
+
] }),
|
|
4280
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { marginBottom: 18 }, children: [
|
|
4281
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { fontSize: 10, fontWeight: 700, color: "rgba(255,255,255,0.3)", textTransform: "uppercase", letterSpacing: "0.1em", marginBottom: 8, borderBottom: "1px solid rgba(255,255,255,0.06)", paddingBottom: 4 }, children: [
|
|
4282
|
+
"Bild hochladen \u2192 test/",
|
|
4283
|
+
"{",
|
|
4284
|
+
"id",
|
|
4285
|
+
"}",
|
|
4286
|
+
".jpg"
|
|
4287
|
+
] }),
|
|
4288
|
+
imgTests.map((t) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
4289
|
+
TestCard,
|
|
4290
|
+
{
|
|
4291
|
+
id: t.id,
|
|
4292
|
+
label: t.label,
|
|
4293
|
+
icon: t.icon,
|
|
4294
|
+
desc: t.desc,
|
|
4295
|
+
disabled: noToken || noImg || results[t.id]?.status === "running",
|
|
4296
|
+
state: results[t.id],
|
|
4297
|
+
onRun: () => run(t.id),
|
|
4298
|
+
expanded: !!expanded[t.id],
|
|
4299
|
+
onToggle: () => setExpanded((e) => ({ ...e, [t.id]: !e[t.id] }))
|
|
4300
|
+
},
|
|
4301
|
+
t.id
|
|
4302
|
+
))
|
|
4303
|
+
] }),
|
|
4304
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { children: [
|
|
4305
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { fontSize: 10, fontWeight: 700, color: "rgba(255,255,255,0.3)", textTransform: "uppercase", letterSpacing: "0.1em", marginBottom: 8, borderBottom: "1px solid rgba(255,255,255,0.06)", paddingBottom: 4 }, children: [
|
|
4306
|
+
"Event schreiben \u2192 ",
|
|
4307
|
+
namespace || "(kein namespace)",
|
|
4308
|
+
"test/events/"
|
|
4309
|
+
] }),
|
|
4310
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
4311
|
+
TestCard,
|
|
4312
|
+
{
|
|
4313
|
+
id: "event",
|
|
4314
|
+
label: "Write Event",
|
|
4315
|
+
icon: "bolt",
|
|
4316
|
+
desc: "Kleines JSON-Event hochladen (direct commit)",
|
|
4317
|
+
disabled: noToken || results["event"]?.status === "running",
|
|
4318
|
+
state: results["event"],
|
|
4319
|
+
onRun: () => run("event"),
|
|
4320
|
+
expanded: !!expanded["event"],
|
|
4321
|
+
onToggle: () => setExpanded((e) => ({ ...e, event: !e.event }))
|
|
4322
|
+
}
|
|
4323
|
+
)
|
|
4324
|
+
] })
|
|
4325
|
+
] });
|
|
4326
|
+
}
|
|
4327
|
+
|
|
4328
|
+
// src/components/AvatarArchitectApp.tsx
|
|
4329
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
4330
|
+
function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onSelectMedia, buildInfo, initialHfToken, hfNamespace, allowDevNamespace, onFetchServerProjects, onServerSave, onServerLoad, onServerDelete }) {
|
|
4331
|
+
(0, import_react23.useEffect)(() => {
|
|
3456
4332
|
const id = "flow-styles";
|
|
3457
4333
|
if (!document.getElementById(id)) {
|
|
3458
4334
|
const style = document.createElement("style");
|
|
@@ -3461,22 +4337,92 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
3461
4337
|
document.head.appendChild(style);
|
|
3462
4338
|
}
|
|
3463
4339
|
}, []);
|
|
3464
|
-
const [showStart, setShowStart] = (0,
|
|
3465
|
-
const [layoutChoice, setLayoutChoice] = (0,
|
|
4340
|
+
const [showStart, setShowStart] = (0, import_react23.useState)(true);
|
|
4341
|
+
const [layoutChoice, setLayoutChoice] = (0, import_react23.useState)(() => {
|
|
3466
4342
|
try {
|
|
3467
4343
|
return localStorage.getItem("aa-layout") || null;
|
|
3468
4344
|
} catch {
|
|
3469
4345
|
return null;
|
|
3470
4346
|
}
|
|
3471
4347
|
});
|
|
3472
|
-
const [projectLoaded, setProjectLoaded] = (0,
|
|
3473
|
-
const [hfToken, setHfToken] = (0,
|
|
3474
|
-
const [hfTokenInput, setHfTokenInput] = (0,
|
|
3475
|
-
const [isLoadingFromHF, setIsLoadingFromHF] = (0,
|
|
3476
|
-
const [
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
4348
|
+
const [projectLoaded, setProjectLoaded] = (0, import_react23.useState)(false);
|
|
4349
|
+
const [hfToken, setHfToken] = (0, import_react23.useState)(initialHfToken || "");
|
|
4350
|
+
const [hfTokenInput, setHfTokenInput] = (0, import_react23.useState)(initialHfToken || "");
|
|
4351
|
+
const [isLoadingFromHF, setIsLoadingFromHF] = (0, import_react23.useState)(false);
|
|
4352
|
+
const [hfNamespaceLocal, setHfNamespaceLocal] = (0, import_react23.useState)(() => {
|
|
4353
|
+
try {
|
|
4354
|
+
const stored = localStorage.getItem("aa-hf-namespace");
|
|
4355
|
+
if (stored !== null) return stored;
|
|
4356
|
+
return allowDevNamespace ? "app.art-by-rolands.de/" : "";
|
|
4357
|
+
} catch {
|
|
4358
|
+
return "";
|
|
4359
|
+
}
|
|
4360
|
+
});
|
|
4361
|
+
const [hfNamespaceFromServer, setHfNamespaceFromServer] = (0, import_react23.useState)(null);
|
|
4362
|
+
(0, import_react23.useEffect)(() => {
|
|
4363
|
+
if (hfNamespace !== void 0) return;
|
|
4364
|
+
const backendUrl = typeof window !== "undefined" ? window.BACKEND_URL || window.location.origin : null;
|
|
4365
|
+
if (!backendUrl) return;
|
|
4366
|
+
fetch(`${backendUrl}/api/status`).then((r) => r.json()).then((d) => {
|
|
4367
|
+
if (typeof d.hfNamespace === "string" && d.hfNamespace) setHfNamespaceFromServer(d.hfNamespace);
|
|
4368
|
+
}).catch(() => {
|
|
4369
|
+
});
|
|
4370
|
+
}, [hfNamespace]);
|
|
4371
|
+
const effectiveNamespace = hfNamespace ?? hfNamespaceFromServer ?? hfNamespaceLocal;
|
|
4372
|
+
const {
|
|
4373
|
+
state: hfState,
|
|
4374
|
+
isLoading: isHfRefreshing,
|
|
4375
|
+
pendingBufferCount,
|
|
4376
|
+
eventCount,
|
|
4377
|
+
writeEvent: hfWriteEvent,
|
|
4378
|
+
refresh: refreshHF,
|
|
4379
|
+
hasStateZip
|
|
4380
|
+
} = useHFState(hfToken, effectiveNamespace);
|
|
4381
|
+
const [bootstrapLog, setBootstrapLog] = (0, import_react23.useState)([]);
|
|
4382
|
+
const [isBootstrapping, setIsBootstrapping] = (0, import_react23.useState)(false);
|
|
4383
|
+
const syncTopSlot = /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
4384
|
+
pendingBufferCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { background: "linear-gradient(90deg,#f59e0b,#ef4444)", padding: "4px 10px", fontSize: 11, color: "#fff", borderRadius: 4, marginBottom: 4 }, children: [
|
|
4385
|
+
pendingBufferCount,
|
|
4386
|
+
" \xC4nderung",
|
|
4387
|
+
pendingBufferCount > 1 ? "en" : "",
|
|
4388
|
+
" lokal \u2014 bei Flow-Reload verloren wenn nicht synchronisiert"
|
|
4389
|
+
] }),
|
|
4390
|
+
eventCount > 100 && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { background: "#dc2626", color: "#fff", padding: "5px 10px", borderRadius: 4, marginBottom: 4, fontWeight: 600, fontSize: 11 }, children: [
|
|
4391
|
+
"\u26A0 ",
|
|
4392
|
+
eventCount,
|
|
4393
|
+
" Events nicht konsolidiert \u2014 Konsolidierung dringend empfohlen"
|
|
4394
|
+
] }),
|
|
4395
|
+
eventCount > 50 && eventCount <= 100 && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { background: "#44403c", color: "#a8a29e", padding: "4px 10px", borderRadius: 4, marginBottom: 4, fontSize: 11 }, children: [
|
|
4396
|
+
eventCount,
|
|
4397
|
+
" Events seit letzter Konsolidierung \u2014 Konsolidierung empfohlen"
|
|
4398
|
+
] }),
|
|
4399
|
+
hfToken && !hasStateZip && !isHfRefreshing && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { background: "#1c1917", border: "1px solid #44403c", borderRadius: 6, padding: "10px 12px" }, children: [
|
|
4400
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { fontSize: 12, color: "#a8a29e", marginBottom: 6 }, children: effectiveNamespace ? `Kein State-Snapshot in HF (${effectiveNamespace}) \u2014 aus Legacy-Daten (tags.json + metadata.json) migrieren?` : "Namespace wird geladen\u2026" }),
|
|
4401
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4402
|
+
"button",
|
|
4403
|
+
{
|
|
4404
|
+
disabled: isBootstrapping || !effectiveNamespace,
|
|
4405
|
+
onClick: async () => {
|
|
4406
|
+
setIsBootstrapping(true);
|
|
4407
|
+
setBootstrapLog([]);
|
|
4408
|
+
try {
|
|
4409
|
+
await hfBootstrapFromLegacy(effectiveNamespace, hfToken, (msg) => setBootstrapLog((prev) => [...prev, msg]));
|
|
4410
|
+
setBootstrapLog((prev) => [...prev, "\u2713 Fertig"]);
|
|
4411
|
+
setTimeout(() => refreshHF(), 1500);
|
|
4412
|
+
} catch (e) {
|
|
4413
|
+
setBootstrapLog((prev) => [...prev, `Fehler: ${e.message}`]);
|
|
4414
|
+
} finally {
|
|
4415
|
+
setIsBootstrapping(false);
|
|
4416
|
+
}
|
|
4417
|
+
},
|
|
4418
|
+
style: { padding: "5px 12px", background: "#0ea5e9", color: "#fff", border: "none", borderRadius: 4, cursor: isBootstrapping || !effectiveNamespace ? "not-allowed" : "pointer", fontSize: 11, fontWeight: 600, opacity: isBootstrapping || !effectiveNamespace ? 0.6 : 1 },
|
|
4419
|
+
children: isBootstrapping ? "Migriere\u2026" : "Legacy-Migration starten"
|
|
4420
|
+
}
|
|
4421
|
+
),
|
|
4422
|
+
bootstrapLog.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { marginTop: 6, fontFamily: "monospace", fontSize: 10, color: "#78716c", lineHeight: 1.6 }, children: bootstrapLog.map((l, i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { children: l }, i)) })
|
|
4423
|
+
] })
|
|
4424
|
+
] });
|
|
4425
|
+
const wsInputRef = (0, import_react23.useRef)(null);
|
|
3480
4426
|
const startApp = (choice) => {
|
|
3481
4427
|
try {
|
|
3482
4428
|
localStorage.setItem("aa-layout", choice);
|
|
@@ -3485,70 +4431,110 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
3485
4431
|
setLayoutChoice(choice);
|
|
3486
4432
|
setShowStart(false);
|
|
3487
4433
|
};
|
|
3488
|
-
const [nodes, setNodes] = (0,
|
|
3489
|
-
const [edges, setEdges] = (0,
|
|
3490
|
-
const [history, setHistory] = (0,
|
|
3491
|
-
const [galleryItems, setGalleryItems] = (0,
|
|
3492
|
-
const galleryItemsRef = (0,
|
|
3493
|
-
(0,
|
|
4434
|
+
const [nodes, setNodes] = (0, import_react23.useState)([{ id: "1", type: "custom", position: { x: 0, y: 0 }, data: { label: "Fine Art Project", placeholder: "Name..." } }]);
|
|
4435
|
+
const [edges, setEdges] = (0, import_react23.useState)([]);
|
|
4436
|
+
const [history, setHistory] = (0, import_react23.useState)([]);
|
|
4437
|
+
const [galleryItems, setGalleryItems] = (0, import_react23.useState)([]);
|
|
4438
|
+
const galleryItemsRef = (0, import_react23.useRef)([]);
|
|
4439
|
+
(0, import_react23.useEffect)(() => {
|
|
3494
4440
|
galleryItemsRef.current = galleryItems;
|
|
3495
4441
|
}, [galleryItems]);
|
|
3496
|
-
const
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
4442
|
+
const hfImageNotFoundRef = (0, import_react23.useRef)(/* @__PURE__ */ new Set());
|
|
4443
|
+
(0, import_react23.useEffect)(() => {
|
|
4444
|
+
if (!hfState) return;
|
|
4445
|
+
if (hfState.tags?.by_category) setWorkspaceTags(hfState.tags);
|
|
4446
|
+
const hfIds = new Set(hfState.metadata.map((m) => m.id));
|
|
4447
|
+
const skeletons = hfState.metadata.map((m) => ({
|
|
4448
|
+
id: m.id,
|
|
4449
|
+
nodeId: m.id,
|
|
4450
|
+
prompt: m.prompt,
|
|
4451
|
+
seed: m.seed,
|
|
4452
|
+
model: m.model,
|
|
4453
|
+
tags: m.tags || [],
|
|
4454
|
+
timestamp: m.timestamp,
|
|
4455
|
+
status: "done"
|
|
4456
|
+
}));
|
|
4457
|
+
setGalleryItems((prev) => {
|
|
4458
|
+
const localOnly = prev.filter((g) => !hfIds.has(g.id));
|
|
4459
|
+
const merged = skeletons.map((s) => prev.find((g) => g.id === s.id) ?? s);
|
|
4460
|
+
return [...localOnly, ...merged];
|
|
4461
|
+
});
|
|
4462
|
+
setHistory((prev) => {
|
|
4463
|
+
const localOnly = prev.filter((g) => !hfIds.has(g.id));
|
|
4464
|
+
const merged = skeletons.map((s) => prev.find((g) => g.id === s.id) ?? s);
|
|
4465
|
+
return [...localOnly, ...merged];
|
|
4466
|
+
});
|
|
4467
|
+
for (const entry of hfState.metadata) {
|
|
4468
|
+
if (hfImageNotFoundRef.current.has(entry.id)) continue;
|
|
4469
|
+
hfLoadImageAsBase64(entry.id, hfToken).then((b64) => {
|
|
4470
|
+
if (!b64) {
|
|
4471
|
+
hfImageNotFoundRef.current.add(entry.id);
|
|
4472
|
+
return;
|
|
4473
|
+
}
|
|
4474
|
+
const prefix = `data:${entry.mimeType || "image/jpeg"};base64,`;
|
|
4475
|
+
setGalleryItems((prev) => prev.map((g) => g.id === entry.id && !g.base64 ? { ...g, base64: prefix + b64 } : g));
|
|
4476
|
+
setHistory((prev) => prev.map((g) => g.id === entry.id && !g.base64 ? { ...g, base64: prefix + b64 } : g));
|
|
4477
|
+
}).catch(() => {
|
|
4478
|
+
hfImageNotFoundRef.current.add(entry.id);
|
|
4479
|
+
});
|
|
4480
|
+
}
|
|
4481
|
+
}, [hfState]);
|
|
4482
|
+
const [activePrompt, setActivePrompt] = (0, import_react23.useState)("");
|
|
4483
|
+
const [isSynthesizing, setIsSynthesizing] = (0, import_react23.useState)(false);
|
|
4484
|
+
const [activeGenerationsCount, setActiveGenerationsCount] = (0, import_react23.useState)(0);
|
|
4485
|
+
const [currentResult, setCurrentResult] = (0, import_react23.useState)(null);
|
|
4486
|
+
const [focusedNodeId, setFocusedNodeId] = (0, import_react23.useState)(null);
|
|
4487
|
+
const [leftTab, setLeftTab] = (0, import_react23.useState)("prompt");
|
|
4488
|
+
const [promptFeedback, setPromptFeedback] = (0, import_react23.useState)(null);
|
|
4489
|
+
const [lastPromptPayload, setLastPromptPayload] = (0, import_react23.useState)(null);
|
|
4490
|
+
const [isPromptTabGenerating, setIsPromptTabGenerating] = (0, import_react23.useState)(false);
|
|
4491
|
+
const [activeTab, setActiveTab] = (0, import_react23.useState)("history");
|
|
4492
|
+
const [mobileTab, setMobileTab] = (0, import_react23.useState)("stage");
|
|
4493
|
+
const [middlePanel, setMiddlePanel] = (0, import_react23.useState)("stage");
|
|
4494
|
+
const [recentLabItems, setRecentLabItems] = (0, import_react23.useState)([]);
|
|
4495
|
+
const [aspectRatio, setAspectRatio] = (0, import_react23.useState)("1:1");
|
|
4496
|
+
const [selectedModel, setSelectedModel] = (0, import_react23.useState)("\u{1F34C} Nano Banana Pro");
|
|
4497
|
+
const [seed, setSeed] = (0, import_react23.useState)(Math.floor(Math.random() * 1e6));
|
|
4498
|
+
const [seedMode, setSeedMode] = (0, import_react23.useState)("random");
|
|
4499
|
+
const [isLeftCollapsed, setIsLeftCollapsed] = (0, import_react23.useState)(false);
|
|
4500
|
+
const [isRightCollapsed, setIsRightCollapsed] = (0, import_react23.useState)(false);
|
|
4501
|
+
const [leftPanelWidth, setLeftPanelWidth] = (0, import_react23.useState)(() => {
|
|
3516
4502
|
try {
|
|
3517
4503
|
return parseInt(localStorage.getItem("aa-left-width") || "260", 10);
|
|
3518
4504
|
} catch {
|
|
3519
4505
|
return 260;
|
|
3520
4506
|
}
|
|
3521
4507
|
});
|
|
3522
|
-
const [rightPanelWidth, setRightPanelWidth] = (0,
|
|
4508
|
+
const [rightPanelWidth, setRightPanelWidth] = (0, import_react23.useState)(() => {
|
|
3523
4509
|
try {
|
|
3524
4510
|
return parseInt(localStorage.getItem("aa-right-width") || "320", 10);
|
|
3525
4511
|
} catch {
|
|
3526
4512
|
return 320;
|
|
3527
4513
|
}
|
|
3528
4514
|
});
|
|
3529
|
-
const [isPromptCollapsed, setIsPromptCollapsed] = (0,
|
|
3530
|
-
const [projectActionState, setProjectActionState] = (0,
|
|
3531
|
-
const syncServerDataRef = (0,
|
|
3532
|
-
const [workspaceTags, setWorkspaceTags] = (0,
|
|
3533
|
-
const [serverProjects, setServerProjects] = (0,
|
|
3534
|
-
const [isLoadingFromServer, setIsLoadingFromServer] = (0,
|
|
3535
|
-
const [highContrast, setHighContrast] = (0,
|
|
4515
|
+
const [isPromptCollapsed, setIsPromptCollapsed] = (0, import_react23.useState)(false);
|
|
4516
|
+
const [projectActionState, setProjectActionState] = (0, import_react23.useState)("idle");
|
|
4517
|
+
const syncServerDataRef = (0, import_react23.useRef)(null);
|
|
4518
|
+
const [workspaceTags, setWorkspaceTags] = (0, import_react23.useState)(null);
|
|
4519
|
+
const [serverProjects, setServerProjects] = (0, import_react23.useState)([]);
|
|
4520
|
+
const [isLoadingFromServer, setIsLoadingFromServer] = (0, import_react23.useState)(false);
|
|
4521
|
+
const [highContrast, setHighContrast] = (0, import_react23.useState)(() => {
|
|
3536
4522
|
try {
|
|
3537
4523
|
return localStorage.getItem("aa-contrast") === "high";
|
|
3538
4524
|
} catch {
|
|
3539
4525
|
return false;
|
|
3540
4526
|
}
|
|
3541
4527
|
});
|
|
3542
|
-
const [activeReferenceId, setActiveReferenceId] = (0,
|
|
3543
|
-
const [activeReferenceThumbnail, setActiveReferenceThumbnail] = (0,
|
|
3544
|
-
const [isScanningImage, setIsScanningImage] = (0,
|
|
3545
|
-
const [touchStartX, setTouchStartX] = (0,
|
|
3546
|
-
const [isFullscreen, setIsFullscreen] = (0,
|
|
3547
|
-
const [zoomScale, setZoomScale] = (0,
|
|
3548
|
-
const [zoomOffset, setZoomOffset] = (0,
|
|
3549
|
-
const lastPinchDist = (0,
|
|
3550
|
-
const lastTapTime = (0,
|
|
3551
|
-
const dragStart = (0,
|
|
4528
|
+
const [activeReferenceId, setActiveReferenceId] = (0, import_react23.useState)(null);
|
|
4529
|
+
const [activeReferenceThumbnail, setActiveReferenceThumbnail] = (0, import_react23.useState)(null);
|
|
4530
|
+
const [isScanningImage, setIsScanningImage] = (0, import_react23.useState)(false);
|
|
4531
|
+
const [touchStartX, setTouchStartX] = (0, import_react23.useState)(null);
|
|
4532
|
+
const [isFullscreen, setIsFullscreen] = (0, import_react23.useState)(false);
|
|
4533
|
+
const [zoomScale, setZoomScale] = (0, import_react23.useState)(1);
|
|
4534
|
+
const [zoomOffset, setZoomOffset] = (0, import_react23.useState)({ x: 0, y: 0 });
|
|
4535
|
+
const lastPinchDist = (0, import_react23.useRef)(null);
|
|
4536
|
+
const lastTapTime = (0, import_react23.useRef)(0);
|
|
4537
|
+
const dragStart = (0, import_react23.useRef)(null);
|
|
3552
4538
|
const openFullscreen = () => {
|
|
3553
4539
|
setIsFullscreen(true);
|
|
3554
4540
|
setZoomScale(1);
|
|
@@ -3611,7 +4597,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
3611
4597
|
setActiveReferenceId(null);
|
|
3612
4598
|
setActiveReferenceThumbnail(null);
|
|
3613
4599
|
};
|
|
3614
|
-
const labServices = (0,
|
|
4600
|
+
const labServices = (0, import_react23.useMemo)(() => {
|
|
3615
4601
|
const available = groupGenerationsToLabItems([...galleryItems, ...history]);
|
|
3616
4602
|
return {
|
|
3617
4603
|
availableItems: available,
|
|
@@ -3691,17 +4677,17 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
3691
4677
|
setIsScanningImage(false);
|
|
3692
4678
|
}
|
|
3693
4679
|
};
|
|
3694
|
-
const currentIndex = (0,
|
|
3695
|
-
const goToPrev = (0,
|
|
4680
|
+
const currentIndex = (0, import_react23.useMemo)(() => history.findIndex((h) => h.id === currentResult?.id), [history, currentResult]);
|
|
4681
|
+
const goToPrev = (0, import_react23.useCallback)(() => {
|
|
3696
4682
|
if (currentIndex > 0) setCurrentResult(history[currentIndex - 1]);
|
|
3697
4683
|
}, [currentIndex, history]);
|
|
3698
|
-
const goToNext = (0,
|
|
4684
|
+
const goToNext = (0, import_react23.useCallback)(() => {
|
|
3699
4685
|
if (currentIndex < history.length - 1) setCurrentResult(history[currentIndex + 1]);
|
|
3700
4686
|
}, [currentIndex, history]);
|
|
3701
4687
|
const hcStyle = highContrast ? { filter: "brightness(1.6) contrast(1.05)" } : void 0;
|
|
3702
4688
|
const isGenerating = activeGenerationsCount > 0;
|
|
3703
4689
|
useKeyboardNavigation(history, currentResult, setCurrentResult);
|
|
3704
|
-
const getSubtreeFormat = (0,
|
|
4690
|
+
const getSubtreeFormat = (0, import_react23.useCallback)((nodeId, depth = 0) => {
|
|
3705
4691
|
const node = nodes.find((n) => n.id === nodeId);
|
|
3706
4692
|
if (!node) return "";
|
|
3707
4693
|
const childrenIds = edges.filter((e) => e.source === nodeId).map((e) => e.target);
|
|
@@ -3709,7 +4695,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
3709
4695
|
return `${indent}- ${node.data.label || "(unbenannt)"}
|
|
3710
4696
|
` + childrenIds.map((id) => getSubtreeFormat(id, depth + 1)).join("");
|
|
3711
4697
|
}, [nodes, edges]);
|
|
3712
|
-
const activePath = (0,
|
|
4698
|
+
const activePath = (0, import_react23.useMemo)(() => {
|
|
3713
4699
|
if (!focusedNodeId) return /* @__PURE__ */ new Set();
|
|
3714
4700
|
const path = /* @__PURE__ */ new Set([focusedNodeId]);
|
|
3715
4701
|
let currId = focusedNodeId;
|
|
@@ -3741,7 +4727,11 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
3741
4727
|
if (prev.id === genId || !options.silent) return finishedGen;
|
|
3742
4728
|
return prev;
|
|
3743
4729
|
});
|
|
3744
|
-
|
|
4730
|
+
console.log("[HF] handleGenerateImage \u2014 condition check:", { hfToken: !!hfToken, base64: !!base64, effectiveNamespace });
|
|
4731
|
+
if (hfToken && base64 && effectiveNamespace) {
|
|
4732
|
+
hfUploadImage(base64, genId, hfToken).catch((e) => {
|
|
4733
|
+
console.error("[HF] hfUploadImage failed:", e);
|
|
4734
|
+
});
|
|
3745
4735
|
const entry = {
|
|
3746
4736
|
id: genId,
|
|
3747
4737
|
prompt: promptToUse || void 0,
|
|
@@ -3751,20 +4741,9 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
3751
4741
|
timestamp: Date.now(),
|
|
3752
4742
|
mimeType: "image/jpeg"
|
|
3753
4743
|
};
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
hfMetaSaveQueue.current = hfMetaSaveQueue.current.then(async () => {
|
|
3758
|
-
try {
|
|
3759
|
-
const existing = await hfLoadMetadata(token);
|
|
3760
|
-
const ids = new Set((existing || []).map((e) => e.id));
|
|
3761
|
-
if (!ids.has(genId)) {
|
|
3762
|
-
const next = [...existing || [], entry];
|
|
3763
|
-
await hfSaveMetadata(next, token);
|
|
3764
|
-
setHfMetadata(next);
|
|
3765
|
-
}
|
|
3766
|
-
} catch {
|
|
3767
|
-
}
|
|
4744
|
+
console.log("[HF] calling hfWriteEvent, namespace:", effectiveNamespace);
|
|
4745
|
+
hfWriteEvent("image_added", entry).catch((e) => {
|
|
4746
|
+
console.error("[HF] hfWriteEvent outer catch:", e);
|
|
3768
4747
|
});
|
|
3769
4748
|
}
|
|
3770
4749
|
} catch (err) {
|
|
@@ -3800,6 +4779,11 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
3800
4779
|
all: [...prev.all, { ...newTagOption, category: tag.category }]
|
|
3801
4780
|
};
|
|
3802
4781
|
});
|
|
4782
|
+
if (hfToken && effectiveNamespace) {
|
|
4783
|
+
const p = { category: tag.category, label: tag.label, value: tag.value, is_user_created: true };
|
|
4784
|
+
hfWriteEvent("tag_upserted", p).catch(() => {
|
|
4785
|
+
});
|
|
4786
|
+
}
|
|
3803
4787
|
};
|
|
3804
4788
|
const handleTagUpdate = (originalLabel, originalCategory, updates) => {
|
|
3805
4789
|
setWorkspaceTags((prev) => {
|
|
@@ -3812,8 +4796,14 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
3812
4796
|
);
|
|
3813
4797
|
return { by_category: { ...prev.by_category, [originalCategory]: updatedCat }, all: updatedAll };
|
|
3814
4798
|
});
|
|
4799
|
+
if (hfToken && effectiveNamespace) {
|
|
4800
|
+
const p = { category: originalCategory, label: updates.label, value: updates.value, is_user_created: true };
|
|
4801
|
+
hfWriteEvent("tag_upserted", p).catch(() => {
|
|
4802
|
+
});
|
|
4803
|
+
}
|
|
3815
4804
|
};
|
|
3816
4805
|
const handleTagDelete = (label, category) => {
|
|
4806
|
+
const tagValue = workspaceTags?.by_category[category]?.find((t) => t.label === label)?.value;
|
|
3817
4807
|
setWorkspaceTags((prev) => {
|
|
3818
4808
|
if (!prev) return prev;
|
|
3819
4809
|
const updatedCat = (prev.by_category[category] || []).map(
|
|
@@ -3824,6 +4814,11 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
3824
4814
|
);
|
|
3825
4815
|
return { by_category: { ...prev.by_category, [category]: updatedCat }, all: updatedAll };
|
|
3826
4816
|
});
|
|
4817
|
+
if (hfToken && effectiveNamespace && tagValue) {
|
|
4818
|
+
const p = { category, label, value: tagValue, is_deleted: true };
|
|
4819
|
+
hfWriteEvent("tag_upserted", p).catch(() => {
|
|
4820
|
+
});
|
|
4821
|
+
}
|
|
3827
4822
|
};
|
|
3828
4823
|
const handleTagReorder = (category, reorderedTags) => {
|
|
3829
4824
|
setWorkspaceTags((prev) => {
|
|
@@ -3973,38 +4968,39 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
3973
4968
|
await fetchServerProjects();
|
|
3974
4969
|
};
|
|
3975
4970
|
const handleHfInitialSync = async (onProgress) => {
|
|
3976
|
-
if (!hfToken) return;
|
|
3977
|
-
const
|
|
4971
|
+
if (!hfToken || !effectiveNamespace) return;
|
|
4972
|
+
const existingIds = new Set((hfState?.metadata || []).map((m) => m.id));
|
|
4973
|
+
const gens = galleryItems.filter((g) => g.base64 && g.status === "done" && !existingIds.has(g.id));
|
|
3978
4974
|
const total = gens.length;
|
|
3979
4975
|
onProgress(0, total);
|
|
3980
4976
|
let done = 0;
|
|
3981
4977
|
for (const gen of gens) {
|
|
3982
4978
|
const raw = gen.base64.includes(",") ? gen.base64.split(",")[1] : gen.base64;
|
|
3983
4979
|
const mimeType = gen.base64.startsWith("data:image/png") ? "image/png" : "image/jpeg";
|
|
3984
|
-
await hfUploadImage(raw, gen.id, hfToken, mimeType)
|
|
4980
|
+
await hfUploadImage(raw, gen.id, hfToken, mimeType).catch(() => {
|
|
4981
|
+
});
|
|
4982
|
+
const entry = {
|
|
4983
|
+
id: gen.id,
|
|
4984
|
+
prompt: gen.prompt || void 0,
|
|
4985
|
+
seed: gen.seed,
|
|
4986
|
+
model: gen.model,
|
|
4987
|
+
tags: gen.tags || [],
|
|
4988
|
+
timestamp: gen.timestamp,
|
|
4989
|
+
mimeType
|
|
4990
|
+
};
|
|
4991
|
+
await hfWriteEvent("image_added", entry).catch(() => {
|
|
4992
|
+
});
|
|
3985
4993
|
done++;
|
|
3986
4994
|
onProgress(done, total);
|
|
3987
4995
|
}
|
|
3988
|
-
const localEntries = gens.map((g) => ({
|
|
3989
|
-
id: g.id,
|
|
3990
|
-
prompt: g.prompt || void 0,
|
|
3991
|
-
seed: g.seed,
|
|
3992
|
-
model: g.model,
|
|
3993
|
-
tags: g.tags || [],
|
|
3994
|
-
timestamp: g.timestamp,
|
|
3995
|
-
mimeType: g.base64.startsWith("data:image/png") ? "image/png" : "image/jpeg"
|
|
3996
|
-
}));
|
|
3997
|
-
const existingMeta = await hfLoadMetadata(hfToken);
|
|
3998
|
-
const existingIds = new Set((existingMeta || []).map((e) => e.id));
|
|
3999
|
-
const newEntries = localEntries.filter((e) => !existingIds.has(e.id));
|
|
4000
|
-
const mergedMeta = [...existingMeta || [], ...newEntries];
|
|
4001
|
-
await hfSaveMetadata(mergedMeta, hfToken);
|
|
4002
|
-
setHfMetadata(mergedMeta);
|
|
4003
4996
|
if (workspaceTags) {
|
|
4004
|
-
const
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4997
|
+
for (const [category, tags] of Object.entries(workspaceTags.by_category)) {
|
|
4998
|
+
for (const tag of tags) {
|
|
4999
|
+
const p = { category, label: tag.label, value: tag.value, is_user_created: tag.is_user_created, is_deleted: tag.is_deleted };
|
|
5000
|
+
await hfWriteEvent("tag_upserted", p).catch(() => {
|
|
5001
|
+
});
|
|
5002
|
+
}
|
|
5003
|
+
}
|
|
4008
5004
|
}
|
|
4009
5005
|
};
|
|
4010
5006
|
const handleComputeSyncDiff = async () => {
|
|
@@ -4043,87 +5039,9 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4043
5039
|
setTimeout(() => setProjectActionState("idle"), 4e3);
|
|
4044
5040
|
}
|
|
4045
5041
|
};
|
|
4046
|
-
(0,
|
|
5042
|
+
(0, import_react23.useEffect)(() => {
|
|
4047
5043
|
if (activeTab === "setup" || activeTab === "sync") fetchServerProjects();
|
|
4048
5044
|
}, [activeTab]);
|
|
4049
|
-
const [isHfRefreshing, setIsHfRefreshing] = (0, import_react21.useState)(false);
|
|
4050
|
-
const loadFromHF = (0, import_react21.useCallback)(async (token) => {
|
|
4051
|
-
setIsHfRefreshing(true);
|
|
4052
|
-
try {
|
|
4053
|
-
hfLoadTags(token).then((tags) => {
|
|
4054
|
-
if (tags?.by_category) setWorkspaceTags(tags);
|
|
4055
|
-
}).catch(() => {
|
|
4056
|
-
});
|
|
4057
|
-
const entries = await hfLoadMetadata(token);
|
|
4058
|
-
if (!Array.isArray(entries) || entries.length === 0) return;
|
|
4059
|
-
setHfMetadata(entries);
|
|
4060
|
-
const hfIds = new Set(entries.map((e) => e.id));
|
|
4061
|
-
const hfSkeletons = entries.map((e) => ({
|
|
4062
|
-
id: e.id,
|
|
4063
|
-
nodeId: e.id,
|
|
4064
|
-
prompt: e.prompt,
|
|
4065
|
-
seed: e.seed,
|
|
4066
|
-
model: e.model,
|
|
4067
|
-
tags: e.tags || [],
|
|
4068
|
-
timestamp: e.timestamp,
|
|
4069
|
-
status: "done"
|
|
4070
|
-
}));
|
|
4071
|
-
setGalleryItems((prev) => {
|
|
4072
|
-
const localOnly = prev.filter((g) => !hfIds.has(g.id));
|
|
4073
|
-
const merged = hfSkeletons.map((s) => prev.find((g) => g.id === s.id) ?? s);
|
|
4074
|
-
return [...localOnly, ...merged];
|
|
4075
|
-
});
|
|
4076
|
-
setHistory((prev) => {
|
|
4077
|
-
const localOnly = prev.filter((g) => !hfIds.has(g.id));
|
|
4078
|
-
const merged = hfSkeletons.map((s) => prev.find((g) => g.id === s.id) ?? s);
|
|
4079
|
-
return [...localOnly, ...merged];
|
|
4080
|
-
});
|
|
4081
|
-
for (const entry of entries) {
|
|
4082
|
-
hfLoadImageAsBase64(entry.id, token).then((b64) => {
|
|
4083
|
-
if (!b64) return;
|
|
4084
|
-
const prefix = `data:${entry.mimeType || "image/jpeg"};base64,`;
|
|
4085
|
-
setGalleryItems((prev) => prev.map((g) => g.id === entry.id && !g.base64 ? { ...g, base64: prefix + b64 } : g));
|
|
4086
|
-
setHistory((prev) => prev.map((g) => g.id === entry.id && !g.base64 ? { ...g, base64: prefix + b64 } : g));
|
|
4087
|
-
}).catch(() => {
|
|
4088
|
-
});
|
|
4089
|
-
}
|
|
4090
|
-
const localOnlyItems = galleryItemsRef.current.filter((g) => !hfIds.has(g.id) && g.base64 && g.status === "done");
|
|
4091
|
-
if (localOnlyItems.length > 0) {
|
|
4092
|
-
hfMetaSaveQueue.current = hfMetaSaveQueue.current.then(async () => {
|
|
4093
|
-
try {
|
|
4094
|
-
let currentMeta = await hfLoadMetadata(token);
|
|
4095
|
-
const existingIds = new Set((currentMeta || []).map((e) => e.id));
|
|
4096
|
-
for (const gen of localOnlyItems) {
|
|
4097
|
-
if (existingIds.has(gen.id)) continue;
|
|
4098
|
-
const raw = gen.base64.includes(",") ? gen.base64.split(",")[1] : gen.base64;
|
|
4099
|
-
const mimeType = gen.base64.startsWith("data:image/png") ? "image/png" : "image/jpeg";
|
|
4100
|
-
await hfUploadImage(raw, gen.id, token, mimeType).catch(() => {
|
|
4101
|
-
});
|
|
4102
|
-
const entry = {
|
|
4103
|
-
id: gen.id,
|
|
4104
|
-
prompt: gen.prompt || void 0,
|
|
4105
|
-
seed: gen.seed,
|
|
4106
|
-
model: gen.model,
|
|
4107
|
-
tags: gen.tags || [],
|
|
4108
|
-
timestamp: gen.timestamp,
|
|
4109
|
-
mimeType
|
|
4110
|
-
};
|
|
4111
|
-
currentMeta = [...currentMeta || [], entry];
|
|
4112
|
-
existingIds.add(gen.id);
|
|
4113
|
-
}
|
|
4114
|
-
await hfSaveMetadata(currentMeta, token);
|
|
4115
|
-
setHfMetadata(currentMeta);
|
|
4116
|
-
} catch {
|
|
4117
|
-
}
|
|
4118
|
-
});
|
|
4119
|
-
}
|
|
4120
|
-
} finally {
|
|
4121
|
-
setIsHfRefreshing(false);
|
|
4122
|
-
}
|
|
4123
|
-
}, []);
|
|
4124
|
-
(0, import_react21.useEffect)(() => {
|
|
4125
|
-
if (hfToken) loadFromHF(hfToken);
|
|
4126
|
-
}, [hfToken]);
|
|
4127
5045
|
const mergeWorkspaceTags = (local, remote) => {
|
|
4128
5046
|
if (!remote?.by_category) return local;
|
|
4129
5047
|
const merged = {};
|
|
@@ -4143,25 +5061,9 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4143
5061
|
const all = Object.entries(merged).flatMap(([cat, tags]) => tags.map((t) => ({ ...t, category: cat })));
|
|
4144
5062
|
return { by_category: merged, all };
|
|
4145
5063
|
};
|
|
4146
|
-
(0, import_react21.useEffect)(() => {
|
|
4147
|
-
if (!hfToken || !workspaceTags) return;
|
|
4148
|
-
if (hfTagSaveTimer.current) clearTimeout(hfTagSaveTimer.current);
|
|
4149
|
-
hfTagSaveTimer.current = setTimeout(async () => {
|
|
4150
|
-
const remote = await hfLoadTags(hfToken).catch(() => null);
|
|
4151
|
-
const merged = mergeWorkspaceTags(workspaceTags, remote);
|
|
4152
|
-
await hfSaveTags(merged, hfToken).catch(() => {
|
|
4153
|
-
});
|
|
4154
|
-
if (Object.values(merged.by_category).some(
|
|
4155
|
-
(tags, i) => tags.length !== Object.values(workspaceTags.by_category)[i]?.length
|
|
4156
|
-
)) setWorkspaceTags(merged);
|
|
4157
|
-
}, 1500);
|
|
4158
|
-
return () => {
|
|
4159
|
-
if (hfTagSaveTimer.current) clearTimeout(hfTagSaveTimer.current);
|
|
4160
|
-
};
|
|
4161
|
-
}, [workspaceTags, hfToken]);
|
|
4162
5064
|
if (isFullscreen && currentResult?.base64) {
|
|
4163
5065
|
const fsBase64 = currentResult.base64.startsWith("data:") ? currentResult.base64 : `data:image/png;base64,${currentResult.base64}`;
|
|
4164
|
-
return /* @__PURE__ */ (0,
|
|
5066
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
4165
5067
|
"div",
|
|
4166
5068
|
{
|
|
4167
5069
|
className: "fixed inset-0 bg-black z-50 flex items-center justify-center overflow-hidden touch-none",
|
|
@@ -4169,7 +5071,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4169
5071
|
onTouchMove: handleFsTouchMove,
|
|
4170
5072
|
onTouchEnd: handleFsTouchEnd,
|
|
4171
5073
|
children: [
|
|
4172
|
-
/* @__PURE__ */ (0,
|
|
5074
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4173
5075
|
"img",
|
|
4174
5076
|
{
|
|
4175
5077
|
src: fsBase64,
|
|
@@ -4186,77 +5088,77 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4186
5088
|
}
|
|
4187
5089
|
}
|
|
4188
5090
|
),
|
|
4189
|
-
/* @__PURE__ */ (0,
|
|
4190
|
-
zoomScale > 1 && /* @__PURE__ */ (0,
|
|
5091
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: closeFullscreen, className: "absolute top-4 right-4 w-10 h-10 flex items-center justify-center rounded-full bg-black/70 border border-white/20 z-10", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[22px]", children: "close" }) }),
|
|
5092
|
+
zoomScale > 1 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => {
|
|
4191
5093
|
setZoomScale(1);
|
|
4192
5094
|
setZoomOffset({ x: 0, y: 0 });
|
|
4193
|
-
}, className: "absolute top-4 left-4 w-10 h-10 flex items-center justify-center rounded-full bg-black/70 border border-white/20 z-10", children: /* @__PURE__ */ (0,
|
|
4194
|
-
history.length > 1 && /* @__PURE__ */ (0,
|
|
4195
|
-
/* @__PURE__ */ (0,
|
|
5095
|
+
}, className: "absolute top-4 left-4 w-10 h-10 flex items-center justify-center rounded-full bg-black/70 border border-white/20 z-10", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "zoom_out_map" }) }),
|
|
5096
|
+
history.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
5097
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => {
|
|
4196
5098
|
if (currentIndex > 0) setCurrentResult(history[currentIndex - 1]);
|
|
4197
|
-
}, disabled: currentIndex <= 0, className: "absolute left-2 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center rounded-full bg-black/60 border border-white/10 disabled:opacity-0", children: /* @__PURE__ */ (0,
|
|
4198
|
-
/* @__PURE__ */ (0,
|
|
5099
|
+
}, disabled: currentIndex <= 0, className: "absolute left-2 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center rounded-full bg-black/60 border border-white/10 disabled:opacity-0", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[22px]", children: "chevron_left" }) }),
|
|
5100
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => {
|
|
4199
5101
|
if (currentIndex < history.length - 1) setCurrentResult(history[currentIndex + 1]);
|
|
4200
|
-
}, disabled: currentIndex >= history.length - 1, className: "absolute right-2 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center rounded-full bg-black/60 border border-white/10 disabled:opacity-0", children: /* @__PURE__ */ (0,
|
|
4201
|
-
/* @__PURE__ */ (0,
|
|
5102
|
+
}, disabled: currentIndex >= history.length - 1, className: "absolute right-2 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center rounded-full bg-black/60 border border-white/10 disabled:opacity-0", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[22px]", children: "chevron_right" }) }),
|
|
5103
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "absolute bottom-6 left-1/2 -translate-x-1/2 bg-black/60 rounded-full px-3 py-0.5 text-[10px] text-white/40 font-mono", children: [
|
|
4202
5104
|
currentIndex + 1,
|
|
4203
5105
|
" / ",
|
|
4204
5106
|
history.length
|
|
4205
5107
|
] })
|
|
4206
5108
|
] }),
|
|
4207
|
-
zoomScale === 1 && /* @__PURE__ */ (0,
|
|
5109
|
+
zoomScale === 1 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "absolute bottom-6 right-4 text-[9px] text-white/20 font-mono", children: "Pinch zum Zoomen \xB7 Doppeltipp 2.5\xD7" })
|
|
4208
5110
|
]
|
|
4209
5111
|
}
|
|
4210
5112
|
);
|
|
4211
5113
|
}
|
|
4212
5114
|
if (showStart) {
|
|
4213
|
-
return /* @__PURE__ */ (0,
|
|
4214
|
-
/* @__PURE__ */ (0,
|
|
5115
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "fixed inset-0 bg-[#0e0e0e] flex flex-col items-center justify-center p-6", style: { gap: 28, ...hcStyle }, children: [
|
|
5116
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("input", { ref: wsInputRef, type: "file", accept: ".zip", className: "hidden", onChange: (e) => {
|
|
4215
5117
|
const f = e.target.files?.[0];
|
|
4216
5118
|
if (f) handleProjectImport(f);
|
|
4217
5119
|
e.target.value = "";
|
|
4218
5120
|
} }),
|
|
4219
|
-
/* @__PURE__ */ (0,
|
|
4220
|
-
/* @__PURE__ */ (0,
|
|
4221
|
-
/* @__PURE__ */ (0,
|
|
4222
|
-
/* @__PURE__ */ (0,
|
|
5121
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col items-center gap-1", children: [
|
|
5122
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-white/15 text-[44px]", children: "palette" }),
|
|
5123
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-white/25 text-[10px] font-bold uppercase tracking-[0.25em]", children: "Avatar Architect" }),
|
|
5124
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "text-white text-[13px] font-mono", children: [
|
|
4223
5125
|
"v",
|
|
4224
5126
|
LIB_VERSION
|
|
4225
5127
|
] })
|
|
4226
5128
|
] }),
|
|
4227
|
-
/* @__PURE__ */ (0,
|
|
5129
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
4228
5130
|
"button",
|
|
4229
5131
|
{
|
|
4230
5132
|
onClick: toggleContrast,
|
|
4231
5133
|
className: "flex items-center gap-3 px-5 py-3 rounded-2xl border transition-colors",
|
|
4232
5134
|
style: { borderColor: highContrast ? "rgba(255,255,255,0.3)" : "rgba(255,255,255,0.08)", background: highContrast ? "rgba(255,255,255,0.08)" : "transparent" },
|
|
4233
5135
|
children: [
|
|
4234
|
-
/* @__PURE__ */ (0,
|
|
4235
|
-
/* @__PURE__ */ (0,
|
|
4236
|
-
/* @__PURE__ */ (0,
|
|
4237
|
-
/* @__PURE__ */ (0,
|
|
5136
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[22px]", style: { color: highContrast ? "#fff" : "rgba(255,255,255,0.35)" }, children: highContrast ? "light_mode" : "dark_mode" }),
|
|
5137
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col items-start", children: [
|
|
5138
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-[13px] font-bold", style: { color: highContrast ? "#fff" : "rgba(255,255,255,0.5)" }, children: highContrast ? "Hoher Kontrast" : "Normaler Kontrast" }),
|
|
5139
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-[10px]", style: { color: "rgba(255,255,255,0.25)" }, children: "Tippen zum Umschalten" })
|
|
4238
5140
|
] })
|
|
4239
5141
|
]
|
|
4240
5142
|
}
|
|
4241
5143
|
),
|
|
4242
|
-
/* @__PURE__ */ (0,
|
|
4243
|
-
/* @__PURE__ */ (0,
|
|
5144
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col items-center gap-2 w-full max-w-[280px]", children: [
|
|
5145
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
4244
5146
|
"button",
|
|
4245
5147
|
{
|
|
4246
5148
|
onClick: () => wsInputRef.current?.click(),
|
|
4247
5149
|
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",
|
|
4248
5150
|
style: { height: 56, background: projectLoaded ? "#16a34a" : "#0284c7" },
|
|
4249
5151
|
children: [
|
|
4250
|
-
/* @__PURE__ */ (0,
|
|
5152
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[22px]", children: projectLoaded ? "check_circle" : "folder_zip" }),
|
|
4251
5153
|
projectLoaded ? "Projekt geladen \u2713" : "Projekt laden (.zip)"
|
|
4252
5154
|
]
|
|
4253
5155
|
}
|
|
4254
5156
|
),
|
|
4255
|
-
!projectLoaded && /* @__PURE__ */ (0,
|
|
5157
|
+
!projectLoaded && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-white/20 text-[10px] text-center", children: "Baum, Bilder und Einstellungen wiederherstellen" })
|
|
4256
5158
|
] }),
|
|
4257
|
-
/* @__PURE__ */ (0,
|
|
4258
|
-
!initialHfToken && /* @__PURE__ */ (0,
|
|
4259
|
-
/* @__PURE__ */ (0,
|
|
5159
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col items-center gap-2 w-full max-w-[280px]", children: [
|
|
5160
|
+
!initialHfToken && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex gap-2 w-full", children: [
|
|
5161
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4260
5162
|
"input",
|
|
4261
5163
|
{
|
|
4262
5164
|
type: "password",
|
|
@@ -4272,7 +5174,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4272
5174
|
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)" }
|
|
4273
5175
|
}
|
|
4274
5176
|
),
|
|
4275
|
-
hfTokenInput.trim() && /* @__PURE__ */ (0,
|
|
5177
|
+
hfTokenInput.trim() && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4276
5178
|
"button",
|
|
4277
5179
|
{
|
|
4278
5180
|
type: "button",
|
|
@@ -4283,7 +5185,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4283
5185
|
}
|
|
4284
5186
|
)
|
|
4285
5187
|
] }),
|
|
4286
|
-
hfToken && /* @__PURE__ */ (0,
|
|
5188
|
+
hfToken && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
4287
5189
|
"button",
|
|
4288
5190
|
{
|
|
4289
5191
|
disabled: isLoadingFromHF,
|
|
@@ -4305,15 +5207,15 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4305
5207
|
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",
|
|
4306
5208
|
style: { height: 56, background: "#f59e0b" },
|
|
4307
5209
|
children: [
|
|
4308
|
-
/* @__PURE__ */ (0,
|
|
5210
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: `material-symbols-outlined text-[22px]${isLoadingFromHF ? " animate-spin" : ""}`, children: isLoadingFromHF ? "sync" : "cloud_download" }),
|
|
4309
5211
|
isLoadingFromHF ? "Laden\u2026" : "Von HF laden"
|
|
4310
5212
|
]
|
|
4311
5213
|
}
|
|
4312
5214
|
),
|
|
4313
|
-
hfToken && /* @__PURE__ */ (0,
|
|
5215
|
+
hfToken && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-white/20 text-[10px] text-center", children: "Letzten Stand von Hugging Face laden" })
|
|
4314
5216
|
] }),
|
|
4315
|
-
onFetchServerProjects && /* @__PURE__ */ (0,
|
|
4316
|
-
/* @__PURE__ */ (0,
|
|
5217
|
+
onFetchServerProjects && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col items-center gap-2 w-full max-w-[280px]", children: [
|
|
5218
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
4317
5219
|
"button",
|
|
4318
5220
|
{
|
|
4319
5221
|
disabled: isLoadingFromServer,
|
|
@@ -4334,35 +5236,57 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4334
5236
|
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",
|
|
4335
5237
|
style: { height: 56, background: "#7c3aed" },
|
|
4336
5238
|
children: [
|
|
4337
|
-
/* @__PURE__ */ (0,
|
|
5239
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: `material-symbols-outlined text-[22px]${isLoadingFromServer ? " animate-spin" : ""}`, children: isLoadingFromServer ? "sync" : "cloud_download" }),
|
|
4338
5240
|
isLoadingFromServer ? "Laden\u2026" : "Vom Server laden"
|
|
4339
5241
|
]
|
|
4340
5242
|
}
|
|
4341
5243
|
),
|
|
4342
|
-
/* @__PURE__ */ (0,
|
|
5244
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-white/20 text-[10px] text-center", children: "Letzten Stand vom Server wiederherstellen" })
|
|
4343
5245
|
] }),
|
|
4344
|
-
/* @__PURE__ */ (0,
|
|
4345
|
-
/* @__PURE__ */ (0,
|
|
4346
|
-
/* @__PURE__ */ (0,
|
|
5246
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col items-center gap-2 w-full max-w-[280px]", children: [
|
|
5247
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-white/25 text-[10px] uppercase tracking-widest font-bold", children: "Layout w\xE4hlen & starten" }),
|
|
5248
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "grid grid-cols-2 gap-2 w-full", children: [
|
|
4347
5249
|
{ id: "mobile", icon: "smartphone", label: "Mobile" },
|
|
4348
5250
|
{ id: "mobile-desktop", icon: "phonelink", label: "Mobile+" },
|
|
4349
5251
|
{ id: "desktop", icon: "desktop_windows", label: "Desktop" },
|
|
4350
5252
|
{ id: "tablet-landscape", icon: "tablet", label: "Landscape" }
|
|
4351
|
-
].map((opt) => /* @__PURE__ */ (0,
|
|
5253
|
+
].map((opt) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
4352
5254
|
"button",
|
|
4353
5255
|
{
|
|
4354
5256
|
onClick: () => startApp(opt.id),
|
|
4355
5257
|
className: "flex flex-col items-center gap-2 py-4 rounded-2xl border transition-colors",
|
|
4356
5258
|
style: { borderColor: layoutChoice === opt.id ? "rgba(255,255,255,0.35)" : "rgba(255,255,255,0.08)", background: layoutChoice === opt.id ? "rgba(255,255,255,0.07)" : "transparent" },
|
|
4357
5259
|
children: [
|
|
4358
|
-
/* @__PURE__ */ (0,
|
|
4359
|
-
/* @__PURE__ */ (0,
|
|
5260
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[24px]", style: { color: layoutChoice === opt.id ? "#fff" : "rgba(255,255,255,0.4)" }, children: opt.icon }),
|
|
5261
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-[11px] font-bold", style: { color: layoutChoice === opt.id ? "#fff" : "rgba(255,255,255,0.4)" }, children: opt.label })
|
|
4360
5262
|
]
|
|
4361
5263
|
},
|
|
4362
5264
|
opt.id
|
|
4363
5265
|
)) }),
|
|
4364
|
-
layoutChoice === "mobile-desktop" && /* @__PURE__ */ (0,
|
|
4365
|
-
layoutChoice === "tablet-landscape" && /* @__PURE__ */ (0,
|
|
5266
|
+
layoutChoice === "mobile-desktop" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-white/20 text-[9px] text-center", children: "Mobil-Layout skaliert f\xFCr Desktop-Modus" }),
|
|
5267
|
+
layoutChoice === "tablet-landscape" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-white/20 text-[9px] text-center", children: "2-Spalten-Layout f\xFCr Landscape-Tablet im Desktop-Mode" })
|
|
5268
|
+
] }),
|
|
5269
|
+
!hfNamespace && !hfNamespaceFromServer && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-3 w-full max-w-[280px]", children: [
|
|
5270
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-white/25 text-[10px] uppercase tracking-widest font-bold", children: "State:" }),
|
|
5271
|
+
["app.art-by-rolands.de/", "dev-app.art-by-rolands.de/"].map((ns, i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
5272
|
+
"button",
|
|
5273
|
+
{
|
|
5274
|
+
onClick: () => {
|
|
5275
|
+
setHfNamespaceLocal(ns);
|
|
5276
|
+
try {
|
|
5277
|
+
localStorage.setItem("aa-hf-namespace", ns);
|
|
5278
|
+
} catch {
|
|
5279
|
+
}
|
|
5280
|
+
},
|
|
5281
|
+
className: "px-3 py-1 rounded-lg text-[11px] font-bold transition-colors",
|
|
5282
|
+
style: {
|
|
5283
|
+
background: hfNamespaceLocal === ns ? "#e7e5e4" : "#44403c",
|
|
5284
|
+
color: hfNamespaceLocal === ns ? "#1c1917" : "#e7e5e4"
|
|
5285
|
+
},
|
|
5286
|
+
children: i === 0 ? "PROD" : "DEV"
|
|
5287
|
+
},
|
|
5288
|
+
ns
|
|
5289
|
+
))
|
|
4366
5290
|
] })
|
|
4367
5291
|
] });
|
|
4368
5292
|
}
|
|
@@ -4371,21 +5295,21 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4371
5295
|
const mdScale = mdMode ? window.innerWidth / 430 : 1;
|
|
4372
5296
|
const mdW = mdMode ? 430 : void 0;
|
|
4373
5297
|
const mdH = mdMode ? Math.ceil(window.innerHeight / mdScale) : void 0;
|
|
4374
|
-
const mobileRoot = /* @__PURE__ */ (0,
|
|
5298
|
+
const mobileRoot = /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col bg-[#0e0e0e] text-white overflow-hidden", style: {
|
|
4375
5299
|
width: mdMode ? mdW : "100vw",
|
|
4376
5300
|
height: mdMode ? mdH : "100dvh",
|
|
4377
5301
|
transform: mdMode ? `scale(${mdScale})` : void 0,
|
|
4378
5302
|
transformOrigin: mdMode ? "top left" : void 0,
|
|
4379
5303
|
...hcStyle || {}
|
|
4380
5304
|
}, children: [
|
|
4381
|
-
mobileTab === "labs" && /* @__PURE__ */ (0,
|
|
5305
|
+
mobileTab === "labs" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex flex-col flex-1 min-h-0", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LabsTab, { services: labServices, onResult: (item) => {
|
|
4382
5306
|
const frame = item.frames[0];
|
|
4383
5307
|
if (frame?.base64) {
|
|
4384
5308
|
setCurrentResult(frameToGeneration(frame, item));
|
|
4385
5309
|
setMobileTab("stage");
|
|
4386
5310
|
}
|
|
4387
5311
|
} }) }),
|
|
4388
|
-
mobileTab === "tags" && workspaceTags && /* @__PURE__ */ (0,
|
|
5312
|
+
mobileTab === "tags" && workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex flex-col flex-1 min-h-0", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4389
5313
|
TagManagerPanel,
|
|
4390
5314
|
{
|
|
4391
5315
|
workspaceTags,
|
|
@@ -4396,21 +5320,21 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4396
5320
|
onTagMove: handleTagMove
|
|
4397
5321
|
}
|
|
4398
5322
|
) }),
|
|
4399
|
-
mobileTab === "stage" && /* @__PURE__ */ (0,
|
|
4400
|
-
/* @__PURE__ */ (0,
|
|
4401
|
-
/* @__PURE__ */ (0,
|
|
4402
|
-
/* @__PURE__ */ (0,
|
|
4403
|
-
/* @__PURE__ */ (0,
|
|
4404
|
-
activeReferenceThumbnail ? /* @__PURE__ */ (0,
|
|
4405
|
-
/* @__PURE__ */ (0,
|
|
4406
|
-
/* @__PURE__ */ (0,
|
|
4407
|
-
/* @__PURE__ */ (0,
|
|
4408
|
-
] }) : /* @__PURE__ */ (0,
|
|
4409
|
-
/* @__PURE__ */ (0,
|
|
4410
|
-
/* @__PURE__ */ (0,
|
|
5323
|
+
mobileTab === "stage" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col flex-1 min-h-0", children: [
|
|
5324
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-2 px-3 border-b border-white/5 bg-black/30 shrink-0", style: { height: 52 }, children: [
|
|
5325
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CompactDropdown, { value: aspectRatio, onChange: setAspectRatio, options: [{ label: "1:1", value: "1:1" }, { label: "16:9", value: "16:9" }, { label: "9:16", value: "9:16" }] }),
|
|
5326
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CompactDropdown, { value: selectedModel, onChange: setSelectedModel, options: [{ value: "\u{1F34C} Nano Banana Pro", label: "\u{1F34C} Nano Banana Pro" }, { value: "\u{1F34C} Nano Banana 2", label: "\u{1F34C} Nano Banana 2" }, { value: "Imagen 4", label: "Imagen 4" }] }),
|
|
5327
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex-1" }),
|
|
5328
|
+
activeReferenceThumbnail ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-1 rounded-lg border border-white/20 bg-white/5 overflow-hidden mr-2", style: { height: 28 }, children: [
|
|
5329
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("img", { src: activeReferenceThumbnail, className: "h-full aspect-square object-cover" }),
|
|
5330
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-[10px] text-white/60 font-bold uppercase tracking-wide px-1", children: "Ref" }),
|
|
5331
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: clearReference, className: "w-6 h-full flex items-center justify-center text-white/30 active:text-white/80 transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "close" }) })
|
|
5332
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: handleSelectReference, className: "text-white/20 active:text-white/60 transition-colors mr-2", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "add_photo_alternate" }) }),
|
|
5333
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: toggleContrast, className: "text-white/20 active:text-white/60 transition-colors mr-2", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: highContrast ? "light_mode" : "dark_mode" }) }),
|
|
5334
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => setShowStart(true), className: "text-white/20 active:text-white/60 transition-colors mr-1", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "desktop_windows" }) })
|
|
4411
5335
|
] }),
|
|
4412
|
-
/* @__PURE__ */ (0,
|
|
4413
|
-
/* @__PURE__ */ (0,
|
|
5336
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "px-3 pt-3 pb-2 shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: `relative rounded-xl border transition-all ${isSynthesizing ? "prompt-loading" : "bg-white/5 border-white/10"}`, children: [
|
|
5337
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4414
5338
|
"textarea",
|
|
4415
5339
|
{
|
|
4416
5340
|
value: activePrompt,
|
|
@@ -4420,26 +5344,26 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4420
5344
|
placeholder: "Prompt eingeben..."
|
|
4421
5345
|
}
|
|
4422
5346
|
),
|
|
4423
|
-
activePrompt && !isSynthesizing && /* @__PURE__ */ (0,
|
|
5347
|
+
activePrompt && !isSynthesizing && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => setActivePrompt(""), className: "absolute top-2 right-2 w-8 h-8 flex items-center justify-center text-white/20 active:text-white transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[18px]", children: "close" }) })
|
|
4424
5348
|
] }) }),
|
|
4425
|
-
/* @__PURE__ */ (0,
|
|
5349
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "px-3 pb-3 shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4426
5350
|
"button",
|
|
4427
5351
|
{
|
|
4428
5352
|
onClick: () => handleGenerateImage(),
|
|
4429
5353
|
disabled: !activePrompt.trim() || isGenerating,
|
|
4430
5354
|
className: "w-full flex items-center justify-center gap-2 rounded-xl font-bold text-[14px] uppercase tracking-wide transition-all disabled:opacity-30 active:scale-95",
|
|
4431
5355
|
style: { height: 48, background: activePrompt.trim() && !isGenerating ? "#0284c7" : void 0, border: "1px solid rgba(255,255,255,0.1)" },
|
|
4432
|
-
children: isGenerating ? /* @__PURE__ */ (0,
|
|
4433
|
-
/* @__PURE__ */ (0,
|
|
4434
|
-
/* @__PURE__ */ (0,
|
|
4435
|
-
] }) : /* @__PURE__ */ (0,
|
|
4436
|
-
/* @__PURE__ */ (0,
|
|
4437
|
-
/* @__PURE__ */ (0,
|
|
5356
|
+
children: isGenerating ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
5357
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "w-4 h-4 border-t-2 border-white rounded-full animate-spin" }),
|
|
5358
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: "Generiere..." })
|
|
5359
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
5360
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "bolt" }),
|
|
5361
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: "Generieren" })
|
|
4438
5362
|
] })
|
|
4439
5363
|
}
|
|
4440
5364
|
) }),
|
|
4441
|
-
/* @__PURE__ */ (0,
|
|
4442
|
-
/* @__PURE__ */ (0,
|
|
5365
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex-1 min-h-0 px-3 pb-3 flex flex-col", children: [
|
|
5366
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
4443
5367
|
"div",
|
|
4444
5368
|
{
|
|
4445
5369
|
className: "w-full rounded-2xl border border-white/5 bg-black/40 relative overflow-hidden flex items-center justify-center",
|
|
@@ -4453,25 +5377,25 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4453
5377
|
setTouchStartX(null);
|
|
4454
5378
|
},
|
|
4455
5379
|
children: [
|
|
4456
|
-
currentResult?.status === "processing" && /* @__PURE__ */ (0,
|
|
4457
|
-
/* @__PURE__ */ (0,
|
|
4458
|
-
/* @__PURE__ */ (0,
|
|
5380
|
+
currentResult?.status === "processing" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col items-center gap-3", children: [
|
|
5381
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "w-10 h-10 border-t-2 border-white rounded-full animate-spin" }),
|
|
5382
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-[11px] text-white/40 uppercase font-bold tracking-widest", children: "Erstelle Bild..." })
|
|
4459
5383
|
] }),
|
|
4460
|
-
currentResult?.status === "error" && /* @__PURE__ */ (0,
|
|
4461
|
-
/* @__PURE__ */ (0,
|
|
4462
|
-
/* @__PURE__ */ (0,
|
|
4463
|
-
/* @__PURE__ */ (0,
|
|
5384
|
+
currentResult?.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "p-6 text-center flex flex-col items-center gap-3", children: [
|
|
5385
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-red-400 text-[36px]", children: "warning" }),
|
|
5386
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-white/50 text-[13px]", children: currentResult.error?.message }),
|
|
5387
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => handleGenerateImage(currentResult.prompt), className: "px-4 py-2 rounded-lg border border-white/20 text-[13px] text-white/70 active:bg-white/10", children: "Erneut versuchen" })
|
|
4464
5388
|
] }),
|
|
4465
|
-
currentResult?.status === "done" && currentResult.base64 && /* @__PURE__ */ (0,
|
|
4466
|
-
!currentResult && /* @__PURE__ */ (0,
|
|
4467
|
-
/* @__PURE__ */ (0,
|
|
4468
|
-
/* @__PURE__ */ (0,
|
|
5389
|
+
currentResult?.status === "done" && currentResult.base64 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("img", { src: currentResult.base64, className: "w-full h-full object-contain" }),
|
|
5390
|
+
!currentResult && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col items-center gap-2 opacity-10", children: [
|
|
5391
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[64px]", children: "palette" }),
|
|
5392
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-[11px] font-bold uppercase tracking-[0.2em]", children: "Avatar Architect" })
|
|
4469
5393
|
] }),
|
|
4470
|
-
currentResult?.status === "done" && /* @__PURE__ */ (0,
|
|
4471
|
-
history.length > 1 && currentResult && /* @__PURE__ */ (0,
|
|
4472
|
-
/* @__PURE__ */ (0,
|
|
4473
|
-
/* @__PURE__ */ (0,
|
|
4474
|
-
/* @__PURE__ */ (0,
|
|
5394
|
+
currentResult?.status === "done" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: openFullscreen, className: "absolute top-2 right-2 w-8 h-8 flex items-center justify-center rounded-full bg-black/60 border border-white/10 z-10", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[18px]", children: "fullscreen" }) }),
|
|
5395
|
+
history.length > 1 && currentResult && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
5396
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: goToPrev, disabled: currentIndex <= 0, className: "absolute left-2 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center rounded-full bg-black/60 border border-white/10 disabled:opacity-0 transition-opacity", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[22px]", children: "chevron_left" }) }),
|
|
5397
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: goToNext, disabled: currentIndex >= history.length - 1, className: "absolute right-2 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center rounded-full bg-black/60 border border-white/10 disabled:opacity-0 transition-opacity", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[22px]", children: "chevron_right" }) }),
|
|
5398
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "absolute bottom-2 left-1/2 -translate-x-1/2 bg-black/60 rounded-full px-3 py-0.5 text-[10px] text-white/40 font-mono", children: [
|
|
4475
5399
|
currentIndex + 1,
|
|
4476
5400
|
" / ",
|
|
4477
5401
|
history.length
|
|
@@ -4480,33 +5404,33 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4480
5404
|
]
|
|
4481
5405
|
}
|
|
4482
5406
|
),
|
|
4483
|
-
currentResult?.status === "done" && /* @__PURE__ */ (0,
|
|
4484
|
-
/* @__PURE__ */ (0,
|
|
4485
|
-
/* @__PURE__ */ (0,
|
|
4486
|
-
/* @__PURE__ */ (0,
|
|
5407
|
+
currentResult?.status === "done" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex gap-2 mt-3", children: [
|
|
5408
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("button", { onClick: () => setActivePrompt(currentResult.prompt || ""), className: "flex-1 flex items-center justify-center gap-1.5 rounded-xl border border-white/10 bg-white/5 active:bg-white/10 transition-colors", style: { height: 44 }, children: [
|
|
5409
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[18px] text-white/60", children: "replay" }),
|
|
5410
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-[12px] text-white/60", children: "Prompt" })
|
|
4487
5411
|
] }),
|
|
4488
|
-
/* @__PURE__ */ (0,
|
|
4489
|
-
/* @__PURE__ */ (0,
|
|
4490
|
-
/* @__PURE__ */ (0,
|
|
5412
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("button", { onClick: () => handleGenerateImage(currentResult.prompt || activePrompt, currentResult.mediaId, void 0, { silent: true }), className: "flex-1 flex items-center justify-center gap-1.5 rounded-xl bg-white/10 active:bg-white/15 transition-colors", style: { height: 44 }, children: [
|
|
5413
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[18px] text-white/80", children: "auto_fix_high" }),
|
|
5414
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-[12px] text-white/80 font-bold", children: "Referenz" })
|
|
4491
5415
|
] }),
|
|
4492
|
-
/* @__PURE__ */ (0,
|
|
4493
|
-
/* @__PURE__ */ (0,
|
|
4494
|
-
/* @__PURE__ */ (0,
|
|
5416
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("button", { onClick: handleDownloadSingle, className: "flex-1 flex items-center justify-center gap-1.5 rounded-xl border border-white/10 bg-white/5 active:bg-white/10 transition-colors", style: { height: 44 }, children: [
|
|
5417
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[18px] text-white/60", children: "download" }),
|
|
5418
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-[12px] text-white/60", children: "Laden" })
|
|
4495
5419
|
] })
|
|
4496
5420
|
] })
|
|
4497
5421
|
] })
|
|
4498
5422
|
] }),
|
|
4499
|
-
mobileTab === "browse" && /* @__PURE__ */ (0,
|
|
4500
|
-
/* @__PURE__ */ (0,
|
|
4501
|
-
["history", "gallery", "inspect"].map((tab) => /* @__PURE__ */ (0,
|
|
4502
|
-
hfToken && /* @__PURE__ */ (0,
|
|
5423
|
+
mobileTab === "browse" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col flex-1 min-h-0", children: [
|
|
5424
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex border-b border-white/5 shrink-0", style: { height: 52 }, children: [
|
|
5425
|
+
["history", "gallery", "inspect"].map((tab) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => setActiveTab(tab), className: `flex-1 flex items-center justify-center gap-1.5 transition-colors text-[11px] font-bold uppercase tracking-wide ${activeTab === tab ? "text-white border-b-2 border-white" : "text-white/30"}`, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: tab === "history" ? "history" : tab === "gallery" ? "photo_library" : "info" }) }, tab)),
|
|
5426
|
+
hfToken && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => refreshHF(), disabled: isHfRefreshing, className: "w-12 flex items-center justify-center text-white/20 active:text-white transition-colors disabled:opacity-30", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: `material-symbols-outlined text-[20px]${isHfRefreshing ? " animate-spin" : ""}`, children: "sync" }) })
|
|
4503
5427
|
] }),
|
|
4504
|
-
/* @__PURE__ */ (0,
|
|
4505
|
-
activeTab === "history" && /* @__PURE__ */ (0,
|
|
5428
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex-1 overflow-hidden relative", children: [
|
|
5429
|
+
activeTab === "history" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: (g) => {
|
|
4506
5430
|
setCurrentResult(g);
|
|
4507
5431
|
setMobileTab("stage");
|
|
4508
5432
|
}, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)) }),
|
|
4509
|
-
activeTab === "gallery" && /* @__PURE__ */ (0,
|
|
5433
|
+
activeTab === "gallery" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4510
5434
|
MediaLibrary,
|
|
4511
5435
|
{
|
|
4512
5436
|
items: galleryItems,
|
|
@@ -4526,39 +5450,43 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4526
5450
|
}
|
|
4527
5451
|
}
|
|
4528
5452
|
),
|
|
4529
|
-
activeTab === "inspect" && /* @__PURE__ */ (0,
|
|
5453
|
+
activeTab === "inspect" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectPanel, { currentResult, history, onSelect: (g) => {
|
|
4530
5454
|
setCurrentResult(g);
|
|
4531
5455
|
} })
|
|
4532
5456
|
] })
|
|
4533
5457
|
] }),
|
|
4534
|
-
/* @__PURE__ */ (0,
|
|
4535
|
-
/* @__PURE__ */ (0,
|
|
4536
|
-
workspaceTags && /* @__PURE__ */ (0,
|
|
5458
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: mobileTab === "tools" ? "flex" : "none" }, className: "flex flex-col flex-1 min-h-0", children: [
|
|
5459
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex border-b border-white/5 shrink-0", style: { height: 52 }, children: [
|
|
5460
|
+
workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("button", { onClick: () => {
|
|
4537
5461
|
setLeftTab("prompt");
|
|
4538
5462
|
if (activeTab === "setup" || activeTab === "sync") setActiveTab("history");
|
|
4539
5463
|
}, className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${leftTab === "prompt" && activeTab !== "setup" && activeTab !== "sync" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: [
|
|
4540
|
-
/* @__PURE__ */ (0,
|
|
5464
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "auto_fix_high" }),
|
|
4541
5465
|
"Prompt"
|
|
4542
5466
|
] }),
|
|
4543
|
-
/* @__PURE__ */ (0,
|
|
5467
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("button", { onClick: () => {
|
|
4544
5468
|
setLeftTab("hierarchy");
|
|
4545
5469
|
if (activeTab === "setup" || activeTab === "sync") setActiveTab("history");
|
|
4546
5470
|
}, className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${leftTab === "hierarchy" && activeTab !== "setup" && activeTab !== "sync" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: [
|
|
4547
|
-
/* @__PURE__ */ (0,
|
|
5471
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "account_tree" }),
|
|
4548
5472
|
"Hierarchie"
|
|
4549
5473
|
] }),
|
|
4550
|
-
/* @__PURE__ */ (0,
|
|
4551
|
-
/* @__PURE__ */ (0,
|
|
5474
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("button", { onClick: () => setActiveTab("setup"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "setup" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: [
|
|
5475
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "settings" }),
|
|
4552
5476
|
"Setup"
|
|
4553
5477
|
] }),
|
|
4554
|
-
/* @__PURE__ */ (0,
|
|
4555
|
-
/* @__PURE__ */ (0,
|
|
5478
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("button", { onClick: () => setActiveTab("sync"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "sync" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: [
|
|
5479
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "cloud_sync" }),
|
|
4556
5480
|
"Sync"
|
|
4557
5481
|
] }),
|
|
4558
|
-
|
|
5482
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("button", { onClick: () => setActiveTab("hftest"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "hftest" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: [
|
|
5483
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "biotech" }),
|
|
5484
|
+
"HF"
|
|
5485
|
+
] }),
|
|
5486
|
+
workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => setActiveTab("tags"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "tags" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "label" }) })
|
|
4559
5487
|
] }),
|
|
4560
|
-
/* @__PURE__ */ (0,
|
|
4561
|
-
leftTab === "hierarchy" && activeTab !== "setup" && activeTab !== "sync" && /* @__PURE__ */ (0,
|
|
5488
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex-1 overflow-hidden relative", children: [
|
|
5489
|
+
leftTab === "hierarchy" && activeTab !== "setup" && activeTab !== "sync" && activeTab !== "hftest" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "absolute inset-0", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4562
5490
|
ListView,
|
|
4563
5491
|
{
|
|
4564
5492
|
nodes,
|
|
@@ -4589,14 +5517,15 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4589
5517
|
isGeneratingNodeId: (id) => isSynthesizing && focusedNodeId === id
|
|
4590
5518
|
}
|
|
4591
5519
|
) }),
|
|
4592
|
-
workspaceTags && /* @__PURE__ */ (0,
|
|
5520
|
+
workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { display: leftTab === "prompt" && activeTab !== "setup" && activeTab !== "sync" && activeTab !== "hftest" ? "flex" : "none" }, className: "absolute inset-0 flex-col", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PromptTab, { workspaceTags, onGenerate: handlePromptTabGenerate, isGenerating: isPromptTabGenerating, feedback: promptFeedback, promptResult: activePrompt || null, lastPayload: lastPromptPayload, onGenerateImage: (prompt) => {
|
|
4593
5521
|
handleGenerateImage(prompt);
|
|
4594
5522
|
setMobileTab("stage");
|
|
4595
5523
|
}, onTagCreate: handleTagCreate, onTagUpdate: handleTagUpdate, onTagDelete: handleTagDelete, onScanImage: handleScanImage, isScanning: isScanningImage }) }),
|
|
4596
|
-
activeTab === "setup" && /* @__PURE__ */ (0,
|
|
4597
|
-
activeTab === "sync" && /* @__PURE__ */ (0,
|
|
5524
|
+
activeTab === "setup" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SetupPanel, { onWorkspaceImport: handleWorkspaceImport, buildInfo }),
|
|
5525
|
+
activeTab === "sync" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4598
5526
|
ProjectSyncTab,
|
|
4599
5527
|
{
|
|
5528
|
+
topSlot: syncTopSlot,
|
|
4600
5529
|
onProjectExport: handleProjectExport,
|
|
4601
5530
|
onProjectImport: (f) => handleProjectImport(f),
|
|
4602
5531
|
onWorkspaceImport: handleWorkspaceImport,
|
|
@@ -4617,7 +5546,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4617
5546
|
onHfInitialSync: hfToken ? handleHfInitialSync : void 0
|
|
4618
5547
|
}
|
|
4619
5548
|
),
|
|
4620
|
-
activeTab === "tags" && workspaceTags && /* @__PURE__ */ (0,
|
|
5549
|
+
activeTab === "tags" && workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4621
5550
|
TagManagerPanel,
|
|
4622
5551
|
{
|
|
4623
5552
|
workspaceTags,
|
|
@@ -4627,22 +5556,23 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4627
5556
|
onTagReorder: handleTagReorder,
|
|
4628
5557
|
onTagMove: handleTagMove
|
|
4629
5558
|
}
|
|
4630
|
-
)
|
|
5559
|
+
),
|
|
5560
|
+
activeTab === "hftest" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "absolute inset-0", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(HFTestTab, { token: hfToken, namespace: effectiveNamespace, galleryItems }) })
|
|
4631
5561
|
] })
|
|
4632
5562
|
] }),
|
|
4633
|
-
/* @__PURE__ */ (0,
|
|
5563
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex border-t border-white/10 bg-black shrink-0", style: { height: 56, paddingBottom: "env(safe-area-inset-bottom, 0px)" }, children: [
|
|
4634
5564
|
{ id: "tools", icon: "auto_fix_high", label: "Prompt" },
|
|
4635
5565
|
{ id: "stage", icon: "palette", label: "Stage" },
|
|
4636
5566
|
{ id: "labs", icon: "science", label: "Labs" },
|
|
4637
5567
|
...workspaceTags ? [{ id: "tags", icon: "label", label: "Tags" }] : [],
|
|
4638
5568
|
{ id: "browse", icon: "photo_library", label: "Galerie" }
|
|
4639
|
-
].map((tab) => /* @__PURE__ */ (0,
|
|
4640
|
-
/* @__PURE__ */ (0,
|
|
4641
|
-
/* @__PURE__ */ (0,
|
|
5569
|
+
].map((tab) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("button", { onClick: () => setMobileTab(tab.id), className: `flex-1 flex flex-col items-center justify-center gap-0.5 transition-colors ${mobileTab === tab.id ? "text-white" : "text-white/30"}`, children: [
|
|
5570
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[24px]", children: tab.icon }),
|
|
5571
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-[10px] font-bold uppercase tracking-wide", children: tab.label })
|
|
4642
5572
|
] }, tab.id)) })
|
|
4643
5573
|
] });
|
|
4644
5574
|
if (mdMode) {
|
|
4645
|
-
return /* @__PURE__ */ (0,
|
|
5575
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { position: "fixed", inset: 0, overflow: "hidden", background: "#0e0e0e" }, children: mobileRoot });
|
|
4646
5576
|
}
|
|
4647
5577
|
return mobileRoot;
|
|
4648
5578
|
}
|
|
@@ -4650,17 +5580,17 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4650
5580
|
const tlScale = Math.min(window.innerWidth / 920, window.innerHeight / 520);
|
|
4651
5581
|
const tlW = 920;
|
|
4652
5582
|
const tlH = 520;
|
|
4653
|
-
return /* @__PURE__ */ (0,
|
|
4654
|
-
/* @__PURE__ */ (0,
|
|
4655
|
-
/* @__PURE__ */ (0,
|
|
4656
|
-
/* @__PURE__ */ (0,
|
|
4657
|
-
/* @__PURE__ */ (0,
|
|
4658
|
-
/* @__PURE__ */ (0,
|
|
4659
|
-
/* @__PURE__ */ (0,
|
|
4660
|
-
/* @__PURE__ */ (0,
|
|
5583
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { position: "fixed", inset: 0, background: "#0e0e0e", display: "flex", alignItems: "center", justifyContent: "center", overflow: "hidden", ...hcStyle || {} }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { width: tlW, height: tlH, transform: `scale(${tlScale})`, transformOrigin: "center center", display: "flex", flexDirection: "row", color: "#fff", overflow: "hidden", borderRadius: 0 }, children: [
|
|
5584
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { width: 320, height: tlH, display: "flex", flexDirection: "column", borderRight: "1px solid rgba(255,255,255,0.05)", background: "#000", flexShrink: 0 }, children: [
|
|
5585
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { height: 52, borderBottom: "1px solid rgba(255,255,255,0.05)", display: "flex", alignItems: "center", gap: 8, padding: "0 12px", flexShrink: 0 }, children: [
|
|
5586
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CompactDropdown, { value: aspectRatio, onChange: setAspectRatio, options: [{ label: "1:1", value: "1:1" }, { label: "16:9", value: "16:9" }, { label: "9:16", value: "9:16" }] }),
|
|
5587
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CompactDropdown, { value: selectedModel, onChange: setSelectedModel, options: [{ value: "\u{1F34C} Nano Banana Pro", label: "\u{1F34C} Nano Banana Pro" }, { value: "\u{1F34C} Nano Banana 2", label: "\u{1F34C} Nano Banana 2" }, { value: "Imagen 4", label: "Imagen 4" }] }),
|
|
5588
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { flex: 1 } }),
|
|
5589
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: toggleContrast, style: { color: "rgba(255,255,255,0.2)", background: "none", border: "none", cursor: "pointer", padding: 4, lineHeight: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: highContrast ? "light_mode" : "dark_mode" }) }),
|
|
5590
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => setShowStart(true), style: { color: "rgba(255,255,255,0.2)", background: "none", border: "none", cursor: "pointer", padding: 4, lineHeight: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: "apps" }) })
|
|
4661
5591
|
] }),
|
|
4662
|
-
/* @__PURE__ */ (0,
|
|
4663
|
-
/* @__PURE__ */ (0,
|
|
5592
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { padding: "12px 12px 8px", flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { position: "relative", borderRadius: 12, border: `1px solid ${isSynthesizing ? "rgba(255,255,255,0.2)" : "rgba(255,255,255,0.1)"}`, background: "rgba(255,255,255,0.05)" }, children: [
|
|
5593
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4664
5594
|
"textarea",
|
|
4665
5595
|
{
|
|
4666
5596
|
value: activePrompt,
|
|
@@ -4669,27 +5599,27 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4669
5599
|
placeholder: "Prompt eingeben..."
|
|
4670
5600
|
}
|
|
4671
5601
|
),
|
|
4672
|
-
activePrompt && /* @__PURE__ */ (0,
|
|
5602
|
+
activePrompt && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => setActivePrompt(""), style: { position: "absolute", top: 6, right: 6, width: 22, height: 22, display: "flex", alignItems: "center", justifyContent: "center", color: "rgba(255,255,255,0.2)", background: "none", border: "none", cursor: "pointer", padding: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 15 }, children: "close" }) })
|
|
4673
5603
|
] }) }),
|
|
4674
|
-
/* @__PURE__ */ (0,
|
|
5604
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { padding: "0 12px 10px", flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4675
5605
|
"button",
|
|
4676
5606
|
{
|
|
4677
5607
|
onClick: () => handleGenerateImage(),
|
|
4678
5608
|
disabled: !activePrompt.trim() || isGenerating,
|
|
4679
5609
|
style: { width: "100%", height: 42, display: "flex", alignItems: "center", justifyContent: "center", gap: 8, borderRadius: 10, fontWeight: "bold", fontSize: 13, textTransform: "uppercase", letterSpacing: "0.05em", border: "1px solid rgba(255,255,255,0.1)", background: activePrompt.trim() && !isGenerating ? "#0284c7" : "transparent", color: "#fff", cursor: activePrompt.trim() && !isGenerating ? "pointer" : "default", opacity: !activePrompt.trim() || isGenerating ? 0.3 : 1, fontFamily: "inherit", transition: "background 0.2s" },
|
|
4680
|
-
children: isGenerating ? /* @__PURE__ */ (0,
|
|
4681
|
-
/* @__PURE__ */ (0,
|
|
4682
|
-
/* @__PURE__ */ (0,
|
|
4683
|
-
] }) : /* @__PURE__ */ (0,
|
|
4684
|
-
/* @__PURE__ */ (0,
|
|
4685
|
-
/* @__PURE__ */ (0,
|
|
5610
|
+
children: isGenerating ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
5611
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { width: 14, height: 14, borderTop: "2px solid #fff", borderRadius: "50%", animation: "spin 1s linear infinite" } }),
|
|
5612
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: "Generiere..." })
|
|
5613
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
5614
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: "bolt" }),
|
|
5615
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: "Generieren" })
|
|
4686
5616
|
] })
|
|
4687
5617
|
}
|
|
4688
5618
|
) }),
|
|
4689
|
-
/* @__PURE__ */ (0,
|
|
5619
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { flex: 1, overflow: "hidden", position: "relative" }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: setCurrentResult, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)) }) })
|
|
4690
5620
|
] }),
|
|
4691
|
-
/* @__PURE__ */ (0,
|
|
4692
|
-
/* @__PURE__ */ (0,
|
|
5621
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { flex: 1, height: tlH, display: "flex", flexDirection: "column", background: "#0b0b0b" }, children: [
|
|
5622
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4693
5623
|
"div",
|
|
4694
5624
|
{
|
|
4695
5625
|
style: { flex: 1, padding: 16, display: "flex", alignItems: "center", justifyContent: "center", position: "relative" },
|
|
@@ -4701,26 +5631,26 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4701
5631
|
else if (dx > 50) goToPrev();
|
|
4702
5632
|
setTouchStartX(null);
|
|
4703
5633
|
},
|
|
4704
|
-
children: /* @__PURE__ */ (0,
|
|
4705
|
-
currentResult?.status === "processing" && /* @__PURE__ */ (0,
|
|
4706
|
-
/* @__PURE__ */ (0,
|
|
4707
|
-
/* @__PURE__ */ (0,
|
|
5634
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { height: "100%", width: "100%", borderRadius: 20, border: "1px solid rgba(255,255,255,0.05)", background: "rgba(0,0,0,0.4)", position: "relative", overflow: "hidden", display: "flex", alignItems: "center", justifyContent: "center" }, children: [
|
|
5635
|
+
currentResult?.status === "processing" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 12 }, children: [
|
|
5636
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { width: 36, height: 36, borderTop: "2px solid #fff", borderRadius: "50%", animation: "spin 1s linear infinite" } }),
|
|
5637
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { style: { fontSize: 10, color: "rgba(255,255,255,0.4)", textTransform: "uppercase", fontWeight: "bold", letterSpacing: "0.15em" }, children: "Erstelle Bild..." })
|
|
4708
5638
|
] }),
|
|
4709
|
-
currentResult?.status === "error" && /* @__PURE__ */ (0,
|
|
4710
|
-
/* @__PURE__ */ (0,
|
|
4711
|
-
/* @__PURE__ */ (0,
|
|
4712
|
-
/* @__PURE__ */ (0,
|
|
5639
|
+
currentResult?.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { padding: 24, textAlign: "center", display: "flex", flexDirection: "column", alignItems: "center", gap: 12 }, children: [
|
|
5640
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 32, color: "#f87171" }, children: "warning" }),
|
|
5641
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { style: { fontSize: 11, color: "rgba(255,255,255,0.5)", margin: 0 }, children: currentResult.error?.message }),
|
|
5642
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => handleGenerateImage(currentResult.prompt), style: { padding: "8px 16px", borderRadius: 8, border: "1px solid rgba(255,255,255,0.2)", fontSize: 11, color: "rgba(255,255,255,0.7)", background: "none", cursor: "pointer", fontFamily: "inherit" }, children: "Erneut versuchen" })
|
|
4713
5643
|
] }),
|
|
4714
|
-
currentResult?.status === "done" && currentResult.base64 && /* @__PURE__ */ (0,
|
|
4715
|
-
!currentResult && /* @__PURE__ */ (0,
|
|
4716
|
-
/* @__PURE__ */ (0,
|
|
4717
|
-
/* @__PURE__ */ (0,
|
|
5644
|
+
currentResult?.status === "done" && currentResult.base64 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("img", { src: currentResult.base64, style: { maxWidth: "100%", maxHeight: "100%", objectFit: "contain" } }),
|
|
5645
|
+
!currentResult && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 8, opacity: 0.1 }, children: [
|
|
5646
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 64 }, children: "palette" }),
|
|
5647
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { style: { fontSize: 11, fontWeight: "bold", textTransform: "uppercase", letterSpacing: "0.2em" }, children: "Avatar Architect" })
|
|
4718
5648
|
] }),
|
|
4719
|
-
currentResult?.status === "done" && /* @__PURE__ */ (0,
|
|
4720
|
-
history.length > 1 && currentResult && /* @__PURE__ */ (0,
|
|
4721
|
-
/* @__PURE__ */ (0,
|
|
4722
|
-
/* @__PURE__ */ (0,
|
|
4723
|
-
/* @__PURE__ */ (0,
|
|
5649
|
+
currentResult?.status === "done" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: openFullscreen, style: { position: "absolute", top: 8, right: 8, width: 32, height: 32, display: "flex", alignItems: "center", justifyContent: "center", borderRadius: "50%", background: "rgba(0,0,0,0.6)", border: "1px solid rgba(255,255,255,0.1)", cursor: "pointer", color: "#fff" }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: "fullscreen" }) }),
|
|
5650
|
+
history.length > 1 && currentResult && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
5651
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: goToPrev, disabled: currentIndex <= 0, style: { position: "absolute", left: 8, top: "50%", transform: "translateY(-50%)", width: 36, height: 36, display: "flex", alignItems: "center", justifyContent: "center", borderRadius: "50%", background: "rgba(0,0,0,0.6)", border: "1px solid rgba(255,255,255,0.1)", cursor: "pointer", color: "#fff", opacity: currentIndex <= 0 ? 0 : 1, transition: "opacity 0.2s" }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 20 }, children: "chevron_left" }) }),
|
|
5652
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: goToNext, disabled: currentIndex >= history.length - 1, style: { position: "absolute", right: 8, top: "50%", transform: "translateY(-50%)", width: 36, height: 36, display: "flex", alignItems: "center", justifyContent: "center", borderRadius: "50%", background: "rgba(0,0,0,0.6)", border: "1px solid rgba(255,255,255,0.1)", cursor: "pointer", color: "#fff", opacity: currentIndex >= history.length - 1 ? 0 : 1, transition: "opacity 0.2s" }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 20 }, children: "chevron_right" }) }),
|
|
5653
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { position: "absolute", bottom: 8, left: "50%", transform: "translateX(-50%)", background: "rgba(0,0,0,0.6)", borderRadius: 999, padding: "2px 12px", fontSize: 10, color: "rgba(255,255,255,0.4)", fontFamily: "monospace" }, children: [
|
|
4724
5654
|
currentIndex + 1,
|
|
4725
5655
|
" / ",
|
|
4726
5656
|
history.length
|
|
@@ -4729,42 +5659,42 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4729
5659
|
] })
|
|
4730
5660
|
}
|
|
4731
5661
|
),
|
|
4732
|
-
currentResult?.status === "done" && /* @__PURE__ */ (0,
|
|
4733
|
-
/* @__PURE__ */ (0,
|
|
4734
|
-
/* @__PURE__ */ (0,
|
|
4735
|
-
/* @__PURE__ */ (0,
|
|
5662
|
+
currentResult?.status === "done" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { padding: "0 16px 16px", display: "flex", gap: 8, flexShrink: 0 }, children: [
|
|
5663
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("button", { onClick: () => setActivePrompt(currentResult.prompt || ""), style: { flex: 1, height: 40, display: "flex", alignItems: "center", justifyContent: "center", gap: 6, borderRadius: 10, border: "1px solid rgba(255,255,255,0.1)", background: "rgba(255,255,255,0.05)", color: "rgba(255,255,255,0.6)", fontSize: 11, cursor: "pointer", fontFamily: "inherit" }, children: [
|
|
5664
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "replay" }),
|
|
5665
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: "Prompt" })
|
|
4736
5666
|
] }),
|
|
4737
|
-
/* @__PURE__ */ (0,
|
|
4738
|
-
/* @__PURE__ */ (0,
|
|
4739
|
-
/* @__PURE__ */ (0,
|
|
5667
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("button", { onClick: () => handleGenerateImage(currentResult.prompt || activePrompt, currentResult.mediaId, void 0, { silent: true }), style: { flex: 1, height: 40, display: "flex", alignItems: "center", justifyContent: "center", gap: 6, borderRadius: 10, border: "none", background: "rgba(255,255,255,0.1)", color: "rgba(255,255,255,0.8)", fontSize: 11, fontWeight: "bold", cursor: "pointer", fontFamily: "inherit" }, children: [
|
|
5668
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "auto_fix_high" }),
|
|
5669
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: "Referenz" })
|
|
4740
5670
|
] }),
|
|
4741
|
-
/* @__PURE__ */ (0,
|
|
4742
|
-
/* @__PURE__ */ (0,
|
|
4743
|
-
/* @__PURE__ */ (0,
|
|
5671
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("button", { onClick: handleDownloadSingle, style: { flex: 1, height: 40, display: "flex", alignItems: "center", justifyContent: "center", gap: 6, borderRadius: 10, border: "1px solid rgba(255,255,255,0.1)", background: "rgba(255,255,255,0.05)", color: "rgba(255,255,255,0.6)", fontSize: 11, cursor: "pointer", fontFamily: "inherit" }, children: [
|
|
5672
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "download" }),
|
|
5673
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: "Laden" })
|
|
4744
5674
|
] })
|
|
4745
5675
|
] })
|
|
4746
5676
|
] })
|
|
4747
5677
|
] }) });
|
|
4748
5678
|
}
|
|
4749
|
-
return /* @__PURE__ */ (0,
|
|
4750
|
-
/* @__PURE__ */ (0,
|
|
4751
|
-
/* @__PURE__ */ (0,
|
|
4752
|
-
/* @__PURE__ */ (0,
|
|
4753
|
-
!isLeftCollapsed && /* @__PURE__ */ (0,
|
|
4754
|
-
workspaceTags && /* @__PURE__ */ (0,
|
|
4755
|
-
/* @__PURE__ */ (0,
|
|
5679
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex h-screen w-screen bg-[#0e0e0e] text-white overflow-hidden", style: hcStyle, children: [
|
|
5680
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "absolute top-2 right-2 z-50", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => setShowStart(true), className: "text-white/10 hover:text-white/30 transition-colors text-[10px]", children: "\u21C4" }) }),
|
|
5681
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col border-r border-white/5 overflow-hidden relative bg-black/10 shrink-0", style: { width: isLeftCollapsed ? 48 : leftPanelWidth, transition: "none" }, children: [
|
|
5682
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "h-14 border-b border-white/5 flex items-center justify-between shrink-0 px-1", children: [
|
|
5683
|
+
!isLeftCollapsed && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-1 gap-1", children: [
|
|
5684
|
+
workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("button", { onClick: () => setLeftTab("prompt"), className: `flex-1 flex items-center justify-center gap-1 h-8 rounded-lg text-[8px] font-bold uppercase tracking-wide transition-colors ${leftTab === "prompt" ? "bg-white/10 text-white" : "text-white/30 hover:text-white/60"}`, children: [
|
|
5685
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "auto_fix_high" }),
|
|
4756
5686
|
"Prompt"
|
|
4757
5687
|
] }),
|
|
4758
|
-
/* @__PURE__ */ (0,
|
|
4759
|
-
/* @__PURE__ */ (0,
|
|
5688
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("button", { onClick: () => setLeftTab("hierarchy"), className: `flex-1 flex items-center justify-center gap-1 h-8 rounded-lg text-[8px] font-bold uppercase tracking-wide transition-colors ${leftTab === "hierarchy" ? "bg-white/10 text-white" : "text-white/30 hover:text-white/60"}`, children: [
|
|
5689
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "account_tree" }),
|
|
4760
5690
|
"Hierarchie"
|
|
4761
5691
|
] }),
|
|
4762
|
-
workspaceTags && /* @__PURE__ */ (0,
|
|
5692
|
+
workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => setActiveTab("tags"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "tags" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "label" }) })
|
|
4763
5693
|
] }),
|
|
4764
|
-
/* @__PURE__ */ (0,
|
|
5694
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => setIsLeftCollapsed(!isLeftCollapsed), className: "material-symbols-outlined text-[18px] text-white/40 hover:text-white transition-all w-10 flex items-center justify-center", children: isLeftCollapsed ? "chevron_right" : "chevron_left" })
|
|
4765
5695
|
] }),
|
|
4766
|
-
!isLeftCollapsed && /* @__PURE__ */ (0,
|
|
4767
|
-
activeTab === "tags" && workspaceTags && /* @__PURE__ */ (0,
|
|
5696
|
+
!isLeftCollapsed && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex-1 overflow-hidden relative", children: [
|
|
5697
|
+
activeTab === "tags" && workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4768
5698
|
TagManagerPanel,
|
|
4769
5699
|
{
|
|
4770
5700
|
workspaceTags,
|
|
@@ -4775,11 +5705,11 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4775
5705
|
onTagMove: handleTagMove
|
|
4776
5706
|
}
|
|
4777
5707
|
),
|
|
4778
|
-
activeTab === "tags" && !workspaceTags && /* @__PURE__ */ (0,
|
|
4779
|
-
/* @__PURE__ */ (0,
|
|
4780
|
-
/* @__PURE__ */ (0,
|
|
5708
|
+
activeTab === "tags" && !workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex items-center justify-center h-full p-8 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
|
|
5709
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[40px] text-white/10 block mb-3", children: "label_off" }),
|
|
5710
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-[11px] text-white/20", children: "Erst Workspace importieren um Tags zu verwalten." })
|
|
4781
5711
|
] }) }),
|
|
4782
|
-
leftTab === "hierarchy" && activeTab !== "tags" && /* @__PURE__ */ (0,
|
|
5712
|
+
leftTab === "hierarchy" && activeTab !== "tags" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "absolute inset-0", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4783
5713
|
ListView,
|
|
4784
5714
|
{
|
|
4785
5715
|
nodes,
|
|
@@ -4804,18 +5734,18 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4804
5734
|
isGeneratingNodeId: (id) => isSynthesizing && focusedNodeId === id
|
|
4805
5735
|
}
|
|
4806
5736
|
) }),
|
|
4807
|
-
leftTab === "prompt" && workspaceTags && activeTab !== "tags" && /* @__PURE__ */ (0,
|
|
5737
|
+
leftTab === "prompt" && workspaceTags && activeTab !== "tags" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PromptTab, { workspaceTags, onGenerate: handlePromptTabGenerate, isGenerating: isPromptTabGenerating, feedback: promptFeedback, promptResult: activePrompt || null, lastPayload: lastPromptPayload, onGenerateImage: (prompt) => handleGenerateImage(prompt), onTagCreate: handleTagCreate, onTagUpdate: handleTagUpdate, onTagDelete: handleTagDelete, onScanImage: handleScanImage, isScanning: isScanningImage })
|
|
4808
5738
|
] })
|
|
4809
5739
|
] }),
|
|
4810
|
-
!isLeftCollapsed && /* @__PURE__ */ (0,
|
|
4811
|
-
/* @__PURE__ */ (0,
|
|
4812
|
-
/* @__PURE__ */ (0,
|
|
4813
|
-
/* @__PURE__ */ (0,
|
|
4814
|
-
/* @__PURE__ */ (0,
|
|
4815
|
-
/* @__PURE__ */ (0,
|
|
5740
|
+
!isLeftCollapsed && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { onMouseDown: startLeftResize, className: "w-1 shrink-0 cursor-col-resize hover:bg-white/20 active:bg-white/30 transition-colors", style: { background: "transparent" } }),
|
|
5741
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex-1 flex flex-col bg-[#0b0b0b] overflow-hidden", children: [
|
|
5742
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "h-14 border-b border-white/5 flex items-center px-4 gap-2 justify-between shrink-0 bg-black/20", children: [
|
|
5743
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
5744
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CompactDropdown, { value: aspectRatio, onChange: setAspectRatio, options: [{ label: "1:1", value: "1:1" }, { label: "16:9", value: "16:9" }, { label: "9:16", value: "9:16" }] }),
|
|
5745
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CompactDropdown, { value: selectedModel, onChange: setSelectedModel, options: [{ value: "\u{1F34C} Nano Banana Pro", label: "\u{1F34C} Nano Banana Pro" }, { value: "\u{1F34C} Nano Banana 2", label: "\u{1F34C} Nano Banana 2" }, { value: "Imagen 4", label: "Imagen 4" }] })
|
|
4816
5746
|
] }),
|
|
4817
|
-
/* @__PURE__ */ (0,
|
|
4818
|
-
/* @__PURE__ */ (0,
|
|
5747
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-1 mx-auto", children: [
|
|
5748
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4819
5749
|
"button",
|
|
4820
5750
|
{
|
|
4821
5751
|
onClick: () => setMiddlePanel("stage"),
|
|
@@ -4823,7 +5753,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4823
5753
|
children: "Stage"
|
|
4824
5754
|
}
|
|
4825
5755
|
),
|
|
4826
|
-
/* @__PURE__ */ (0,
|
|
5756
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4827
5757
|
"button",
|
|
4828
5758
|
{
|
|
4829
5759
|
onClick: () => setMiddlePanel("labs"),
|
|
@@ -4832,68 +5762,68 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4832
5762
|
}
|
|
4833
5763
|
)
|
|
4834
5764
|
] }),
|
|
4835
|
-
/* @__PURE__ */ (0,
|
|
4836
|
-
activeReferenceThumbnail ? /* @__PURE__ */ (0,
|
|
4837
|
-
/* @__PURE__ */ (0,
|
|
4838
|
-
/* @__PURE__ */ (0,
|
|
4839
|
-
/* @__PURE__ */ (0,
|
|
4840
|
-
] }) : /* @__PURE__ */ (0,
|
|
4841
|
-
/* @__PURE__ */ (0,
|
|
4842
|
-
/* @__PURE__ */ (0,
|
|
5765
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
5766
|
+
activeReferenceThumbnail ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-1 rounded-lg border border-white/20 bg-white/5 overflow-hidden", style: { height: 28 }, children: [
|
|
5767
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("img", { src: activeReferenceThumbnail, className: "h-full aspect-square object-cover" }),
|
|
5768
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-[10px] text-white/60 font-bold uppercase tracking-wide px-1", children: "Ref" }),
|
|
5769
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: clearReference, className: "w-6 h-full flex items-center justify-center text-white/30 hover:text-white/80 transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "close" }) })
|
|
5770
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("button", { onClick: handleSelectReference, className: "flex items-center gap-1 h-7 px-2 rounded-lg border border-white/10 text-white/30 hover:text-white/60 hover:border-white/20 transition-colors text-[10px] font-bold uppercase tracking-wide", children: [
|
|
5771
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "add_photo_alternate" }),
|
|
5772
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: "Ref" })
|
|
4843
5773
|
] }),
|
|
4844
|
-
/* @__PURE__ */ (0,
|
|
4845
|
-
/* @__PURE__ */ (0,
|
|
5774
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => setIsPromptCollapsed(!isPromptCollapsed), className: "text-white/40 hover:text-white transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", children: isPromptCollapsed ? "expand_more" : "expand_less" }) }),
|
|
5775
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PillButton, { variant: "solid", icon: "bolt", loading: isGenerating, disabled: !activePrompt.trim(), onClick: () => handleGenerateImage(), children: "Generieren" })
|
|
4846
5776
|
] })
|
|
4847
5777
|
] }),
|
|
4848
|
-
/* @__PURE__ */ (0,
|
|
4849
|
-
!isPromptCollapsed && /* @__PURE__ */ (0,
|
|
4850
|
-
/* @__PURE__ */ (0,
|
|
4851
|
-
activePrompt && !isSynthesizing && /* @__PURE__ */ (0,
|
|
5778
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex-1 flex flex-col overflow-hidden relative", children: [
|
|
5779
|
+
!isPromptCollapsed && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "px-6 py-4 border-b border-white/5 bg-black/10 overflow-hidden shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: `relative min-h-[60px] p-4 rounded-2xl border transition-all ${isSynthesizing ? "prompt-loading" : "bg-white/5 border-white/10"}`, children: [
|
|
5780
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("textarea", { value: activePrompt, onChange: (e) => setActivePrompt(e.target.value), className: "w-full bg-transparent border-none outline-none text-[12px] leading-relaxed text-white/80 resize-none h-20 dark-scrollbar", placeholder: "W\xE4hle einen Knoten oder tippe einen Prompt..." }),
|
|
5781
|
+
activePrompt && !isSynthesizing && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => setActivePrompt(""), className: "absolute top-2 right-2 w-6 h-6 rounded-full bg-white/5 hover:bg-white/10 flex items-center justify-center transition-colors text-white/20 hover:text-white", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "close" }) })
|
|
4852
5782
|
] }) }),
|
|
4853
|
-
middlePanel === "labs" ? /* @__PURE__ */ (0,
|
|
5783
|
+
middlePanel === "labs" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LabsTab, { services: labServices, onResult: (item) => {
|
|
4854
5784
|
const frame = item.frames[0];
|
|
4855
5785
|
if (frame?.base64) setCurrentResult(frameToGeneration(frame, item));
|
|
4856
|
-
} }) }) : /* @__PURE__ */ (0,
|
|
4857
|
-
isGenerating && currentResult?.status === "done" && /* @__PURE__ */ (0,
|
|
4858
|
-
/* @__PURE__ */ (0,
|
|
4859
|
-
/* @__PURE__ */ (0,
|
|
5786
|
+
} }) }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex-1 p-6 overflow-hidden flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "h-full w-full max-w-4xl aspect-square rounded-3xl border border-white/5 bg-black/40 relative overflow-hidden flex items-center justify-center group shadow-2xl", children: [
|
|
5787
|
+
isGenerating && currentResult?.status === "done" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "absolute top-6 right-6 z-30 bg-black/60 backdrop-blur-md px-4 py-2 rounded-full border border-white/10 flex items-center gap-3", children: [
|
|
5788
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "w-3 h-3 border-t-2 border-white rounded-full animate-spin" }),
|
|
5789
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-[10px] text-white/60 uppercase font-bold tracking-widest", children: "Neue Referenz..." })
|
|
4860
5790
|
] }),
|
|
4861
|
-
currentResult ? currentResult.status === "processing" ? /* @__PURE__ */ (0,
|
|
4862
|
-
/* @__PURE__ */ (0,
|
|
4863
|
-
/* @__PURE__ */ (0,
|
|
4864
|
-
] }) : currentResult.status === "error" ? /* @__PURE__ */ (0,
|
|
4865
|
-
/* @__PURE__ */ (0,
|
|
4866
|
-
/* @__PURE__ */ (0,
|
|
4867
|
-
/* @__PURE__ */ (0,
|
|
4868
|
-
/* @__PURE__ */ (0,
|
|
5791
|
+
currentResult ? currentResult.status === "processing" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col items-center gap-4", children: [
|
|
5792
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "w-10 h-10 border-t-2 border-white rounded-full animate-spin" }),
|
|
5793
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-[10px] text-white/40 uppercase font-bold tracking-widest", children: "Erstelle Bild..." })
|
|
5794
|
+
] }) : currentResult.status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "p-10 text-center flex flex-col items-center gap-5 max-w-md", children: [
|
|
5795
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "w-16 h-16 rounded-full bg-red-500/10 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-red-500 text-[32px]", children: "warning" }) }),
|
|
5796
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
5797
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { className: "text-[11px] font-bold uppercase tracking-widest text-red-400", children: "Generierungsfehler" }),
|
|
5798
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-white/60 text-[12px] leading-relaxed", children: currentResult.error?.message })
|
|
4869
5799
|
] }),
|
|
4870
|
-
/* @__PURE__ */ (0,
|
|
4871
|
-
] }) : /* @__PURE__ */ (0,
|
|
4872
|
-
/* @__PURE__ */ (0,
|
|
4873
|
-
/* @__PURE__ */ (0,
|
|
4874
|
-
/* @__PURE__ */ (0,
|
|
4875
|
-
/* @__PURE__ */ (0,
|
|
4876
|
-
/* @__PURE__ */ (0,
|
|
5800
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PillButton, { variant: "outline", icon: "refresh", onClick: () => handleGenerateImage(currentResult.prompt), children: "Erneut versuchen" })
|
|
5801
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "h-full w-full relative flex items-center justify-center", children: [
|
|
5802
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("img", { src: currentResult.base64, className: "max-h-full max-w-full object-contain rounded-xl shadow-2xl" }),
|
|
5803
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "absolute bottom-6 flex gap-2 opacity-0 group-hover:opacity-100 transition-all translate-y-4 group-hover:translate-y-0 z-20", children: [
|
|
5804
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PillButton, { variant: "outline", icon: "replay", onClick: () => setActivePrompt(currentResult.prompt || ""), children: "Prompt" }),
|
|
5805
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PillButton, { variant: "solid", icon: "auto_fix_high", onClick: () => handleGenerateImage(currentResult.prompt || activePrompt, currentResult.mediaId, void 0, { silent: true }), children: "Referenz" }),
|
|
5806
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PillButton, { variant: "outline", icon: "download", onClick: handleDownloadSingle, children: "Speichern" })
|
|
4877
5807
|
] })
|
|
4878
|
-
] }) : /* @__PURE__ */ (0,
|
|
4879
|
-
/* @__PURE__ */ (0,
|
|
4880
|
-
/* @__PURE__ */ (0,
|
|
5808
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col items-center gap-2 opacity-10", children: [
|
|
5809
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[100px]", children: "palette" }),
|
|
5810
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-[12px] font-bold uppercase tracking-[0.2em]", children: "Avatar Architect" })
|
|
4881
5811
|
] })
|
|
4882
5812
|
] }) })
|
|
4883
5813
|
] })
|
|
4884
5814
|
] }),
|
|
4885
|
-
!isRightCollapsed && /* @__PURE__ */ (0,
|
|
4886
|
-
/* @__PURE__ */ (0,
|
|
4887
|
-
/* @__PURE__ */ (0,
|
|
4888
|
-
/* @__PURE__ */ (0,
|
|
5815
|
+
!isRightCollapsed && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { onMouseDown: startRightResize, className: "w-1 shrink-0 cursor-col-resize hover:bg-white/20 active:bg-white/30 transition-colors", style: { background: "transparent" } }),
|
|
5816
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col border-l border-white/5 bg-[#0e0e0e] shrink-0", style: { width: isRightCollapsed ? 60 : rightPanelWidth, transition: "none" }, children: [
|
|
5817
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex border-b border-white/5 h-14 shrink-0 overflow-hidden", children: [
|
|
5818
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex flex-1", children: ["history", "gallery", "inspect", "setup", "sync", "tags"].map((tab) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => {
|
|
4889
5819
|
setActiveTab(tab);
|
|
4890
5820
|
setIsRightCollapsed(false);
|
|
4891
|
-
}, className: `flex-1 flex items-center justify-center relative transition-colors ${activeTab === tab ? "text-white" : "text-white/20"}`, children: /* @__PURE__ */ (0,
|
|
4892
|
-
hfToken && /* @__PURE__ */ (0,
|
|
4893
|
-
/* @__PURE__ */ (0,
|
|
5821
|
+
}, className: `flex-1 flex items-center justify-center relative transition-colors ${activeTab === tab ? "text-white" : "text-white/20"}`, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: tab === "history" ? "history" : tab === "gallery" ? "photo_library" : tab === "inspect" ? "info" : tab === "setup" ? "settings" : tab === "sync" ? "cloud_sync" : "label" }) }, tab)) }),
|
|
5822
|
+
hfToken && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => refreshHF(), disabled: isHfRefreshing, className: "w-10 flex items-center justify-center text-white/20 hover:text-white/60 transition-colors disabled:opacity-30", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: `material-symbols-outlined text-[18px]${isHfRefreshing ? " animate-spin" : ""}`, children: "sync" }) }),
|
|
5823
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => setIsRightCollapsed(!isRightCollapsed), className: "w-10 flex items-center justify-center text-white/20 hover:text-white", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[18px]", children: isRightCollapsed ? "chevron_left" : "chevron_right" }) })
|
|
4894
5824
|
] }),
|
|
4895
|
-
!isRightCollapsed && /* @__PURE__ */ (0,
|
|
4896
|
-
activeTab === "tags" && workspaceTags && /* @__PURE__ */ (0,
|
|
5825
|
+
!isRightCollapsed && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex-1 overflow-hidden relative", children: [
|
|
5826
|
+
activeTab === "tags" && workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4897
5827
|
TagManagerPanel,
|
|
4898
5828
|
{
|
|
4899
5829
|
workspaceTags,
|
|
@@ -4904,12 +5834,12 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4904
5834
|
onTagMove: handleTagMove
|
|
4905
5835
|
}
|
|
4906
5836
|
),
|
|
4907
|
-
activeTab === "tags" && !workspaceTags && /* @__PURE__ */ (0,
|
|
4908
|
-
/* @__PURE__ */ (0,
|
|
4909
|
-
/* @__PURE__ */ (0,
|
|
5837
|
+
activeTab === "tags" && !workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex items-center justify-center h-full p-8 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
|
|
5838
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[40px] text-white/10 block mb-3", children: "label_off" }),
|
|
5839
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-[11px] text-white/20", children: "Erst Workspace importieren um Tags zu verwalten." })
|
|
4910
5840
|
] }) }),
|
|
4911
|
-
activeTab === "history" && /* @__PURE__ */ (0,
|
|
4912
|
-
activeTab === "gallery" && /* @__PURE__ */ (0,
|
|
5841
|
+
activeTab === "history" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: setCurrentResult, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)) }),
|
|
5842
|
+
activeTab === "gallery" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4913
5843
|
MediaLibrary,
|
|
4914
5844
|
{
|
|
4915
5845
|
items: galleryItems,
|
|
@@ -4923,11 +5853,12 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4923
5853
|
onGenerateReference: (item) => handleGenerateImage(item.prompt || activePrompt, item.mediaId, void 0, { silent: true })
|
|
4924
5854
|
}
|
|
4925
5855
|
),
|
|
4926
|
-
activeTab === "inspect" && /* @__PURE__ */ (0,
|
|
4927
|
-
activeTab === "setup" && /* @__PURE__ */ (0,
|
|
4928
|
-
activeTab === "sync" && /* @__PURE__ */ (0,
|
|
5856
|
+
activeTab === "inspect" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectPanel, { currentResult, history, onSelect: setCurrentResult }),
|
|
5857
|
+
activeTab === "setup" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SetupPanel, { onWorkspaceImport: handleWorkspaceImport, buildInfo }),
|
|
5858
|
+
activeTab === "sync" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4929
5859
|
ProjectSyncTab,
|
|
4930
5860
|
{
|
|
5861
|
+
topSlot: syncTopSlot,
|
|
4931
5862
|
onProjectExport: handleProjectExport,
|
|
4932
5863
|
onProjectImport: (f) => handleProjectImport(f),
|
|
4933
5864
|
onWorkspaceImport: handleWorkspaceImport,
|
|
@@ -4954,7 +5885,8 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
4954
5885
|
}
|
|
4955
5886
|
|
|
4956
5887
|
// src/components/FaApp.tsx
|
|
4957
|
-
var
|
|
5888
|
+
var import_react24 = require("react");
|
|
5889
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
4958
5890
|
function FaApp({
|
|
4959
5891
|
onGenerateImage,
|
|
4960
5892
|
onGeneratePrompt,
|
|
@@ -4965,17 +5897,27 @@ function FaApp({
|
|
|
4965
5897
|
onFlowUpload: _onFlowUpload,
|
|
4966
5898
|
onFlowMediaUpload: _onFlowMediaUpload,
|
|
4967
5899
|
libToken,
|
|
5900
|
+
allowDevNamespace,
|
|
5901
|
+
serverBaseUrl,
|
|
4968
5902
|
onFetchServerProjects,
|
|
4969
5903
|
onServerSave,
|
|
4970
5904
|
onServerLoad,
|
|
4971
5905
|
onServerDelete,
|
|
4972
5906
|
buildInfo
|
|
4973
5907
|
}) {
|
|
5908
|
+
const [hfNamespace, setHfNamespace] = (0, import_react24.useState)(void 0);
|
|
5909
|
+
(0, import_react24.useEffect)(() => {
|
|
5910
|
+
if (!serverBaseUrl) return;
|
|
5911
|
+
fetch(`${serverBaseUrl}/api/status`).then((r) => r.json()).then((d) => {
|
|
5912
|
+
if (typeof d.hfNamespace === "string") setHfNamespace(d.hfNamespace);
|
|
5913
|
+
}).catch(() => {
|
|
5914
|
+
});
|
|
5915
|
+
}, [serverBaseUrl]);
|
|
4974
5916
|
const wrappedPrompt = async (text, options) => {
|
|
4975
5917
|
const result = await onGeneratePrompt(text, options);
|
|
4976
5918
|
return result.text;
|
|
4977
5919
|
};
|
|
4978
|
-
return /* @__PURE__ */ (0,
|
|
5920
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4979
5921
|
AvatarArchitectApp,
|
|
4980
5922
|
{
|
|
4981
5923
|
onGenerateImage,
|
|
@@ -4983,6 +5925,8 @@ function FaApp({
|
|
|
4983
5925
|
onDownload,
|
|
4984
5926
|
onSelectMedia,
|
|
4985
5927
|
initialHfToken: libToken ? libToken.startsWith("hf_") ? libToken : `hf_${libToken}` : void 0,
|
|
5928
|
+
hfNamespace,
|
|
5929
|
+
allowDevNamespace: !hfNamespace && allowDevNamespace,
|
|
4986
5930
|
onFetchServerProjects,
|
|
4987
5931
|
onServerSave,
|
|
4988
5932
|
onServerLoad,
|
|
@@ -4994,7 +5938,8 @@ function FaApp({
|
|
|
4994
5938
|
|
|
4995
5939
|
// src/index.ts
|
|
4996
5940
|
init_hfStateService();
|
|
4997
|
-
|
|
5941
|
+
init_hfStateService();
|
|
5942
|
+
var LIB_VERSION = "2.0.13";
|
|
4998
5943
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4999
5944
|
0 && (module.exports = {
|
|
5000
5945
|
AvatarArchitectApp,
|
|
@@ -5020,9 +5965,12 @@ var LIB_VERSION = "1.3.18";
|
|
|
5020
5965
|
SectionLabel,
|
|
5021
5966
|
SetupPanel,
|
|
5022
5967
|
TagManagerPanel,
|
|
5968
|
+
applyEvent,
|
|
5969
|
+
applyEvents,
|
|
5023
5970
|
autoLabel,
|
|
5024
5971
|
buildBlendInstruction,
|
|
5025
5972
|
buildCompareInstruction,
|
|
5973
|
+
buildDag,
|
|
5026
5974
|
buildFallbackPrompt,
|
|
5027
5975
|
buildGenerationPrompt,
|
|
5028
5976
|
buildImageGenerationOptions,
|
|
@@ -5034,27 +5982,36 @@ var LIB_VERSION = "1.3.18";
|
|
|
5034
5982
|
cleanAiResponse,
|
|
5035
5983
|
createFlowServices,
|
|
5036
5984
|
exportProjectToZip,
|
|
5985
|
+
findForks,
|
|
5986
|
+
findTips,
|
|
5037
5987
|
formatTreeToMarkdown,
|
|
5038
5988
|
frameToGeneration,
|
|
5039
5989
|
getFormattedTimestamp,
|
|
5040
5990
|
getHFToken,
|
|
5991
|
+
getSessionClientId,
|
|
5041
5992
|
groupGenerationsToLabItems,
|
|
5993
|
+
hfBatchArchive,
|
|
5994
|
+
hfBootstrapFromLegacy,
|
|
5042
5995
|
hfDeleteProject,
|
|
5043
5996
|
hfDownloadProject,
|
|
5997
|
+
hfListDir,
|
|
5044
5998
|
hfListProjects,
|
|
5045
5999
|
hfLoadImageAsBase64,
|
|
5046
|
-
hfLoadMetadata,
|
|
5047
|
-
hfLoadTags,
|
|
5048
|
-
hfSaveMetadata,
|
|
5049
|
-
hfSaveTags,
|
|
5050
6000
|
hfUploadImage,
|
|
5051
6001
|
hfUploadProjectForm,
|
|
6002
|
+
hfUploadSmallFile,
|
|
5052
6003
|
importProjectFromZip,
|
|
5053
6004
|
injectXMPMetadata,
|
|
5054
6005
|
interpretSdkError,
|
|
6006
|
+
loadHFState,
|
|
6007
|
+
loadPendingEvents,
|
|
5055
6008
|
parsePromptFile,
|
|
5056
6009
|
parsePromptResponse,
|
|
5057
6010
|
setHFToken,
|
|
6011
|
+
topoSort,
|
|
6012
|
+
tsFromEventPath,
|
|
6013
|
+
useHFState,
|
|
5058
6014
|
useKeyboardNavigation,
|
|
5059
|
-
useOnClickOutside
|
|
6015
|
+
useOnClickOutside,
|
|
6016
|
+
writeHFEvent
|
|
5060
6017
|
});
|