@rslsp1/fa-app-tools 2.0.56 → 2.0.61

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -404,11 +404,16 @@ async function loadHFState(namespace, token) {
404
404
  meta: JSON.parse(metaStr)
405
405
  };
406
406
  }
407
- async function loadPendingEvents(namespace, token, sinceTs) {
407
+ async function loadPendingEvents(namespace, token, sinceTs, knownPaths) {
408
408
  const files = await hfListDir(namespace, "events", token);
409
- const pending = files.filter((f) => f.type === "file" && tsFromEventPath(f.path) > sinceTs).sort((a, b) => a.path.localeCompare(b.path));
409
+ const pending = files.filter((f) => f.type === "file" && tsFromEventPath(f.path) > sinceTs && !knownPaths?.has(f.path)).sort((a, b) => a.path.localeCompare(b.path));
410
+ if (!pending.length) return [];
410
411
  const raw = await Promise.all(
411
- pending.map((f) => hfDownloadJsonByPath(f.path, token))
412
+ pending.map(async (f) => {
413
+ const result = await hfDownloadJsonByPath(f.path, token);
414
+ knownPaths?.add(f.path);
415
+ return result;
416
+ })
412
417
  );
413
418
  return raw.flatMap((e) => Array.isArray(e) ? e : [e]);
414
419
  }
@@ -1028,10 +1033,8 @@ var CompactDropdown = ({
1028
1033
  };
1029
1034
 
1030
1035
  // src/components/HistoryPanel.tsx
1031
- var import_react4 = require("react");
1032
- var import_react5 = require("motion/react");
1036
+ var import_react4 = require("motion/react");
1033
1037
  var import_jsx_runtime5 = require("react/jsx-runtime");
1034
- var PAGE_SIZE = 20;
1035
1038
  var formatFriendlyTimestamp = (timestamp) => {
1036
1039
  const date = new Date(timestamp);
1037
1040
  const now = /* @__PURE__ */ new Date();
@@ -1043,8 +1046,7 @@ var formatFriendlyTimestamp = (timestamp) => {
1043
1046
  if (date.toDateString() === yesterday.toDateString()) return `Gestern, ${timeStr}`;
1044
1047
  return `${date.toLocaleDateString([], { day: "2-digit", month: "2-digit" })}, ${timeStr}`;
1045
1048
  };
1046
- var HistoryPanel = ({ history, currentResultId, onSelect, onDelete }) => {
1047
- const [visibleCount, setVisibleCount] = (0, import_react4.useState)(PAGE_SIZE);
1049
+ var HistoryPanel = ({ history, currentResultId, onSelect, onDelete, visibleCount, onLoadMore }) => {
1048
1050
  const visibleHistory = history.slice(0, visibleCount);
1049
1051
  if (history.length === 0) {
1050
1052
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-col items-center justify-center py-20 text-center gap-4 opacity-10", children: [
@@ -1052,7 +1054,7 @@ var HistoryPanel = ({ history, currentResultId, onSelect, onDelete }) => {
1052
1054
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-[10px] font-bold uppercase tracking-widest", children: "Keine Historie" })
1053
1055
  ] });
1054
1056
  }
1055
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react5.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, className: "absolute inset-0 p-4 flex flex-col gap-3 overflow-y-auto dark-scrollbar", children: [
1057
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react4.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, className: "absolute inset-0 p-4 flex flex-col gap-3 overflow-y-auto dark-scrollbar", children: [
1056
1058
  visibleHistory.map((gen) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1057
1059
  "div",
1058
1060
  {
@@ -1088,7 +1090,7 @@ var HistoryPanel = ({ history, currentResultId, onSelect, onDelete }) => {
1088
1090
  },
1089
1091
  gen.id
1090
1092
  )),
1091
- visibleCount < history.length && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("button", { type: "button", onClick: () => setVisibleCount((c) => c + PAGE_SIZE), className: "w-full py-2 bg-white/5 hover:bg-white/10 border border-white/10 rounded-xl text-[10px] font-bold uppercase text-white/60 hover:text-white transition-all", children: [
1093
+ visibleCount < history.length && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("button", { type: "button", onClick: onLoadMore, className: "w-full py-2 bg-white/5 hover:bg-white/10 border border-white/10 rounded-xl text-[10px] font-bold uppercase text-white/60 hover:text-white transition-all", children: [
1092
1094
  history.length - visibleCount,
1093
1095
  " weitere laden"
1094
1096
  ] })
@@ -1096,11 +1098,11 @@ var HistoryPanel = ({ history, currentResultId, onSelect, onDelete }) => {
1096
1098
  };
1097
1099
 
1098
1100
  // src/components/InspectPanel.tsx
1099
- var import_react6 = require("react");
1100
- var import_react7 = require("motion/react");
1101
+ var import_react5 = require("react");
1102
+ var import_react6 = require("motion/react");
1101
1103
  var import_jsx_runtime6 = require("react/jsx-runtime");
1102
1104
  var InspectPanel = ({ currentResult, history, onSelect, workspaceTags, onTagToggle }) => {
1103
- const currentIndex = (0, import_react6.useMemo)(() => history.findIndex((h) => h.id === currentResult?.id), [history, currentResult]);
1105
+ const currentIndex = (0, import_react5.useMemo)(() => history.findIndex((h) => h.id === currentResult?.id), [history, currentResult]);
1104
1106
  if (!currentResult) {
1105
1107
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-col items-center justify-center py-20 text-center gap-4 opacity-10", children: [
1106
1108
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "material-symbols-outlined text-[64px]", children: "info" }),
@@ -1108,7 +1110,7 @@ var InspectPanel = ({ currentResult, history, onSelect, workspaceTags, onTagTogg
1108
1110
  ] });
1109
1111
  }
1110
1112
  const fullDateStr = new Date(currentResult.timestamp).toLocaleString([], { day: "2-digit", month: "2-digit", year: "numeric", hour: "2-digit", minute: "2-digit", second: "2-digit" });
1111
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react7.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, className: "absolute inset-0 flex flex-col overflow-hidden", children: [
1113
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react6.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, className: "absolute inset-0 flex flex-col overflow-hidden", children: [
1112
1114
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex-shrink-0 border-b border-white/5 bg-black/20 py-3 px-4", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex gap-2 overflow-x-auto no-scrollbar pb-1", children: history.map((gen) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { onClick: () => onSelect(gen), className: `w-10 h-10 rounded-lg overflow-hidden border shrink-0 transition-all ${currentResult.id === gen.id ? "border-white scale-105 shadow-lg" : "border-white/5 opacity-40 hover:opacity-100"}`, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("img", { src: gen.base64 ? gen.base64.startsWith("data:") ? gen.base64 : `data:image/png;base64,${gen.base64}` : "", className: "w-full h-full object-cover", alt: "Thumbnail" }) }, gen.id)) }) }),
1113
1115
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex-1 overflow-y-auto p-4 flex flex-col gap-6 dark-scrollbar pb-10", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-col gap-4", children: [
1114
1116
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SectionLabel, { children: "Vorschau" }),
@@ -1161,8 +1163,8 @@ var InspectPanel = ({ currentResult, history, onSelect, workspaceTags, onTagTogg
1161
1163
  };
1162
1164
 
1163
1165
  // src/components/SetupPanel.tsx
1164
- var import_react8 = require("react");
1165
- var import_react9 = require("motion/react");
1166
+ var import_react7 = require("react");
1167
+ var import_react8 = require("motion/react");
1166
1168
  var import_jsx_runtime7 = require("react/jsx-runtime");
1167
1169
  var PRESET_URLS = [
1168
1170
  "https://jsonplaceholder.typicode.com/todos/1",
@@ -1170,12 +1172,12 @@ var PRESET_URLS = [
1170
1172
  "https://esm.sh/@rslsp1/fa-app-tools@latest"
1171
1173
  ];
1172
1174
  var SetupPanel = ({ onWorkspaceImport, buildInfo }) => {
1173
- const workspaceInputRef = (0, import_react8.useRef)(null);
1174
- const [urlInput, setUrlInput] = (0, import_react8.useState)("");
1175
- const [tokenInput, setTokenInput] = (0, import_react8.useState)("");
1176
- const [testStatus, setTestStatus] = (0, import_react8.useState)("idle");
1177
- const [result, setResult] = (0, import_react8.useState)(null);
1178
- const [fetchError, setFetchError] = (0, import_react8.useState)(null);
1175
+ const workspaceInputRef = (0, import_react7.useRef)(null);
1176
+ const [urlInput, setUrlInput] = (0, import_react7.useState)("");
1177
+ const [tokenInput, setTokenInput] = (0, import_react7.useState)("");
1178
+ const [testStatus, setTestStatus] = (0, import_react7.useState)("idle");
1179
+ const [result, setResult] = (0, import_react7.useState)(null);
1180
+ const [fetchError, setFetchError] = (0, import_react7.useState)(null);
1179
1181
  const runTest = async (url) => {
1180
1182
  if (!url.trim()) return;
1181
1183
  setTestStatus("loading");
@@ -1215,7 +1217,7 @@ var SetupPanel = ({ onWorkspaceImport, buildInfo }) => {
1215
1217
  setTestStatus("error");
1216
1218
  }
1217
1219
  };
1218
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react9.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, className: "absolute inset-0 p-6 flex flex-col gap-10 overflow-y-auto", children: [
1220
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react8.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, className: "absolute inset-0 p-6 flex flex-col gap-10 overflow-y-auto", children: [
1219
1221
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-4", children: [
1220
1222
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-1", children: [
1221
1223
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SectionLabel, { children: "Workspace Management" }),
@@ -1338,8 +1340,7 @@ var SetupPanel = ({ onWorkspaceImport, buildInfo }) => {
1338
1340
  };
1339
1341
 
1340
1342
  // src/components/MediaLibrary.tsx
1341
- var import_react10 = require("react");
1342
- var import_react11 = require("motion/react");
1343
+ var import_react9 = require("motion/react");
1343
1344
 
1344
1345
  // src/lib/grouping.ts
1345
1346
  function groupByPrompt(items) {
@@ -1364,9 +1365,7 @@ function groupByPrompt(items) {
1364
1365
 
1365
1366
  // src/components/MediaLibrary.tsx
1366
1367
  var import_jsx_runtime8 = require("react/jsx-runtime");
1367
- var PAGE_SIZE2 = 20;
1368
- var MediaLibrary = ({ items, onImport, onDelete, onSelect, onToggleSelection, onBatchDownload, onGenerateReference }) => {
1369
- const [visibleCount, setVisibleCount] = (0, import_react10.useState)(PAGE_SIZE2);
1368
+ var MediaLibrary = ({ items, onImport, onDelete, onSelect, onToggleSelection, onBatchDownload, onGenerateReference, visibleCount, onLoadMore }) => {
1370
1369
  const selectedCount = items.filter((i) => i.selectedForExport).length;
1371
1370
  const groups = groupByPrompt(items);
1372
1371
  const visibleGroups = groups.slice(0, visibleCount);
@@ -1387,7 +1386,7 @@ var MediaLibrary = ({ items, onImport, onDelete, onSelect, onToggleSelection, on
1387
1386
  "Laden"
1388
1387
  ] })
1389
1388
  ] }),
1390
- selectedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react11.motion.div, { initial: { opacity: 0, y: -10 }, animate: { opacity: 1, y: 0 }, className: "flex items-center justify-between bg-blue-500/10 border border-blue-500/20 p-2 rounded-xl", children: [
1389
+ selectedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react9.motion.div, { initial: { opacity: 0, y: -10 }, animate: { opacity: 1, y: 0 }, className: "flex items-center justify-between bg-blue-500/10 border border-blue-500/20 p-2 rounded-xl", children: [
1391
1390
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "text-[9px] font-bold uppercase text-blue-400 ml-1", children: [
1392
1391
  selectedCount,
1393
1392
  " ausgew\xE4hlt"
@@ -1408,7 +1407,7 @@ var MediaLibrary = ({ items, onImport, onDelete, onSelect, onToggleSelection, on
1408
1407
  visibleGroups.map((group) => {
1409
1408
  const rep = group.representative;
1410
1409
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1411
- import_react11.motion.div,
1410
+ import_react9.motion.div,
1412
1411
  {
1413
1412
  initial: { opacity: 0, scale: 0.9 },
1414
1413
  animate: { opacity: 1, scale: 1 },
@@ -1439,7 +1438,7 @@ var MediaLibrary = ({ items, onImport, onDelete, onSelect, onToggleSelection, on
1439
1438
  rep.id
1440
1439
  );
1441
1440
  }),
1442
- visibleCount < groups.length && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "col-span-2 flex justify-center pt-2 pb-4", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("button", { type: "button", onClick: () => setVisibleCount((c) => c + PAGE_SIZE2), className: "px-4 py-2 bg-white/5 hover:bg-white/10 border border-white/10 rounded-lg text-[10px] font-bold uppercase text-white/60 hover:text-white transition-all", children: [
1441
+ visibleCount < groups.length && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "col-span-2 flex justify-center pt-2 pb-4", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("button", { type: "button", onClick: onLoadMore, className: "px-4 py-2 bg-white/5 hover:bg-white/10 border border-white/10 rounded-lg text-[10px] font-bold uppercase text-white/60 hover:text-white transition-all", children: [
1443
1442
  groups.length - visibleCount,
1444
1443
  " weitere laden"
1445
1444
  ] }) })
@@ -1448,10 +1447,10 @@ var MediaLibrary = ({ items, onImport, onDelete, onSelect, onToggleSelection, on
1448
1447
  };
1449
1448
 
1450
1449
  // src/components/ListView.tsx
1451
- var import_react12 = require("react");
1450
+ var import_react10 = require("react");
1452
1451
  var import_jsx_runtime9 = require("react/jsx-runtime");
1453
1452
  var ListNode = ({ node, depth, onNodeChange, onAddChild, onDeleteNode, onMoveNode, onIndentNode, onOutdentNode, onAddSibling, isActive, isInPath, onFocus, onGenerate, onGenerateBranch, onGenerateSubtree, isGenerating, isCollapsed, toggleCollapse, renderNode, children }) => {
1454
- const inputRef = (0, import_react12.useRef)(null);
1453
+ const inputRef = (0, import_react10.useRef)(null);
1455
1454
  const hasChildren = children && children.length > 0;
1456
1455
  const handleKeyDown = (e) => {
1457
1456
  if (e.key === "Tab") {
@@ -1479,7 +1478,7 @@ var ListNode = ({ node, depth, onNodeChange, onAddChild, onDeleteNode, onMoveNod
1479
1478
  onMoveNode(node.id, "down");
1480
1479
  }
1481
1480
  };
1482
- (0, import_react12.useEffect)(() => {
1481
+ (0, import_react10.useEffect)(() => {
1483
1482
  if (isActive && inputRef.current) inputRef.current.focus();
1484
1483
  }, [isActive]);
1485
1484
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-col w-full", children: [
@@ -1513,7 +1512,7 @@ var ListNode = ({ node, depth, onNodeChange, onAddChild, onDeleteNode, onMoveNod
1513
1512
  ] });
1514
1513
  };
1515
1514
  function ListView({ nodes, edges, onNodeChange, onAddChild, onDeleteNode, onMoveNode, onIndentNode, onOutdentNode, onAddSibling, focusedNodeId, onFocus, activePath, onGenerate, onGenerateBranch, onGenerateSubtree, isGeneratingNodeId }) {
1516
- const [collapsed, setCollapsed] = (0, import_react12.useState)(/* @__PURE__ */ new Set());
1515
+ const [collapsed, setCollapsed] = (0, import_react10.useState)(/* @__PURE__ */ new Set());
1517
1516
  const toggleCollapse = (id) => {
1518
1517
  setCollapsed((prev) => {
1519
1518
  const next = new Set(prev);
@@ -1541,13 +1540,13 @@ function ListView({ nodes, edges, onNodeChange, onAddChild, onDeleteNode, onMove
1541
1540
  }
1542
1541
 
1543
1542
  // src/components/AvatarArchitectApp.tsx
1544
- var import_react27 = require("react");
1543
+ var import_react25 = require("react");
1545
1544
 
1546
1545
  // src/components/PromptTab.tsx
1547
- var import_react14 = require("react");
1546
+ var import_react12 = require("react");
1548
1547
 
1549
1548
  // src/components/CollapsibleCard.tsx
1550
- var import_react13 = require("react");
1549
+ var import_react11 = require("react");
1551
1550
  var import_jsx_runtime10 = require("react/jsx-runtime");
1552
1551
  var CollapsibleCard = ({
1553
1552
  title,
@@ -1558,7 +1557,7 @@ var CollapsibleCard = ({
1558
1557
  collapsible = true,
1559
1558
  className = ""
1560
1559
  }) => {
1561
- const [isOpen, setIsOpen] = (0, import_react13.useState)(defaultOpen);
1560
+ const [isOpen, setIsOpen] = (0, import_react11.useState)(defaultOpen);
1562
1561
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: `border border-neutral-800 rounded-lg ${className}`, children: [
1563
1562
  /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1564
1563
  "div",
@@ -1605,20 +1604,20 @@ var PromptTab = ({
1605
1604
  onTagUpdate,
1606
1605
  onTagDelete
1607
1606
  }) => {
1608
- const [selectedLabels, setSelectedLabels] = (0, import_react14.useState)(/* @__PURE__ */ new Set());
1609
- const [instructions, setInstructions] = (0, import_react14.useState)("");
1610
- const [rules, setRules] = (0, import_react14.useState)("");
1611
- const [activeCategory, setActiveCategory] = (0, import_react14.useState)(null);
1612
- const [copied, setCopied] = (0, import_react14.useState)(false);
1613
- const imgInputRef = (0, import_react14.useRef)(null);
1614
- const [addingInCat, setAddingInCat] = (0, import_react14.useState)(null);
1615
- const [newLabel, setNewLabel] = (0, import_react14.useState)("");
1616
- const [newValue, setNewValue] = (0, import_react14.useState)("");
1617
- const [editingTag, setEditingTag] = (0, import_react14.useState)(null);
1618
- const [editLabel, setEditLabel] = (0, import_react14.useState)("");
1619
- const [editValue, setEditValue] = (0, import_react14.useState)("");
1620
- const longPressTimer = (0, import_react14.useRef)(null);
1621
- const longPressActivated = (0, import_react14.useRef)(false);
1607
+ const [selectedLabels, setSelectedLabels] = (0, import_react12.useState)(/* @__PURE__ */ new Set());
1608
+ const [instructions, setInstructions] = (0, import_react12.useState)("");
1609
+ const [rules, setRules] = (0, import_react12.useState)("");
1610
+ const [activeCategory, setActiveCategory] = (0, import_react12.useState)(null);
1611
+ const [copied, setCopied] = (0, import_react12.useState)(false);
1612
+ const imgInputRef = (0, import_react12.useRef)(null);
1613
+ const [addingInCat, setAddingInCat] = (0, import_react12.useState)(null);
1614
+ const [newLabel, setNewLabel] = (0, import_react12.useState)("");
1615
+ const [newValue, setNewValue] = (0, import_react12.useState)("");
1616
+ const [editingTag, setEditingTag] = (0, import_react12.useState)(null);
1617
+ const [editLabel, setEditLabel] = (0, import_react12.useState)("");
1618
+ const [editValue, setEditValue] = (0, import_react12.useState)("");
1619
+ const longPressTimer = (0, import_react12.useRef)(null);
1620
+ const longPressActivated = (0, import_react12.useRef)(false);
1622
1621
  const toggleTag = (label) => {
1623
1622
  setSelectedLabels((prev) => {
1624
1623
  const next = new Set(prev);
@@ -2065,7 +2064,7 @@ var PromptTab = ({
2065
2064
  };
2066
2065
 
2067
2066
  // src/components/ProjectSyncTab.tsx
2068
- var import_react15 = require("react");
2067
+ var import_react13 = require("react");
2069
2068
  init_hfStateService();
2070
2069
  var import_jsx_runtime12 = require("react/jsx-runtime");
2071
2070
  var ProjectSyncTab = ({
@@ -2086,14 +2085,14 @@ var ProjectSyncTab = ({
2086
2085
  onProjectExportBase64,
2087
2086
  onHfInitialSync
2088
2087
  }) => {
2089
- const projectInputRef = (0, import_react15.useRef)(null);
2090
- const workspaceInputRef = (0, import_react15.useRef)(null);
2091
- const [saveName, setSaveName] = (0, import_react15.useState)("");
2092
- const [isSaving, setIsSaving] = (0, import_react15.useState)(false);
2093
- const [isExporting, setIsExporting] = (0, import_react15.useState)(false);
2094
- const [syncState, setSyncState] = (0, import_react15.useState)("idle");
2095
- const [syncDiff, setSyncDiff] = (0, import_react15.useState)(null);
2096
- const [selectedLocalIds, setSelectedLocalIds] = (0, import_react15.useState)(/* @__PURE__ */ new Set());
2088
+ const projectInputRef = (0, import_react13.useRef)(null);
2089
+ const workspaceInputRef = (0, import_react13.useRef)(null);
2090
+ const [saveName, setSaveName] = (0, import_react13.useState)("");
2091
+ const [isSaving, setIsSaving] = (0, import_react13.useState)(false);
2092
+ const [isExporting, setIsExporting] = (0, import_react13.useState)(false);
2093
+ const [syncState, setSyncState] = (0, import_react13.useState)("idle");
2094
+ const [syncDiff, setSyncDiff] = (0, import_react13.useState)(null);
2095
+ const [selectedLocalIds, setSelectedLocalIds] = (0, import_react13.useState)(/* @__PURE__ */ new Set());
2097
2096
  const handleExport = async () => {
2098
2097
  if (!onProjectExport) return;
2099
2098
  setIsExporting(true);
@@ -2139,13 +2138,13 @@ var ProjectSyncTab = ({
2139
2138
  });
2140
2139
  };
2141
2140
  const isWorking = projectActionState === "working" || projectActionState === "working-full";
2142
- const [hfProjects, setHfProjects] = (0, import_react15.useState)([]);
2143
- const [hfLoading, setHfLoading] = (0, import_react15.useState)(false);
2144
- const [hfSaving, setHfSaving] = (0, import_react15.useState)(false);
2145
- const [hfError, setHfError] = (0, import_react15.useState)(null);
2146
- const [hfSaveName, setHfSaveName] = (0, import_react15.useState)("");
2147
- const [hfSyncProgress, setHfSyncProgress] = (0, import_react15.useState)(null);
2148
- const [hfSyncing, setHfSyncing] = (0, import_react15.useState)(false);
2141
+ const [hfProjects, setHfProjects] = (0, import_react13.useState)([]);
2142
+ const [hfLoading, setHfLoading] = (0, import_react13.useState)(false);
2143
+ const [hfSaving, setHfSaving] = (0, import_react13.useState)(false);
2144
+ const [hfError, setHfError] = (0, import_react13.useState)(null);
2145
+ const [hfSaveName, setHfSaveName] = (0, import_react13.useState)("");
2146
+ const [hfSyncProgress, setHfSyncProgress] = (0, import_react13.useState)(null);
2147
+ const [hfSyncing, setHfSyncing] = (0, import_react13.useState)(false);
2149
2148
  const loadHfProjects = async (token) => {
2150
2149
  setHfLoading(true);
2151
2150
  setHfError(null);
@@ -2157,7 +2156,7 @@ var ProjectSyncTab = ({
2157
2156
  setHfLoading(false);
2158
2157
  }
2159
2158
  };
2160
- (0, import_react15.useEffect)(() => {
2159
+ (0, import_react13.useEffect)(() => {
2161
2160
  if (hfToken) loadHfProjects(hfToken);
2162
2161
  }, [hfToken]);
2163
2162
  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: [
@@ -2571,7 +2570,7 @@ function toPromptImages(images) {
2571
2570
  init_hfStateService();
2572
2571
 
2573
2572
  // src/hooks/useHFState.ts
2574
- var import_react16 = require("react");
2573
+ var import_react14 = require("react");
2575
2574
  init_hfStateService();
2576
2575
 
2577
2576
  // src/lib/hfReducer.ts
@@ -2704,18 +2703,19 @@ function writeOfflineBuffer(events) {
2704
2703
  }
2705
2704
  }
2706
2705
  function useHFState(token, namespace) {
2707
- const [state, setState] = (0, import_react16.useState)(null);
2708
- const [isLoading, setIsLoading] = (0, import_react16.useState)(false);
2709
- const [error, setError] = (0, import_react16.useState)(null);
2710
- const [eventCount, setEventCount] = (0, import_react16.useState)(0);
2711
- const [localOnlyCount, setLocalOnlyCount] = (0, import_react16.useState)(0);
2712
- const [forks, setForks] = (0, import_react16.useState)([]);
2713
- const [pendingBufferCount, setPendingBufferCount] = (0, import_react16.useState)(readOfflineBuffer().length);
2714
- const [lastEventTs, setLastEventTs] = (0, import_react16.useState)(0);
2715
- const [hasStateZip, setHasStateZip] = (0, import_react16.useState)(false);
2716
- const knownEventPaths = (0, import_react16.useRef)(/* @__PURE__ */ new Set());
2717
- const allEventsRef = (0, import_react16.useRef)([]);
2718
- const applyNewEvents = (0, import_react16.useCallback)((snapshot, newEvents) => {
2706
+ const [state, setState] = (0, import_react14.useState)(null);
2707
+ const [isLoading, setIsLoading] = (0, import_react14.useState)(false);
2708
+ const [error, setError] = (0, import_react14.useState)(null);
2709
+ const [eventCount, setEventCount] = (0, import_react14.useState)(0);
2710
+ const [localOnlyCount, setLocalOnlyCount] = (0, import_react14.useState)(0);
2711
+ const [forks, setForks] = (0, import_react14.useState)([]);
2712
+ const [pendingBufferCount, setPendingBufferCount] = (0, import_react14.useState)(readOfflineBuffer().length);
2713
+ const [lastEventTs, setLastEventTs] = (0, import_react14.useState)(0);
2714
+ const [hasStateZip, setHasStateZip] = (0, import_react14.useState)(false);
2715
+ const knownEventPaths = (0, import_react14.useRef)(/* @__PURE__ */ new Set());
2716
+ const knownFilePaths = (0, import_react14.useRef)(/* @__PURE__ */ new Set());
2717
+ const allEventsRef = (0, import_react14.useRef)([]);
2718
+ const applyNewEvents = (0, import_react14.useCallback)((snapshot, newEvents) => {
2719
2719
  if (!newEvents.length && allEventsRef.current.length === 0) {
2720
2720
  setEventCount(0);
2721
2721
  return snapshot;
@@ -2729,10 +2729,11 @@ function useHFState(token, namespace) {
2729
2729
  if (afterConsolidation.length) setLastEventTs(Math.max(...afterConsolidation.map((e) => e.ts)));
2730
2730
  return applyEvents(snapshot, afterConsolidation);
2731
2731
  }, []);
2732
- const loadFull = (0, import_react16.useCallback)(async () => {
2732
+ const loadFull = (0, import_react14.useCallback)(async () => {
2733
2733
  if (!token || !namespace) return;
2734
2734
  setIsLoading(true);
2735
2735
  setError(null);
2736
+ knownFilePaths.current = /* @__PURE__ */ new Set();
2736
2737
  try {
2737
2738
  const snapshot = await loadHFState(namespace, token);
2738
2739
  setHasStateZip(snapshot !== null);
@@ -2741,7 +2742,7 @@ function useHFState(token, namespace) {
2741
2742
  tags: { by_category: {}, all: [] },
2742
2743
  meta: { consolidatedAt: 0, version: 1 }
2743
2744
  };
2744
- const hfEvents = await loadPendingEvents(namespace, token, base.meta.consolidatedAt);
2745
+ const hfEvents = await loadPendingEvents(namespace, token, base.meta.consolidatedAt, knownFilePaths.current);
2745
2746
  const hfEventKeys = new Set(hfEvents.map((e) => `${e.ts}_${e.clientId}`));
2746
2747
  const localOnlyEvents = allEventsRef.current.filter(
2747
2748
  (e) => !hfEventKeys.has(`${e.ts}_${e.clientId}`)
@@ -2766,7 +2767,7 @@ function useHFState(token, namespace) {
2766
2767
  }
2767
2768
  writeOfflineBuffer(failed);
2768
2769
  setPendingBufferCount(failed.length);
2769
- const freshEvents = await loadPendingEvents(namespace, token, base.meta.consolidatedAt);
2770
+ const freshEvents = await loadPendingEvents(namespace, token, base.meta.consolidatedAt, knownFilePaths.current);
2770
2771
  freshEvents.forEach((e) => knownEventPaths.current.add(`${e.ts}_${e.clientId}`));
2771
2772
  setState((prev) => prev ? applyNewEvents(base, freshEvents) : prev);
2772
2773
  }
@@ -2776,10 +2777,10 @@ function useHFState(token, namespace) {
2776
2777
  setIsLoading(false);
2777
2778
  }
2778
2779
  }, [token, namespace, applyNewEvents]);
2779
- const pollNew = (0, import_react16.useCallback)(async () => {
2780
+ const pollNew = (0, import_react14.useCallback)(async () => {
2780
2781
  if (!token || !namespace || !state) return;
2781
2782
  try {
2782
- const events = await loadPendingEvents(namespace, token, state.meta.consolidatedAt);
2783
+ const events = await loadPendingEvents(namespace, token, state.meta.consolidatedAt, knownFilePaths.current);
2783
2784
  const newEvents = events.filter((e) => !knownEventPaths.current.has(`${e.ts}_${e.clientId}`));
2784
2785
  if (!newEvents.length) return;
2785
2786
  newEvents.forEach((e) => knownEventPaths.current.add(`${e.ts}_${e.clientId}`));
@@ -2790,15 +2791,15 @@ function useHFState(token, namespace) {
2790
2791
  } catch {
2791
2792
  }
2792
2793
  }, [token, namespace, state, applyNewEvents]);
2793
- (0, import_react16.useEffect)(() => {
2794
+ (0, import_react14.useEffect)(() => {
2794
2795
  if (token && namespace) loadFull();
2795
2796
  }, [token, namespace]);
2796
- (0, import_react16.useEffect)(() => {
2797
+ (0, import_react14.useEffect)(() => {
2797
2798
  if (!token || !namespace) return;
2798
2799
  const id = setInterval(pollNew, POLL_INTERVAL_MS);
2799
2800
  return () => clearInterval(id);
2800
2801
  }, [token, namespace, pollNew]);
2801
- const writeEvent = (0, import_react16.useCallback)(async (type, payload) => {
2802
+ const writeEvent = (0, import_react14.useCallback)(async (type, payload) => {
2802
2803
  const prevTs = lastEventTs ? [lastEventTs] : [state?.meta.consolidatedAt ?? 0];
2803
2804
  console.log("[HF] writeEvent called:", { type, namespace, tokenOk: !!token, prevTs });
2804
2805
  await pollNew();
@@ -2848,13 +2849,13 @@ function useHFState(token, namespace) {
2848
2849
  }
2849
2850
 
2850
2851
  // src/components/labs/LabsTab.tsx
2851
- var import_react23 = require("react");
2852
+ var import_react21 = require("react");
2852
2853
 
2853
2854
  // src/components/labs/LabRemix.tsx
2854
- var import_react18 = require("react");
2855
+ var import_react16 = require("react");
2855
2856
 
2856
2857
  // src/components/labs/LabImagePicker.tsx
2857
- var import_react17 = require("react");
2858
+ var import_react15 = require("react");
2858
2859
  var import_jsx_runtime13 = require("react/jsx-runtime");
2859
2860
  var LabImagePicker = ({
2860
2861
  availableItems,
@@ -2863,8 +2864,8 @@ var LabImagePicker = ({
2863
2864
  onClose,
2864
2865
  title = "Bild w\xE4hlen"
2865
2866
  }) => {
2866
- const [search, setSearch] = (0, import_react17.useState)("");
2867
- const [drillItem, setDrillItem] = (0, import_react17.useState)(null);
2867
+ const [search, setSearch] = (0, import_react15.useState)("");
2868
+ const [drillItem, setDrillItem] = (0, import_react15.useState)(null);
2868
2869
  const filtered = availableItems.filter(
2869
2870
  (item) => !search || item.prompt.toLowerCase().includes(search.toLowerCase())
2870
2871
  );
@@ -2966,13 +2967,13 @@ var LabImagePicker = ({
2966
2967
  // src/components/labs/LabRemix.tsx
2967
2968
  var import_jsx_runtime14 = require("react/jsx-runtime");
2968
2969
  var LabRemix = ({ services, onResult }) => {
2969
- const [showPicker, setShowPicker] = (0, import_react18.useState)(false);
2970
- const [selected, setSelected] = (0, import_react18.useState)(null);
2971
- const [instruction, setInstruction] = (0, import_react18.useState)("");
2972
- const [generatedPrompt, setGeneratedPrompt] = (0, import_react18.useState)("");
2973
- const [resultImage, setResultImage] = (0, import_react18.useState)(null);
2974
- const [isGeneratingPrompt, setIsGeneratingPrompt] = (0, import_react18.useState)(false);
2975
- const [isGeneratingImage, setIsGeneratingImage] = (0, import_react18.useState)(false);
2970
+ const [showPicker, setShowPicker] = (0, import_react16.useState)(false);
2971
+ const [selected, setSelected] = (0, import_react16.useState)(null);
2972
+ const [instruction, setInstruction] = (0, import_react16.useState)("");
2973
+ const [generatedPrompt, setGeneratedPrompt] = (0, import_react16.useState)("");
2974
+ const [resultImage, setResultImage] = (0, import_react16.useState)(null);
2975
+ const [isGeneratingPrompt, setIsGeneratingPrompt] = (0, import_react16.useState)(false);
2976
+ const [isGeneratingImage, setIsGeneratingImage] = (0, import_react16.useState)(false);
2976
2977
  const handleSelectImage = (item, frame) => {
2977
2978
  services.onItemUsed(item);
2978
2979
  setSelected({
@@ -3155,16 +3156,16 @@ var LabRemix = ({ services, onResult }) => {
3155
3156
  };
3156
3157
 
3157
3158
  // src/components/labs/LabBlend.tsx
3158
- var import_react19 = require("react");
3159
+ var import_react17 = require("react");
3159
3160
  var import_jsx_runtime15 = require("react/jsx-runtime");
3160
3161
  var LabBlend = ({ services, onResult }) => {
3161
- const [showPickerFor, setShowPickerFor] = (0, import_react19.useState)(null);
3162
- const [selectedImages, setSelectedImages] = (0, import_react19.useState)([]);
3163
- const [instruction, setInstruction] = (0, import_react19.useState)("");
3164
- const [generatedPrompt, setGeneratedPrompt] = (0, import_react19.useState)("");
3165
- const [resultImage, setResultImage] = (0, import_react19.useState)(null);
3166
- const [isGeneratingPrompt, setIsGeneratingPrompt] = (0, import_react19.useState)(false);
3167
- const [isGeneratingImage, setIsGeneratingImage] = (0, import_react19.useState)(false);
3162
+ const [showPickerFor, setShowPickerFor] = (0, import_react17.useState)(null);
3163
+ const [selectedImages, setSelectedImages] = (0, import_react17.useState)([]);
3164
+ const [instruction, setInstruction] = (0, import_react17.useState)("");
3165
+ const [generatedPrompt, setGeneratedPrompt] = (0, import_react17.useState)("");
3166
+ const [resultImage, setResultImage] = (0, import_react17.useState)(null);
3167
+ const [isGeneratingPrompt, setIsGeneratingPrompt] = (0, import_react17.useState)(false);
3168
+ const [isGeneratingImage, setIsGeneratingImage] = (0, import_react17.useState)(false);
3168
3169
  const handleSelectImage = (index, item, frame) => {
3169
3170
  services.onItemUsed(item);
3170
3171
  const newImg = {
@@ -3351,17 +3352,17 @@ var LabBlend = ({ services, onResult }) => {
3351
3352
  };
3352
3353
 
3353
3354
  // src/components/labs/LabCompare.tsx
3354
- var import_react20 = require("react");
3355
+ var import_react18 = require("react");
3355
3356
  var import_jsx_runtime16 = require("react/jsx-runtime");
3356
3357
  var LabCompare = ({ services, onResult }) => {
3357
- const [showPickerFor, setShowPickerFor] = (0, import_react20.useState)(null);
3358
- const [selectedImages, setSelectedImages] = (0, import_react20.useState)([]);
3359
- const [instruction, setInstruction] = (0, import_react20.useState)("");
3360
- const [analysis, setAnalysis] = (0, import_react20.useState)("");
3361
- const [generatedPrompt, setGeneratedPrompt] = (0, import_react20.useState)("");
3362
- const [resultImage, setResultImage] = (0, import_react20.useState)(null);
3363
- const [isAnalyzing, setIsAnalyzing] = (0, import_react20.useState)(false);
3364
- const [isGeneratingImage, setIsGeneratingImage] = (0, import_react20.useState)(false);
3358
+ const [showPickerFor, setShowPickerFor] = (0, import_react18.useState)(null);
3359
+ const [selectedImages, setSelectedImages] = (0, import_react18.useState)([]);
3360
+ const [instruction, setInstruction] = (0, import_react18.useState)("");
3361
+ const [analysis, setAnalysis] = (0, import_react18.useState)("");
3362
+ const [generatedPrompt, setGeneratedPrompt] = (0, import_react18.useState)("");
3363
+ const [resultImage, setResultImage] = (0, import_react18.useState)(null);
3364
+ const [isAnalyzing, setIsAnalyzing] = (0, import_react18.useState)(false);
3365
+ const [isGeneratingImage, setIsGeneratingImage] = (0, import_react18.useState)(false);
3365
3366
  const handleSelectImage = (index, item, frame) => {
3366
3367
  services.onItemUsed(item);
3367
3368
  const newImg = {
@@ -3524,14 +3525,14 @@ var LabCompare = ({ services, onResult }) => {
3524
3525
  };
3525
3526
 
3526
3527
  // src/components/labs/LabLoop.tsx
3527
- var import_react21 = require("react");
3528
+ var import_react19 = require("react");
3528
3529
  var import_jsx_runtime17 = require("react/jsx-runtime");
3529
3530
  var LabLoop = ({ services, onResult }) => {
3530
- const [rounds, setRounds] = (0, import_react21.useState)([]);
3531
- const [currentInstruction, setCurrentInstruction] = (0, import_react21.useState)("");
3532
- const [showPickerForRound, setShowPickerForRound] = (0, import_react21.useState)(null);
3533
- const [pendingImages, setPendingImages] = (0, import_react21.useState)([]);
3534
- const [isGenerating, setIsGenerating] = (0, import_react21.useState)(false);
3531
+ const [rounds, setRounds] = (0, import_react19.useState)([]);
3532
+ const [currentInstruction, setCurrentInstruction] = (0, import_react19.useState)("");
3533
+ const [showPickerForRound, setShowPickerForRound] = (0, import_react19.useState)(null);
3534
+ const [pendingImages, setPendingImages] = (0, import_react19.useState)([]);
3535
+ const [isGenerating, setIsGenerating] = (0, import_react19.useState)(false);
3535
3536
  const currentPrompt = rounds.length > 0 ? rounds[rounds.length - 1].prompt : "";
3536
3537
  const handleAddImage = (item, frame) => {
3537
3538
  services.onItemUsed(item);
@@ -3687,7 +3688,7 @@ var LabLoop = ({ services, onResult }) => {
3687
3688
  };
3688
3689
 
3689
3690
  // src/components/labs/LabFrameExtractor.tsx
3690
- var import_react22 = require("react");
3691
+ var import_react20 = require("react");
3691
3692
  var import_jsx_runtime18 = require("react/jsx-runtime");
3692
3693
  var formatTime = (s) => {
3693
3694
  const m = Math.floor(s / 60);
@@ -3701,15 +3702,15 @@ var LabFrameExtractor = ({
3701
3702
  onResult,
3702
3703
  resolveVideoUrl
3703
3704
  }) => {
3704
- const videoRef = (0, import_react22.useRef)(null);
3705
- const canvasRef = (0, import_react22.useRef)(null);
3706
- const cancelledRef = (0, import_react22.useRef)(false);
3707
- const [selectedItem, setSelectedItem] = (0, import_react22.useState)(null);
3708
- const [videoSrc, setVideoSrc] = (0, import_react22.useState)(null);
3709
- const [videoReady, setVideoReady] = (0, import_react22.useState)(false);
3710
- const [frames, setFrames] = (0, import_react22.useState)([]);
3711
- const [isExtracting, setIsExtracting] = (0, import_react22.useState)(false);
3712
- const [intervalSec, setIntervalSec] = (0, import_react22.useState)("1");
3705
+ const videoRef = (0, import_react20.useRef)(null);
3706
+ const canvasRef = (0, import_react20.useRef)(null);
3707
+ const cancelledRef = (0, import_react20.useRef)(false);
3708
+ const [selectedItem, setSelectedItem] = (0, import_react20.useState)(null);
3709
+ const [videoSrc, setVideoSrc] = (0, import_react20.useState)(null);
3710
+ const [videoReady, setVideoReady] = (0, import_react20.useState)(false);
3711
+ const [frames, setFrames] = (0, import_react20.useState)([]);
3712
+ const [isExtracting, setIsExtracting] = (0, import_react20.useState)(false);
3713
+ const [intervalSec, setIntervalSec] = (0, import_react20.useState)("1");
3713
3714
  const handleVideoSelect = (item) => {
3714
3715
  const mediaId = item.frames[0]?.mediaId;
3715
3716
  if (!mediaId) return;
@@ -3719,7 +3720,7 @@ var LabFrameExtractor = ({
3719
3720
  setVideoReady(false);
3720
3721
  cancelledRef.current = false;
3721
3722
  };
3722
- const captureAt = (0, import_react22.useCallback)(
3723
+ const captureAt = (0, import_react20.useCallback)(
3723
3724
  (t, label) => new Promise((resolve) => {
3724
3725
  const video = videoRef.current;
3725
3726
  const canvas = canvasRef.current;
@@ -3946,7 +3947,7 @@ var BASE_TABS = [
3946
3947
  ];
3947
3948
  var FRAMES_TAB = { key: "frames", label: "Frames", icon: "crop_original" };
3948
3949
  var LabsTab = ({ services, onResult, videoItems, resolveVideoUrl }) => {
3949
- const [activeTab, setActiveTab] = (0, import_react23.useState)("remix");
3950
+ const [activeTab, setActiveTab] = (0, import_react21.useState)("remix");
3950
3951
  const showFrames = !!(videoItems && resolveVideoUrl);
3951
3952
  const tabs = showFrames ? [...BASE_TABS, FRAMES_TAB] : BASE_TABS;
3952
3953
  return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex flex-col h-full overflow-hidden", children: [
@@ -3980,19 +3981,19 @@ var LabsTab = ({ services, onResult, videoItems, resolveVideoUrl }) => {
3980
3981
  };
3981
3982
 
3982
3983
  // src/components/TagManagerPanel.tsx
3983
- var import_react24 = require("react");
3984
+ var import_react22 = require("react");
3984
3985
  var import_jsx_runtime20 = require("react/jsx-runtime");
3985
3986
  function TagManagerPanel({ workspaceTags, onTagCreate, onTagUpdate, onTagDelete, onTagReorder, onTagMove }) {
3986
3987
  const categories = Object.keys(workspaceTags.by_category).filter(
3987
3988
  (cat) => (workspaceTags.by_category[cat] || []).some((t) => !t.is_deleted)
3988
3989
  );
3989
- const [selectedCategory, setSelectedCategory] = (0, import_react24.useState)(categories[0] || "");
3990
+ const [selectedCategory, setSelectedCategory] = (0, import_react22.useState)(categories[0] || "");
3990
3991
  const effectiveCategory = categories.includes(selectedCategory) ? selectedCategory : categories[0] || "";
3991
- const [editingLabel, setEditingLabel] = (0, import_react24.useState)(null);
3992
- const [editState, setEditState] = (0, import_react24.useState)({ label: "", value: "" });
3993
- const [newTag, setNewTag] = (0, import_react24.useState)({ label: "", value: "" });
3994
- const [movingLabel, setMovingLabel] = (0, import_react24.useState)(null);
3995
- const [moveTarget, setMoveTarget] = (0, import_react24.useState)("");
3992
+ const [editingLabel, setEditingLabel] = (0, import_react22.useState)(null);
3993
+ const [editState, setEditState] = (0, import_react22.useState)({ label: "", value: "" });
3994
+ const [newTag, setNewTag] = (0, import_react22.useState)({ label: "", value: "" });
3995
+ const [movingLabel, setMovingLabel] = (0, import_react22.useState)(null);
3996
+ const [moveTarget, setMoveTarget] = (0, import_react22.useState)("");
3996
3997
  const tags = (workspaceTags.by_category[effectiveCategory] || []).filter((t) => !t.is_deleted);
3997
3998
  const otherCategories = categories.filter((c) => c !== effectiveCategory);
3998
3999
  const startEdit = (tag) => {
@@ -4188,7 +4189,7 @@ function TagManagerPanel({ workspaceTags, onTagCreate, onTagUpdate, onTagDelete,
4188
4189
  }
4189
4190
 
4190
4191
  // src/components/HFTestTab.tsx
4191
- var import_react25 = require("react");
4192
+ var import_react23 = require("react");
4192
4193
  var import_jsx_runtime21 = require("react/jsx-runtime");
4193
4194
  var HF_BASE2 = "https://huggingface.co";
4194
4195
  var HF_REPO2 = "RolandSch/fa-app-state";
@@ -4381,7 +4382,7 @@ function tryFmt(s) {
4381
4382
  }
4382
4383
  }
4383
4384
  function CopyBtn({ text }) {
4384
- const [done, setDone] = (0, import_react25.useState)(false);
4385
+ const [done, setDone] = (0, import_react23.useState)(false);
4385
4386
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
4386
4387
  "button",
4387
4388
  {
@@ -4553,9 +4554,9 @@ function EventMonitor({ events, confirmedEventKeys, galleryItems, imageUploadSta
4553
4554
  ] });
4554
4555
  }
4555
4556
  function HFTestTab({ token, namespace, galleryItems, allEvents = [], confirmedEventKeys = /* @__PURE__ */ new Set(), imageUploadStatus = /* @__PURE__ */ new Map(), missingImages = [] }) {
4556
- const [selected, setSelected] = (0, import_react25.useState)(null);
4557
- const [results, setResults] = (0, import_react25.useState)({});
4558
- const [expanded, setExpanded] = (0, import_react25.useState)({});
4557
+ const [selected, setSelected] = (0, import_react23.useState)(null);
4558
+ const [results, setResults] = (0, import_react23.useState)({});
4559
+ const [expanded, setExpanded] = (0, import_react23.useState)({});
4559
4560
  const withResults = galleryItems.filter((g) => g.base64 && g.status === "done");
4560
4561
  const setRunning = (id) => setResults((r) => ({ ...r, [id]: { status: "running", steps: [], totalMs: 0 } }));
4561
4562
  const setDone = (id, steps, t0) => {
@@ -4753,7 +4754,7 @@ function HFTestTab({ token, namespace, galleryItems, allEvents = [], confirmedEv
4753
4754
  }
4754
4755
 
4755
4756
  // src/components/ServerTab.tsx
4756
- var import_react26 = require("react");
4757
+ var import_react24 = require("react");
4757
4758
  var import_jsx_runtime22 = require("react/jsx-runtime");
4758
4759
  function StarRating({ rating = 0 }) {
4759
4760
  return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex gap-[2px]", children: [1, 2, 3, 4, 5].map((i) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: `material-symbols-outlined text-[12px] ${i <= rating ? "text-yellow-400" : "text-white/15"}`, children: "star" }, i)) });
@@ -4766,21 +4767,21 @@ async function serverGet(baseUrl, path) {
4766
4767
  return json && typeof json === "object" && "data" in json ? json.data : json;
4767
4768
  }
4768
4769
  function ServerTab({ serverBaseUrl }) {
4769
- const [step, setStep] = (0, import_react26.useState)("user");
4770
- const [users, setUsers] = (0, import_react26.useState)([]);
4771
- const [usersLoading, setUsersLoading] = (0, import_react26.useState)(false);
4772
- const [usersError, setUsersError] = (0, import_react26.useState)(null);
4773
- const [selectedUser, setSelectedUser] = (0, import_react26.useState)(null);
4774
- const [contexts, setContexts] = (0, import_react26.useState)([]);
4775
- const [contextsLoading, setContextsLoading] = (0, import_react26.useState)(false);
4776
- const [selectedContext, setSelectedContext] = (0, import_react26.useState)(null);
4777
- const [tags, setTags] = (0, import_react26.useState)([]);
4778
- const [items, setItems] = (0, import_react26.useState)([]);
4779
- const [libLoading, setLibLoading] = (0, import_react26.useState)(false);
4780
- const [libError, setLibError] = (0, import_react26.useState)(null);
4781
- const [activeTag, setActiveTag] = (0, import_react26.useState)(null);
4782
- const [preview, setPreview] = (0, import_react26.useState)(null);
4783
- (0, import_react26.useEffect)(() => {
4770
+ const [step, setStep] = (0, import_react24.useState)("user");
4771
+ const [users, setUsers] = (0, import_react24.useState)([]);
4772
+ const [usersLoading, setUsersLoading] = (0, import_react24.useState)(false);
4773
+ const [usersError, setUsersError] = (0, import_react24.useState)(null);
4774
+ const [selectedUser, setSelectedUser] = (0, import_react24.useState)(null);
4775
+ const [contexts, setContexts] = (0, import_react24.useState)([]);
4776
+ const [contextsLoading, setContextsLoading] = (0, import_react24.useState)(false);
4777
+ const [selectedContext, setSelectedContext] = (0, import_react24.useState)(null);
4778
+ const [tags, setTags] = (0, import_react24.useState)([]);
4779
+ const [items, setItems] = (0, import_react24.useState)([]);
4780
+ const [libLoading, setLibLoading] = (0, import_react24.useState)(false);
4781
+ const [libError, setLibError] = (0, import_react24.useState)(null);
4782
+ const [activeTag, setActiveTag] = (0, import_react24.useState)(null);
4783
+ const [preview, setPreview] = (0, import_react24.useState)(null);
4784
+ (0, import_react24.useEffect)(() => {
4784
4785
  if (!serverBaseUrl) return;
4785
4786
  setUsersLoading(true);
4786
4787
  setUsersError(null);
@@ -4933,7 +4934,7 @@ function ServerTab({ serverBaseUrl }) {
4933
4934
  // src/components/AvatarArchitectApp.tsx
4934
4935
  var import_jsx_runtime23 = require("react/jsx-runtime");
4935
4936
  function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onSelectMedia, buildInfo, initialHfToken, hfNamespace, allowDevNamespace, serverBaseUrl, onFetchServerProjects, onServerSave, onServerLoad, onServerDelete }) {
4936
- (0, import_react27.useEffect)(() => {
4937
+ (0, import_react25.useEffect)(() => {
4937
4938
  const id = "flow-styles";
4938
4939
  if (!document.getElementById(id)) {
4939
4940
  const style = document.createElement("style");
@@ -4942,19 +4943,19 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4942
4943
  document.head.appendChild(style);
4943
4944
  }
4944
4945
  }, []);
4945
- const [showStart, setShowStart] = (0, import_react27.useState)(true);
4946
- const [layoutChoice, setLayoutChoice] = (0, import_react27.useState)(() => {
4946
+ const [showStart, setShowStart] = (0, import_react25.useState)(true);
4947
+ const [layoutChoice, setLayoutChoice] = (0, import_react25.useState)(() => {
4947
4948
  try {
4948
4949
  return localStorage.getItem("aa-layout") || null;
4949
4950
  } catch {
4950
4951
  return null;
4951
4952
  }
4952
4953
  });
4953
- const [projectLoaded, setProjectLoaded] = (0, import_react27.useState)(false);
4954
- const [hfToken, setHfToken] = (0, import_react27.useState)(initialHfToken || "");
4955
- const [hfTokenInput, setHfTokenInput] = (0, import_react27.useState)(initialHfToken || "");
4956
- const [isLoadingFromHF, setIsLoadingFromHF] = (0, import_react27.useState)(false);
4957
- const [hfNamespaceLocal, setHfNamespaceLocal] = (0, import_react27.useState)(() => {
4954
+ const [projectLoaded, setProjectLoaded] = (0, import_react25.useState)(false);
4955
+ const [hfToken, setHfToken] = (0, import_react25.useState)(initialHfToken || "");
4956
+ const [hfTokenInput, setHfTokenInput] = (0, import_react25.useState)(initialHfToken || "");
4957
+ const [isLoadingFromHF, setIsLoadingFromHF] = (0, import_react25.useState)(false);
4958
+ const [hfNamespaceLocal, setHfNamespaceLocal] = (0, import_react25.useState)(() => {
4958
4959
  const KNOWN = ["app.art-by-rolands.de/", "dev-app.art-by-rolands.de/"];
4959
4960
  const DEFAULT = "app.art-by-rolands.de/";
4960
4961
  try {
@@ -4966,8 +4967,8 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4966
4967
  return DEFAULT;
4967
4968
  }
4968
4969
  });
4969
- const [hfNamespaceFromServer, setHfNamespaceFromServer] = (0, import_react27.useState)(null);
4970
- (0, import_react27.useEffect)(() => {
4970
+ const [hfNamespaceFromServer, setHfNamespaceFromServer] = (0, import_react25.useState)(null);
4971
+ (0, import_react25.useEffect)(() => {
4971
4972
  if (hfNamespace !== void 0) return;
4972
4973
  const backendUrl = typeof window !== "undefined" ? window.BACKEND_URL || window.location.origin : null;
4973
4974
  if (!backendUrl) return;
@@ -4989,10 +4990,10 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4989
4990
  refresh: refreshHF,
4990
4991
  hasStateZip
4991
4992
  } = useHFState(hfToken, effectiveNamespace);
4992
- const [imageUploadStatus, setImageUploadStatus] = (0, import_react27.useState)(/* @__PURE__ */ new Map());
4993
- const [bootstrapLog, setBootstrapLog] = (0, import_react27.useState)([]);
4994
- const [isBootstrapping, setIsBootstrapping] = (0, import_react27.useState)(false);
4995
- const [hfMissingImages, setHfMissingImages] = (0, import_react27.useState)([]);
4993
+ const [imageUploadStatus, setImageUploadStatus] = (0, import_react25.useState)(/* @__PURE__ */ new Map());
4994
+ const [bootstrapLog, setBootstrapLog] = (0, import_react25.useState)([]);
4995
+ const [isBootstrapping, setIsBootstrapping] = (0, import_react25.useState)(false);
4996
+ const [hfMissingImages, setHfMissingImages] = (0, import_react25.useState)([]);
4996
4997
  const syncTopSlot = /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
4997
4998
  localOnlyCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { background: "rgba(234,179,8,0.15)", border: "1px solid rgba(234,179,8,0.3)", padding: "4px 10px", fontSize: 11, color: "#fbbf24", borderRadius: 4, marginBottom: 4 }, children: [
4998
4999
  "\u26A0 ",
@@ -5042,7 +5043,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5042
5043
  bootstrapLog.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { marginTop: 6, fontFamily: "monospace", fontSize: 10, color: "#78716c", lineHeight: 1.6 }, children: bootstrapLog.map((l, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { children: l }, i)) })
5043
5044
  ] })
5044
5045
  ] });
5045
- const wsInputRef = (0, import_react27.useRef)(null);
5046
+ const wsInputRef = (0, import_react25.useRef)(null);
5046
5047
  const startApp = (choice) => {
5047
5048
  try {
5048
5049
  localStorage.setItem("aa-layout", choice);
@@ -5051,16 +5052,37 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5051
5052
  setLayoutChoice(choice);
5052
5053
  setShowStart(false);
5053
5054
  };
5054
- const [nodes, setNodes] = (0, import_react27.useState)([{ id: "1", type: "custom", position: { x: 0, y: 0 }, data: { label: "Fine Art Project", placeholder: "Name..." } }]);
5055
- const [edges, setEdges] = (0, import_react27.useState)([]);
5056
- const [history, setHistory] = (0, import_react27.useState)([]);
5057
- const [galleryItems, setGalleryItems] = (0, import_react27.useState)([]);
5058
- const galleryItemsRef = (0, import_react27.useRef)([]);
5059
- (0, import_react27.useEffect)(() => {
5055
+ const [nodes, setNodes] = (0, import_react25.useState)([{ id: "1", type: "custom", position: { x: 0, y: 0 }, data: { label: "Fine Art Project", placeholder: "Name..." } }]);
5056
+ const [edges, setEdges] = (0, import_react25.useState)([]);
5057
+ const [history, setHistory] = (0, import_react25.useState)([]);
5058
+ const [galleryItems, setGalleryItems] = (0, import_react25.useState)([]);
5059
+ const galleryItemsRef = (0, import_react25.useRef)([]);
5060
+ (0, import_react25.useEffect)(() => {
5060
5061
  galleryItemsRef.current = galleryItems;
5061
5062
  }, [galleryItems]);
5062
- const hfImageNotFoundRef = (0, import_react27.useRef)(/* @__PURE__ */ new Map());
5063
- (0, import_react27.useEffect)(() => {
5063
+ const hfImageNotFoundRef = (0, import_react25.useRef)(/* @__PURE__ */ new Map());
5064
+ const [galleryVisibleCount, setGalleryVisibleCount] = (0, import_react25.useState)(20);
5065
+ const [historyVisibleCount, setHistoryVisibleCount] = (0, import_react25.useState)(20);
5066
+ const loadThumbnailsForEntries = (0, import_react25.useCallback)(async (entries) => {
5067
+ for (const entry of entries) {
5068
+ if (galleryItemsRef.current.find((g) => g.id === entry.id)?.base64) continue;
5069
+ if (hfImageNotFoundRef.current.has(entry.id)) continue;
5070
+ try {
5071
+ const b64 = await hfLoadImageAsBase64(entry.id, hfToken, effectiveNamespace, entry.filename, void 0, entry.mimeType, entry.hasThumb);
5072
+ if (!b64) {
5073
+ hfImageNotFoundRef.current.set(entry.id, Date.now());
5074
+ setHfMissingImages((prev) => prev.find((e) => e.id === entry.id) ? prev : [...prev, { id: entry.id, filename: entry.filename, mimeType: entry.mimeType ?? "image/jpeg", timestamp: entry.timestamp ?? 0 }]);
5075
+ continue;
5076
+ }
5077
+ const prefix = `data:${entry.mimeType || "image/jpeg"};base64,`;
5078
+ setGalleryItems((prev) => prev.map((g) => g.id === entry.id && !g.base64 ? { ...g, base64: prefix + b64 } : g));
5079
+ setHistory((prev) => prev.map((g) => g.id === entry.id && !g.base64 ? { ...g, base64: prefix + b64 } : g));
5080
+ } catch {
5081
+ hfImageNotFoundRef.current.set(entry.id, Date.now());
5082
+ }
5083
+ }
5084
+ }, [hfToken, effectiveNamespace]);
5085
+ (0, import_react25.useEffect)(() => {
5064
5086
  if (!hfState) return;
5065
5087
  if (hfState.tags?.by_category) setWorkspaceTags(hfState.tags);
5066
5088
  const hfIds = new Set(hfState.metadata.map((m) => m.id));
@@ -5086,90 +5108,97 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5086
5108
  const merged = skeletons.map((s) => prev.find((g) => g.id === s.id) ?? s);
5087
5109
  return [...localOnly, ...merged].sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0));
5088
5110
  });
5089
- const sortedEntries = [...hfState.metadata].sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0));
5090
- const galleryRepIds = new Set(groupByPrompt(skeletons).slice(0, 20).map((g) => g.representative.id));
5091
- const historyIds = new Set(sortedEntries.slice(0, 20).map((e) => e.id));
5092
- const initialIds = /* @__PURE__ */ new Set([...galleryRepIds, ...historyIds]);
5093
- const toLoad = sortedEntries.filter((e) => initialIds.has(e.id));
5094
- (async () => {
5095
- for (const entry of toLoad) {
5096
- if (galleryItemsRef.current.find((g) => g.id === entry.id)?.base64) continue;
5097
- if (hfImageNotFoundRef.current.has(entry.id)) continue;
5098
- try {
5099
- const b64 = await hfLoadImageAsBase64(entry.id, hfToken, effectiveNamespace, entry.filename, void 0, entry.mimeType, entry.hasThumb);
5100
- if (!b64) {
5101
- hfImageNotFoundRef.current.set(entry.id, Date.now());
5102
- setHfMissingImages((prev) => {
5103
- if (prev.find((e) => e.id === entry.id)) return prev;
5104
- return [...prev, { id: entry.id, filename: entry.filename, mimeType: entry.mimeType, timestamp: entry.timestamp }];
5105
- });
5106
- continue;
5107
- }
5108
- const prefix = `data:${entry.mimeType || "image/jpeg"};base64,`;
5109
- setGalleryItems((prev) => prev.map((g) => g.id === entry.id && !g.base64 ? { ...g, base64: prefix + b64 } : g));
5110
- setHistory((prev) => prev.map((g) => g.id === entry.id && !g.base64 ? { ...g, base64: prefix + b64 } : g));
5111
- } catch {
5112
- hfImageNotFoundRef.current.set(entry.id, Date.now());
5113
- }
5114
- }
5115
- })();
5116
5111
  }, [hfState]);
5117
- const [activePrompt, setActivePrompt] = (0, import_react27.useState)("");
5118
- const [isSynthesizing, setIsSynthesizing] = (0, import_react27.useState)(false);
5119
- const [activeGenerationsCount, setActiveGenerationsCount] = (0, import_react27.useState)(0);
5120
- const [currentResult, setCurrentResult] = (0, import_react27.useState)(null);
5121
- const [focusedNodeId, setFocusedNodeId] = (0, import_react27.useState)(null);
5122
- const [leftTab, setLeftTab] = (0, import_react27.useState)("prompt");
5123
- const [promptFeedback, setPromptFeedback] = (0, import_react27.useState)(null);
5124
- const [lastPromptPayload, setLastPromptPayload] = (0, import_react27.useState)(null);
5125
- const [isPromptTabGenerating, setIsPromptTabGenerating] = (0, import_react27.useState)(false);
5126
- const [activeTab, setActiveTab] = (0, import_react27.useState)("history");
5127
- const [mobileTab, setMobileTab] = (0, import_react27.useState)("stage");
5128
- const [middlePanel, setMiddlePanel] = (0, import_react27.useState)("stage");
5129
- const [recentLabItems, setRecentLabItems] = (0, import_react27.useState)([]);
5130
- const [aspectRatio, setAspectRatio] = (0, import_react27.useState)("1:1");
5131
- const [selectedModel, setSelectedModel] = (0, import_react27.useState)("\u{1F34C} Nano Banana Pro");
5132
- const [seed, setSeed] = (0, import_react27.useState)(Math.floor(Math.random() * 1e6));
5133
- const [seedMode, setSeedMode] = (0, import_react27.useState)("random");
5134
- const [isLeftCollapsed, setIsLeftCollapsed] = (0, import_react27.useState)(false);
5135
- const [isRightCollapsed, setIsRightCollapsed] = (0, import_react27.useState)(false);
5136
- const [leftPanelWidth, setLeftPanelWidth] = (0, import_react27.useState)(() => {
5112
+ (0, import_react25.useEffect)(() => {
5113
+ if (!hfState) return;
5114
+ const sortedMeta = [...hfState.metadata].sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0));
5115
+ const skeletons = sortedMeta.map((m) => ({ id: m.id, prompt: m.prompt, timestamp: m.timestamp, status: "done", nodeId: m.id, tags: m.tags || [] }));
5116
+ const repIds = new Set(groupByPrompt(skeletons).slice(0, galleryVisibleCount).map((g) => g.representative.id));
5117
+ loadThumbnailsForEntries(sortedMeta.filter((e) => repIds.has(e.id)));
5118
+ }, [hfState, galleryVisibleCount, loadThumbnailsForEntries]);
5119
+ (0, import_react25.useEffect)(() => {
5120
+ if (!hfState) return;
5121
+ const sortedMeta = [...hfState.metadata].sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0));
5122
+ loadThumbnailsForEntries(sortedMeta.slice(0, historyVisibleCount));
5123
+ }, [hfState, historyVisibleCount, loadThumbnailsForEntries]);
5124
+ const [activePrompt, setActivePrompt] = (0, import_react25.useState)("");
5125
+ const [isSynthesizing, setIsSynthesizing] = (0, import_react25.useState)(false);
5126
+ const [activeGenerationsCount, setActiveGenerationsCount] = (0, import_react25.useState)(0);
5127
+ const [currentResult, setCurrentResult] = (0, import_react25.useState)(null);
5128
+ const [focusedNodeId, setFocusedNodeId] = (0, import_react25.useState)(null);
5129
+ const [leftTab, setLeftTab] = (0, import_react25.useState)("prompt");
5130
+ const [promptFeedback, setPromptFeedback] = (0, import_react25.useState)(null);
5131
+ const [lastPromptPayload, setLastPromptPayload] = (0, import_react25.useState)(null);
5132
+ const [isPromptTabGenerating, setIsPromptTabGenerating] = (0, import_react25.useState)(false);
5133
+ const [activeTab, setActiveTab] = (0, import_react25.useState)("history");
5134
+ const [mobileTab, setMobileTab] = (0, import_react25.useState)("stage");
5135
+ const [middlePanel, setMiddlePanel] = (0, import_react25.useState)("stage");
5136
+ const [recentLabItems, setRecentLabItems] = (0, import_react25.useState)([]);
5137
+ const [aspectRatio, setAspectRatio] = (0, import_react25.useState)("1:1");
5138
+ const [selectedModel, setSelectedModel] = (0, import_react25.useState)("\u{1F34C} Nano Banana Pro");
5139
+ const [seed, setSeed] = (0, import_react25.useState)(Math.floor(Math.random() * 1e6));
5140
+ const [seedMode, setSeedMode] = (0, import_react25.useState)("random");
5141
+ const [imageCount, setImageCount] = (0, import_react25.useState)(() => {
5142
+ try {
5143
+ const v = parseInt(localStorage.getItem("aa-image-count") || "", 10);
5144
+ return v >= 1 && v <= 8 ? v : 4;
5145
+ } catch {
5146
+ return 4;
5147
+ }
5148
+ });
5149
+ const updateImageCount = (val) => {
5150
+ const n = Math.max(1, Math.min(8, parseInt(val, 10) || 4));
5151
+ setImageCount(n);
5152
+ try {
5153
+ localStorage.setItem("aa-image-count", String(n));
5154
+ } catch {
5155
+ }
5156
+ };
5157
+ const imageCountOptions = [
5158
+ { label: "1 Bild", value: "1" },
5159
+ { label: "2 Bilder", value: "2" },
5160
+ { label: "4 Bilder", value: "4" },
5161
+ { label: "8 Bilder", value: "8" }
5162
+ ];
5163
+ const [isLeftCollapsed, setIsLeftCollapsed] = (0, import_react25.useState)(false);
5164
+ const [isRightCollapsed, setIsRightCollapsed] = (0, import_react25.useState)(false);
5165
+ const [leftPanelWidth, setLeftPanelWidth] = (0, import_react25.useState)(() => {
5137
5166
  try {
5138
5167
  return parseInt(localStorage.getItem("aa-left-width") || "260", 10);
5139
5168
  } catch {
5140
5169
  return 260;
5141
5170
  }
5142
5171
  });
5143
- const [rightPanelWidth, setRightPanelWidth] = (0, import_react27.useState)(() => {
5172
+ const [rightPanelWidth, setRightPanelWidth] = (0, import_react25.useState)(() => {
5144
5173
  try {
5145
5174
  return parseInt(localStorage.getItem("aa-right-width") || "320", 10);
5146
5175
  } catch {
5147
5176
  return 320;
5148
5177
  }
5149
5178
  });
5150
- const [isPromptCollapsed, setIsPromptCollapsed] = (0, import_react27.useState)(false);
5151
- const [projectActionState, setProjectActionState] = (0, import_react27.useState)("idle");
5152
- const syncServerDataRef = (0, import_react27.useRef)(null);
5153
- const [workspaceTags, setWorkspaceTags] = (0, import_react27.useState)(null);
5154
- const [serverProjects, setServerProjects] = (0, import_react27.useState)([]);
5155
- const [isLoadingFromServer, setIsLoadingFromServer] = (0, import_react27.useState)(false);
5156
- const [highContrast, setHighContrast] = (0, import_react27.useState)(() => {
5179
+ const [isPromptCollapsed, setIsPromptCollapsed] = (0, import_react25.useState)(false);
5180
+ const [projectActionState, setProjectActionState] = (0, import_react25.useState)("idle");
5181
+ const syncServerDataRef = (0, import_react25.useRef)(null);
5182
+ const [workspaceTags, setWorkspaceTags] = (0, import_react25.useState)(null);
5183
+ const [serverProjects, setServerProjects] = (0, import_react25.useState)([]);
5184
+ const [isLoadingFromServer, setIsLoadingFromServer] = (0, import_react25.useState)(false);
5185
+ const [highContrast, setHighContrast] = (0, import_react25.useState)(() => {
5157
5186
  try {
5158
5187
  return localStorage.getItem("aa-contrast") === "high";
5159
5188
  } catch {
5160
5189
  return false;
5161
5190
  }
5162
5191
  });
5163
- const [activeReferenceId, setActiveReferenceId] = (0, import_react27.useState)(null);
5164
- const [activeReferenceThumbnail, setActiveReferenceThumbnail] = (0, import_react27.useState)(null);
5165
- const [isScanningImage, setIsScanningImage] = (0, import_react27.useState)(false);
5166
- const [touchStartX, setTouchStartX] = (0, import_react27.useState)(null);
5167
- const [isFullscreen, setIsFullscreen] = (0, import_react27.useState)(false);
5168
- const [zoomScale, setZoomScale] = (0, import_react27.useState)(1);
5169
- const [zoomOffset, setZoomOffset] = (0, import_react27.useState)({ x: 0, y: 0 });
5170
- const lastPinchDist = (0, import_react27.useRef)(null);
5171
- const lastTapTime = (0, import_react27.useRef)(0);
5172
- const dragStart = (0, import_react27.useRef)(null);
5192
+ const [activeReferenceId, setActiveReferenceId] = (0, import_react25.useState)(null);
5193
+ const [activeReferenceThumbnail, setActiveReferenceThumbnail] = (0, import_react25.useState)(null);
5194
+ const [isScanningImage, setIsScanningImage] = (0, import_react25.useState)(false);
5195
+ const [touchStartX, setTouchStartX] = (0, import_react25.useState)(null);
5196
+ const [isFullscreen, setIsFullscreen] = (0, import_react25.useState)(false);
5197
+ const [zoomScale, setZoomScale] = (0, import_react25.useState)(1);
5198
+ const [zoomOffset, setZoomOffset] = (0, import_react25.useState)({ x: 0, y: 0 });
5199
+ const lastPinchDist = (0, import_react25.useRef)(null);
5200
+ const lastTapTime = (0, import_react25.useRef)(0);
5201
+ const dragStart = (0, import_react25.useRef)(null);
5173
5202
  const openFullscreen = () => {
5174
5203
  setIsFullscreen(true);
5175
5204
  setZoomScale(1);
@@ -5232,7 +5261,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5232
5261
  setActiveReferenceId(null);
5233
5262
  setActiveReferenceThumbnail(null);
5234
5263
  };
5235
- const labServices = (0, import_react27.useMemo)(() => {
5264
+ const labServices = (0, import_react25.useMemo)(() => {
5236
5265
  const available = groupGenerationsToLabItems([...galleryItems, ...history]);
5237
5266
  return {
5238
5267
  availableItems: available,
@@ -5312,17 +5341,17 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5312
5341
  setIsScanningImage(false);
5313
5342
  }
5314
5343
  };
5315
- const currentIndex = (0, import_react27.useMemo)(() => history.findIndex((h) => h.id === currentResult?.id), [history, currentResult]);
5316
- const goToPrev = (0, import_react27.useCallback)(() => {
5344
+ const currentIndex = (0, import_react25.useMemo)(() => history.findIndex((h) => h.id === currentResult?.id), [history, currentResult]);
5345
+ const goToPrev = (0, import_react25.useCallback)(() => {
5317
5346
  if (currentIndex > 0) setCurrentResult(history[currentIndex - 1]);
5318
5347
  }, [currentIndex, history]);
5319
- const goToNext = (0, import_react27.useCallback)(() => {
5348
+ const goToNext = (0, import_react25.useCallback)(() => {
5320
5349
  if (currentIndex < history.length - 1) setCurrentResult(history[currentIndex + 1]);
5321
5350
  }, [currentIndex, history]);
5322
- const handleGallerySelect = (0, import_react27.useCallback)((g) => {
5351
+ const handleGallerySelect = (0, import_react25.useCallback)((g) => {
5323
5352
  setCurrentResult(g);
5324
5353
  setMobileTab("stage");
5325
- if (g.filename && hfToken && !g.fullBase64) {
5354
+ if (g.hasThumb && g.filename && hfToken && !g.fullBase64) {
5326
5355
  hfLoadImageAsBase64(g.id, hfToken, effectiveNamespace, g.filename, void 0, g.mimeType, false).then((b64) => {
5327
5356
  if (!b64) return;
5328
5357
  const full = `data:${g.mimeType || "image/jpeg"};base64,${b64}`;
@@ -5332,7 +5361,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5332
5361
  });
5333
5362
  }
5334
5363
  }, [hfToken, effectiveNamespace]);
5335
- const handleTitleSet = (0, import_react27.useCallback)((id) => {
5364
+ const handleTitleSet = (0, import_react25.useCallback)((id) => {
5336
5365
  const ts = Date.now();
5337
5366
  setGalleryItems((prev) => prev.map((g) => g.id === id ? { ...g, titleTs: ts } : g));
5338
5367
  setHistory((prev) => prev.map((g) => g.id === id ? { ...g, titleTs: ts } : g));
@@ -5341,13 +5370,13 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5341
5370
  });
5342
5371
  }
5343
5372
  }, [hfToken, effectiveNamespace, hfWriteEvent]);
5344
- const currentGroup = (0, import_react27.useMemo)(() => {
5373
+ const currentGroup = (0, import_react25.useMemo)(() => {
5345
5374
  if (!currentResult?.prompt) return [];
5346
5375
  const groups = groupByPrompt(galleryItems.filter((g) => g.status === "done" && !!g.base64));
5347
5376
  const group = groups.find((gr) => gr.prompt === currentResult.prompt);
5348
5377
  return group ? group.items : [];
5349
5378
  }, [galleryItems, currentResult?.prompt]);
5350
- (0, import_react27.useEffect)(() => {
5379
+ (0, import_react25.useEffect)(() => {
5351
5380
  if (!currentResult?.prompt || !hfToken || !effectiveNamespace || !hfState) return;
5352
5381
  const siblings = galleryItemsRef.current.filter(
5353
5382
  (g) => g.prompt === currentResult.prompt && !g.base64 && !hfImageNotFoundRef.current.has(g.id)
@@ -5373,9 +5402,20 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5373
5402
  })();
5374
5403
  }, [currentResult?.id, currentResult?.prompt]);
5375
5404
  const hcStyle = highContrast ? { filter: "brightness(1.6) contrast(1.05)" } : void 0;
5376
- const isGenerating = activeGenerationsCount > 0;
5405
+ const runningBadge = activeGenerationsCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
5406
+ "div",
5407
+ {
5408
+ className: "flex items-center gap-1 rounded-full bg-sky-500/15 border border-sky-400/30 px-2 shrink-0",
5409
+ style: { height: 24 },
5410
+ title: `${activeGenerationsCount} Generierung${activeGenerationsCount === 1 ? "" : "en"} l\xE4uft gerade`,
5411
+ children: [
5412
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-sky-300", style: { fontSize: 14, lineHeight: 1 }, children: "autorenew" }),
5413
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[11px] font-bold text-sky-300 tabular-nums", children: activeGenerationsCount })
5414
+ ]
5415
+ }
5416
+ ) : null;
5377
5417
  useKeyboardNavigation(history, currentResult, setCurrentResult);
5378
- const getSubtreeFormat = (0, import_react27.useCallback)((nodeId, depth = 0) => {
5418
+ const getSubtreeFormat = (0, import_react25.useCallback)((nodeId, depth = 0) => {
5379
5419
  const node = nodes.find((n) => n.id === nodeId);
5380
5420
  if (!node) return "";
5381
5421
  const childrenIds = edges.filter((e) => e.source === nodeId).map((e) => e.target);
@@ -5383,7 +5423,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5383
5423
  return `${indent}- ${node.data.label || "(unbenannt)"}
5384
5424
  ` + childrenIds.map((id) => getSubtreeFormat(id, depth + 1)).join("");
5385
5425
  }, [nodes, edges]);
5386
- const activePath = (0, import_react27.useMemo)(() => {
5426
+ const activePath = (0, import_react25.useMemo)(() => {
5387
5427
  if (!focusedNodeId) return /* @__PURE__ */ new Set();
5388
5428
  const path = /* @__PURE__ */ new Set([focusedNodeId]);
5389
5429
  let currId = focusedNodeId;
@@ -5446,6 +5486,15 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5446
5486
  setActiveGenerationsCount((prev) => Math.max(0, prev - 1));
5447
5487
  }
5448
5488
  };
5489
+ const handleGenerateBatch = (customPrompt, useReferenceId, overrideNodeId, options = { silent: false }) => {
5490
+ const count = Math.max(1, Math.min(8, imageCount));
5491
+ return Promise.all(
5492
+ Array.from(
5493
+ { length: count },
5494
+ (_, i) => handleGenerateImage(customPrompt, useReferenceId, overrideNodeId, { silent: options.silent || i > 0 })
5495
+ )
5496
+ );
5497
+ };
5449
5498
  const handleSynthesizePrompt = async (nodeId, autoGenerate = false) => {
5450
5499
  setIsSynthesizing(true);
5451
5500
  try {
@@ -5732,7 +5781,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5732
5781
  setTimeout(() => setProjectActionState("idle"), 4e3);
5733
5782
  }
5734
5783
  };
5735
- (0, import_react27.useEffect)(() => {
5784
+ (0, import_react25.useEffect)(() => {
5736
5785
  if (activeTab === "setup" || activeTab === "sync") fetchServerProjects();
5737
5786
  }, [activeTab]);
5738
5787
  const mergeWorkspaceTags = (local, remote) => {
@@ -6019,7 +6068,9 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6019
6068
  /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-2 px-3 border-b border-white/5 bg-black/30 shrink-0", style: { height: 52 }, children: [
6020
6069
  /* @__PURE__ */ (0, import_jsx_runtime23.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" }] }),
6021
6070
  /* @__PURE__ */ (0, import_jsx_runtime23.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" }] }),
6071
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CompactDropdown, { value: String(imageCount), displayValue: `${imageCount}\xD7`, onChange: updateImageCount, options: imageCountOptions }),
6022
6072
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex-1" }),
6073
+ runningBadge,
6023
6074
  activeReferenceThumbnail ? /* @__PURE__ */ (0, import_jsx_runtime23.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: [
6024
6075
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("img", { src: activeReferenceThumbnail, className: "h-full aspect-square object-cover" }),
6025
6076
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[10px] text-white/60 font-bold uppercase tracking-wide px-1", children: "Ref" }),
@@ -6041,20 +6092,17 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6041
6092
  ),
6042
6093
  activePrompt && !isSynthesizing && /* @__PURE__ */ (0, import_jsx_runtime23.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_runtime23.jsx)("span", { className: "material-symbols-outlined text-[18px]", children: "close" }) })
6043
6094
  ] }) }),
6044
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "px-3 pb-3 shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6095
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "px-3 pb-3 shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
6045
6096
  "button",
6046
6097
  {
6047
- onClick: () => handleGenerateImage(),
6048
- disabled: !activePrompt.trim() || isGenerating,
6098
+ onClick: () => handleGenerateBatch(),
6099
+ disabled: !activePrompt.trim(),
6049
6100
  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",
6050
- style: { height: 48, background: activePrompt.trim() && !isGenerating ? "#0284c7" : void 0, border: "1px solid rgba(255,255,255,0.1)" },
6051
- children: isGenerating ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
6052
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "w-4 h-4 border-t-2 border-white rounded-full animate-spin" }),
6053
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: "Generiere..." })
6054
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
6101
+ style: { height: 48, background: activePrompt.trim() ? "#0284c7" : void 0, border: "1px solid rgba(255,255,255,0.1)" },
6102
+ children: [
6055
6103
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "bolt" }),
6056
6104
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: "Generieren" })
6057
- ] })
6105
+ ]
6058
6106
  }
6059
6107
  ) }),
6060
6108
  /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex-1 min-h-0 px-3 pb-3 flex flex-col", children: [
@@ -6072,9 +6120,9 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6072
6120
  setTouchStartX(null);
6073
6121
  },
6074
6122
  children: [
6075
- currentResult?.status === "processing" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col items-center gap-3", children: [
6076
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "w-10 h-10 border-t-2 border-white rounded-full animate-spin" }),
6077
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[11px] text-white/40 uppercase font-bold tracking-widest", children: "Erstelle Bild..." })
6123
+ currentResult?.status === "processing" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col items-center gap-3 opacity-40", children: [
6124
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[40px]", children: "hourglass_top" }),
6125
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[11px] uppercase font-bold tracking-widest", children: "Erstelle Bild..." })
6078
6126
  ] }),
6079
6127
  currentResult?.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "p-6 text-center flex flex-col items-center gap-3", children: [
6080
6128
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-red-400 text-[36px]", children: "warning" }),
@@ -6147,7 +6195,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6147
6195
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[18px] text-white/60", children: "replay" }),
6148
6196
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[12px] text-white/60", children: "Prompt" })
6149
6197
  ] }),
6150
- /* @__PURE__ */ (0, import_jsx_runtime23.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: [
6198
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("button", { onClick: () => handleGenerateBatch(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: [
6151
6199
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[18px] text-white/80", children: "auto_fix_high" }),
6152
6200
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[12px] text-white/80 font-bold", children: "Referenz" })
6153
6201
  ] }),
@@ -6164,7 +6212,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6164
6212
  hfToken && /* @__PURE__ */ (0, import_jsx_runtime23.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_runtime23.jsx)("span", { className: `material-symbols-outlined text-[20px]${isHfRefreshing ? " animate-spin" : ""}`, children: "sync" }) })
6165
6213
  ] }),
6166
6214
  /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex-1 overflow-hidden relative", children: [
6167
- activeTab === "history" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)) }),
6215
+ activeTab === "history" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)), visibleCount: historyVisibleCount, onLoadMore: () => setHistoryVisibleCount((c) => c + 20) }),
6168
6216
  activeTab === "gallery" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6169
6217
  MediaLibrary,
6170
6218
  {
@@ -6177,9 +6225,11 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6177
6225
  onDelete: (id) => setGalleryItems((g) => g.filter((x) => x.id !== id)),
6178
6226
  onSelect: handleGallerySelect,
6179
6227
  onGenerateReference: (item) => {
6180
- handleGenerateImage(item.prompt || activePrompt, item.mediaId, void 0, { silent: true });
6228
+ handleGenerateBatch(item.prompt || activePrompt, item.mediaId, void 0, { silent: true });
6181
6229
  setMobileTab("stage");
6182
- }
6230
+ },
6231
+ visibleCount: galleryVisibleCount,
6232
+ onLoadMore: () => setGalleryVisibleCount((c) => c + 20)
6183
6233
  }
6184
6234
  ),
6185
6235
  activeTab === "inspect" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(InspectPanel, { currentResult, history, onSelect: (g) => {
@@ -6251,7 +6301,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6251
6301
  }
6252
6302
  ) }),
6253
6303
  workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime23.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_runtime23.jsx)(PromptTab, { workspaceTags, onGenerate: handlePromptTabGenerate, isGenerating: isPromptTabGenerating, feedback: promptFeedback, promptResult: activePrompt || null, lastPayload: lastPromptPayload, onGenerateImage: (prompt) => {
6254
- handleGenerateImage(prompt);
6304
+ handleGenerateBatch(prompt);
6255
6305
  setMobileTab("stage");
6256
6306
  }, onTagCreate: handleTagCreate, onTagUpdate: handleTagUpdate, onTagDelete: handleTagDelete, onScanImage: handleScanImage, isScanning: isScanningImage }) }),
6257
6307
  activeTab === "setup" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SetupPanel, { onWorkspaceImport: handleWorkspaceImport, buildInfo }),
@@ -6331,7 +6381,9 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6331
6381
  /* @__PURE__ */ (0, import_jsx_runtime23.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: [
6332
6382
  /* @__PURE__ */ (0, import_jsx_runtime23.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" }] }),
6333
6383
  /* @__PURE__ */ (0, import_jsx_runtime23.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" }] }),
6384
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CompactDropdown, { value: String(imageCount), displayValue: `${imageCount}\xD7`, onChange: updateImageCount, options: imageCountOptions }),
6334
6385
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { flex: 1 } }),
6386
+ runningBadge,
6335
6387
  /* @__PURE__ */ (0, import_jsx_runtime23.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_runtime23.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: highContrast ? "light_mode" : "dark_mode" }) }),
6336
6388
  /* @__PURE__ */ (0, import_jsx_runtime23.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_runtime23.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: "apps" }) })
6337
6389
  ] }),
@@ -6347,22 +6399,19 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6347
6399
  ),
6348
6400
  activePrompt && /* @__PURE__ */ (0, import_jsx_runtime23.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_runtime23.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 15 }, children: "close" }) })
6349
6401
  ] }) }),
6350
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { padding: "0 12px 10px", flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6402
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { padding: "0 12px 10px", flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
6351
6403
  "button",
6352
6404
  {
6353
- onClick: () => handleGenerateImage(),
6354
- disabled: !activePrompt.trim() || isGenerating,
6355
- 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" },
6356
- children: isGenerating ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
6357
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { width: 14, height: 14, borderTop: "2px solid #fff", borderRadius: "50%", animation: "spin 1s linear infinite" } }),
6358
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: "Generiere..." })
6359
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
6405
+ onClick: () => handleGenerateBatch(),
6406
+ disabled: !activePrompt.trim(),
6407
+ 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() ? "#0284c7" : "transparent", color: "#fff", cursor: activePrompt.trim() ? "pointer" : "default", opacity: !activePrompt.trim() ? 0.3 : 1, fontFamily: "inherit", transition: "background 0.2s" },
6408
+ children: [
6360
6409
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: "bolt" }),
6361
6410
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: "Generieren" })
6362
- ] })
6411
+ ]
6363
6412
  }
6364
6413
  ) }),
6365
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { flex: 1, overflow: "hidden", position: "relative" }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)) }) })
6414
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { flex: 1, overflow: "hidden", position: "relative" }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)), visibleCount: historyVisibleCount, onLoadMore: () => setHistoryVisibleCount((c) => c + 20) }) })
6366
6415
  ] }),
6367
6416
  /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { flex: 1, height: tlH, display: "flex", flexDirection: "column", background: "#0b0b0b" }, children: [
6368
6417
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
@@ -6378,9 +6427,9 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6378
6427
  setTouchStartX(null);
6379
6428
  },
6380
6429
  children: /* @__PURE__ */ (0, import_jsx_runtime23.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: [
6381
- currentResult?.status === "processing" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 12 }, children: [
6382
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { width: 36, height: 36, borderTop: "2px solid #fff", borderRadius: "50%", animation: "spin 1s linear infinite" } }),
6383
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { style: { fontSize: 10, color: "rgba(255,255,255,0.4)", textTransform: "uppercase", fontWeight: "bold", letterSpacing: "0.15em" }, children: "Erstelle Bild..." })
6430
+ currentResult?.status === "processing" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 12, opacity: 0.4 }, children: [
6431
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 36 }, children: "hourglass_top" }),
6432
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { style: { fontSize: 10, color: "rgba(255,255,255,0.6)", textTransform: "uppercase", fontWeight: "bold", letterSpacing: "0.15em" }, children: "Erstelle Bild..." })
6384
6433
  ] }),
6385
6434
  currentResult?.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { padding: 24, textAlign: "center", display: "flex", flexDirection: "column", alignItems: "center", gap: 12 }, children: [
6386
6435
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 32, color: "#f87171" }, children: "warning" }),
@@ -6410,7 +6459,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6410
6459
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "replay" }),
6411
6460
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: "Prompt" })
6412
6461
  ] }),
6413
- /* @__PURE__ */ (0, import_jsx_runtime23.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: [
6462
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("button", { onClick: () => handleGenerateBatch(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: [
6414
6463
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "auto_fix_high" }),
6415
6464
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: "Referenz" })
6416
6465
  ] }),
@@ -6480,7 +6529,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6480
6529
  isGeneratingNodeId: (id) => isSynthesizing && focusedNodeId === id
6481
6530
  }
6482
6531
  ) }),
6483
- leftTab === "prompt" && workspaceTags && activeTab !== "tags" && /* @__PURE__ */ (0, import_jsx_runtime23.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 })
6532
+ leftTab === "prompt" && workspaceTags && activeTab !== "tags" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PromptTab, { workspaceTags, onGenerate: handlePromptTabGenerate, isGenerating: isPromptTabGenerating, feedback: promptFeedback, promptResult: activePrompt || null, lastPayload: lastPromptPayload, onGenerateImage: (prompt) => handleGenerateBatch(prompt), onTagCreate: handleTagCreate, onTagUpdate: handleTagUpdate, onTagDelete: handleTagDelete, onScanImage: handleScanImage, isScanning: isScanningImage })
6484
6533
  ] })
6485
6534
  ] }),
