| 1 |
- import{i as e}from"./chunk-aKtaBQYM.js";import{C as t,D as n,S as r,a as i,d as a,l as o,w as ee}from"./client-BdOyoZJz.js";import{n as te}from"./QueryClientProvider-Clbyr4Jg.js";import{t as s}from"./useQuery-CCy0EwsM.js";import{t as ne}from"./useMutation-qh3Iyscy.js";import{t as c}from"./createLucideIcon-Yo2YoYjm.js";import{n as re}from"./ToastContext-VFOrCCoA.js";import{a as ie,i as ae,n as oe,r as se,t as ce}from"./CameraDiagnoseModal-DWbtempu.js";import{t as le}from"./triangle-alert-gIik0G2C.js";import{n as ue,t as de}from"./zoom-out-C85W_TC5.js";import{Ct as fe,Ft as pe,Kt as me,Pn as he,Un as ge,Wn as _e,n as ve,yt as ye}from"./index-BoVbGTav.js";var be=c(`maximize`,[[`path`,{d:`M8 3H5a2 2 0 0 0-2 2v3`,key:`1dcmit`}],[`path`,{d:`M21 8V5a2 2 0 0 0-2-2h-3`,key:`1e4gt3`}],[`path`,{d:`M3 16v3a2 2 0 0 0 2 2h3`,key:`wsl5sc`}],[`path`,{d:`M16 21h3a2 2 0 0 0 2-2v-3`,key:`18trek`}]]),l=e(n(),1),u=t(),d=5,xe=2e3,Se=3e4,Ce=5e3;function f(){let{t:e}=ee(),t=te(),{showToast:n}=re(),{hasPermission:c,authEnabled:f,user:we}=ye(),{printerId:Te}=ge(),p=parseInt(Te||`0`,10),[Ee]=_e(),De=parseInt(Ee.get(`fps`)||`15`,10),Oe=Math.min(Math.max(isNaN(De)?15:De,1),30);ve();let{data:ke,isPending:Ae}=s({queryKey:[`camera-stream-token`,we?.id??null],queryFn:()=>i.getCameraStreamToken(),enabled:f?!!we:!0,staleTime:3e3*1e3}),m=ke?.token??a(),[h,je]=(0,l.useState)(`stream`),[Me,Ne]=(0,l.useState)(!1),[Pe,g]=(0,l.useState)(!1),[_,v]=(0,l.useState)(!1),[y,b]=(0,l.useState)(!0),[x,S]=(0,l.useState)(Date.now()),[C,w]=(0,l.useState)(!1),[Fe,Ie]=(0,l.useState)(!1),[T,E]=(0,l.useState)(0),[D,O]=(0,l.useState)(!1),[Le,Re]=(0,l.useState)(0),[k,A]=(0,l.useState)(1),[j,M]=(0,l.useState)({x:0,y:0}),[N,P]=(0,l.useState)(!1),[F,ze]=(0,l.useState)({x:0,y:0}),[Be,I]=(0,l.useState)(null),[L,R]=(0,l.useState)(null),z=(0,l.useRef)(null),B=(0,l.useRef)(null),V=(0,l.useRef)(null),H=(0,l.useRef)(null),U=(0,l.useRef)(null),W=(0,l.useRef)(0),{data:G}=s({queryKey:[`printer`,p],queryFn:()=>i.getPrinter(p),enabled:p>0}),{data:K}=s({queryKey:[`printerStatus`,p],queryFn:()=>i.getPrinterStatus(p),refetchInterval:3e4,enabled:p>0}),Ve=ne({mutationFn:e=>i.setChamberLight(p,e),onMutate:async e=>{await t.cancelQueries({queryKey:[`printerStatus`,p]});let n=t.getQueryData([`printerStatus`,p]);return t.setQueryData([`printerStatus`,p],t=>({...t,chamber_light:e})),{previousStatus:n}},onSuccess:(e,t)=>{n(`Chamber light ${t?`on`:`off`}`)},onError:(r,i,a)=>{a?.previousStatus&&t.setQueryData([`printerStatus`,p],a.previousStatus),n(r.message||e(`printers.toast.failedToControlChamberLight`),`error`)}}),q=(K?.state===`RUNNING`||K?.state===`PAUSE`)&&(K?.printable_objects_count??0)>=2;(0,l.useEffect)(()=>(G&&(document.title=`${G.name} - Camera`),()=>{document.title=`Bambuddy`}),[G]);let J=(0,l.useRef)(!1);(0,l.useEffect)(()=>{let e=`/api/v1/printers/${p}/camera/stop`;J.current=!1;let t=()=>{if(p>0&&!J.current){J.current=!0;let t={},n=o();n&&(t.Authorization=`Bearer ${n}`),fetch(e,{method:`POST`,keepalive:!0,headers:t}).catch(()=>{})}},n=()=>{t()};window.addEventListener(`beforeunload`,n);let r=z.current;return()=>{window.removeEventListener(`beforeunload`,n),r&&(r.src=``),t()}},[p]),(0,l.useEffect)(()=>{if(y&&!C){let e=setTimeout(()=>{b(!1)},h===`stream`?3e3:2e4);return()=>clearTimeout(e)}},[h,y,x,C]),(0,l.useEffect)(()=>{let e=()=>{Ie(!!document.fullscreenElement),A(1),M({x:0,y:0}),h===`stream`&&!C&&(z.current&&(z.current.src=``),setTimeout(()=>{b(!0),S(Date.now())},200))};return document.addEventListener(`fullscreenchange`,e),()=>document.removeEventListener(`fullscreenchange`,e)},[h,C]),(0,l.useEffect)(()=>{let e,t=()=>{clearTimeout(e),e=setTimeout(()=>{localStorage.setItem(`cameraWindowState`,JSON.stringify({width:window.outerWidth,height:window.outerHeight,left:window.screenX,top:window.screenY}))},500)};return window.addEventListener(`resize`,t),()=>{clearTimeout(e),window.removeEventListener(`resize`,t)}},[]),(0,l.useEffect)(()=>()=>{V.current&&clearTimeout(V.current),H.current&&clearInterval(H.current),U.current&&clearInterval(U.current)},[]);let Y=(0,l.useCallback)(()=>{if(T>=d){O(!1),v(!0);return}let e=Math.min(xe*2**T,Se);O(!0),Re(Math.ceil(e/1e3)),H.current=setInterval(()=>{Re(e=>e<=1?(H.current&&clearInterval(H.current),0):e-1)},1e3),V.current=setTimeout(()=>{E(e=>e+1),O(!1),b(!0),v(!1),z.current&&(z.current.src=``),S(Date.now())},e)},[T]);(0,l.useEffect)(()=>{if(h!==`stream`||y||D||C){U.current&&=(clearInterval(U.current),null);return}return W.current=0,U.current=setInterval(async()=>{try{let e=await i.getCameraStatus(p);if(!(e.stalled||!e.active&&!_)){W.current=0;return}if(W.current+=1,W.current<2)return;W.current=0,console.log(`Stream issue detected: stalled=${e.stalled}, active=${e.active}, reconnecting...`),U.current&&=(clearInterval(U.current),null),b(!1),Y()}catch{}},Ce),()=>{U.current&&=(clearInterval(U.current),null)}},[h,y,_,D,C,p,Y]);let He=()=>{b(!1),h===`stream`&&T<d?Y():v(!0)},Ue=()=>{if(b(!1),v(!1),E(0),W.current=0,O(!1),V.current&&clearTimeout(V.current),H.current&&clearInterval(H.current),z.current&&!localStorage.getItem(`cameraWindowState`)){let e=z.current,t=e.naturalWidth,n=e.naturalHeight;if(t>0&&n>0){let e=window.outerWidth-window.innerWidth,r=window.outerHeight-window.innerHeight,i=t+16+e,a=n+45+16+r;try{window.resizeTo(i,a)}catch{}}}},We=()=>{if(p>0){let e={},t=o();t&&(e.Authorization=`Bearer ${t}`),fetch(`/api/v1/printers/${p}/camera/stop`,{method:`POST`,headers:e}).catch(()=>{})}},Ge=e=>{h===e||C||(w(!0),b(!0),v(!1),E(0),O(!1),A(1),M({x:0,y:0}),V.current&&clearTimeout(V.current),H.current&&clearInterval(H.current),z.current&&(z.current.src=``),h===`stream`&&We(),setTimeout(()=>{je(e),S(Date.now()),w(!1)},100))},X=()=>{C||(w(!0),b(!0),v(!1),E(0),O(!1),V.current&&clearTimeout(V.current),H.current&&clearInterval(H.current),z.current&&(z.current.src=``),h===`stream`&&We(),setTimeout(()=>{S(Date.now()),w(!1)},100))},Ke=()=>{B.current&&(document.fullscreenElement?document.exitFullscreen():B.current.requestFullscreen())},qe=()=>{A(e=>Math.min(e+.5,4))},Je=()=>{A(e=>{let t=Math.max(e-.5,1);return t===1&&M({x:0,y:0}),t})},Ye=e=>{e.preventDefault(),e.deltaY<0?qe():Je()},Xe=e=>{k>1&&(e.preventDefault(),P(!0),ze({x:e.clientX-j.x,y:e.clientY-j.y}))},Z=(0,l.useCallback)(()=>{if(!B.current)return{x:300,y:200};let e=B.current.getBoundingClientRect(),t=e.width*(k-1)/2,n=e.height*(k-1)/2;return{x:Math.max(50,t),y:Math.max(50,n)}},[k]),Ze=e=>{if(N&&k>1){let t=e.clientX-F.x,n=e.clientY-F.y,r=Z();M({x:Math.max(-r.x,Math.min(r.x,t)),y:Math.max(-r.y,Math.min(r.y,n))})}},Qe=()=>{P(!1)},$e=e=>{if(e.length<2)return 0;let t=e[0].clientX-e[1].clientX,n=e[0].clientY-e[1].clientY;return Math.sqrt(t*t+n*n)},et=e=>e.length<2?{x:e[0].clientX,y:e[0].clientY}:{x:(e[0].clientX+e[1].clientX)/2,y:(e[0].clientY+e[1].clientY)/2},tt=e=>{e.touches.length===2?(e.preventDefault(),I($e(e.touches)),R(et(e.touches))):e.touches.length===1&&k>1&&(e.preventDefault(),P(!0),ze({x:e.touches[0].clientX-j.x,y:e.touches[0].clientY-j.y}))},nt=e=>{if(e.touches.length===2&&Be!==null){e.preventDefault();let t=$e(e.touches),n=t/Be;A(e=>{let t=Math.max(1,Math.min(4,e*n));return t===1&&M({x:0,y:0}),t}),I(t);let r=et(e.touches);if(L){let e=Z();M(t=>({x:Math.max(-e.x,Math.min(e.x,t.x+(r.x-L.x))),y:Math.max(-e.y,Math.min(e.y,t.y+(r.y-L.y)))}))}R(r)}else if(e.touches.length===1&&N&&k>1){e.preventDefault();let t=e.touches[0].clientX-F.x,n=e.touches[0].clientY-F.y,r=Z();M({x:Math.max(-r.x,Math.min(r.x,t)),y:Math.max(-r.y,Math.min(r.y,n))})}},rt=e=>{e.touches.length<2&&(I(null),R(null)),e.touches.length===0&&P(!1)},it=()=>{A(1),M({x:0,y:0})},Q=C||!m&&(f||Ae)?``:(e=>m?`${e}&token=${encodeURIComponent(m)}`:r(e))(h===`stream`?`/api/v1/printers/${p}/camera/stream?fps=${Oe}&t=${x}`:`/api/v1/printers/${p}/camera/snapshot?t=${x}`),$=y||C||D;return p?(0,u.jsxs)(`div`,{ref:B,className:`min-h-screen bg-black flex flex-col`,children:[(0,u.jsxs)(`div`,{className:`flex items-center justify-between px-4 py-2 bg-bambu-dark-secondary border-b border-bambu-dark-tertiary`,children:[(0,u.jsxs)(`h1`,{className:`text-sm font-medium text-white flex items-center gap-2`,children:[(0,u.jsx)(he,{className:`w-4 h-4`}),G?.name||`Printer ${p}`]}),(0,u.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,u.jsxs)(`div`,{className:`flex bg-bambu-dark rounded p-0.5`,children:[(0,u.jsx)(`button`,{onClick:()=>Ge(`stream`),disabled:$,className:`px-3 py-1 text-xs rounded transition-colors ${h===`stream`?`bg-bambu-green text-white`:`text-bambu-gray hover:text-white disabled:opacity-50`}`,children:e(`camera.live`)}),(0,u.jsx)(`button`,{onClick:()=>Ge(`snapshot`),disabled:$,className:`px-3 py-1 text-xs rounded transition-colors ${h===`snapshot`?`bg-bambu-green text-white`:`text-bambu-gray hover:text-white disabled:opacity-50`}`,children:e(`camera.snapshot`)})]}),(0,u.jsx)(`button`,{onClick:()=>Ve.mutate(!K?.chamber_light),disabled:!K?.connected||Ve.isPending||!c(`printers:control`),className:`p-1.5 rounded disabled:opacity-50 ${K?.chamber_light?`bg-yellow-500/20 hover:bg-yellow-500/30`:`hover:bg-bambu-dark-tertiary`}`,title:c(`printers:control`)?e(`camera.chamberLight`):e(`printers.permission.noControl`),children:(0,u.jsx)(ae,{on:K?.chamber_light??!1,className:`w-4 h-4`})}),(0,u.jsx)(`button`,{onClick:()=>Ne(!0),disabled:!q||!c(`printers:control`),className:`p-1.5 rounded disabled:opacity-50 ${q&&c(`printers:control`)?`hover:bg-bambu-dark-tertiary`:``}`,title:c(`printers:control`)?e(q?`printers.skipObjects.tooltip`:`printers.skipObjects.onlyWhilePrinting`):e(`printers.permission.noControl`),children:(0,u.jsx)(oe,{className:`w-4 h-4 text-bambu-gray`})}),(0,u.jsx)(`button`,{onClick:X,disabled:$,className:`p-1.5 hover:bg-bambu-dark-tertiary rounded disabled:opacity-50`,title:e(h===`stream`?`camera.restartStream`:`camera.refreshSnapshot`),children:(0,u.jsx)(me,{className:`w-4 h-4 text-bambu-gray ${$?`animate-spin`:``}`})}),(0,u.jsx)(`button`,{onClick:()=>g(!0),className:`p-1.5 hover:bg-bambu-dark-tertiary rounded`,title:e(`camera.diagnose.button`),children:(0,u.jsx)(pe,{className:`w-4 h-4 text-bambu-gray`})}),(0,u.jsx)(`button`,{onClick:Ke,className:`p-1.5 hover:bg-bambu-dark-tertiary rounded`,title:e(Fe?`camera.exitFullscreen`:`camera.fullscreen`),children:Fe?(0,u.jsx)(ie,{className:`w-4 h-4 text-bambu-gray`}):(0,u.jsx)(be,{className:`w-4 h-4 text-bambu-gray`})})]})]}),(0,u.jsx)(`div`,{className:`flex-1 flex items-center justify-center p-2 overflow-hidden`,onWheel:Ye,onMouseMove:Ze,onMouseUp:Qe,onMouseLeave:Qe,onTouchStart:tt,onTouchMove:nt,onTouchEnd:rt,style:{touchAction:`none`},children:(0,u.jsxs)(`div`,{className:`relative w-full h-full flex items-center justify-center`,children:[(y||C)&&!D&&(0,u.jsx)(`div`,{className:`absolute inset-0 flex items-center justify-center bg-black/50 z-10`,children:(0,u.jsxs)(`div`,{className:`text-center`,children:[(0,u.jsx)(me,{className:`w-8 h-8 text-bambu-gray animate-spin mx-auto mb-2`}),(0,u.jsx)(`p`,{className:`text-sm text-bambu-gray`,children:e(h===`stream`?`camera.connectingToCamera`:`camera.capturingSnapshot`)})]})}),D&&(0,u.jsx)(`div`,{className:`absolute inset-0 flex items-center justify-center bg-black/80 z-10`,children:(0,u.jsxs)(`div`,{className:`text-center p-4`,children:[(0,u.jsx)(fe,{className:`w-10 h-10 text-orange-400 mx-auto mb-3`}),(0,u.jsx)(`p`,{className:`text-white mb-2`,children:e(`camera.connectionLost`)}),(0,u.jsx)(`p`,{className:`text-sm text-bambu-gray mb-3`,children:e(`camera.reconnecting`,{countdown:Le,attempt:Math.min(T+1,d),max:d})}),(0,u.jsx)(`button`,{onClick:X,className:`px-4 py-2 bg-bambu-green text-white text-sm rounded hover:bg-bambu-green/80 transition-colors`,children:e(`camera.reconnectNow`)})]})}),_&&!D&&(0,u.jsx)(`div`,{className:`absolute inset-0 flex items-center justify-center bg-black z-10`,children:(0,u.jsxs)(`div`,{className:`text-center p-4`,children:[(0,u.jsx)(le,{className:`w-12 h-12 text-orange-400 mx-auto mb-3`}),(0,u.jsx)(`p`,{className:`text-white mb-2`,children:e(`camera.cameraUnavailable`)}),(0,u.jsx)(`p`,{className:`text-xs text-bambu-gray mb-4 max-w-md`,children:e(`camera.cameraUnavailableDesc`)}),(0,u.jsxs)(`div`,{className:`flex gap-2 justify-center`,children:[(0,u.jsx)(`button`,{onClick:X,className:`px-4 py-2 bg-bambu-green text-white rounded hover:bg-bambu-green/80 transition-colors`,children:e(`camera.retry`)}),(0,u.jsx)(`button`,{onClick:()=>g(!0),className:`px-4 py-2 bg-bambu-dark border border-bambu-dark-tertiary text-bambu-gray hover:text-white rounded transition-colors`,children:e(`camera.diagnose.button`)})]})]})}),(0,u.jsx)(`img`,{ref:z,src:Q,alt:e(`camera.cameraStream`),className:`max-w-full max-h-full object-contain select-none`,style:{transform:`scale(${k}) translate(${j.x/k}px, ${j.y/k}px) rotate(${G?.camera_rotation||0}deg)`,...G?.camera_rotation===90||G?.camera_rotation===270?{maxWidth:`100vh`,maxHeight:`100vw`}:{},cursor:k>1?N?`grabbing`:`grab`:`default`},onError:Q?He:void 0,onLoad:Q?Ue:void 0,onMouseDown:Xe,draggable:!1},x),(0,u.jsxs)(`div`,{className:`absolute bottom-4 left-4 flex items-center gap-1.5 bg-black/60 rounded-lg px-2 py-1.5`,children:[(0,u.jsx)(`button`,{onClick:Je,disabled:k<=1,className:`p-1.5 hover:bg-white/10 rounded disabled:opacity-30`,title:e(`camera.zoomOut`),children:(0,u.jsx)(de,{className:`w-4 h-4 text-white`})}),(0,u.jsxs)(`button`,{onClick:it,className:`px-2 py-1 text-sm text-white hover:bg-white/10 rounded min-w-[48px]`,title:e(`camera.resetZoom`),children:[Math.round(k*100),`%`]}),(0,u.jsx)(`button`,{onClick:qe,disabled:k>=4,className:`p-1.5 hover:bg-white/10 rounded disabled:opacity-30`,title:e(`camera.zoomIn`),children:(0,u.jsx)(ue,{className:`w-4 h-4 text-white`})})]})]})}),(0,u.jsx)(se,{printerId:p,isOpen:Me,onClose:()=>Ne(!1)}),Pe&&(0,u.jsx)(ce,{printerId:p,printerName:G?.name||null,onClose:()=>g(!1)})]}):(0,u.jsx)(`div`,{className:`min-h-screen bg-black flex items-center justify-center`,children:(0,u.jsx)(`p`,{className:`text-white`,children:e(`camera.invalidPrinterId`)})})}export{f as CameraPage};
|