1import { j as jsxRuntimeExports, r as reactExports, a as router3 } from './app-DcfwjElx.js'; 2import { C as CircleQuestionMark, A as AuthenticatedLayout } from './AuthenticatedLayout-DywEqxU_.js'; 3import { s } from './index-CiWNx9kG.js'; 4import { G as GenerationResultTitle, T as Thumbnail, W as WarningModal } from './GenerationResultTitle-CVozX48j.js'; 5import { W as WalletGenerateButtons, n as newIdempotencyKey, c as createImageTask, h as createParallelImageTasks, j as getImageTask, G as GenerationDetailModal, g as deleteMediaByTaskId, v as validateImageItem, b as useGenerationCredit } from './mediaApi-B1pP7RD7.js'; 6import { D as DeleteConfirmModal } from './DeleteConfirmModal-BoUnuZRd.js'; 7import { T as Toaster, t as toast } from './index-CfJ5oEMN.js'; 8import { F as FilePickerModal } from './AddFileMenuTile-skspJIlE.js'; 9import { u as uploadImage, G as GenerateResult, I as IMAGE_VALIDATION_OPTIONS } from './uploadImageValidation-BgPyghc_.js'; 10import { p as promptLength, m as mergeModes, M as ModelMultiSelect, a as ModeSelect, P as PromptInput, S as SelectMenu, G as GenerateSize, b as GenerateSeed, u as useTaskPollingPool, c as useParallelProgress, f as flattenImages, d as createParallelTask, e as patchTask, i as isSettled, t as totalCount, g as progressSummary, h as progressBreakdown, j as ModelResultCard, k as StatusChip, l as defaultMode, n as findModel, o as modesOf, q as findMode, r as mergeRatios, s as mergeResolutions, v as SLOT, w as mergeMaxCount, x as mergePromptRequired, y as mergePromptMaxLength, z as mergeParams, A as mergeSlots, B as SINGLE_ONLY_LIMITS, C as hasSlot, D as slotMax, E as keepOrDefaultMode, F as keepOrFirst, H as findModelByAnyId, I as useMultiModelCredit, J as modeFromQuery } from './useMultiModelCredit-BeVZMQRL.js'; 11import { C as CompactImageUpload, u as useImageUpload } from './useImageUpload-DHoVcxXH.js'; 12import { X } from './x-Hr0nmDWA.js'; 13import { U as Upload } from './upload-DpZtQ1KH.js'; 14import { P as ProjectPostPicker, a as ProjectPostModal } from './ProjectPostModal-Cbyk-oMj.js'; 15import { L as LoaderCircle } from './loader-circle-CYWCs6PF.js'; 16import { D as Download } from './download-DAwV5Buz.js'; 17import { c as consumeReusePrompt } from './reuseOriginalCharacter-CdJErSgd.js'; 18import './createLucideIcon-DdfqdVik.js'; 19import './search-TiiXekoU.js'; 20import './users-lQI8w5Xn.js'; 21import './Logo-BVNRcjAq.js'; 22import './gift-CBaDsIlA.js'; 23import './transition-B9acLIsI.js'; 24import './user-BAoeAiea.js'; 25import './log-out-C427prMT.js'; 26import './heart-1wQw6Yxc.js'; 27import './external-link-DGZAgNbN.js'; 28import './pencil-CFuV0xlC.js'; 29import './trash-2-DSZuUwBI.js'; 30import './chevron-left-BhY4ZaaN.js'; 31import './chevron-right-bDYPGnsn.js'; 32import './music-C8ZZaTCu.js'; 33import './link-BU3mQUjy.js'; 34import './index-nIruWruQ.js'; 35import './fileApi-D_CekV5D.js'; 36import './play-CmyQeS9Y.js'; 37import './image-plus-CZHyJOfn.js'; 38import './useReadymadePrompt-C_IAzFIv.js'; 39import './triangle-alert-CVtr3DZy.js'; 40import './chevron-down-BWSmdTsA.js'; 41import './formatSize-GgmYFGEy.js'; 42import './folder-plus-BSCIjgw-.js'; 43import './circle-x-BCXNFL-V.js'; 44 45function GenerationCount({ selectedCount, setSelectedCount, counts, onlySingleGenerateModel }) { 46 return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [ 47 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-xs font-medium text-foreground flex items-center gap-1", children: "çæææ°" }), 48 /* @__PURE__ */ jsxRuntimeExports.jsx( 49 "select", 50 { 51 value: selectedCount, 52 onChange: (e) => setSelectedCount(e.target.value), 53 className: "w-full px-3 py-1 border border-gray-600 bg-input text-foreground rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent", 54 disabled: onlySingleGenerateModel, 55 "aria-disabled": onlySingleGenerateModel, 56 title: onlySingleGenerateModel ? "ãã®ã¢ãã«ã¯çæææ°ã夿´ã§ãã¾ãã" : void 0, 57 children: (counts || []).map((c) => /* @__PURE__ */ jsxRuntimeExports.jsx( 58 "option", 59 { 60 value: c.id ?? String(c), 61 className: "bg-[#2a3a52] text-foreground", 62 children: c.name ?? String(c) 63 }, 64 c.id ?? String(c) 65 )) 66 } 67 ),
68 onlySingleGenerateModel && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-red-500 mt-1", children: "ãã®ã¢ãã«ã¯çæææ°ã鏿ã§ãã¾ããã" }) 69 ] }); 70} 71 72const BACKGROUND_OPTIONS = [ 73 { id: "opaque", name: "ééãªã" }, 74 { id: "transparent", name: "èæ¯éé" } 75]; 76function BackgroundSelect({ selectedBackground, setSelectedBackground }) { 77 return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [ 78 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-xs font-medium text-foreground flex items-center gap-1", children: "èæ¯éé" }), 79 /* @__PURE__ */ jsxRuntimeExports.jsx( 80 "select", 81 { 82 value: selectedBackground, 83 onChange: (e) => setSelectedBackground(e.target.value), 84 className: "w-full p-3 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent border bg-input text-foreground", 85 children: BACKGROUND_OPTIONS.map((opt) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: opt.id, className: "bg-[#2a3a52] text-foreground", children: opt.name }, opt.id)) 86 } 87 ) 88 ] }); 89} 90 91const INPUT_FIDELITY_OPTIONS = [ 92 { id: "high", name: "å ç»åãä¿æãã¦ç·¨é" }, 93 { id: "low", name: "ããã³ããéè¦ã§ç·¨é" } 94]; 95function InputFidelitySelect({ selectedInputFidelity, setSelectedInputFidelity }) { 96 return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [ 97 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-xs font-medium text-foreground flex items-center gap-1", children: "ç·¨éã¢ã¼ã" }), 98 /* @__PURE__ */ jsxRuntimeExports.jsx( 99 "select", 100 { 101 value: selectedInputFidelity, 102 onChange: (e) => setSelectedInputFidelity(e.target.value), 103 className: "w-full p-3 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent border bg-input text-foreground", 104 children: INPUT_FIDELITY_OPTIONS.map((opt) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: opt.id, className: "bg-[#2a3a52] text-foreground", children: opt.name }, opt.id)) 105 } 106 ) 107 ] }); 108} 109 110function MaskUpload({ 111 maskPreview, 112 setMaskPreview, 113 maskUrl, 114 setMaskUrl, 115 redirectToLogout 116}) { 117 const [isUploading, setIsUploading] = reactExports.useState(false); 118 const handleFile = async (file) => { 119 if (!file.type.startsWith("image/")) { 120 alert("ç»åãã¡ã¤ã«ã®ã¿ã¢ãããã¼ãã§ãã¾ãã"); 121 return; 122 } 123 const reader = new FileReader(); 124 reader.onload = (ev) => setMaskPreview(String(ev.target?.result || "")); 125 reader.readAsDataURL(file); 126 setIsUploading(true); 127 try { 128 const res = await uploadImage(file); 129 const text = await res.text(); 130 if (!res.ok) { 131 if (res.status === 401) { 132 redirectToLogout(); 133 return; 134 } 135 throw new Error(`ã¢ãããã¼ãã«å¤±æãã¾ããï¼${res.status}ï¼`); 136 } 137 const data = JSON.parse(text); 138 if (data?.image_url) { 139 setMaskUrl(data.image_url); 140 } 141 } catch (err) { 142 console.error("ãã¹ã¯ã¢ãããã¼ãã¨ã©ã¼:", err); 143 alert(err.message || "ãã¹ã¯ç»åã®ã¢ãããã¼ãã«å¤±æãã¾ãã"); 144 setMaskPreview(null); 145 setMaskUrl(null); 146 } finally { 147 setIsUploading(false); 148 } 149 }; 150 const handleClear = () => { 151 setMaskPreview(null); 152 setMaskUrl(null); 153 }; 154 return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [ 155 /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "text-xs font-medium text-foreground flex items-center gap-1", children: [ 156 "ãã¹ã¯ç»åï¼ä»»æï¼",
157 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "relative group cursor-pointer", children: [ 158 /* @__PURE__ */ jsxRuntimeExports.jsxs( 159 "span", 160 { 161 className: "absolute left-1/2 -translate-x-[30%] bottom-full mb-2 w-max max-w-xs px-3 py-2 rounded-lg bg-muted text-foreground text-xs shadow-lg border border-gray-700 opacity-0 group-hover:opacity-100 pointer-events-none transition-opacity z-10", 162 style: { whiteSpace: "pre-line" }, 163 role: "tooltip", 164 children: [ 165 "ã¢ãããã¼ãç»åã«åããµã¤ãºã®ãã¡ã¤ã«ãã¢ãããã¼ãããå¿ è¦ãããã¾ãã", 166 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute left-1/2 top-full -translate-x-1/2 mt-1 w-3 h-3 overflow-hidden leading-none pointer-events-none z-10", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "block w-3 h-3 bg-muted border border-gray-700 rotate-45 -translate-y-2" }) }) 167 ] 168 } 169 ),
170 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground flex items-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx(CircleQuestionMark, { className: "w-4 h-4" }) }) 171 ] }) 172 ] }), 173 maskPreview ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative inline-block", children: [ 174 /* @__PURE__ */ jsxRuntimeExports.jsx( 175 "img", 176 { 177 src: maskPreview, 178 alt: "ãã¹ã¯ãã¬ãã¥ã¼", 179 className: "w-20 h-20 object-cover rounded-lg border border-gray-600" 180 } 181 ), 182 /* @__PURE__ */ jsxRuntimeExports.jsx( 183 "button", 184 { 185 onClick: handleClear, 186 className: "absolute -top-2 -right-2 bg-gray-600 text-white rounded-full w-6 h-6 flex items-center justify-center hover:bg-gray-700 transition-opacity", 187 title: "åé¤", 188 children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { size: 14 }) 189 } 190 ) 191 ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
192 /* @__PURE__ */ jsxRuntimeExports.jsx( 193 "input", 194 { 195 type: "file", 196 accept: "image/*", 197 onChange: (e) => { 198 const file = e.target.files?.[0]; 199 if (file) handleFile(file); 200 e.target.value = ""; 201 }, 202 style: { display: "none" }, 203 id: "mask-upload" 204 } 205 ), 206 /* @__PURE__ */ jsxRuntimeExports.jsxs( 207 "label", 208 { 209 htmlFor: "mask-upload", 210 className: `inline-flex items-center gap-2 px-3 py-2 bg-card text-foreground border bg-add-media-hover rounded cursor-pointer text-sm ${isUploading ? "opacity-60 pointer-events-none" : ""}`, 211 children: [ 212 /* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { size: 14 }), 213 isUploading ? "ã¢ãããã¼ãä¸..." : "ãã¹ã¯ç»åã鏿" 214 ] 215 } 216 ) 217 ] }) 218 ] }); 219} 220 221function PromptEffectBar({ 222 promptStrength, 223 setPromptStrength 224}) { 225 const min = 1; 226 const max = 10; 227 const thumb = 14; 228 const half = thumb / 2; 229 const adjust = -3; 230 const trackRef = reactExports.useRef(null); 231 const percent = (promptStrength - min) / (max - min) * 100; 232 const handleMove = (clientX) => { 233 if (!trackRef.current) return; 234 const rect = trackRef.current.getBoundingClientRect(); 235 const x = Math.min(Math.max(clientX - rect.left, 0), rect.width); 236 const ratio = x / rect.width; 237 const value = min + ratio * (max - min); 238 setPromptStrength(Number(value.toFixed(1))); 239 }; 240 const handleMouseDown = (e) => { 241 handleMove(e.clientX); 242 const move = (ev) => handleMove(ev.clientX); 243 const up = () => { 244 window.removeEventListener("mousemove", move); 245 window.removeEventListener("mouseup", up); 246 }; 247 window.addEventListener("mousemove", move); 248 window.addEventListener("mouseup", up); 249 }; 250 return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [ 251 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-center", children: [
252 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-xs font-medium text-foreground", children: "ããã³ããå½±é¿åº¦" }), 253 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-muted-foreground font-semibold", children: promptStrength.toFixed(1) }) 254 ] }), 255 /* @__PURE__ */ jsxRuntimeExports.jsxs( 256 "div", 257 { 258 ref: trackRef, 259 onMouseDown: handleMouseDown, 260 className: "relative w-full h-[14px] rounded-full bg-muted cursor-pointer select-none", 261 children: [ 262 /* @__PURE__ */ jsxRuntimeExports.jsx( 263 "div", 264 { 265 className: "absolute left-0 top-0 h-full rounded-full bg-[var(--text-color)]", 266 style: { width: `${percent}%` } 267 } 268 ), 269 /* @__PURE__ */ jsxRuntimeExports.jsx( 270 "div", 271 { 272 className: "absolute top-1/2 -translate-y-1/2 -translate-x-1/2 w-[14px] h-[14px] rounded-full border-2", 273 style: { 274 left: `clamp(${half}px, calc(${percent}% + ${adjust}px), calc(100% - ${half}px))`, 275 backgroundColor: "var(--bg-background-color)", 276 borderColor: "var(--text-color)" 277 } 278 } 279 ) 280 ] 281 } 282 ) 283 ] }); 284} 285 286function ImageSettingCard({ 287 iconComponent: IconComponent, 288 models, 289 selectedModel, 290 selectedModels, 291 setSelectedModels, 292 limits, 293 creditBreakdown, 294 slotNotices, 295 setSelectedModel, 296 selectedMode, 297 setSelectedMode, 298 capability, 299 showUpload, 300 uploadedImages, 301 setUploadedImages, 302 uploadedImageUrls, 303 setUploadedImageUrls, 304 isDragOver, 305 handleDragOver, 306 handleDragLeave, 307 handleDrop, 308 safeProcessFiles, 309 uploadValidationError, 310 setUploadValidationError, 311 maxUploads, 312 onOpenFilePicker, 313 prompt, 314 setPrompt, 315 placeholders, 316 promptLanguage, 317 selectedResolution, 318 setSelectedResolution, 319 selectedSize, 320 setSelectedSize, 321 sizeOptions, 322 selectedCount, 323 setSelectedCount, 324 counts, 325 seed, 326 setSeed, 327 selectedBackground, 328 setSelectedBackground, 329 selectedInputFidelity, 330 setSelectedInputFidelity, 331 maskPreview, 332 setMaskPreview, 333 maskUrl, 334 setMaskUrl, 335 promptStrength, 336 setPromptStrength, 337 redirectToLogout, 338 isGenerating, 339 remainingCredits, 340 requiredCredits, 341 handleGenerate, 342 canUseTeamWallet = false, 343 teamRemainingCredits = null, 344 consumeCredits, 345 generationProgress 346}) { 347 const params = capability?.params ?? []; 348 const promptMaxLength = capability?.promptMaxLength ?? 1e3; 349 const promptOverLimit = promptLength(prompt) > promptMaxLength; 350 const inputImagesRequired = Boolean(capability?.slots.find((slot) => slot.slot === "input_images")?.required); 351 const isUploadingImages = uploadedImages.length > uploadedImageUrls.length; 352 const selectedModelObjects = models.filter((m) => selectedModels.includes(m.id)); 353 const sharedModeValues = mergeModes(selectedModelObjects); 354 const sharedModes = (selectedModelObjects[0]?.modes ?? []).filter((m) => sharedModeValues.includes(m.mode)); 355 const resolutionOptions = (capability?.resolutions ?? []).map((id) => ({ id, name: id === "512" ? "512px" : id })); 356 return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-card rounded-lg border shadow-sm", children: [ 357 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pt-5 px-5 pb-1", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("h3", { className: "flex items-center space-x-2 text-sm font-medium text-foreground", children: [
358 /* @__PURE__ */ jsxRuntimeExports.jsx(IconComponent, {}), 359 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "ç»åçæè¨å®" }) 360 ] }) }), 361 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-5 space-y-4", children: [ 362 /* @__PURE__ */ jsxRuntimeExports.jsx( 363 ModelMultiSelect, 364 { 365 models, 366 selected: selectedModels, 367 onChange: setSelectedModels, 368 mode: selectedMode, 369 limits 370 } 371 ), 372 /* @__PURE__ */ jsxRuntimeExports.jsx( 373 ModeSelect, 374 { 375 selectedMode, 376 setSelectedMode, 377 modes: sharedModes 378 } 379 ), 380 showUpload && /* @__PURE__ */ jsxRuntimeExports.jsx( 381 CompactImageUpload, 382 { 383 uploadedImages, 384 setUploadedImages, 385 uploadedImageUrls, 386 setUploadedImageUrls, 387 isDragOver, 388 handleDragOver, 389 handleDragLeave, 390 handleDrop, 391 safeProcessFiles, 392 uploadValidationError, 393 setUploadValidationError, 394 maxUploads, 395 onOpenFilePicker, 396 label: inputImagesRequired ? "å ¥åç»å" : "å ¥åç»åï¼ä»»æï¼" 397 } 398 ),
399 /* @__PURE__ */ jsxRuntimeExports.jsx( 400 PromptInput, 401 { 402 prompt, 403 setPrompt, 404 placeholders, 405 promptLanguage, 406 maxLength: promptMaxLength, 407 surface: "image", 408 targetModel: selectedModel 409 } 410 ), 411 capability?.resolutionSelectable && resolutionOptions.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx( 412 SelectMenu, 413 { 414 label: "è§£å度", 415 value: selectedResolution, 416 onChange: setSelectedResolution, 417 items: resolutionOptions 418 } 419 ), 420 params.includes("background") && /* @__PURE__ */ jsxRuntimeExports.jsx( 421 BackgroundSelect, 422 { 423 selectedBackground, 424 setSelectedBackground 425 } 426 ), 427 params.includes("input_fidelity") && showUpload && /* @__PURE__ */ jsxRuntimeExports.jsx( 428 InputFidelitySelect, 429 { 430 selectedInputFidelity, 431 setSelectedInputFidelity 432 } 433 ), 434 capability?.slots.some((slot) =>
434 slot.slot === "mask") && /* @__PURE__ */ jsxRuntimeExports.jsx( 435 MaskUpload, 436 { 437 maskPreview, 438 setMaskPreview, 439 maskUrl, 440 setMaskUrl, 441 redirectToLogout 442 } 443 ), 444 sizeOptions.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx( 445 GenerateSize, 446 { 447 selectedSize, 448 setSelectedSize, 449 sizeOptions, 450 compact: true 451 } 452 ), 453 params.includes("guidance_scale") && /* @__PURE__ */ jsxRuntimeExports.jsx( 454 PromptEffectBar, 455 { 456 promptStrength, 457 setPromptStrength 458 } 459 ), 460 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-2 mt-2", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-[1fr_2fr] gap-4", children: [ 461 /* @__PURE__ */ jsxRuntimeExports.jsx( 462 GenerationCount, 463 { 464 selectedCount, 465 setSelectedCount, 466 counts, 467 onlySingleGenerateModel: (capability?.maxCount ?? 1) <= 1 468 } 469 ),
470 /* @__PURE__ */ jsxRuntimeExports.jsx( 471 GenerateSeed, 472 { 473 seed, 474 setSeed, 475 minValue: capability?.seedMin ?? -1 476 } 477 ) 478 ] }) }) }), 479 slotNotices && slotNotices.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-3 space-y-1 bg-draft rounded-lg", children: [ 480 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] font-semibold text-foreground", children: "次ã®å ¥åã¯ãä¸é¨ã®ã¢ãã«ã§ã¯ä½¿ããã¾ãã" }), 481 /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { className: "space-y-0.5", children: slotNotices.map((notice) => /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { className: "text-[11px] text-muted-foreground", children: [ 482 "ã»", 483 notice 484 ] }, notice)) }) 485 ] }), 486 creditBreakdown && creditBreakdown.length > 1 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-3 space-y-1.5 bg-muted/60 rounded-lg", children: [ 487 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] font-semibold text-foreground", children: "ã¢ãã«å¥ã®æ¶è²»ã¯ã¬ã¸ãã" }), 488 creditBreakdown.map((row) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-[11px] text-muted-foreground", children: [
489 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 min-w-0 truncate", children: row.label }), 490 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "tabular-nums", children: row.credits === null ? "試ç®ã§ãã¾ããã§ãã" : `${row.credits} ã¯ã¬ã¸ãã` }) 491 ] }, row.id)), 492 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 pt-1 border-t-theme text-[11px] font-semibold text-foreground", children: [ 493 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1", children: "åè¨" }), 494 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "tabular-nums", children: creditBreakdown.every((row) => typeof row.credits === "number") ? `${creditBreakdown.reduce((sum, row) => sum + row.credits, 0)} ã¯ã¬ã¸ãã` : "â" }) 495 ] }) 496 ] }), 497 /* @__PURE__ */ jsxRuntimeExports.jsx( 498 WalletGenerateButtons, 499 { 500 canUseTeamWallet, 501 teamRemainingCredits, 502 isGenerating, 503 prompt: capability?.promptRequired ? prompt : void 0, 504 disabled: showUpload && (uploadedImageUrls.length === 0 || isUploadingImages) || promptOverLimit || Boolean(creditBreakdown && (creditBreakdown.length !== selectedModels.length || creditBreakdown.some((row) => row.credits === null))), 505 remainingCredits, 506 requiredCreditsGenerate: requiredCredits, 507 consumeCredits, 508 generationProgress, 509 handleGenerate, 510 singleLabel: "ç»åãçæ", 511 progressLabel: "AIç»åçæä¸" 512 } 513 ) 514 ] }) 515 ] }); 516} 517 518const TIMEOUT_MS = 1e3 * 60 * 5; 519function useParallelImageGeneration(callbacks) { 520 const [tasks, setTasks] = reactExports.useState([]); 521 const [isSubmitting, setIsSubmitting] = reactExports.useState(false); 522 const singleModelRef = reactExports.useRef(false); 523 const pendingAttemptRef = reactExports.useRef(null); 524 const pool = useTaskPollingPool({ 525 fetchTask: getImageTask, 526 timeoutMs: TIMEOUT_MS, 527 onUnauthorized: () => callbacks.redirectToLogout(), 528 onSucceeded: (taskId, data) => { 529 const images = (data.images || []).map((img) => ({ 530 ...img, 531 type: "image", 532 is_favorite: img.is_favorite || false 533 })); 534 setTasks((prev) => patchTask(prev, taskId, { status: "succeeded", progress: 100, images })); 535 callbacks.router.reload({ only: ["auth"] }); 536 }, 537 onFailed: (taskId, message) => { 538 if (singleModelRef.current) callbacks.onError(message); 539 setTasks((prev) => patchTask(prev, taskId, { status: "failed", progress: 100, error: message })); 540 callbacks.router.reload({ only: ["auth"] }); 541 }, 542 onTimeout: (taskId) => { 543 const message = "çæã«æéãããã£ã¦ãã¾ããå®äºããã¨ãã¤ã®ã£ã©ãªã¼ã«åæ ããã¾ãã"; 544 if (singleModelRef.current) callbacks.onError(message); 545 setTasks((prev) => patchTask(prev, taskId, { status: "timeout", progress: 100, error: message })); 546 } 547 }); 548 const progress = useParallelProgress(tasks); 549 const setGeneratedImages = reactExports.useCallback((value) => { 550 setTasks((prev) => { 551 const flat = flattenImages(prev); 552 const next = typeof value === "function" ? value(flat) : value; 553 return prev.map((task) => ({ 554 ...task, 555 // æ®ã£ã¦ãããã®ã ãããæ´æ°å¾ã®å å®¹ã§æã¡ç´ãï¼åé¤ã¯è½ã¡ããæ°ã«å ¥ãã¯åæ ãããï¼ 556 images: task.images.map((image) => next.find((n) => n.id === image.id)).filter((image) => image !== void 0) 557 })); 558 }); 559 }, []); 560 const submit = reactExports.useCallback(async (params) => { 561 if (params.models.length === 0) return; 562 if (params.storageUsage?.generation_usage_rate !== null && Number(params.storageUsage?.generation_usage_rate) >= 100) { 563 callbacks.setShowStorageModal(true); 564 return; 565 } 566 pool.cancelAll(); 567 setTasks([]); 568 setIsSubmitting(true); 569 const wallet = params.wallet ?? "personal"; 570 const body = { 571 prompt: params.prompt, 572 size: params.size, 573 ...params.resolution ? { resolution: params.resolution } : {}, 574 count: Number(params.count), 575 seed: params.seed, 576 watermark: false, 577 ...params.extraParams 578 }; 579 const parallelPayload = { 580 models: params.models.map((m) => m.id), 581 mode: params.mode, 582 params: body, 583 slots: params.slots, 584 wallet 585 }; 586 const signature = JSON.stringify(parallelPayload); 587 const idempotencyKey = pendingAttemptRef.current?.signature === signature ? pendingAttemptRef.current.key : newIdempotencyKey(); 588 pendingAttemptRef.current = { signature, key: idempotencyKey }; 589 try { 590 const res = params.models.length === 1 ? await createImageTask({ 591 model: params.models[0].id, 592 mode: params.mode, 593 slots: params.slots, 594 ...body, 595 count: params.count, 596 wallet 597 }) : await createParallelImageTasks(parallelPayload, idempotencyKey); 598 const raw = await res.text(); 599 if (res.status === 401) { 600 callbacks.redirectToLogout(); 601 return; 602 } 603 if (!res.ok) { 604 const message = errorMessageOf(res.status, raw, callbacks.setShowStorageModal); 605 if (message === "") return; 606 throw new Error(message); 607 } 608 pendingAttemptRef.current = null; 609 const data = JSON.parse(raw); 610 const created = Array.isArray(data.items) ? data.items.map((item) => createParallelTask({ 611 index: Number(item.index ?? 0), 612 modelId: String(item.model), 613 modelLabel: params.models.find((m) => m.id === item.model)?.label ?? String(item.model), 614 taskId: String(item.task_id), 615 count: Number(item.count ?? params.count), 616 credits: Number(item.credits ?? 0) 617 })) : [createParallelTask({ 618 index: 0, 619 modelId: params.models[0].id, 620 modelLabel: params.models[0].label, 621 taskId: String(data.id), 622 count: Number(params.count), 623 credits: 0 624 })]; 625 if (created.some((task) => !task.taskId || task.taskId === "undefined")) { 626 throw new Error("ãµã¼ãã¼ãã䏿£ãªå¿çãè¿ããã¾ãã"); 627 } 628 singleModelRef.current = created.length === 1; 629 setTasks(created); 630 callbacks.router.reload({ only: ["auth"] }); 631 for (const task of created) { 632 setTasks((prev) => patchTask(prev, task.taskId, { status: "generating" })); 633 pool.start(task.taskId); 634 } 635 } catch (error) { 636 console.error("ç»åçæã¨ã©ã¼:", error); 637 setTasks([]); 638 callbacks.router.reload({ only: ["auth"] }); 639 callbacks.onError(error?.message || "ç»åçæã«å¤±æãã¾ãããããä¸åº¦ã試ããã ããã"); 640 } finally { 641 setIsSubmitting(false); 642 } 643 }, [callbacks, pool]); 644 const generatedImages = reactExports.useMemo(() => flattenImages(tasks), [tasks]); 645 const isGenerating = isSubmitting || tasks.length > 0 && tasks.some((task) => !isSettled(task)); 646 return { 647 tasks, 648 setTasks, 649 submit, 650 setGeneratedImages, 651 generatedImages, 652 isGenerating, 653 progress, 654 /** ç»é¢ã«åºããN / M æãã®åæ¯ãå ¨ã¢ãã«ã®ã¯ã©ã³ãå¾ã®åè¨ */ 655 expectedCount: totalCount(tasks) 656 }; 657} 658function errorMessageOf(status, raw, setShowStorageModal) { 659 let parsed = null; 660 try { 661 parsed = JSON.parse(raw); 662 } catch { 663 if (raw?.startsWith("<!DOCTYPE") || raw?.startsWith("<html")) { 664 return "ç»åãçæã§ãã¾ããããã°ãããã¦ããããä¸åº¦ã試ããã ããã"; 665 } 666 } 667 if (status === 422) { 668 const first = parsed?.errors ? Object.values(parsed.errors)[0] : null; 669 return (Array.isArray(first) ? first[0] : first) || parsed?.message || "å ¥åå 容ãã確èªãã ããã"; 670 } 671 if (status === 403 && parsed?.error === "Storage limit exceeded") { 672 setShowStorageModal(true); 673 return ""; 674 } 675 if (status === 402 || status === 409) { 676 return parsed?.message ?? (status === 409 ? "ä»ã«é²è¡ä¸ã®çæã¿ã¹ã¯ããããããç¾å¨ã¯æ°ããçæãéå§ã§ãã¾ãããå®äºããå¾ ã¡ãã ããã" : "ã¯ã¬ã¸ãããä¸è¶³ãã¦ãã¾ãã"); 677 } 678 return parsed?.message ? `ãã¥ã¼æå ¥ã«å¤±æãã¾ããï¼${status}ï¼: ${parsed.message}` : `ãã¥ã¼æå ¥ã«å¤±æãã¾ããï¼${status}ï¼`; 679} 680 681const VIEW_STORAGE_KEY = "parallel-result-view"; 682function ParallelResultPanel({ 683 tasks, 684 models, 685 setImages, 686 onImageClick, 687 setDeleteTarget,
688 showFavoriteButton, 689 onDownload, 690 galleryHref 691}) { 692 const [view, setView] = reactExports.useState("by-model"); 693 const [selectedPostIds, setSelectedPostIds] = reactExports.useState(/* @__PURE__ */ new Set()); 694 const [postResults, setPostResults] = reactExports.useState(null); 695 const postableIds = reactExports.useMemo( 696 () => tasks.flatMap((task) => task.images.map((image) => image.id)), 697 [tasks] 698 ); 699 const postableKey = postableIds.join(","); 700 reactExports.useEffect(() => { 701 setSelectedPostIds((prev) => { 702 const available = new Set(postableIds); 703 const next = new Set([...prev].filter((id) => available.has(id))); 704 return next.size === prev.size ? prev : next; 705 }); 706 }, [postableKey]); 707 const allSelected = postableIds.length > 0 && selectedPostIds.size === postableIds.length; 708 const toggleOne = (id) => { 709 setSelectedPostIds((prev) => { 710 const next = new Set(prev); 711 next.has(id) ? next.delete(id) : next.add(id); 712 return next; 713 }); 714 }; 715 const toggleAll = () => { 716 setSelectedPostIds(allSelected ? /* @__PURE__ */ new Set() : new Set(postableIds)); 717 }; 718 const selectedPostItems = postableIds.filter((id) => selectedPostIds.has(id)).map((id) => ({ type: "image", id })); 719 const generationIds = reactExports.useMemo( 720 () => Array.from(new Set( 721 tasks.flatMap((task) => task.images.map((image) => image.generation_id)).filter((id) => typeof id === "number") 722 )), 723 [tasks] 724 ); 725 const maxItemCount = reactExports.useMemo( 726 () => tasks.reduce((max, task) => Math.max(max, task.images.length), 0), 727 [tasks] 728 ); 729 const initialTitle = reactExports.useMemo(() => { 730 const first = tasks.flatMap((task) => task.images).find((image) => image.generation_id === generationIds[0]); 731 return String(first?.title ?? "").replace(/\s*\(\d+\)\s*$/, ""); 732 }, [tasks, generationIds]); 733 const applyResolvedTitles = (items) => { 734 setImages((prev) => prev.map((image) => { 735 const found = items.find((it) => it.type === "image" && it.id === image.id); 736 return found ? { ...image, title: found.title, title_source: found.title_source } : image; 737 })); 738 }; 739 reactExports.useEffect(() => { 740 try { 741 const stored = window.localStorage.getItem(VIEW_STORAGE_KEY); 742 if (stored === "flat" || stored === "by-model") setView(stored); 743 } catch { 744 } 745 }, []); 746 const changeView = (next) => {
747 setView(next); 748 try { 749 window.localStorage.setItem(VIEW_STORAGE_KEY, next); 750 } catch { 751 } 752 }; 753 const allSettled = tasks.length > 0 && tasks.every(isSettled); 754 const doneImages = tasks.reduce((sum, task) => sum + task.images.length, 0); 755 const expected = totalCount(tasks); 756 return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-card rounded-lg border shadow-sm", children: [ 757 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 px-6 pt-5 pb-3 border-b-theme", children: [ 758 /* @__PURE__ */ jsxRuntimeExports.jsxs("h3", { className: "flex-1 min-w-0 text-sm font-medium text-foreground", children: [ 759 "çæçµæï¼", 760 doneImages, 761 " / ", 762 expected, 763 " æ" 764 ] }), 765 postableIds.length > 1 && /* @__PURE__ */ jsxRuntimeExports.jsx( 766 "button", 767 { 768 type: "button", 769 onClick: toggleAll, 770 "aria-pressed": allSelected, 771 className: "text-xs font-semibold text-blue-500 hover:text-blue-400 transition-colors", 772 children: allSelected ? "鏿ãè§£é¤" : "ãã¹ã¦é¸æ" 773 } 774 ),
775 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 p-0.5 bg-muted rounded-md", role: "group", "aria-label": "表示ã®åãæ¿ã", children: [ 776 /* @__PURE__ */ jsxRuntimeExports.jsx( 777 "button", 778 { 779 type: "button", 780 onClick: () => changeView("by-model"), 781 "aria-pressed": view === "by-model", 782 className: `px-2 py-1 text-[11px] font-semibold rounded focus:outline-none focus:ring-2 focus:ring-blue-500 ${view === "by-model" ? "bg-card text-foreground shadow-sm" : "text-muted-foreground"}`, 783 children: "ã¢ãã«å¥è¡¨ç¤º" 784 } 785 ), 786 /* @__PURE__ */ jsxRuntimeExports.jsx( 787 "button", 788 { 789 type: "button", 790 onClick: () => changeView("flat"), 791 "aria-pressed": view === "flat", 792 className: `px-2 py-1 text-[11px] font-semibold rounded focus:outline-none focus:ring-2 focus:ring-blue-500 ${view === "flat" ? "bg-card text-foreground shadow-sm" : "text-muted-foreground"}`, 793 children: "並ã¹ã¦è¡¨ç¤º" 794 } 795 ) 796 ] }) 797 ] }), 798 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-6 pt-3", children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] text-muted-foreground", children: allSettled ? progressSummary(tasks) : progressBreakdown(tasks) }) }), 799 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-6 space-y-4", children: [ 800 allSettled && generationIds.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx( 801 GenerationResultTitle, 802 { 803 generationId: generationIds[0], 804 additionalGenerationIds: generationIds.slice(1), 805 itemCount: maxItemCount, 806 initialTitle, 807 numberingNote: "ã¢ãã«ãã¨ã«ãåç»å㸠(1)(2)⦠ã®é£çªãä»ãã¦ä¿åãã¾ãã", 808 pollForAuto: true, 809 onResolved: applyResolvedTitles 810 } 811 ), 812 view === "by-model" ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4", children: tasks.map((task) => /* @__PURE__ */ jsxRuntimeExports.jsx( 813 ModelResultCard, 814 { 815 task, 816 provider: models.find((m) => m.id === task.modelId)?.provider, 817 setImages, 818 onImageClick, 819 setDeleteTarget, 820 showFavoriteButton, 821 onDownload, 822 galleryHref, 823 selectedPostIds: postableIds.length > 1 ? selectedPostIds : void 0, 824 onTogglePost: postableIds.length > 1 ? toggleOne : void 0 825 }, 826 task.taskId ?? task.modelId 827 )) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-2 lg:grid-cols-4 gap-4", children: tasks.flatMap((task) => { 828 if (task.images.length === 0) { 829 if (task.status === "succeeded") { 830 return [/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1", children: [
831 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "aspect-square grid place-items-center rounded-md bg-muted/60 text-center px-3", children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] text-muted-foreground", children: "çæçµæããã¹ã¦åé¤ãã¾ãã" }) }), 832 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] text-muted-foreground truncate", children: task.modelLabel }) 833 ] }, `deleted-${task.taskId ?? task.modelId}`)]; 834 } 835 if (task.status !== "failed" && task.status !== "timeout") { 836 return Array.from({ length: Math.max(1, task.count) }, (_, slot) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1", children: [ 837 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "aspect-square grid place-items-center rounded-md bg-muted animate-pulse", children: /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "w-5 h-5 text-muted-foreground animate-spin" }) }),
838 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] text-muted-foreground truncate", children: task.modelLabel }) 839 ] }, `pending-${task.taskId ?? task.modelId}-${slot}`)); 840 } 841 return [/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1", children: [ 842 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "aspect-square grid place-items-center rounded-md bg-muted/60 text-center px-3", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [ 843 /* @__PURE__ */ jsxRuntimeExports.jsx(StatusChip, { status: task.status }), 844 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] text-muted-foreground break-words", children: task.error }), 845 task.status === "timeout" && galleryHref && /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: galleryHref, className: "inline-block text-[11px] font-semibold text-blue-500 hover:underline", children: "ãã¤ã®ã£ã©ãªã¼ã§ç¢ºèªãã" }) 846 ] }) }),
847 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] text-muted-foreground truncate", children: task.modelLabel }) 848 ] }, `failed-${task.taskId ?? task.modelId}`)]; 849 } 850 return task.images.map((image, index) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1", children: [ 851 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `relative rounded-lg ${selectedPostIds.has(image.id) ? "ring-2 ring-blue-500" : ""}`, children: [ 852 postableIds.length > 1 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute top-2 left-2 z-20", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxRuntimeExports.jsx( 853 "input", 854 { 855 type: "checkbox", 856 checked: selectedPostIds.has(image.id), 857 onChange: () => toggleOne(image.id), 858 className: "w-4 h-4 rounded border-white/60 bg-black/40 accent-blue-500 cursor-pointer", 859 "aria-label": `${task.modelLabel}ã®ç»å${index + 1}ãæç¨¿å¯¾è±¡ã«é¸æ` 860 } 861 ) }),
862 /* @__PURE__ */ jsxRuntimeExports.jsx( 863 Thumbnail, 864 { 865 image, 866 setImages, 867 handleImageClick: onImageClick, 868 setDeleteTarget, 869 showFavoriteButton 870 } 871 ), 872 /* @__PURE__ */ jsxRuntimeExports.jsx( 873 "button", 874 { 875 type: "button", 876 onClick: (e) => onDownload(image.id, e), 877 "aria-label": `${task.modelLabel} ã®ç»åããã¦ã³ãã¼ã`, 878 className: "absolute bottom-2 right-2 z-10 p-1.5 rounded-full bg-black/45 text-white hover:bg-black/65 focus:outline-none focus:ring-2 focus:ring-white/70", 879 children: /* @__PURE__ */ jsxRuntimeExports.jsx(Download, { className: "w-3.5 h-3.5" }) 880 } 881 ) 882 ] }), 883 /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-[11px] text-muted-foreground truncate", children: [ 884 task.modelLabel, 885 task.images.length > 1 ? `ï¼${index + 1}ï¼` : "" 886 ] }) 887 ] }, image.id)); 888 }) }), 889 postableIds.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-2 pt-2", children: [ 890 postableIds.length > 1 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-semibold text-muted-foreground", children: selectedPostItems.length > 0 ? `${selectedPostItems.length}ä»¶ã鏿ä¸` : "æç¨¿ããç»åã鏿ãã¦ãã ãã" }), 891 (postableIds.length === 1 || selectedPostItems.length > 0) && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: postableIds.length > 1 ? "ml-auto" : "", children: /* @__PURE__ */ jsxRuntimeExports.jsx( 892 ProjectPostPicker, 893 { 894 items: postableIds.length === 1 ? [{ type: "image", id: postableIds[0] }] : selectedPostItems, 895 onPosted: () => setSelectedPostIds(/* @__PURE__ */ new Set()), 896 onFailures: setPostResults 897 } 898 ) }) 899 ] }) 900 ] }), 901 /* @__PURE__ */ jsxRuntimeExports.jsx(ProjectPostModal, { results: postResults, onClose: () => setPostResults(null) }) 902 ] }); 903} 904 905const PLACEHOLDERS = { 906 ja: "ä¾ï¼æ¡å²ãæ¥ã®å ¬åã§éã¶åä¾ãã¡ãæããåå¾ã®å ããã¹ãã«èª¿ã®åªããè²åã" 907}; 908const WandIcon = () => /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: [ 909 /* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 12a3 3 0 11-6 0 3 3 0 016 0z" }), 910 /* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" }) 911] }); 912function ImageGenerationPanel({ 913 capabilities, 914 parallel, 915 sizes, 916 counts, 917 auth, 918 isFreePlan, 919 storage_usage, 920 initialMode, 921 setShowStorageModal, 922 consumeCredits, 923 fetchImageCredits 924}) { 925 const limits = parallel ?? SINGLE_ONLY_LIMITS; 926 const [selectedModels, setSelectedModels] = reactExports.useState(() => capabilities[0] ? [capabilities[0].id] : []); 927 const selectedModel = selectedModels[0] ?? ""; 928 const setSelectedModel = (id) => setSelectedModels([id]); 929 const isParallel = selectedModels.length > 1; 930 const [selectedMode, setSelectedMode] = reactExports.useState(() => initialMode ?? defaultMode(capabilities[0] ?? null)); 931 const [prompt, setPrompt] = reactExports.useState(""); 932 const [selectedSize, setSelectedSize] = reactExports.useState(() => Array.isArray(sizes) && sizes.length > 0 ? String(sizes[0].id) : ""); 933 const [selectedResolution, setSelectedResolution] = reactExports.useState(""); 934 const [selectedCount, setSelectedCount] = reactExports.useState("2"); 935 const [seed, setSeed] = reactExports.useState(-1); 936 const [promptStrength, setPromptStrength] = reactExports.useState(4);
937 const [selectedBackground, setSelectedBackground] = reactExports.useState("opaque"); 938 const [selectedInputFidelity, setSelectedInputFidelity] = reactExports.useState("high"); 939 const [maskPreview, setMaskPreview] = reactExports.useState(null); 940 const [maskUrl, setMaskUrl] = reactExports.useState(null); 941 const [uploadedImages, setUploadedImages] = reactExports.useState([]); 942 const [uploadedImageUrls, setUploadedImageUrls] = reactExports.useState([]); 943 const [uploadValidationError, setUploadValidationError] = reactExports.useState(null); 944 const [isDragOver, setIsDragOver] = reactExports.useState(false); 945 const [showFilePicker, setShowFilePicker] = reactExports.useState(false); 946 const [selectedImage, setSelectedImage] = reactExports.useState(null); 947 const [showModal, setShowModal] = reactExports.useState(false); 948 const [deleteTarget, setDeleteTarget] = reactExports.useState(null); 949 const [isDeleting, setIsDeleting] = reactExports.useState(false); 950 const [deleteError, setDeleteError] = reactExports.useState(null); 951 const model = findModel(capabilities, selectedModel); 952 const selectedModelObjects = reactExports.useMemo( 953 () => capabilities.filter((m) => selectedModels.includes(m.id)), 954 [capabilities, selectedModels] 955 ); 956 const capability = reactExports.useMemo(() => { 957 const modes = modesOf(selectedModelObjects, selectedMode); 958 const base = modes[0] ?? findMode(model, selectedMode); 959 if (!base) return null; 960 if (modes.length <= 1) return base; 961 const ratios = mergeRatios(modes); 962 const resolutions = mergeResolutions(modes); 963 const allowMask = modes.every((m) => m.slots.some((slot) => slot.slot === SLOT.mask)); 964 return { 965 ...base, 966 slots: mergeSlots(selectedModelObjects, selectedMode).filter((slot) => slot.slot !== SLOT.mask || allowMask), 967 ratios, 968 ratioSelectable: ratios.length > 0, 969 resolutions, 970 resolutionSelectable: resolutions.length > 0, 971 params: mergeParams(modes), 972 promptMaxLength: mergePromptMaxLength(modes) ?? base.promptMaxLength, 973 promptRequired: mergePromptRequired(modes), 974 maxCount: mergeMaxCount(modes, limits, selectedModels.length), 975 // ã·ã¼ãã¯å ¨ã¢ãã«ã§0以ä¸ã«æããï¼ãµã¼ãã®åä»ãåãç¯å²ã§è¦ãï¼ã 976 // 宣è¨ã¯ -1ï¼ã©ã³ãã ï¼ã許ãã¢ãã«ãå¤ãããè¤æ°é¸æã¯æ¯è¼ãç®çã§ 977 // ã¢ãã«ãã¨ã«éãå¤ãå½ãã£ã¦ã¯æ¡ä»¶ãæããªããããä¸éã 0 ã§åºå®ãã 978 seedMin: Math.max(0, ...modes.map((m) => m.seedMin)), 979 seedSupported: modes.every((m) => m.seedSupported) 980 }; 981 }, [selectedModelObjects, selectedMode, model, limits, selectedModels.length]); 982 const showUpload = hasSlot(capability, SLOT.inputImages); 983 const uploadLimit = slotMax(capability, SLOT.inputImages); 984 const maxUploads = uploadLimit ?? 10; 985 const { 986 tasks, 987 submit, 988 setGeneratedImages, 989 generatedImages, 990 isGenerating, 991 progress: generationProgress, 992 expectedCount 993 } = useParallelImageGeneration({ 994 setShowStorageModal, 995 redirectToLogout, 996 router: router3, 997 onError: (message) => toast.error(message) 998 }); 999 const activeCount = String(expectedCount || selectedCount); 1000 function redirectToLogout() { 1001 router3.visit(s("logout.success", { title: "ã»ãã·ã§ã³ãåãã¾ãã", message: "å度ãã°ã¤ã³ãã¦ãã ããã" }), { 1002 preserveScroll: false, 1003 preserveState: false 1004 }); 1005 } 1006 const { 1007 safeProcessFiles, 1008 handleDragOver, 1009 handleDragLeave, 1010 handleDrop 1011 } = useImageUpload(uploadedImages, maxUploads, { 1012 setUploadedImages, 1013 setUploadedImageUrls, 1014 setUploadValidationError, 1015 setIsDragOver, 1016 redirectToLogout 1017 }); 1018 reactExports.useEffect(() => { 1019 setSelectedMode((current) => { 1020 if (selectedModelObjects.length <= 1) return keepOrDefaultMode(model, current); 1021 const shared = mergeModes(selectedModelObjects); 1022 if (shared.includes(current)) return current; 1023 return shared[0] ?? keepOrDefaultMode(model, current); 1024 }); 1025 }, [selectedModels.join(",")]); 1026 const prevSingleCountRef = reactExports.useRef((capability?.maxCount ?? 1) <= 1); 1027 reactExports.useEffect(() => { 1028 const onlySingle = (capability?.maxCount ?? 1) <= 1; 1029 if (onlySingle) { 1030 setSelectedCount("1"); 1031 } else if (prevSingleCountRef.current) { 1032 setSelectedCount("2"); 1033 } 1034 prevSingleCountRef.current = onlySingle; 1035 }, [capability]); 1036 reactExports.useEffect(() => { 1037 if (uploadLimit === null) return; 1038 setUploadedImages((prev) => prev.length > uploadLimit ? prev.slice(0, uploadLimit) : prev); 1039 setUploadedImageUrls((prev) => prev.length > uploadLimit ? prev.slice(0, uploadLimit) : prev); 1040 }, [uploadLimit]); 1041 reactExports.useEffect(() => { 1042 if (!capability) return; 1043 setSelectedResolution((current) => capability.resolutions.length === 0 ? "" : keepOrFirst(capability.resolutions, current, "2K")); 1044 setSelectedCount((current) => String(Math.min(Number(current) || 1, capability.maxCount))); 1045 setSeed((current) => current < capability.seedMin ? capability.seedMin : current); 1046 }, [selectedModel, selectedMode, capability]); 1047 const sizeOptions = reactExports.useMemo(() => { 1048 const allowed = capability?.ratios ?? []; 1049 if (allowed.length === 0) return []; 1050 return (sizes || []).filter((size) => allowed.includes(String(size.id))).map((size) => ({ 1051 id: String(size.id), 1052 name: size.name ?? size.id, 1053 disabled: false 1054 })); 1055 }, [sizes, capability]); 1056 reactExports.useEffect(() => { 1057 if (sizeOptions.some((size) => size.id === selectedSize)) return; 1058 const fallback = sizeOptions.find((size) => size.name === "1:1") ?? sizeOptions[0]; 1059 if (fallback) setSelectedSize(fallback.id); 1060 }, [sizeOptions, selectedSize]); 1061 const filteredCounts = reactExports.useMemo( 1062 () => (counts || []).filter((count) => Number(count.id) <= (capability?.maxCount ?? 1)), 1063 [counts, capability] 1064 ); 1065 const effectiveResolution = reactExports.useMemo( 1066 () => (capability?.resolutions.length ?? 0) === 0 ? "" : keepOrFirst(capability.resolutions, selectedResolution, "2K"), 1067 [capability, selectedResolution] 1068 ); 1069 const effectiveSize = reactExports.useMemo(() => { 1070 const allowed = capability?.ratios ?? []; 1071 if (allowed.length === 0 || allowed.includes(String(selectedSize))) return selectedSize; 1072 const fallback = (sizes || []).find((size) => allowed.includes(String(size.id)) && size.name === "1:1") ?? (sizes || []).find((size) => allowed.includes(String(size.id))); 1073 return fallback ? String(fallback.id) : selectedSize; 1074 }, [capability, selectedSize, sizes]); 1075 const effectiveCount = reactExports.useMemo( 1076 () => String(Math.min(Number(selectedCount) || 1, capability?.maxCount ?? 1)), 1077 [capability, selectedCount] 1078 ); 1079 reactExports.useEffect(() => { 1080 if (!selectedModel || !selectedMode || !selectedSize || !capability) return; 1081 if (isParallel) return; 1082 fetchImageCredits({ 1083 model: selectedModel, 1084 mode: selectedMode, 1085 size: effectiveSize, 1086 ...effectiveResolution ? { resolution: effectiveResolution } : {}, 1087 count: Number(effectiveCount) 1088 }); 1089 }, [selectedModel, selectedMode, effectiveSize, effectiveResolution, effectiveCount, capability, isParallel, fetchImageCredits]); 1090 reactExports.useEffect(() => { 1091 if (typeof window === "undefined") return; 1092 const stored = consumeReusePrompt(); 1093 if (stored) { 1094 setPrompt(stored); 1095 return; 1096 } 1097 const params = new URLSearchParams(window.location.search); 1098 const queryPrompt = params.get("prompt"); 1099 if (queryPrompt) setPrompt(queryPrompt); 1100 }, []); 1101 reactExports.useEffect(() => { 1102 if (typeof window === "undefined") return; 1103 const params = new URLSearchParams(window.location.search);
1104 const queryModel = params.get("model"); 1105 if (!queryModel) return; 1106 const matched = findModelByAnyId(capabilities, queryModel); 1107 if (matched) setSelectedModel(matched.id); 1108 params.delete("model"); 1109 const newUrl = params.toString() ? `${window.location.pathname}?${params.toString()}` : window.location.pathname; 1110 window.history.replaceState({}, "", newUrl); 1111 }, []); 1112 reactExports.useEffect(() => { 1113 if (!deleteError) return; 1114 const timer = setTimeout(() => setDeleteError(null), 5e3); 1115 return () => clearTimeout(timer); 1116 }, [deleteError]); 1117 const slotNotices = reactExports.useMemo(() => { 1118 if (!isParallel) return []; 1119 const filled = { 1120 [SLOT.inputImages]: uploadedImageUrls.length, 1121 [SLOT.mask]: maskUrl ? 1 : 0 1122 }; 1123 return mergeSlots(selectedModelObjects, selectedMode).filter((slot) => (filled[slot.slot] ?? 0) > 0).flatMap((slot) => { 1124 const messages = []; 1125 if (slot.unsupportedBy.length > 0) { 1126 messages.push(slot.slot === SLOT.mask ? `${slot.label}ã¯ã対å¿ãã¦ããªãã¢ãã«ãå«ã¾ãããã使ããã¾ãã` : `${slot.label}㯠${slot.unsupportedBy.join("ã»")} ã§ã¯ä½¿ããã¾ãã`); 1127 } 1128 for (const row of slot.clampedBy) { 1129 if ((filled[slot.slot] ?? 0) > row.max) { 1130 messages.push(`${slot.label}㯠${row.label} ã§ã¯å é ${row.max}ä»¶ã®ã¿ä½¿ããã¾ã`); 1131 } 1132 } 1133 return messages; 1134 }); 1135 }, [isParallel, selectedModelObjects, selectedMode, uploadedImageUrls.length, maskUrl]); 1136 const multiCredit = useMultiModelCredit({ 1137 // ææ°ã¯ã¢ãã«ãã¨ã®ä¸éã¾ã§ä¸¸ããããµã¼ããåã丸ãããã¦ãã課éããã®ã§ã 1138 // æããªãã¨ä¸éã®å°ããã¢ãã«ã®å 訳ã¨åè¨ãå®éããé«ãåºã 1139 models: selectedModelObjects.map((m) => { 1140 const modeCapability = m.modes.find((x) => x.mode === selectedMode); 1141 return { 1142 id: m.id, 1143 label: m.label, 1144 count: Math.min(Number(effectiveCount), modeCapability?.maxCount ?? 1) 1145 }; 1146 }), 1147 mode: selectedMode, 1148 size: effectiveSize, 1149 resolution: effectiveResolution || null, 1150 // æ¯çãæ±ºã¾ããªããã¡ã¯è©¦ç®ããªã 1151 enabled: isParallel && Boolean(effectiveSize) 1152 }); 1153 const remainingCredits = Number(auth?.available_credits ?? auth?.remaining_credits ?? 0); 1154 const singleRequiredCredits = typeof consumeCredits === "number" && !Number.isNaN(consumeCredits) ? consumeCredits : null; 1155 const requiredCredits = isParallel ? multiCredit.total : singleRequiredCredits; 1156 const canUseTeamWallet = Boolean(auth?.team?.can_use_team_wallet); 1157 const teamRemainingCredits = typeof auth?.team?.team_remaining_credits === "number" ? auth.team.team_remaining_credits : null; 1158 const handleGenerate = async (wallet = "personal") => { 1159 const params = capability?.params ?? []; 1160 await submit( 1161 { 1162 models: selectedModelObjects.map((m) => ({ id: m.id, label: m.label })), 1163 mode: selectedMode, 1164 slots: { 1165 ...showUpload && uploadedImageUrls.length > 0 ? { [SLOT.inputImages]: uploadedImageUrls } : {}, 1166 ...maskUrl && hasSlot(capability, SLOT.mask) ? { [SLOT.mask]: maskUrl } : {} 1167 }, 1168 prompt, 1169 size: effectiveSize, 1170 resolution: effectiveResolution || null, 1171 count: effectiveCount, 1172 seed, 1173 extraParams: { 1174 ...params.includes("background") ? { background: selectedBackground } : {}, 1175 ...params.includes("input_fidelity") && showUpload ? { input_fidelity: selectedInputFidelity } : {}, 1176 ...params.includes("guidance_scale") ? { guidance_scale: promptStrength } : {} 1177 }, 1178 storageUsage: storage_usage, 1179 wallet: wallet === "team" ? "team" : "personal" 1180 } 1181 ); 1182 }; 1183 const handleDownload = (imageId, e) => { 1184 e.stopPropagation(); 1185 window.location.href = s("images.download", { id: imageId }); 1186 }; 1187 const handleDeleteConfirm = async () => { 1188 if (!deleteTarget?.id) { 1189 setDeleteTarget(null); 1190 return; 1191 } 1192 setIsDeleting(true); 1193 setDeleteError(null); 1194 try { 1195 await deleteMediaByTaskId("image", deleteTarget.id); 1196 setGeneratedImages((prev) => prev.filter((image) => image.id !== deleteTarget.id)); 1197 setDeleteTarget(null); 1198 setShowModal(false); 1199 } catch (error) { 1200 console.error("ç»åã®åé¤ã«å¤±æãã¾ãã:", error); 1201 setDeleteError(error.message || "ç»åã®åé¤ã«å¤±æãã¾ãããããä¸åº¦ã試ããã ããã"); 1202 } finally { 1203 setIsDeleting(false); 1204 } 1205 }; 1206 const detailModalItem = reactExports.useMemo(() => { 1207 if (!selectedImage) return null; 1208 const latest = generatedImages.find((image) => image.id === selectedImage.id) || selectedImage; 1209 const saved = latest?.meta?.parameters || {}; 1210 const owner = tasks.find((task) => task.images.some((image) => image.id === latest.id)); 1211 const sizeLabel = sizes.find((size) => String(size.id) === String(saved.size ?? selectedSize))?.name ?? selectedSize; 1212 return { 1213 ...latest, 1214 type: "image", 1215 prompt: latest.prompt ?? prompt, 1216 generation_type: latest.generation_type ?? (showUpload ? "image_editing" : "image_generation"), 1217 // size/resolution/count/seed ã¨åãã saved ãåªå ãããçæå¾ã«ã¢ãã«é¸æãå¤ãã¦ã 1218 // 表示ä¸ã®çµæã®ã¢ãã«åããºã¬ãªããsaved.model 㯠ImageTaskController::show ã 1219 // ModelType::label() ã§ä¸æ¸ãæ¸ã¿ãªã®ã§ãã®ã¾ã¾è¡¨ç¤ºã©ãã«ã¨ãã¦ä½¿ããã 1220 model_label: saved.model ?? owner?.modelLabel ?? model?.label ?? selectedModel, 1221 size_label: sizeLabel, 1222 parameters: { 1223 model: saved.model ?? owner?.modelId ?? selectedModel, 1224 size: sizeLabel, 1225 resolution: saved.resolution ?? selectedResolution, 1226 count: saved.count ?? owner?.count ?? activeCount, 1227 // seed 㯠-1ï¼ã©ã³ãã ï¼ãéä¿¡ãã generations.parameters ã«ãã®ã¾ã¾ä¿åãã
1227ãããé ããªãã 1228 // saved åªå ã¯ç¶æï¼çæå¾ã«ããã¯ã¨ã³ããè¿ãå®ã·ã¼ãã®ã»ããæ£ç¢ºï¼ã 1229 seed: "seed" in saved ? saved.seed : seed 1230 } 1231 }; 1232 }, [selectedImage, generatedImages, tasks, selectedModel, selectedSize, selectedResolution, activeCount, seed, sizes, prompt, showUpload, model]); 1233 const pickerRoom = Math.max(0, maxUploads - uploadedImages.length); 1234 const handleFilePicked = async (files) => { 1235 setShowFilePicker(false); 1236 const picked = files.filter((file) => !!file.url); 1237 if (picked.length === 0) return; 1238 const overLimit = picked.length > pickerRoom; 1239 const target = picked.slice(0, pickerRoom); 1240 const valid = []; 1241 let lastError = null; 1242 for (const file of target) { 1243 const message = await validateImageItem(file, IMAGE_VALIDATION_OPTIONS); 1244 if (message) { 1245 lastError = message; 1246 continue; 1247 } 1248 valid.push(file); 1249 } 1250 if (valid.length > 0) { 1251 setUploadedImages((prev) => [...prev, ...valid.map((file) => file.thumbnail || file.url)]); 1252 setUploadedImageUrls((prev) => [...prev, ...valid.map((file) => file.url)]); 1253 } 1254 if (lastError) { 1255 setUploadValidationError(target.length === 1 ? lastError : `ä¸é¨ç»åã追å ã§ãã¾ããã§ããã${lastError}`); 1256 } else { 1257 setUploadValidationError(overLimit ? "å ¥åç»åã®ä¸éãè¶ ããåã¯è¿½å ãã¦ãã¾ããã" : null); 1258 } 1259 }; 1260 return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-10 gap-6 pb-8", children: [ 1261 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-6 lg:col-span-3", children: /* @__PURE__ */ jsxRuntimeExports.jsx( 1262 ImageSettingCard, 1263 { 1264 iconComponent: WandIcon, 1265 models: capabilities, 1266 selectedModel, 1267 setSelectedModel, 1268 selectedModels, 1269 setSelectedModels, 1270 limits, 1271 selectedMode, 1272 setSelectedMode, 1273 capability, 1274 showUpload, 1275 uploadedImages, 1276 setUploadedImages, 1277 uploadedImageUrls, 1278 setUploadedImageUrls, 1279 isDragOver, 1280 handleDragOver, 1281 handleDragLeave, 1282 handleDrop, 1283 safeProcessFiles, 1284 uploadValidationError, 1285 setUploadValidationError, 1286 maxUploads, 1287 onOpenFilePicker: () => setShowFilePicker(true), 1288 prompt, 1289 setPrompt, 1290 placeholders: PLACEHOLDERS, 1291 promptLanguage: "ja", 1292 selectedResolution, 1293 setSelectedResolution, 1294 selectedSize, 1295 setSelectedSize, 1296 sizeOptions, 1297 selectedCount, 1298 setSelectedCount, 1299 counts: filteredCounts, 1300 seed, 1301 setSeed, 1302 selectedBackground, 1303 setSelectedBackground, 1304 selectedInputFidelity, 1305 setSelectedInputFidelity, 1306 maskPreview, 1307 setMaskPreview, 1308 maskUrl, 1309 setMaskUrl, 1310 promptStrength, 1311 setPromptStrength, 1312 redirectToLogout, 1313 isGenerating, 1314 remainingCredits, 1315 requiredCredits, 1316 handleGenerate, 1317 canUseTeamWallet, 1318 teamRemainingCredits, 1319 consumeCredits: requiredCredits, 1320 creditBreakdown: isParallel ? multiCredit.breakdown : void 0, 1321 slotNotices, 1322 generationProgress 1323 } 1324 ) }), 1325 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-6 lg:col-span-7", children: [ 1326 tasks.length > 1 ? /* @__PURE__ */ jsxRuntimeExports.jsx( 1327 ParallelResultPanel, 1328 { 1329 tasks, 1330 models: capabilities, 1331 setImages: setGeneratedImages, 1332 onImageClick: (image) => { 1333 setSelectedImage(image); 1334 setShowModal(true); 1335 }, 1336 setDeleteTarget, 1337 showFavoriteButton: !isFreePlan, 1338 onDownload: handleDownload, 1339 galleryHref: s("my-gallery.index") 1340 } 1341 ) : /* @__PURE__ */ jsxRuntimeExports.jsx( 1342 GenerateResult, 1343 { 1344 projectPostItems: generatedImages.map((image) => ({ 1345 type: "image", 1346 id: image.id 1347 })), 1348 generatedImages, 1349 setGeneratedImages, 1350 handleImageClick: (image) => { 1351 setSelectedImage(image); 1352 setShowModal(true); 1353 }, 1354 setDeleteTarget, 1355 showFavoriteButton: !isFreePlan, 1356 isGenerating, 1357 activeCount, 1358 prompt, 1359 handleDownload, 1360 iconComponent: WandIcon, 1361 children: "ããã³ãããå ¥åãã¦ç»åãçæãã¦ãã ãã" 1362 } 1363 ),
1364 deleteError && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/30 animate-fade-in", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "max-w-md w-full p-4 bg-red-50 border-2 border-red-50 rounded-lg shadow-2xl animate-scale-in", children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-red-800 font-medium", children: deleteError }) }) }) 1365 ] }), 1366 !showModal && /* @__PURE__ */ jsxRuntimeExports.jsx(Toaster, { position: "top-center", richColors: true }), 1367 /* @__PURE__ */ jsxRuntimeExports.jsx( 1368 GenerationDetailModal, 1369 { 1370 isOpen: showModal, 1371 onClose: () => { 1372 setShowModal(false); 1373 setSelectedImage(null); 1374 }, 1375 item: detailModalItem, 1376 items: tasks.length > 1 ? generatedImages : void 0, 1377 onNavigateItem: tasks.length > 1 ? (next) => setSelectedImage(next) : void 0, 1378 onDelete: () => setDeleteTarget(selectedImage), 1379 setGeneration: setGeneratedImages, 1380 showFavoriteButton: !isFreePlan, 1381 source: "other", 1382 onBeforeUnfavorite: void 0 1383 } 1384 ), 1385 /* @__PURE__ */ jsxRuntimeExports.jsx( 1386 DeleteConfirmModal, 1387 { 1388 open: !!deleteTarget, 1389 title: "åé¤ç¢ºèª", 1390 description: "鏿ããã³ã³ãã³ããåé¤ãã¾ããï¼", 1391 onCancel: () => setDeleteTarget(null), 1392 onConfirm: handleDeleteConfirm, 1393 isDeleting 1394 } 1395 ), 1396 /* @__PURE__ */ jsxRuntimeExports.jsx( 1397 FilePickerModal, 1398 { 1399 isOpen: showFilePicker, 1400 onClose: () => setShowFilePicker(false), 1401 onSelect: handleFilePicked, 1402 allowedTypes: ["image"], 1403 multiple: pickerRoom > 1, 1404 maxSelectable: pickerRoom, 1405 title: "ãã¡ã¤ã«ããç»åã鏿" 1406 } 1407 ) 1408 ] }); 1409} 1410 1411function ImageGenerate(props) { 1412 const { auth, sizes, counts, capabilities, parallel } = props; 1413 const { storage_usage, user } = auth; 1414 const PLAN_TYPE_FREE = 0; 1415 const isFreePlan = user?.plan_id === PLAN_TYPE_FREE; 1416 const initialMode = (() => { 1417 if (typeof window === "undefined") return null; 1418 return modeFromQuery(new URLSearchParams(window.location.search), capabilities ?? []); 1419 })(); 1420 const [showStorageModal, setShowStorageModal] = reactExports.useState(false); 1421 const { consumeCredits, fetchImageCredits } = useGenerationCredit(); 1422 return /* @__PURE__ */ jsxRuntimeExports.jsxs(AuthenticatedLayout, { children: [ 1423 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-h-screen", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full px-6 pt-6", children: [
1424 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-6", children: [ 1425 /* @__PURE__ */ jsxRuntimeExports.jsx("h1", { className: "text-xl md:text-2xl font-semibold mb-2 text-foreground", children: "ç»åçæ" }), 1426 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground text-xs md:text-sm", children: "AIã使ã£ã¦ç»åãçæãã¾ã" }) 1427 ] }), 1428 /* @__PURE__ */ jsxRuntimeExports.jsx( 1429 ImageGenerationPanel, 1430 { 1431 capabilities: capabilities ?? [], 1432 parallel, 1433 sizes, 1434 counts, 1435 auth, 1436 isFreePlan, 1437 storage_usage, 1438 initialMode, 1439 setShowStorageModal, 1440 consumeCredits, 1441 fetchImageCredits 1442 } 1443 ) 1444 ] }) }), 1445 /* @__PURE__ */ jsxRuntimeExports.jsx( 1446 WarningModal, 1447 { 1448 show: showStorageModal, 1449 onClose: () => setShowStorageModal(false), 1450 title: "ã¹ãã¬ã¼ã¸å®¹éè¶ é", 1451 message: storage_usage ? `çæã³ã³ãã³ãã®ä¸éï¼${storage_usage.generation_limit_gb} GB / 使ç¨éï¼${storage_usage.generation_storage_gb.toFixed(2)} GB` : "ã¹ãã¬ã¼ã¸æ å ±ãåå¾ã§ãã¾ããã§ãã", 1452 warningText: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [ 1453 "ã¹ãã¬ã¼ã¸ä½¿ç¨éãå å ¥ãã©ã³ã®ä¸éãè¶ ãã¦ãã¾ãã",
1454 /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}), 1455 "ä¸è¦ãªã³ã³ãã³ããåé¤ãããã¾ãã¯ãã©ã³ãã¢ããã°ã¬ã¼ããã¦ãã ããã" 1456 ] }), 1457 secondaryButtonText: "ãã©ã³å¤æ´", 1458 onSecondary: () => { 1459 setShowStorageModal(false); 1460 router3.visit(s("payment.settings")); 1461 }, 1462 confirmButtonText: "ãã¤ã®ã£ã©ãªã¼", 1463 onConfirm: () => { 1464 setShowStorageModal(false); 1465 router3.visit(s("my-gallery.index")); 1466 } 1467 } 1468 ) 1469 ] }); 1470} 1471 1472export { ImageGenerate as default };
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.