6486
6535
  !isLeftCollapsed && /* @__PURE__ */ (0, import_jsx_runtime23.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" } }),
@@ -6488,7 +6537,8 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6488
6537
  /* @__PURE__ */ (0, import_jsx_runtime23.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: [
6489
6538
  /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-1.5", children: [
6490
6539
  /* @__PURE__ */ (0, import_jsx_runtime23.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" }] }),
6491
- /* @__PURE__ */ (0, import_jsx_runtime23.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" }] })
6540
+ /* @__PURE__ */ (0, import_jsx_runtime23.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" }] }),
6541
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CompactDropdown, { value: String(imageCount), displayValue: `${imageCount}\xD7`, onChange: updateImageCount, options: imageCountOptions })
6492
6542
  ] }),
6493
6543
  /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-1 mx-auto", children: [
6494
6544
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
@@ -6518,7 +6568,8 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6518
6568
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: "Ref" })
6519
6569
  ] }),
6520
6570
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => setIsPromptCollapsed(!isPromptCollapsed), className: "text-white/40 hover:text-white transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined", children: isPromptCollapsed ? "expand_more" : "expand_less" }) }),
6521
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PillButton, { variant: "solid", icon: "bolt", loading: isGenerating, disabled: !activePrompt.trim(), onClick: () => handleGenerateImage(), children: "Generieren" })
6571
+ runningBadge,
6572
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PillButton, { variant: "solid", icon: "bolt", disabled: !activePrompt.trim(), onClick: () => handleGenerateBatch(), children: "Generieren" })
6522
6573
  ] })
