1import{b as it,aZ as rt,r,c0 as ot,c1 as ct,aI as lt,j as a,bv as dt,ak as ut,c2 as he,X as mt,c3 as le,w as gt,L as ht,aT as pt,bm as ft,D as xt,aO as vt,c4 as wt,z as v,c5 as de,c6 as ue,bf as me}from"./index-BawMCgu8.js";import{u as ge}from"./useFeatureCreditEstimate-CKYhAOwQ.js";import{U as bt}from"./undo-D42EHzQk.js";import{B as jt}from"./brush-DxaqDCGx.js";import"./locale-en-B8Z5F_o1.js";import"./locale-zh-CN-CFdD1mPv.js";import"./locale-fr-j4CMJpfE.js";import"./locale-de-DuE2gagy.js";import"./locale-it-C6yb6RzN.js";import"./locale-ja-VjZBy5eF.js";import"./locale-ko-Cl0W-Az5.js";import"./locale-es-DwboUZze.js";import"./locale-zh-Hant-uT5aTnfX.js";import"./locale-ru-DEr1xfTZ.js";import"./locale-id-Buh3Uolz.js";import"./locale-pt-BR-CqD5J4_0.js";const pe="image-edit-state";function Nt(){try{const n=localStorage.getItem(pe);return n?JSON.parse(n):{}}catch{return{}}}const yt=[{value:"inpaint",icon:jt,labelKey:"image.inpaint"},{value:"erase",icon:he,labelKey:"image.erase"}];function Yt(){const{t:n}=it(),{requireAuth:fe}=rt(),xe=ge("image_erase"),ve=ge("image_inpaint"),P=r.useRef(null),u=r.useRef(null),we=r.useRef(null),O=r.useRef(null),be=r.useRef(null),w=r.useRef(Nt()).current,[m,R]=r.useState(w.image??null),[je,U]=r.useState(null),[M,y]=r.useState(w.imageUrl??null),[T,Ne]=r.useState({width:0,height:0}),[h,ye]=r.useState(w.editMode??"inpaint"),V=h==="erase"?xe:ve,_=V.estimate,J=V.insufficient,[C,Ce]=r.useState(w.prompt??""),[S,Se]=r.useState(w.negativePrompt??""),[Y,De]=r.useState(!1),[p,Ie]=r.useState(w.brushSize??30),[D,ke]=r.useState(w.strength??.85),[G,Z]=r.useState(!1),[Ee,X]=r.useState(!1),[B,L]=r.useState([]),[A,I]=r.useState(-1),[z,Q]=r.useState(!1),[,g]=r.useState(0),[f,k]=r.useState(w.editedImage??null),[q,ee]=r.useState({x:0,y:0,visible:!1}),{openPicker:Pe,PickerElement:Re}=ot(),{showSourceChoice:Ue,sourceChoiceOpen:Me,pickSource:$}=ct(),{tier:Te,credits:Le,thresholds:Ae}=lt(),te=Te!=="premium",[ze,ae]=r.useState(!1);r.useEffect(()=>{const e={image:m,imageUrl:M,editMode:h,prompt:C,negativePrompt:S,brushSize:p,strength:D,editedImage:f};try{localStorage.setItem(pe,JSON.stringify(e))}catch{}},[m,M,h,C,S,p,D,f]);const Fe=r.useCallback(()=>{const e=O.current,t=u.current;if(!e||!t)return;t.width=e.clientWidth,t.height=e.clientHeight,Ne({width:e.naturalWidth,height:e.naturalHeight});const s=t.getContext("2d");if(s){s.clearRect(0,0,t.width,t.height);const i=s.getImageData(0,0,t.width,t.height);L([{imageData:i}]),I(0)}},[]);r.useEffect(()=>{if(!m)return;const e=()=>{const t=O.current,s=u.current;if(!t||!s)return;const i=s.getContext("2d");if(!i)return;const c=i.getImageData(0,0,s.width,s.height),l=s.width,b=s.height;if(s.width=t.clientWidth,s.height=t.clientHeight,l>0&&b>0){const d=document.createElement("canvas");d.width=l,d.height=b;const o=d.getContext("2d");o&&(o.putImageData(c,0,0),i.drawImage(d,0,0,l,b,0,0,s.width,s.height))}};return window.addEventListener("resize",e),()=>window.removeEventListener("resize",e)},[m]);const se=(e,t)=>{const s=u.current;if(!s)return{x:0,y:0};const i=s.getBoundingClientRect();return{x:e-i.left,y:t-i.top}},ne=(e,t)=>{const s=u.current,i=s==null?void 0:s.getContext("2d");i&&(i.beginPath(),i.arc(e,t,p/2,0,Math.PI*2),i.fillStyle="rgba(255, 255, 255, 0.7)",i.fill())},ie=(e,t)=>{Z(!0);const{x:s,y:i}=se(e,t);ne(s,i)},re=(e,t)=>{if(!G)return;const{x:s,y:i}=se(e,t);ne(s,i)},W=()=>{if(!G)return;Z(!1);const e=u.current,t=e==null?void 0:e.getContext("2d");if(!t||!e)return;const s=t.getImageData(0,0,e.width,e.height),i=B.slice(0,A+1);i.push({imageData:s}),L(i),I(i.length-1),X(!0)},He=e=>{ie(e.clientX,e.clientY)},Oe=e=>{var s;const t=(s=u.current)==null?void 0:s.getBoundingClientRect();t&&ee({x:e.clientX-t.left,y:e.clientY-t.top,visible:!0}),re(e.clientX,e.clientY)},Ye=()=>W(),Xe=()=>{ee(e=>({...e,visible:!1})),W()},Be=e=>{e.preventDefault();const t=e.touches[0];ie(t.clientX,t.clientY)},qe=e=>{e.preventDefault();const t=e.touches[0];re(t.clientX,t.clientY)},$e=e=>{e.preventDefault(),W()},We=()=>{if(A<=0)return;const e=u.current,t=e==null?void 0:e.getContext("2d");if(!t||!e)return;const s=A-1;t.putImageData(B[s].imageData,0,0),I(s);const i=B[s].imageData.data;let c=!1;for(let l=3;l<i.length;l+=4)if(i[l]>0){c=!0;break}X(c)},Ke=()=>{const e=u.current,t=e==null?void 0:e.getContext("2d");if(!t||!e)return;t.clearRect(0,0,e.width,e.height);const s=t.getImageData(0,0,e.width,e.height);L([{imageData:s}]),I(0),X(!1)},oe=e=>{if(e.size>10*1024*1024){v.error(n("image.fileTooLarge",{max:"10MB"}));return}U(e),y(null),k(null);const t=new FileReader;t.onload=s=>{var i;return R((i=s.target)==null?void 0:i.result)}
1,t.readAsDataURL(e)},Ve=e=>{var s;const t=(s=e.target.files)==null?void 0:s[0];t&&oe(t)},_e=e=>{var s;e.preventDefault();const t=(s=e.dataTransfer.files)==null?void 0:s[0];t&&t.type.startsWith("image/")&&oe(t)},Je=async()=>{if(M)return M;let e=je;if(!e&&m){const c=await(await fetch(m)).blob();e=new File([c],"source.png",{type:c.type||"image/png"})}if(!e)throw new Error("No file selected");const s=(await me.uploadImage(e)).data.url;return y(s),s},Ge=async e=>{const s=await(await fetch(e)).blob(),i=new File([s],"mask.png",{type:"image/png"});return(await me.uploadImage(i)).data.url},Ze=()=>{const e=u.current;if(!e)return null;const t=document.createElement("canvas");t.width=T.width,t.height=T.height;const s=t.getContext("2d");if(!s)return null;s.fillStyle="black",s.fillRect(0,0,t.width,t.height);const i=T.width/e.width,c=T.height/e.height,l=e.getContext("2d");if(!l)return null;const b=l.getImageData(0,0,e.width,e.height),d=s.getImageData(0,0,t.width,t.height);for(let o=0;o<t.height;o++)for(let j=0;j<t.width;j++){const ce=Math.floor(j/i),F=(Math.floor(o/c)*e.width+ce)*4,N=(o*t.width+j)*4;b.data[F+3]>0&&(d.data[N]=255,d.data[N+1]=255,d.data[N+2]=255,d.data[N+3]=255)}return s.putImageData(d,0,0),t.toDataURL("image/png")},Qe=()=>{const e=u.current,t=e==null?void 0:e.getContext("2d");if(!t||!e)return!1;const s=t.getImageData(0,0,e.width,e.height);for(let i=3;i<s.data.length;i+=4)if(s.data[i]>0)return!0;return!1},et=async()=>{var s,i,c,l,b,d;if(!fe()||!m)return;if(!Qe()){v.error(n("image.drawAreaRequired"));return}const e=Ze();if(!e){v.error(n("image.drawAreaRequired"));return}if(h==="inpaint"&&!C.trim()){v.error(n("image.promptRequired"));return}Q(!0),g(5);const t=setInterval(()=>{g(o=>o<40?o+1:o<70?o+.5:o<90?o+.2:o)},1e3);try{g(10);const o=await Je();g(20);const j=await Ge(e);g(30);const x=(await de.edit({imageUrl:o,maskUrl:j,mode:h,prompt:h==="inpaint"?C:void 0,negativePrompt:h==="inpaint"&&S.trim()?S:void 0,strength:D})).data;if(x.taskId&&x.status==="processing"){g(40);const F=120,N=2e3;for(let K=0;K<F;K++){const E=(await de.getProcessingTaskStatus(x.taskId)).data;if(g(Math.min(40+Math.floor(K/F*55),95)),E.status==="completed"){const H=((s=E.result)==null?void 0:s.imageUrl)||E.imageUrl;if(H){clearInterval(t),g(100),k(H),v.success(n("image.editSuccess")),ue();return}throw new Error(n("image.editError"))}if(E.status==="failed")throw new Error(E.error||n("image.editError"));await new Promise(H=>setTimeout(H,N))}throw new Error(n("image.editTimeout",{defaultValue:"Processing timed out, please try again"}))}if(clearInterval(t),g(100),x.status==="completed"&&x.imageUrl)k(x.imageUrl),v.success(n("image.editSuccess")),ue();else throw x.error?new Error(x.error):new Error(n("image.editError"))}catch(o){if(clearInterval(t),o.code==="ECONNABORTED"||(i=o.message)!=null&&i.includes("timeout"))v.error(n("image.editTimeout",{defaultValue:"Processing timed out, please try again"}));else if(((c=o.response)==null?void 0:c.status)===403)v.error(((l=o.response.data)==null?void 0:l.message)||n("image.creditsInsufficient",{defaultValue:"Insufficient credits"}));else{const j=((d=(b=o.response)==null?void 0:b.data)==null?void 0:d.message)||o.message||n("image.editError");v.error(j)}}finally{Q(!1),setTimeout(()=>g(0),500)}},tt=async()=>{var t;const e=await Ue();if(e==="local")(t=P.current)==null||t.click();else if(e==="library"){const s=await Pe("image");if(!s)return;R(s.url),U(null),y(s.url)}},at=()=>{R(null),U(null),y(null),k(null),L([]),I(-1),P.current&&(P.current.value="")},st=()=>{f&&(R(f),U(null),y(f),k(null))},nt=()=>{if(!f)return;const e=`/api/v1/image/download?url=${encodeURIComponent(f)}`,t=document.createElement("a");t.href=e,t.download=`edited-${Date.now()}.png`,document.body.appendChild(t),t.click(),document.body.removeChild(t)};return a.jsxs("div",{className:"page-container",children:[a.jsxs("div",{className:"page-header",children:[a.jsx("div",{className:"page-icon",style:{background:"var(--bg-tertiary)",color:"var(--text-secondary)"},children:a.jsx(dt,{className:"w-6 h-6"})}),a.jsxs("div",{children:[a.jsx("h1",{className:"page-title",children:n("nav.imageEdit")}),a.jsx("p",{className:"page-subtitle",children:n("nav.imageEditDesc")})]})]}),a.jsx("div",{className:"page-content",children:a.jsxs("div",{className:"edit-layout",children:[a.jsx("div",{className:"edit-canvas",children:a.jsx("div",{className:"content-card",children:m?a.jsxs("div",{className:"canvas-wrapper",children:[a.jsxs("div",{className:"canvas-toolbar",children:[a.jsxs("div",{className:"toolbar-group",children:[a.jsx("button",{className:"icon-btn",title:n("common.undo"),onClick:We,disabled:A<=0,children:a.jsx(bt,{className:"w-4 h-4"})}),a.jsx("button",{className:"icon-btn",title:n("common.clear",{defaultValue:"Clear"}),onClick:Ke,children:a.jsx(he,{className:"w-4 h-4"})})]}),a.jsx("button",{className:"icon-btn",onClick:at,title:n("common.remove"),children:a.jsx(mt,{className:"w-4 h-4"})})]}),a.jsx("div",{className:"canvas-container",children:a.jsxs("div",{ref:we,style:{position:"relative",display:"inline-block"},children:[a.jsx(le,{ref:O,url:m,alt:"Source",className:"canvas-image",onLoad:Fe,draggable:!1}),a.jsx("canvas",{ref:u,style:{position:"absolute",top:0,left:0,cursor:"none"},onMouseDown:He,onMouseMove:Oe,onMouseUp:Ye,onMouseLeave:Xe,onTouchStart:Be,onTouchMove:qe,onTouchEnd:$e}),q.visible&&a.jsx("div",{ref:be,style:{position:"absolute",left:q.x-p/2,top:q.y-p/2,width:p,height:p,borderRadius:"50%",border:"2px s
1olid rgba(255, 255, 255, 0.8)",boxShadow:"0 0 0 1px rgba(0, 0, 0, 0.3)",pointerEvents:"none"}})]})}),a.jsx("p",{className:"text-xs mt-2 canvas-hint",children:n("image.drawHint")})]}):a.jsxs("div",{className:"upload-area large cursor-pointer",onDrop:_e,onDragOver:e=>e.preventDefault(),onClick:tt,children:[a.jsx("input",{ref:P,type:"file",accept:"image/jpeg,image/png,image/webp,image/svg+xml",onChange:Ve,onClick:e=>e.stopPropagation(),hidden:!0}),a.jsx(ut,{className:"w-12 h-12 mx-auto mb-4",style:{color:"var(--text-tertiary)"}}),a.jsx("p",{className:"font-medium mb-2",style:{color:"var(--text-primary)"},children:n("image.dropOrClick")}),a.jsx("p",{className:"text-sm",style:{color:"var(--text-tertiary)"},children:n("image.supportedFormats")})]})})}),a.jsxs("div",{className:"edit-controls",children:[a.jsxs("div",{className:"content-card",children:[a.jsx("div",{className:"card-header",children:a.jsx("h3",{className:"card-title",children:n("image.editTools")})}),a.jsxs("div",{className:"px-5 pt-4 pb-2 flex flex-col",children:[a.jsxs("div",{className:"option-group",children:[a.jsx("label",{className:"option-label",children:n("image.editMode")}),a.jsx("div",{className:"mode-buttons",children:yt.map(e=>a.jsxs("button",{className:`mode-btn ${h===e.value?"active":""}`,onClick:()=>ye(e.value),children:[a.jsx(e.icon,{className:"w-4 h-4"}),a.jsx("span",{children:n(e.labelKey)})]},e.value))})]}),h==="inpaint"&&a.jsxs(a.Fragment,{children:[a.jsxs("div",{className:"option-group",children:[a.jsx("label",{className:"option-label",children:n("image.editPrompt")}),a.jsx("textarea",{className:"content-textarea small",placeholder:n("image.editPromptPlaceholder"),value:C,onChange:e=>Ce(e.target.value),rows:3,maxLength:1e3})]}),a.jsxs("div",{className:"option-group",children:[a.jsxs("button",{type:"button",className:"option-label neg-prompt-toggle",onClick:()=>De(!Y),children:[n("image.negativePrompt"),a.jsx(gt,{className:`w-3 h-3 transition-transform ${Y?"rotate-180":""}`})]}),Y&&a.jsx("textarea",{className:"content-textarea small",placeholder:n("image.negativePromptPlaceholder"),value:S,onChange:e=>Se(e.target.value),rows:2,maxLength:1e3})]})]}),a.jsxs("div",{className:"option-group",children:[a.jsxs("label",{className:"option-label",children:[n("image.brushSize"),": ",p,"px"]}),a.jsx("input",{type:"range",min:"5",max:"100",value:p,onChange:e=>Ie(parseInt(e.target.value)),className:"range-slider",title:n("image.brushSize")})]}),a.jsxs("div",{className:"option-group",children:[a.jsxs("label",{className:"option-label",children:[n("image.strength"),": ",Math.round(D*100),"%"]}),a.jsx("input",{type:"range",min:"10",max:"100",value:Math.round(D*100),onChange:e=>ke(parseInt(e.target.value)/100),className:"range-slider",title:n("image.strength")})]}),a.jsx("div",{className:"edit-actions",children:a.jsxs("button",{type:"button",className:`btn-primary w-full ${J?"!bg-destructive/20 !text-destructive":""} ${te?"opacity-50":""}`,onClick:()=>{if(te){ae(!0);return}et()},disabled:!m||!Ee||z||J,children:[z&&a.jsx(ht,{className:"w-4 h-4 animate-spin"}),n(z?"image.processing":"image.applyEdit"),_!=null&&!z&&a.jsxs("span",{className:"flex items-center gap-0.5 text-xs opacity-60 ml-1",children:[a.jsx(pt,{className:"w-3 h-3"}),"~",_]})]})}),a.jsxs("div",{className:"mt-4 p-3 rounded-lg text-xs tips-box",children:[a.jsxs("p",{className:"font-medium mb-1",children:[n("image.tips"),":"]}),a.jsxs("ul",{className:"list-disc list-inside space-y-1",children:[a.jsx("li",{children:n("image.editTip1")}),a.jsx("li",{children:n("image.editTip2")}),a.jsx("li",{children:n("image.editTip3")})]})]})]})]}),f&&a.jsxs("div",{className:"content-card mt-4",children:[a.jsxs("div",{className:"card-header",children:[a.jsx("h3",{className:"card-title",children:n("image.result")}),a.jsxs("div",{className:"result-header-actions",children:[a.jsx("button",{type:"button",className:"icon-btn",title:n("image.useAsSource"),onClick:st,children:a.jsx(ft,{className:"w-4 h-4"})}),a.jsx("button",{type:"button",className:"icon-btn",title:n("image.download"),onClick:nt,children:a.jsx(xt,{className:"w-4 h-4"})})]})]}),a.jsx("div",{className:"result-preview",children:a.jsx(le,{url:f,alt:"Edited"})})]})]})]})}),a.jsx(vt,{open:ze,onClose:()=>ae(!1),requiredCredits:Ae.premium,currentCredits:Le}),Re,a.jsx(wt,{open:Me,onLocal:()=>$("local"),onLibrary:()=>$("library"),onClose:()=>$(null)})]})}export{Yt 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.