6523
6574
  ] }),
6524
6575
  /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex-1 flex flex-col overflow-hidden relative", children: [
@@ -6530,33 +6581,27 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6530
6581
  const frame = item.frames[0];
6531
6582
  if (frame?.base64) setCurrentResult(frameToGeneration(frame, item));
6532
6583
  } }) }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex-1 overflow-hidden flex flex-col", children: [
6533
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex-1 p-6 overflow-hidden flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime23.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: [
6534
- isGenerating && currentResult?.status === "done" && /* @__PURE__ */ (0, import_jsx_runtime23.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: [
6535
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "w-3 h-3 border-t-2 border-white rounded-full animate-spin" }),
6536
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[10px] text-white/60 uppercase font-bold tracking-widest", children: "Neue Referenz..." })
6584
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex-1 p-6 overflow-hidden flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("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: currentResult ? currentResult.status === "processing" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col items-center gap-4 opacity-40", children: [
6585
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[40px]", children: "hourglass_top" }),
6586
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[10px] uppercase font-bold tracking-widest", children: "Erstelle Bild..." })
6587
+ ] }) : currentResult.status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "p-10 text-center flex flex-col items-center gap-5 max-w-md", children: [
6588
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "w-16 h-16 rounded-full bg-red-500/10 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-red-500 text-[32px]", children: "warning" }) }),
6589
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col gap-2", children: [
6590
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h3", { className: "text-[11px] font-bold uppercase tracking-widest text-red-400", children: "Generierungsfehler" }),
6591
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-white/60 text-[12px] leading-relaxed", children: currentResult.error?.message })
6537
6592
  ] }),
6538
- currentResult ? currentResult.status === "processing" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col items-center gap-4", children: [
6539
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "w-10 h-10 border-t-2 border-white rounded-full animate-spin" }),
6540
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[10px] text-white/40 uppercase font-bold tracking-widest", children: "Erstelle Bild..." })
6541
- ] }) : currentResult.status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "p-10 text-center flex flex-col items-center gap-5 max-w-md", children: [
6542
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "w-16 h-16 rounded-full bg-red-500/10 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-red-500 text-[32px]", children: "warning" }) }),
6543
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col gap-2", children: [
6544
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h3", { className: "text-[11px] font-bold uppercase tracking-widest text-red-400", children: "Generierungsfehler" }),
6545
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-white/60 text-[12px] leading-relaxed", children: currentResult.error?.message })
6546
- ] }),
6547
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PillButton, { variant: "outline", icon: "refresh", onClick: () => handleGenerateImage(currentResult.prompt), children: "Erneut versuchen" })
6548
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "h-full w-full relative flex items-center justify-center", children: [
6549
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("img", { src: currentResult.fullBase64 || currentResult.base64, className: "max-h-full max-w-full object-contain rounded-xl shadow-2xl" }),
6550
- /* @__PURE__ */ (0, import_jsx_runtime23.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: [
6551
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PillButton, { variant: "outline", icon: "replay", onClick: () => setActivePrompt(currentResult.prompt || ""), children: "Prompt" }),
6552
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PillButton, { variant: "solid", icon: "auto_fix_high", onClick: () => handleGenerateImage(currentResult.prompt || activePrompt, currentResult.mediaId, void 0, { silent: true }), children: "Referenz" }),
6553
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PillButton, { variant: "outline", icon: "download", onClick: handleDownloadSingle, children: "Speichern" })
6554
- ] })
6555
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col items-center gap-2 opacity-10", children: [
6556
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[100px]", children: "palette" }),
6557
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[12px] font-bold uppercase tracking-[0.2em]", children: "Avatar Architect" })
6593
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PillButton, { variant: "outline", icon: "refresh", onClick: () => handleGenerateImage(currentResult.prompt), children: "Erneut versuchen" })
6594
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "h-full w-full relative flex items-center justify-center", children: [
6595
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("img", { src: currentResult.fullBase64 || currentResult.base64, className: "max-h-full max-w-full object-contain rounded-xl shadow-2xl" }),
6596
+ /* @__PURE__ */ (0, import_jsx_runtime23.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: [
6597
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PillButton, { variant: "outline", icon: "replay", onClick: () => setActivePrompt(currentResult.prompt || ""), children: "Prompt" }),
6598
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PillButton, { variant: "solid", icon: "auto_fix_high", onClick: () => handleGenerateBatch(currentResult.prompt || activePrompt, currentResult.mediaId, void 0, { silent: true }), children: "Referenz" }),
6599
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PillButton, { variant: "outline", icon: "download", onClick: handleDownloadSingle, children: "Speichern" })
6558
6600
  ] })
6559
- ] }) }),
6601
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col items-center gap-2 opacity-10", children: [
6602
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[100px]", children: "palette" }),
6603
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[12px] font-bold uppercase tracking-[0.2em]", children: "Avatar Architect" })
6604
+ ] }) }) }),
6560
6605
  currentResult?.status === "done" && currentGroup.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "px-6 pb-4 shrink-0 flex gap-2 overflow-x-auto", style: { scrollbarWidth: "none" }, children: currentGroup.map((item) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { position: "relative", flexShrink: 0 }, children: [
6561
6606
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6562
6607
  "div",
@@ -6638,7 +6683,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6638
6683
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[40px] text-white/10 block mb-3", children: "label_off" }),
6639
6684
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-[11px] text-white/20", children: "Erst Workspace importieren um Tags zu verwalten." })
6640
6685
  ] }) }),
6641
- activeTab === "history" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)) }),
6686
+ activeTab === "history" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)), visibleCount: historyVisibleCount, onLoadMore: () => setHistoryVisibleCount((c) => c + 20) }),
6642
6687
  activeTab === "gallery" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6643
6688
  MediaLibrary,
6644
6689
  {
@@ -6650,7 +6695,9 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6650
6695
  },
6651
6696
  onDelete: (id) => setGalleryItems((g) => g.filter((x) => x.id !== id)),
6652
6697
  onSelect: handleGallerySelect,
6653
- onGenerateReference: (item) => handleGenerateImage(item.prompt || activePrompt, item.mediaId, void 0, { silent: true })
6698
+ onGenerateReference: (item) => handleGenerateBatch(item.prompt || activePrompt, item.mediaId, void 0, { silent: true }),
6699
+ visibleCount: galleryVisibleCount,
6700
+ onLoadMore: () => setGalleryVisibleCount((c) => c + 20)
6654
6701
  }
6655
6702
  ),
6656
6703
  activeTab === "inspect" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(InspectPanel, { currentResult, history, onSelect: setCurrentResult }),
@@ -6686,7 +6733,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6686
6733
  }
6687
6734
 
6688
6735
  // src/components/FaApp.tsx
6689
- var import_react28 = require("react");
6736
+ var import_react26 = require("react");
6690
6737
  var import_jsx_runtime24 = require("react/jsx-runtime");
6691
6738
  function FaApp({
6692
6739
  onGenerateImage,
@@ -6706,8 +6753,8 @@ function FaApp({
6706
6753
  onServerDelete,
6707
6754
  buildInfo
6708
6755
  }) {
6709
- const [hfNamespace, setHfNamespace] = (0, import_react28.useState)(void 0);
6710
- (0, import_react28.useEffect)(() => {
6756
+ const [hfNamespace, setHfNamespace] = (0, import_react26.useState)(void 0);
6757
+ (0, import_react26.useEffect)(() => {
6711
6758
  if (!serverBaseUrl) return;
6712
6759
  fetch(`${serverBaseUrl}/api/status`).then((r) => r.json()).then((d) => {
6713
6760
  if (typeof d.hfNamespace === "string") setHfNamespace(d.hfNamespace);
@@ -6741,7 +6788,7 @@ function FaApp({
6741
6788
  // src/index.ts
6742
6789
  init_hfStateService();
6743
6790
  init_hfStateService();
6744
- var LIB_VERSION = "2.0.56";
6791
+ var LIB_VERSION = "2.0.61";
6745
6792
  // Annotate the CommonJS export names for ESM import in node:
6746
6793
  0 && (module.exports = {
6747
6794
  AvatarArchitectApp,