tmux-weblink 2.0.8 → 2.0.9
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.
|
@@ -1,38 +1,40 @@
|
|
|
1
|
-
var
|
|
2
|
-
`)}selectRows(e,
|
|
3
|
-
`)}
|
|
4
|
-
|
|
5
|
-
`)
|
|
1
|
+
var Ft="https://esm.sh/ghostty-web@0.4.0",Vt=/\x1b\](?:10|11|110|111|104)(?:;[^\x07\x1b]*)?\x1b?(?:\\|\x07)/g;function ie(n){return n.replace(Vt,"")}var ge;function _t(){return ge||(document.querySelector("link[data-tmux-web-xterm-css]")?ge=Promise.resolve():(ge=new Promise(n=>{let e=document.createElement("link");e.rel="stylesheet",e.href="/assets/xterm.css",e.setAttribute("data-tmux-web-xterm-css",""),e.addEventListener("load",()=>n(),{once:!0}),e.addEventListener("error",()=>n(),{once:!0}),document.head.appendChild(e)}),ge))}var Je=class wt{terminal;fitAddon;container;constructor(e,t,i){this.container=e,this.terminal=t,this.fitAddon=i,this.terminal.loadAddon(this.fitAddon),this.terminal.open(e)}static async create(e,t,i){let[{Terminal:a},{FitAddon:l}]=await Promise.all([import("./xterm-BXEES47M.js"),import("./addon-fit-D5N335P2.js"),_t()]),c=new a({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:t,convertEol:!1,theme:i});return new wt(e,c,new l)}get cols(){return this.terminal.cols}get rows(){return this.terminal.rows}write(e){return new Promise(t=>this.terminal.write(e,t))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom()}scrollToLine(e){this.terminal.scrollToLine(Math.max(0,e))}isNearScrollbackTop(){return this.terminal.buffer.active.viewportY<=1}viewportY(){return this.terminal.buffer.active.viewportY}baseY(){return this.terminal.buffer.active.baseY}fit(){let e=Ze(this.container);return e.width<=0||e.height<=0?!1:(this.fitAddon.fit(),!0)}focus(){this.terminal.focus()}pasteText(e){this.terminal.paste(e)}input(e){this.terminal.input(e,!1)}onData(e){this.terminal.onData(e),this.terminal.onBinary(e)}onResize(e){this.terminal.onResize(e)}onScroll(e){this.terminal.onScroll(e)}attachCustomKeyEventHandler(e){this.terminal.attachCustomKeyEventHandler(e)}isFocused(){let e=document.activeElement;return e?e===this.container||e===this.terminal.textarea||this.container.contains(e)||!!e.closest?.(".xterm"):!1}getScreenText(){return this.getRowsText(0,this.terminal.rows-1)}getRowsText(e,t){let i=this.terminal.buffer.active,[a,l]=e<=t?[e,t]:[t,e],c=i.viewportY,r=[];for(let d=a;d<=l;d++){let p=i.getLine(c+d);r.push(p?p.translateToString(!0):"")}return r.join(`
|
|
2
|
+
`)}selectRows(e,t){let i=this.terminal.buffer.active,[a,l]=e<=t?[e,t]:[t,e];this.terminal.selectLines(i.viewportY+a,i.viewportY+l)}selectCells(e,t,i,a){let l=this.terminal.buffer.active,c=Math.min(t,a),r=Math.max(t,a);if(c===r){let d=Math.min(e,i),p=Math.max(e,i);this.terminal.select(d,l.viewportY+c,p-d+1)}else this.terminal.selectLines(l.viewportY+c,l.viewportY+r)}getCellsText(e,t,i,a){let l=this.terminal.buffer.active,c=Math.min(t,a),r=Math.max(t,a),d=t<a?e:t>a?i:Math.min(e,i),p=t<a?i:t>a?e:Math.max(e,i),b=l.viewportY,M=[];for(let w=c;w<=r;w++){let L=l.getLine(b+w);if(!L){M.push("");continue}let H=w===c?d:0,A=w===r?p:this.terminal.cols-1,z="";for(let Y=H;Y<=A;Y++){let N=L.getCell(Y);N&&(z+=N.getChars())}M.push(z.replace(/\s+$/,""))}return M.join(`
|
|
3
|
+
`)}getSelection(){return this.terminal.getSelection()}clearSelection(){this.terminal.clearSelection()}hasSelectionSupport(){return!0}},Ut=class bt{terminal;container;colsValue=80;rowsValue=24;charW=0;charH=0;resizeCallbacks=[];constructor(e,t){this.container=e,this.terminal=t,this.terminal.open(e)}static async create(e,t,i){let a=await import(Ft);await a.init();let l=new a.Terminal({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:t,convertEol:!1,theme:i});return new bt(e,l)}get cols(){return this.colsValue}get rows(){return this.rowsValue}write(e){return new Promise(t=>this.terminal.write(e,t))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom?.()}scrollToLine(e){this.terminal.scrollToLine?.(Math.max(0,e))}isNearScrollbackTop(){let e=this.terminal.buffer?.active;return e?e.viewportY>=e.baseY:!1}viewportY(){return this.terminal.buffer?.active?.viewportY??0}baseY(){return this.terminal.buffer?.active?.baseY??0}fit(){let e=Ze(this.container);if(e.width<=0||e.height<=0)return!1;this.updateCellMetrics(!this.charW||!this.charH);let t=Math.floor(e.width/this.charW),i=Math.floor(e.height/this.charH);if(t<10||i<5)return!1;if(t!==this.colsValue||i!==this.rowsValue){this.colsValue=t,this.rowsValue=i,this.terminal.resize(t,i);for(let a of this.resizeCallbacks)a({cols:t,rows:i})}return!0}focus(){(this.terminal.textarea||this.container.querySelector("textarea")||this.container)?.focus?.()}pasteText(e){let t=this.terminal.getMode?.(2004)??!1;this.input(t?"\x1B[200~"+e+"\x1B[201~":e)}input(e){this.terminal.input?.(e,!1)}onData(e){this.terminal.onData(t=>e(t))}onResize(e){this.resizeCallbacks.push(e)}onScroll(e){this.terminal.onScroll(e)}attachCustomKeyEventHandler(e){this.terminal.attachCustomKeyEventHandler(e)}isFocused(){let e=document.activeElement;return!!e&&(e===this.container||e===this.terminal.textarea||this.container.contains(e))}getScreenText(){return this.getRowsText(0,this.rowsValue-1)}getRowsText(e,t){try{let i=this.terminal.buffer?.active;if(!i||typeof i.getLine!="function")return"";let[a,l]=e<=t?[e,t]:[t,e],c=typeof i.viewportY=="number"?i.viewportY:0,r=[];for(let d=a;d<=l;d++){let p=i.getLine(c+d);r.push(typeof p?.translateToString=="function"?p.translateToString(!0):"")}return r.join(`
|
|
4
|
+
`)}catch{return""}}selectRows(e,t){try{if(typeof this.terminal?.selectLines!="function")return;let i=this.terminal.buffer?.active,a=typeof i?.viewportY=="number"?i.viewportY:0,[l,c]=e<=t?[e,t]:[t,e];this.terminal.selectLines(a+l,a+c)}catch{}}selectCells(e,t,i,a){try{let l=this.terminal.buffer?.active,c=typeof l?.viewportY=="number"?l.viewportY:0,r=Math.min(t,a),d=Math.max(t,a);if(r===d){if(typeof this.terminal?.select!="function"){this.selectRows(r,d);return}let p=Math.min(e,i),b=Math.max(e,i);this.terminal.select(p,c+r,b-p+1)}else this.selectRows(r,d)}catch{this.selectRows(t,a)}}getCellsText(e,t,i,a){try{let l=this.terminal.buffer?.active;if(!l||typeof l.getLine!="function")return this.getRowsText(t,a);let c=typeof l.viewportY=="number"?l.viewportY:0,r=Math.min(t,a),d=Math.max(t,a),p=t<a?e:t>a?i:Math.min(e,i),b=t<a?i:t>a?e:Math.max(e,i),M=[];for(let w=r;w<=d;w++){let L=l.getLine(c+w);if(!L){M.push("");continue}let H=w===r?p:0,A=w===d?b:this.colsValue-1,z="";if(typeof L.getCell=="function")for(let Y=H;Y<=A;Y++){let N=L.getCell(Y);N&&(z+=typeof N.getChars=="function"?N.getChars():"")}else z=typeof L.translateToString=="function"?L.translateToString(!1):"";M.push(z.replace(/\s+$/,""))}return M.join(`
|
|
5
|
+
`)}catch{return this.getRowsText(t,a)}}getSelection(){try{if(typeof this.terminal?.getSelection=="function")return this.terminal.getSelection()}catch{}return""}clearSelection(){try{typeof this.terminal?.clearSelection=="function"&&this.terminal.clearSelection()}catch{}}hasSelectionSupport(){return typeof this.terminal?.selectLines=="function"}updateCellMetrics(e=!1){let t=this.container.querySelector("canvas");if(t instanceof HTMLElement&&t.offsetWidth>0&&t.offsetHeight>0&&this.colsValue>0&&this.rowsValue>0){let i=t.offsetWidth/this.colsValue,a=t.offsetHeight/this.rowsValue;(e||!this.charW||!this.charH)&&(this.charW=i,this.charH=a)}(!this.charW||!this.charH)&&(this.charW=9,this.charH=18)}};function Ze(n){let e=n.getBoundingClientRect(),t=window.visualViewport;return t?{width:Math.min(e.width,t.width),height:Math.max(0,Math.min(e.height,t.height-Math.max(0,e.top)))}:e}function Kt(n,e,t){return n.innerHTML="",n.classList.add("terminal-pending"),(async()=>{let i;if(t.renderer==="ghostty")try{i=await Ut.create(n,t.scrollback,t.theme)}catch{console.error("[tmux-web] ghostty-web failed; falling back to xterm.js"),i=await Je.create(n,t.scrollback,t.theme)}else i=await Je.create(n,t.scrollback,t.theme);let a,l=0,c,r=null,d=0,p="connecting",b=0,M=!1,w=[],L="",H=!1,A=1e3,z=location.protocol==="https:"?"wss:":"ws:",Y=t.wsBase||"/ws",N=z+"//"+location.host+Y+"/"+encodeURIComponent(e),Lt="/api/session/"+encodeURIComponent(e)+"/upload",Et=/^((?!chrome|android|crios|fxios|edgios).)*safari/i.test(navigator.userAgent);function xt(){return w.join("")+L}async function kt(s,o=0){let u=s?i.viewportY():0,v=s?i.baseY():0,B=ie(xt());if(i.reset(),!B){s||i.scrollToBottom();return}await i.write(B),s?i.scrollToLine(v+u+o):i.scrollToBottom()}function X(s){a?.readyState===WebSocket.OPEN&&a.send(JSON.stringify(s))}function Ct(s){let o;try{o=JSON.parse(s)}catch{p==="live"&&(L+=s,i.write(ie(s)));return}if(o.type==="auth.required"){let u=localStorage.getItem("tmux-web-token");u?X({type:"auth.token",token:u}):location.href="/login?returnTo="+encodeURIComponent(location.pathname+location.search);return}if(o.type==="attach_failed"&&typeof o.message=="string"){pe=!0,p="dead",i.reset(),i.write(`\r
|
|
6
|
+
\x1B[31m`+ie(o.message)+`\x1B[0m\r
|
|
7
|
+
`).then(()=>{me();try{a?.close()}catch{}});return}if(o.type==="auth.ok"){o.token&&localStorage.setItem("tmux-web-token",o.token),A=1e3,J(),X({type:"resize",cols:i.cols,rows:i.rows}),k();return}if(o.type==="auth.failed"){if(o.permanentLock||o.retryAfterMs&&o.retryAfterMs>6e4){localStorage.removeItem("tmux-web-token"),location.href="/login?error="+encodeURIComponent(o.message);return}return}if(o.type==="snapshot"&&typeof o.data=="string"){let u=ie(o.data);w=[u],L="",b=typeof o.lines=="number"?o.lines:t.terminal.initialLines,p="live",i.reset(),i.write(u).then(()=>i.scrollToBottom());return}if(o.type==="window_changed"&&typeof o.activeIndex=="number"){let u=new URL(location.href);u.searchParams.get("window")!==String(o.activeIndex)&&(u.searchParams.set("window",String(o.activeIndex)),history.replaceState(history.state,"",u)),window.dispatchEvent(new CustomEvent("tmux:windows",{detail:o.windows}));return}if(o.type==="history"&&typeof o.data=="string"){M=!1,o.lines>0&&o.data&&(w.unshift(o.data),b+=o.lines,kt(!0,o.lines));return}if(o.type==="data"&&typeof o.data=="string"){let u=ie(o.data);if(p==="connecting"){p="live",L=u,i.write(u);return}p==="live"&&(L+=u,i.write(u))}}let pe=!1;function ze(){if(pe)return;let s=N,o=localStorage.getItem("tmux-web-token");o&&(s+=(s.includes("?")?"&":"?")+"token="+encodeURIComponent(o)),a=new WebSocket(s),a.onopen=()=>{p="connecting",b=0,M=!1,w=[],L="",i.reset(),A=1e3},a.onmessage=u=>{typeof u.data=="string"&&Ct(u.data)},a.onclose=()=>{H||(p="connecting",!pe&&setTimeout(()=>{A=Math.min(A*2,1e4),!H&&!pe&&ze()},A))},a.onerror=()=>a?.close()}function fe(s){X({type:"input",data:s})}function J(){return i.fit()}function me(){n.classList.remove("terminal-pending")}function k(){l&&cancelAnimationFrame(l),c&&clearTimeout(c),J(),l=requestAnimationFrame(()=>{l=0,J()&&me()}),c=setTimeout(()=>{J()&&me()},120)}function Tt(){k(),setTimeout(k,50),setTimeout(k,150),setTimeout(k,300)}function Ne(s){return typeof s=="string"&&s.startsWith("image/")}function We(s){return s?.files?.length?s.files[0]??null:null}function Mt(s){if(!s?.items)return null;for(let o=0;o<s.items.length;o++){let u=s.items[o];if(u?.kind==="file"&&Ne(u.type))return u.getAsFile()}return null}async function St(s){let o=new FormData,u=s instanceof File&&s.name?s.name:"upload";o.append("file",s,u);let v=localStorage.getItem("tmux-web-token"),B={};v&&(B.Authorization="Bearer "+v);let ne=await fetch(Lt,{method:"POST",body:o,headers:B});if(!ne.ok){let qe="upload failed";try{let Xe=await ne.json();Xe.error&&(qe=Xe.error)}catch{}throw new Error(qe)}let Oe=await ne.json();if(!Oe.path)throw new Error("no path in response");return Oe.path}async function Be(s){try{let o=await St(s);fe(o)}catch{}}i.onData(s=>fe(s)),i.onResize(({cols:s,rows:o})=>X({type:"resize",cols:s,rows:o})),i.onScroll(()=>{p!=="live"||M||!i.isNearScrollbackTop()||(M=!0,X({type:"load_history",before:b}))});let Z=!1,G=!1,C=null,S=null,Q=document.createElement("div");Q.className="terminal-copy-banner",Q.innerHTML='<strong>Copy mode</strong><span class="hint">drag to select \xB7 Alt+C copies \xB7 Esc exits</span>',Q.hidden=!0,n.appendChild(Q);let $=document.createElement("div");$.className="terminal-copy-banner terminal-copy-toast",$.textContent="Copied",$.hidden=!0,n.appendChild($);function je(s,o){let u=n.querySelector(".xterm-screen, canvas"),v=(u&&u.getBoundingClientRect().width>0?u:n).getBoundingClientRect(),B=v.height>0&&i.rows>0?v.height/i.rows:18,ne=v.width>0&&i.cols>0?v.width/i.cols:9;return{row:Math.max(0,Math.min(i.rows-1,Math.floor((o-v.top)/B))),col:Math.max(0,Math.min(i.cols-1,Math.floor((s-v.left)/ne)))}}async function Ie(s){if(!s)return;try{if(navigator.clipboard?.writeText){await navigator.clipboard.writeText(s);return}}catch{}let o=document.createElement("textarea");o.value=s,o.style.position="fixed",o.style.opacity="0",o.style.pointerEvents="none",document.body.appendChild(o),o.focus(),o.select();try{document.execCommand("copy")}catch{}o.remove()}let ee;function he(){$.hidden=!1,ee&&clearTimeout(ee),ee=setTimeout(()=>{$.hidden=!0},1e3)}function U(s){Z=s,Q.hidden=!s,n.classList.toggle("terminal-copy-mode-active",s),s&&i.focus()}function Fe(){U(!Z)}function Bt(s){H||s.button!==0||G||(Z||s.shiftKey)&&(s.preventDefault(),s.stopPropagation(),G=!0,C=je(s.clientX,s.clientY),S=C,i.selectCells(C.col,C.row,S.col,S.row),document.addEventListener("mousemove",He,!0),document.addEventListener("mouseup",De,!0))}function He(s){H||!G||!C||(s.preventDefault(),s.stopPropagation(),S=je(s.clientX,s.clientY),i.selectCells(C.col,C.row,S.col,S.row))}function De(s){H||!G||!C||!S||(s.preventDefault(),s.stopPropagation(),document.removeEventListener("mousemove",He,!0),document.removeEventListener("mouseup",De,!0),G=!1,U(!1),$.textContent="\u5DF2\u9009\u4E2D \xB7 Alt+C \u590D\u5236",he(),i.focus())}n.addEventListener("mousedown",Bt,!0),document.addEventListener("keydown",It,!0);function It(s){if(!(H||!i.isFocused()||s.defaultPrevented||s.isComposing)){if(Z){if(s.key==="Escape"){s.preventDefault(),s.stopPropagation(),C=null,S=null,i.clearSelection(),U(!1);return}if(s.key==="Enter"||(s.ctrlKey||s.metaKey)&&s.code==="KeyC"){s.preventDefault(),s.stopPropagation(),Ie(i.getScreenText()).then(he),U(!1);return}}if(s.altKey&&s.code==="KeyC"&&!s.ctrlKey&&!s.metaKey){if(s.preventDefault(),s.stopPropagation(),C&&S){let o=i.getCellsText(C.col,C.row,S.col,S.row);C=null,S=null,i.clearSelection(),U(!1),o&&($.textContent="Copied",Ie(o).then(he))}else{let o=i.getSelection();o?(i.clearSelection(),$.textContent="Copied",Ie(o).then(he)):Fe()}return}if((s.ctrlKey||s.metaKey)&&s.code==="KeyV"){s.preventDefault(),s.stopPropagation(),(async()=>{try{if(navigator.clipboard?.read){let o=await navigator.clipboard.read();for(let u of o)for(let v of u.types)if(Ne(v)){let B=await u.getType(v);await Be(B);return}}}catch{}try{let o=await navigator.clipboard?.readText();o&&i.pasteText(Ve(o))}catch{}})();return}}}let ve=0;function Ve(s){return s.split(`\r
|
|
6
8
|
`).join(`
|
|
7
9
|
`).split(`
|
|
8
|
-
`).join("\r")}async function Ht(
|
|
9
|
-
<span>${f(
|
|
10
|
-
<button class="session-edit-btn" data-session="${f(
|
|
11
|
-
`,
|
|
12
|
-
<span>${f(
|
|
10
|
+
`).join("\r")}async function Ht(s){let o=Mt(s.clipboardData);if(o){s.preventDefault(),s.stopPropagation();let B=Date.now();if(B-ve<50)return;ve=B,await Be(o);return}let u=s.clipboardData?.getData("text/plain");if(!u)return;s.preventDefault(),s.stopPropagation();let v=Date.now();v-ve<50||(ve=v,i.pasteText(Ve(u)))}let te=0;function Dt(s){s.preventDefault(),te++,We(s.dataTransfer)&&n.classList.add("terminal-drag-over")}function Rt(s){s.preventDefault(),s.dataTransfer&&(s.dataTransfer.dropEffect="copy")}function At(s){s.preventDefault(),te--,te<=0&&(te=0,n.classList.remove("terminal-drag-over"))}async function Yt(s){s.preventDefault(),te=0,n.classList.remove("terminal-drag-over");let o=We(s.dataTransfer);o&&await Be(o)}function _e(s){!Et||s.key!=="Escape"||Z||s.defaultPrevented||s.repeat||s.metaKey||s.ctrlKey||s.altKey||i.isFocused()&&(s.preventDefault(),s.stopPropagation(),fe("\x1B"))}n.addEventListener("paste",Ht),n.addEventListener("dragenter",Dt),n.addEventListener("dragover",Rt),n.addEventListener("dragleave",At),n.addEventListener("drop",Yt),document.addEventListener("keydown",_e,!0);function $t(s){if(s.touches.length!==1){r=null;return}let o=s.touches[0];o&&(r={startX:o.clientX,startY:o.clientY,lastX:o.clientX,lastY:o.clientY,scrolling:!1},s.stopPropagation())}function Pt(s){if(!r||s.touches.length!==1)return;let o=s.touches[0];if(!o)return;let u=o.clientY-r.startY,v=o.clientX-r.startX;if(!r.scrolling){if(Math.abs(u)<8||Math.abs(u)<Math.abs(v))return;r.scrolling=!0,d=Date.now()+500}s.preventDefault(),s.stopPropagation(),jt(-(o.clientY-r.lastY),o.clientX,o.clientY),r.lastX=o.clientX,r.lastY=o.clientY}function zt(s){if(!r)return;let o=r.scrolling;r=null,s.stopPropagation(),o?(d=Date.now()+500,s.preventDefault()):i.focus()}function Nt(s){r=null,s.stopPropagation()}function Wt(s){s.pointerType==="touch"&&Date.now()<d&&(s.preventDefault(),s.stopPropagation())}function jt(s,o,u){(n.querySelector(".xterm-screen")??n).dispatchEvent(new WheelEvent("wheel",{deltaY:s,deltaMode:WheelEvent.DOM_DELTA_PIXEL,clientX:o,clientY:u,bubbles:!0,cancelable:!0}))}n.addEventListener("touchstart",$t,{passive:!0,capture:!0}),n.addEventListener("touchmove",Pt,{passive:!1,capture:!0}),n.addEventListener("touchend",zt,{passive:!1,capture:!0}),n.addEventListener("touchcancel",Nt,{passive:!0,capture:!0}),n.addEventListener("pointerup",Wt,!0);function Ue(){k()}window.addEventListener("resize",Ue),window.visualViewport?.addEventListener("resize",k),window.visualViewport?.addEventListener("scroll",k);let Ke=new ResizeObserver(()=>k());return Ke.observe(n),document.fonts?.ready.then(()=>{k(),setTimeout(k,50),setTimeout(k,200)}),n.addEventListener("focusin",Tt,!0),requestAnimationFrame(()=>{J()&&me(),ze(),k()}),{destroy(){if(H=!0,U(!1),ee&&clearTimeout(ee),document.removeEventListener("mousemove",He,!0),document.removeEventListener("mouseup",De,!0),a){try{a.close(1e3,"session switch")}catch{}a=void 0}n.innerHTML="",n.classList.remove("terminal-pending"),window.removeEventListener("resize",Ue),Ke.disconnect(),document.removeEventListener("keydown",_e,!0)},focus(){i.focus()},sendInput(s){fe(s)},toggleCopyMode(){Fe()}}})()}var K=window.__TMUX_WEB_SHELL__,h=null,y=null,Ge=typeof window.__TMUX_WEB_SCOPE__?.agentId=="string"?window.__TMUX_WEB_SCOPE__.agentId:null,x=Ge;window.__tmuxWebScopeAgent=Ge;var Qe="sessions",W="",ye="",we="",et="";function T(n){return x?"/a/"+encodeURIComponent(x)+n:n}var m=document.getElementById("sidebar-content"),F=document.getElementById("main-placeholder"),I=document.getElementById("terminal-container"),se=document.getElementById("file-editor"),Ot=document.getElementById("fe-path"),D=document.getElementById("fe-status"),ae=document.getElementById("fe-content"),V=document.getElementById("fe-save"),qt=document.getElementById("fe-delete"),Xt=document.getElementById("fe-back"),tt=document.getElementById("fe-new-name"),Jt=document.getElementById("fe-new-btn"),Re=document.getElementById("settings-backdrop"),nt=document.getElementById("settings-popover"),it=document.querySelector(".sidebar");function Zt(){return window.matchMedia("(max-width: 640px)").matches}function Ae(){Zt()&&it.classList.add("collapsed")}function st(){it.classList.remove("collapsed")}document.getElementById("mode-sessions").addEventListener("click",()=>{st(),at("sessions")}),document.getElementById("mode-files").addEventListener("click",()=>{st(),at("files")});function at(n){Qe=n,document.querySelectorAll(".mode-btn").forEach(t=>t.classList.remove("active"));let e=document.getElementById(n==="sessions"?"mode-sessions":"mode-files");e&&e.classList.add("active"),n==="sessions"?O():rn()}var ot="";async function O(){try{let e=await(await fetch("/api/sidebar/sessions")).json(),t=JSON.stringify({recent:e.recent,agents:e.agents});if(t===ot)return;ot=t,Gt(e)}catch{m.innerHTML+='<div class="file-tree-empty">Failed to load sessions</div>'}let n=document.getElementById("ns-btn");n&&n.addEventListener("click",()=>document.getElementById("new-session-modal")?.classList.add("open"))}function Gt(n){m.innerHTML='<button class="new-session-sidebar-btn" id="ns-btn">+ New Session</button>';let e=n.recent||[],t=document.createElement("div");t.className="sidebar-section-label"+(x?" clickable":""),t.textContent=x?"\u2190 \u8FD4\u56DE\u672C\u673A":"\u672C\u673A",x&&(t.title="Back to hub",t.addEventListener("click",()=>{window.location.href="/"})),m.appendChild(t);for(let a of e){let l=document.createElement("div");l.className="session-item"+(a.name===y&&!x?" active":""),l.setAttribute("data-session",a.name),l.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="${a.attached?"M19 4H5a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2zm0 14H5V6h14v12z":"M4 6h16v2H4V6zm0 5h16v2H4v-2zm0 5h16v2H4v-2z"}"></svg>
|
|
11
|
+
<span>${f(a.name)}</span>
|
|
12
|
+
<button class="session-edit-btn" data-session="${f(a.name)}" title="Edit session"><svg viewBox="0 0 24 24" fill="currentColor" width="14" height="14"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04a1 1 0 000-1.41l-2.34-2.34a1 1 0 00-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></svg></button>
|
|
13
|
+
`,l.addEventListener("click",r=>{r.target.closest(".session-edit-btn")||oe(a.name)}),m.appendChild(l);let c=l.querySelector(".session-edit-btn");c&&c.addEventListener("click",r=>{r.stopPropagation(),fn(a.name,c)})}let i=n.agents||[];for(let a of i){if(!a.sessions||a.sessions.length===0)continue;let l=a.agentId===x,c=document.createElement("div");c.className="sidebar-section-label machine-label"+(a.online?"":" agent-offline-label")+(!l&&a.online?" clickable":""),c.textContent=a.agentName+(a.online?"":" (offline)"),!l&&a.online&&(c.title="\u6253\u5F00 "+a.agentName,c.addEventListener("click",()=>{window.location.href="/a/"+encodeURIComponent(a.agentId)+"/"})),m.appendChild(c);for(let r of a.sessions){let d=document.createElement("div");d.className="session-item"+(r.name===y&&x===a.agentId?" active":"")+(a.online?"":" session-offline"),d.setAttribute("data-session",r.name),d.setAttribute("data-agent",a.agentId),d.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="${r.attached?"M19 4H5a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2zm0 14H5V6h14v12z":"M4 6h16v2H4V6zm0 5h16v2H4v-2zm0 5h16v2H4v-2z"}"></svg>
|
|
14
|
+
<span>${f(r.name)}</span><span class="meta">${a.online?"":"offline"}</span>`,a.online&&d.addEventListener("click",p=>{p.target.closest(".session-edit-btn")||oe(r.name,a.agentId)}),m.appendChild(d)}}}function f(n){return n.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}async function oe(n,e){if(!(y===n&&h&&x===(e||null))){se.style.display="none",F.style.display="none",I.style.display="",I.classList.add("terminal-pending"),Ae(),h&&(Me(),h.destroy(),h=null),y=n,x=e||null,window.__tmuxWebScopeAgent=x;for(let t of m.querySelectorAll(".session-item"))t.classList.toggle("active",t.getAttribute("data-session")===n&&(t.getAttribute("data-agent")||null)===x);try{h=await Kt(I,n,{terminal:K.terminal,scrollback:K.scrollback,theme:K.theme,renderer:K.renderer,wsBase:x?"/ws/a/"+encodeURIComponent(x):K.wsBase||"/ws"}),vt()}catch(t){console.error("[shell] terminal init failed:",t);let i=t&&typeof t=="object"&&"message"in t?t.message:String(t);I.textContent="Failed to open terminal for "+n+": "+i,I.classList.remove("terminal-pending")}}}var be=[],g=null,lt=!1;function Qt(n){if(!g||!g.files.length)return null;let e=g.repoRoot;if(!e||!n.startsWith(e))return null;let t=n.slice(e.length+1);for(let i of g.files)if(i.path===t)return i.status;return null}async function en(n){lt=!0;try{let e=await fetch(T("/api/git/status?path="+encodeURIComponent(n)));e.ok?g=await e.json():g=null}catch{g=null}finally{lt=!1}}function tn(){if(!g||!g.branch)return"";let{branch:n,linesAdded:e,linesRemoved:t}=g,i=`<div class="sidebar-git"><div class="git-branch-badge">
|
|
13
15
|
<svg viewBox="0 0 16 16" fill="currentColor"><path d="M11.63 1.22a.75.75 0 00-1.06 0L5.99 5.8 4.12 3.93a.75.75 0 10-1.06 1.06L4.93 6.87A3.5 3.5 0 003 10.09v3.16a.75.75 0 001 0v-3.16a2.5 2.5 0 012.5-2.5h.27l-1.06 1.06a.75.75 0 001.06 1.06l2.37-2.38a.75.75 0 000-1.06L7.59 5.27l4.04-4.05a.75.75 0 000-1.06L11.63 1.22zM3.25 13.94a.75.75 0 01-.75-.75v-.69a.75.75 0 011.5 0v.69c0 .414-.336.75-.75.75z"/></svg>
|
|
14
|
-
${f(
|
|
15
|
-
<div class="git-popover-footer"><button id="git-popover-browse">Browse repository \u2192</button></div>`;else{let e=`<div class="git-popover-header">${
|
|
16
|
+
${f(n)}</div>`;return(e>0||t>0)&&(i+=`<div class="git-diff-stats">+<span class="add">${e}</span> <span class="del">-${t}</span></div>`),i+"</div>"}m.addEventListener("click",n=>{n.target.closest(".sidebar-git")&&q&&g&&(n.stopPropagation(),pt())});var le=document.getElementById("header-git"),rt=document.getElementById("git-diff-view"),ct=document.getElementById("gd-path"),Le=document.getElementById("gd-status"),Ee=document.getElementById("gd-content"),nn=document.getElementById("gd-back"),q=null;function re(n){if(!n||!n.branch){le.style.display="none",q=null;return}q=n.repoRoot;let{branch:e,linesAdded:t,linesRemoved:i}=n,a=`<span class="branch">${f(e)}</span>`;(t>0||i>0)&&(a+=`<span class="sep">\xB7</span>+<span class="diff-add">${t}</span> <span class="diff-del">-${i}</span>`),le.innerHTML=a,le.style.display="block"}le.addEventListener("click",n=>{q&&g&&(n.stopPropagation(),pt())});var E=document.getElementById("git-popover"),xe=document.getElementById("git-popover-backdrop");function Ye(){let n=le.getBoundingClientRect();E.style.top=n.bottom+4+"px",E.style.left=Math.max(8,Math.min(n.left,window.innerWidth-400))+"px"}function dt(){let n=q,e=document.getElementById("git-popover-browse");e&&e.addEventListener("click",()=>{if(Ce(),n){Qe="files",document.querySelectorAll(".mode-btn").forEach(i=>i.classList.remove("active"));let t=document.getElementById("mode-files");t&&t.classList.add("active"),j(n)}})}var ut="";function pt(){if(!g)return;let n=g.files||[];if(!n.length)E.innerHTML=`<div class="git-popover-header">No changes \u2014 clean working tree</div>
|
|
17
|
+
<div class="git-popover-footer"><button id="git-popover-browse">Browse repository \u2192</button></div>`;else{let e=`<div class="git-popover-header">${n.length} file${n.length>1?"s":""} changed</div>`;for(let t=0;t<n.length;t++){let i=n[t],a=i.additions||0,l=i.deletions||0,c="";switch(i.status){case"M":c='<span class="git-file-status M">M</span>';break;case"A":c='<span class="git-file-status A">A</span>';break;case"D":c='<span class="git-file-status D">D</span>';break;case"?":c='<span class="git-file-status ?">?</span>';break;case"R":c='<span class="git-file-status R">R</span>';break}e+=`<div class="git-popover-item" data-idx="${t}">
|
|
16
18
|
${c}<span class="file-path">${f(i.path)}</span>
|
|
17
|
-
<span class="file-add">${
|
|
18
|
-
<span class="file-del">${
|
|
19
|
-
</div>`}e+='<div class="git-popover-footer"><button id="git-popover-browse">Browse repository \u2192</button></div>',
|
|
19
|
+
<span class="file-add">${a>0?"+"+a:""}</span>
|
|
20
|
+
<span class="file-del">${l>0?"-"+l:""}</span>
|
|
21
|
+
</div>`}e+='<div class="git-popover-footer"><button id="git-popover-browse">Browse repository \u2192</button></div>',ut=e,E.innerHTML=e,E.querySelectorAll(".git-popover-item").forEach(t=>{let i=parseInt(t.dataset.idx||"0",10),a=n[i];!a||a.status==="D"||(t.classList.add("clickable"),t.style.cursor="pointer",t.addEventListener("click",()=>mt(a.path)))})}Ye(),E.classList.add("open"),xe.classList.add("open"),dt()}function sn(){return window.innerWidth>=1024}function ft(n,e){let t=(n+(e&&n?`
|
|
20
22
|
`:"")+e).split(`
|
|
21
|
-
`),i="",
|
|
23
|
+
`),i="",a=0,l=0;for(let c of t){let r=c;if(r.startsWith("@@")){let d=r.match(/@@\s+-(\d+)[^+]*\+(\d+)/);d&&(a=parseInt(d[1],10)-1,l=parseInt(d[2],10)-1),i+=`<div class="diff-line hunk"><span class="ln-body">${f(r)}</span></div>`;continue}if(r.startsWith("diff --git")||r.startsWith("index ")||r.startsWith("--- ")||r.startsWith("+++ ")||r.startsWith("new file")||r.startsWith("deleted file")){r.startsWith("diff --git")&&(i+=`<div class="diff-line header"><span class="ln-body">${f(r)}</span></div>`);continue}if(r.startsWith("+"))l++,i+=`<div class="diff-line add"><span class="ln-no">${l}</span><span class="ln-body">${f(r)}</span></div>`;else if(r.startsWith("-"))a++,i+=`<div class="diff-line del"><span class="ln-no">${a}</span><span class="ln-body">${f(r)}</span></div>`;else if(r.startsWith("\\"))i+=`<div class="diff-line"><span class="ln-body">${f(r)}</span></div>`;else{if(!r&&!a&&!l)continue;a++,l++,i+=`<div class="diff-line"><span class="ln-no">${a}</span><span class="ln-no" style="margin-right:12px">${l}</span><span class="ln-body">${f(r)}</span></div>`}}return{html:i,lineCount:t.length}}var ke=null;async function mt(n){let e=q;if(e)if(Ce(),sn()){I.style.display="none",h&&(Me(),h.destroy(),h=null,ke=y,y=null),re(null),se.style.display="none",F.style.display="none",rt.style.display="flex",ct.textContent=n,Le.textContent="Loading\u2026",Ee.innerHTML="";try{let t=await fetch(T("/api/git/diff?path="+encodeURIComponent(e)+"&file="+encodeURIComponent(n)));if(!t.ok)throw new Error(await t.text());let i=await t.json();on(n,i.diff,i.stagedDiff)}catch(t){let i=t instanceof Error?t.message:String(t);Le.textContent="Error",Ee.innerHTML=`<div class="diff-empty" style="padding:24px;text-align:center;color:var(--panel-muted)">Error: ${f(i)}</div>`}}else{E.innerHTML=`<div class="git-diff-view"><div class="diff-header">
|
|
22
24
|
<button class="diff-back">\u2190 Back</button>
|
|
23
|
-
<span class="diff-filename">${f(
|
|
25
|
+
<span class="diff-filename">${f(n)}</span>
|
|
24
26
|
<span class="diff-loading">Loading\u2026</span>
|
|
25
|
-
</div></div>`,
|
|
27
|
+
</div></div>`,Ye(),E.classList.add("open"),xe.classList.add("open");try{let t=await fetch(T("/api/git/diff?path="+encodeURIComponent(e)+"&file="+encodeURIComponent(n)));if(!t.ok)throw new Error(await t.text());let i=await t.json();an(n,i.diff,i.stagedDiff)}catch(t){let i=t instanceof Error?t.message:String(t);E.innerHTML=`<div class="git-diff-view"><div class="diff-header">
|
|
26
28
|
<button class="diff-back">\u2190 Back</button>
|
|
27
|
-
<span class="diff-filename">${f(
|
|
28
|
-
</div><div class="diff-empty">Error loading diff: ${f(i)}</div></div>`}}}function
|
|
29
|
+
<span class="diff-filename">${f(n)}</span>
|
|
30
|
+
</div><div class="diff-empty">Error loading diff: ${f(i)}</div></div>`}}}function an(n,e,t){if(!e&&!t){E.innerHTML=`<div class="git-diff-view"><div class="diff-header">
|
|
29
31
|
<button class="diff-back">\u2190 Back</button>
|
|
30
|
-
<span class="diff-filename">${f(
|
|
31
|
-
</div><div class="diff-empty">No diff content available</div></div>`;return}let{html:i,lineCount:
|
|
32
|
+
<span class="diff-filename">${f(n)}</span>
|
|
33
|
+
</div><div class="diff-empty">No diff content available</div></div>`;return}let{html:i,lineCount:a}=ft(e,t);E.innerHTML=`<div class="git-diff-view"><div class="diff-header">
|
|
32
34
|
<button class="diff-back">\u2190 Back</button>
|
|
33
|
-
<span class="diff-filename">${f(
|
|
34
|
-
<span class="diff-filesize">${
|
|
35
|
-
</div><div class="diff-content">${i}</div></div>`,
|
|
35
|
+
<span class="diff-filename">${f(n)}</span>
|
|
36
|
+
<span class="diff-filesize">${a} lines</span>
|
|
37
|
+
</div><div class="diff-content">${i}</div></div>`,E.querySelector(".diff-back")?.addEventListener("click",()=>{E.innerHTML=ut,Ye(),g&&E.querySelectorAll(".git-popover-item").forEach(l=>{let c=parseInt(l.dataset.idx||"0",10),r=g.files[c];!r||r.status==="D"||(l.style.cursor="pointer",l.addEventListener("click",()=>mt(r.path)))}),dt()})}function on(n,e,t){if(!e&&!t){Le.textContent="No diff",Ee.innerHTML='<div class="diff-empty" style="padding:24px;text-align:center;color:var(--panel-muted)">No diff content available</div>';return}let{html:i,lineCount:a}=ft(e,t);ct.textContent=n,Le.textContent=a+" lines",Ee.innerHTML=i}function ln(){rt.style.display="none",ke?(I.style.display="",I.classList.add("terminal-pending"),oe(ke),ke=null):y?(I.style.display="",I.classList.add("terminal-pending"),vt()):F.style.display="flex"}nn.addEventListener("click",ln);function Ce(){E.classList.remove("open"),xe.classList.remove("open")}xe.addEventListener("click",Ce),document.addEventListener("keydown",n=>{n.key==="Escape"&&(Ce(),Se())});async function ht(n){try{let e=await(await fetch("/api/fs/session-path?session="+encodeURIComponent(n))).json();if(e.path){let t=await fetch("/api/git/status?path="+encodeURIComponent(e.path));if(t.ok){let i=await t.json();g=i,re(i);return}}}catch{}g=null,re(null)}var Te=null;function vt(){Me(),y&&(ht(y),Te=setInterval(()=>{y&&ht(y)},3e4))}function Me(){Te&&(clearInterval(Te),Te=null)}function rn(){if(be=K.fsRoots||[],be.length===0){if(y){cn(y);return}m.innerHTML='<div class="file-tree-info">Open a session first, then switch to Files to browse its directory.</div>';return}m.innerHTML="";for(let n of be){let e=document.createElement("div");e.className="file-tree-item",e.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor" class="file-icon"><path d="M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/></svg> ${f(n)}`,e.addEventListener("click",()=>j(n)),m.appendChild(e)}}async function cn(n){m.innerHTML='<div class="file-tree-empty">Loading...</div>';try{let e=await(await fetch(T("/api/fs/session-path?session="+encodeURIComponent(n)))).json();e.path?j(e.path):m.innerHTML='<div class="file-tree-info">Could not determine session directory.</div>'}catch{m.innerHTML='<div class="file-tree-error">Failed to get session directory</div>'}}async function j(n){W=n,m.innerHTML='<div class="file-tree-empty">Loading...</div>';let e=en(n);try{let t=await(await fetch(T("/api/fs/list?path="+encodeURIComponent(n)))).json();await e,m.innerHTML="",re(g),m.innerHTML+=tn();let i=dn(n);if(i&&!be.some(l=>n===l)){let l=document.createElement("div");l.className="file-tree-item",l.innerHTML="..",l.addEventListener("click",()=>j(i)),m.appendChild(l)}if(t.dirs)for(let l of t.dirs){let c=l.split("/").pop()||l.split("\\").pop(),r=document.createElement("div");r.className="file-tree-item",r.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor" class="file-icon"><path d="M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/></svg> ${f(c)}`,r.addEventListener("click",()=>j(l)),m.appendChild(r)}else m.innerHTML="";let a=t.files||[];for(let l of a){let c=l.split("/").pop()||l.split("\\").pop(),r=Qt(l),d="",p="";if(r)switch(r){case"M":d="git-mod",p='<span class="git-file-status M">M</span>';break;case"A":d="git-add",p='<span class="git-file-status A">A</span>';break;case"D":d="git-del",p='<span class="git-file-status D">D</span>';break;case"?":d="git-untracked",p='<span class="git-file-status ?">?</span>';break;case"R":d="git-mod",p='<span class="git-file-status R">R</span>';break}let b=document.createElement("div");b.className="file-tree-item file"+(d?" "+d:""),b.innerHTML=`<span class="file-icon">\u{1F4C4}</span> ${p}${f(c)}`,b.addEventListener("click",()=>un(l)),m.appendChild(b)}}catch{m.innerHTML='<div class="file-tree-error">Failed to load directory</div>'}}function dn(n){let e=n.lastIndexOf("/");return e<=0?null:n.substring(0,e)}async function un(n){ye=n,I.style.display="none",h&&(Me(),h.destroy(),h=null,y=null),re(null),Ae(),F.style.display="none",se.style.display="flex",Ot.textContent=n,D.textContent="Loading...",V.style.display="none";try{let e=await fetch(T("/api/file?path="+encodeURIComponent(n)));if(!e.ok){let i=await e.json();D.textContent=i.error||"Failed to load",ae.value="";return}let t=await e.json();ae.value=t.content,we=t.content,et=t.content,D.textContent=t.size+" bytes",V.style.display=""}catch{D.textContent="Failed to load",ae.value=""}}ae.addEventListener("input",()=>{we=ae.value}),V.addEventListener("click",async()=>{V.textContent="Saving...",V.disabled=!0;try{let n=await fetch(T("/api/file"),{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:ye,content:we})});if(!n.ok){let e=await n.json();D.textContent=e.error||"Save failed";return}et=we,D.textContent="Saved"}catch{D.textContent="Save failed"}finally{V.disabled=!1,V.textContent="Save"}}),qt.addEventListener("click",async()=>{if(confirm("Delete "+ye+"?"))try{let n=await fetch(T("/api/file/delete"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:ye})});if(!n.ok){let e=await n.json();D.textContent=e.error||"Delete failed";return}se.style.display="none",F.style.display="flex",W&&j(W)}catch{D.textContent="Delete failed"}}),Xt.addEventListener("click",()=>{se.style.display="none",F.style.display="flex",W&&j(W)}),Jt.addEventListener("click",async()=>{let n=tt.value.trim();if(!n)return;let e=W+"/"+n;try{let t=await fetch(T("/api/file/touch"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:e})});if(!t.ok){let i=await t.json();D.textContent=i.error||"Create failed";return}tt.value="",W&&j(W)}catch{D.textContent="Create failed"}}),document.getElementById("mode-settings").addEventListener("click",()=>{let n=nt.classList.toggle("open");Re.classList.toggle("open",n)}),Re.addEventListener("click",()=>{nt.classList.remove("open"),Re.classList.remove("open")});var _="",ce=document.createElement("div");ce.className="session-popover-backdrop",document.body.appendChild(ce);var P=document.createElement("div");P.id="session-popover",P.className="session-popover",P.style.display="none",P.innerHTML=`<div class="sp-field">
|
|
36
38
|
<label>Rename session</label>
|
|
37
39
|
<input type="text" id="sp-name" />
|
|
38
40
|
</div>
|
|
@@ -41,5 +43,5 @@ var Vt="https://esm.sh/ghostty-web@0.4.0",_t=/\x1b\](?:10|11|110|111|104)(?:;[^\
|
|
|
41
43
|
<button class="btn" id="sp-cancel">Cancel</button>
|
|
42
44
|
</div>
|
|
43
45
|
<hr class="sp-divider" />
|
|
44
|
-
<button class="btn danger" id="sp-delete">Delete session</button>`,document.body.appendChild(
|
|
45
|
-
`).length;
|
|
46
|
+
<button class="btn danger" id="sp-delete">Delete session</button>`,document.body.appendChild(P);function pn(n){let e=n.getBoundingClientRect();P.style.top=e.bottom+4+"px",P.style.left=Math.max(8,Math.min(e.left,window.innerWidth-240))+"px"}function fn(n,e){_=n;let t=document.getElementById("sp-name");t.value=n,ce.classList.add("open"),P.style.display="block",pn(e),setTimeout(()=>t.focus(),50)}function de(){ce.classList.remove("open"),P.style.display="none"}ce.addEventListener("click",de),document.getElementById("sp-save").addEventListener("click",async()=>{let n=document.getElementById("sp-name").value.trim();if(!n||n===_){de();return}try{if(!(await fetch(T("/api/sessions/rename"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({oldName:_,newName:n})})).ok)return;de(),O(),y===_&&oe(n)}catch{}}),document.getElementById("sp-delete").addEventListener("click",async()=>{if(confirm('Delete session "'+_+'"?'))try{if(!(await fetch(T("/api/sessions/kill"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:_})})).ok)return;de(),y===_&&(h&&(h.destroy(),h=null),y=null,I.style.display="none",F.style.display="flex"),O()}catch{}}),document.getElementById("sp-cancel").addEventListener("click",de);var mn={esc:"\x1B",tab:" ","s-tab":"\x1B[Z",up:"\x1B[A",down:"\x1B[B",left:"\x1B[D",right:"\x1B[C",space:" ",enter:"\r",exit:"exit\r",yes:"yes\r"};document.getElementById("mobile-keys").addEventListener("click",n=>{let e=n.target.closest("button[data-key]");if(!e||!h)return;let t=mn[e.dataset.key];t&&(h.sendInput(t),h.focus())});var R=document.getElementById("mk-input"),gt=document.getElementById("mk-send");function yt(){if(!R||!h)return;let n=R.value;n&&(h.sendInput(n+"\r"),R.value="",R.rows=1,h.focus())}if(R&&(R.addEventListener("input",()=>{R.rows=1;let n=R.value.split(`
|
|
47
|
+
`).length;R.rows=Math.min(n,4)}),R.addEventListener("keydown",n=>{n.key==="Enter"&&!n.shiftKey&&(n.preventDefault(),yt())})),gt&>.addEventListener("click",yt),window.visualViewport){let n=document.querySelector(".app-layout"),e=()=>{n&&(n.style.height=window.visualViewport.height+"px"),window.scrollTo(0,0),document.documentElement.scrollTop=0,document.body.scrollTop=0};window.visualViewport.addEventListener("resize",e),window.addEventListener("orientationchange",()=>setTimeout(e,100)),document.addEventListener("touchstart",()=>{(window.scrollY>0||document.documentElement.scrollTop>0)&&window.scrollTo(0,0)},{passive:!0})}var $e=document.getElementById("process-panel"),ue=document.getElementById("proc-list"),hn=document.getElementById("proc-close"),Pe=document.getElementById("proc-backdrop"),vn=document.getElementById("header-ram");function gn(){ue.innerHTML='<div class="proc-empty">Loading\u2026</div>',fetch(T("/api/system/processes")).then(n=>n.json()).then(n=>{if(!Array.isArray(n)||!n.length){ue.innerHTML='<div class="proc-empty">No processes</div>';return}let e="";for(let t of n){let i=t.rss,a=i<1048576?(i/1024).toFixed(0)+"K":(i/1048576).toFixed(1)+"M";e+='<div class="proc-row" data-pid="'+t.pid+'"><span class="proc-mem">'+t.mem+'%</span><span class="proc-rss">'+a+'</span><span class="proc-cmd" title="'+f(t.command)+'">'+f(t.command)+'</span><button class="proc-kill" title="Kill PID '+t.pid+'">×</button></div>'}ue.innerHTML=e;for(let t of ue.querySelectorAll(".proc-row")){let i=t.querySelector(".proc-kill");i&&i.addEventListener("click",a=>{let l=a.target.closest(".proc-row");!l||!confirm("Kill PID "+l.dataset.pid+"?")||fetch(T("/api/system/kill"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({pid:parseInt(l.dataset.pid,10)})}).then(c=>c.json()).then(c=>{c.ok?l.style.opacity="0.3":alert("Failed: "+(c.error||"unknown"))}).catch(()=>alert("Network error"))})}}).catch(()=>{ue.innerHTML='<div class="proc-empty">Failed to load</div>'})}function yn(){$e.classList.add("open"),Pe.classList.add("open"),gn()}function Se(){$e.classList.remove("open"),Pe.classList.remove("open")}vn.addEventListener("click",n=>{n.stopPropagation(),$e.classList.contains("open")?Se():yn()}),hn.addEventListener("click",Se),Pe.addEventListener("click",Se),window.__openSession=oe,window.__refreshSidebar=O,O(),Ae(),setInterval(()=>{document.visibilityState==="visible"&&O()},1e4);
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
const
|
|
2
|
-
`)}selectRows(
|
|
3
|
-
`)}
|
|
4
|
-
|
|
5
|
-
`)
|
|
1
|
+
const kt="https://esm.sh/ghostty-web@0.4.0",Pt=/\x1b\](?:10|11|110|111|104)(?:;[^\x07\x1b]*)?\x1b?(?:\\|\x07)/g;function K(a){return a.replace(Pt,"")}let A;function Ft(){return A||(document.querySelector("link[data-tmux-web-xterm-css]")?A=Promise.resolve():(A=new Promise(e=>{const r=document.createElement("link");r.rel="stylesheet",r.href="/assets/xterm.css",r.setAttribute("data-tmux-web-xterm-css",""),r.addEventListener("load",()=>e(),{once:!0}),r.addEventListener("error",()=>e(),{once:!0}),document.head.appendChild(r)}),A))}class q{terminal;fitAddon;container;constructor(e,r,i){this.container=e,this.terminal=r,this.fitAddon=i,this.terminal.loadAddon(this.fitAddon),this.terminal.open(e)}static async create(e,r,i){const[{Terminal:o},{FitAddon:c}]=await Promise.all([import("@xterm/xterm"),import("@xterm/addon-fit"),Ft()]),h=new o({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:r,convertEol:!1,theme:i});return new q(e,h,new c)}get cols(){return this.terminal.cols}get rows(){return this.terminal.rows}write(e){return new Promise(r=>this.terminal.write(e,r))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom()}scrollToLine(e){this.terminal.scrollToLine(Math.max(0,e))}isNearScrollbackTop(){return this.terminal.buffer.active.viewportY<=1}viewportY(){return this.terminal.buffer.active.viewportY}baseY(){return this.terminal.buffer.active.baseY}fit(){const e=lt(this.container);return e.width<=0||e.height<=0?!1:(this.fitAddon.fit(),!0)}focus(){this.terminal.focus()}pasteText(e){this.terminal.paste(e)}input(e){this.terminal.input(e,!1)}onData(e){this.terminal.onData(e),this.terminal.onBinary(e)}onResize(e){this.terminal.onResize(e)}onScroll(e){this.terminal.onScroll(e)}attachCustomKeyEventHandler(e){this.terminal.attachCustomKeyEventHandler(e)}isFocused(){const e=document.activeElement;return e?e===this.container||e===this.terminal.textarea||this.container.contains(e)||!!e.closest?.(".xterm"):!1}getScreenText(){return this.getRowsText(0,this.terminal.rows-1)}getRowsText(e,r){const i=this.terminal.buffer.active,[o,c]=e<=r?[e,r]:[r,e],h=i.viewportY,l=[];for(let f=o;f<=c;f++){const u=i.getLine(h+f);l.push(u?u.translateToString(!0):"")}return l.join(`
|
|
2
|
+
`)}selectRows(e,r){const i=this.terminal.buffer.active,[o,c]=e<=r?[e,r]:[r,e];this.terminal.selectLines(i.viewportY+o,i.viewportY+c)}selectCells(e,r,i,o){const c=this.terminal.buffer.active,h=Math.min(r,o),l=Math.max(r,o);if(h===l){const f=Math.min(e,i),u=Math.max(e,i);this.terminal.select(f,c.viewportY+h,u-f+1)}else this.terminal.selectLines(c.viewportY+h,c.viewportY+l)}getCellsText(e,r,i,o){const c=this.terminal.buffer.active,h=Math.min(r,o),l=Math.max(r,o),f=r<o?e:r>o?i:Math.min(e,i),u=r<o?i:r>o?e:Math.max(e,i),x=c.viewportY,v=[];for(let p=h;p<=l;p++){const d=c.getLine(x+p);if(!d){v.push("");continue}const T=p===h?f:0,S=p===l?u:this.terminal.cols-1;let M="";for(let L=T;L<=S;L++){const C=d.getCell(L);C&&(M+=C.getChars())}v.push(M.replace(/\s+$/,""))}return v.join(`
|
|
3
|
+
`)}getSelection(){return this.terminal.getSelection()}clearSelection(){this.terminal.clearSelection()}hasSelectionSupport(){return!0}}class ${terminal;container;colsValue=80;rowsValue=24;charW=0;charH=0;resizeCallbacks=[];constructor(e,r){this.container=e,this.terminal=r,this.terminal.open(e)}static async create(e,r,i){const o=await import(kt);await o.init();const c=new o.Terminal({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:r,convertEol:!1,theme:i});return new $(e,c)}get cols(){return this.colsValue}get rows(){return this.rowsValue}write(e){return new Promise(r=>this.terminal.write(e,r))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom?.()}scrollToLine(e){this.terminal.scrollToLine?.(Math.max(0,e))}isNearScrollbackTop(){const e=this.terminal.buffer?.active;return e?e.viewportY>=e.baseY:!1}viewportY(){return this.terminal.buffer?.active?.viewportY??0}baseY(){return this.terminal.buffer?.active?.baseY??0}fit(){const e=lt(this.container);if(e.width<=0||e.height<=0)return!1;this.updateCellMetrics(!this.charW||!this.charH);const r=Math.floor(e.width/this.charW),i=Math.floor(e.height/this.charH);if(r<10||i<5)return!1;if(r!==this.colsValue||i!==this.rowsValue){this.colsValue=r,this.rowsValue=i,this.terminal.resize(r,i);for(const o of this.resizeCallbacks)o({cols:r,rows:i})}return!0}focus(){(this.terminal.textarea||this.container.querySelector("textarea")||this.container)?.focus?.()}pasteText(e){const r=this.terminal.getMode?.(2004)??!1;this.input(r?"\x1B[200~"+e+"\x1B[201~":e)}input(e){this.terminal.input?.(e,!1)}onData(e){this.terminal.onData(r=>e(r))}onResize(e){this.resizeCallbacks.push(e)}onScroll(e){this.terminal.onScroll(e)}attachCustomKeyEventHandler(e){this.terminal.attachCustomKeyEventHandler(e)}isFocused(){const e=document.activeElement;return!!e&&(e===this.container||e===this.terminal.textarea||this.container.contains(e))}getScreenText(){return this.getRowsText(0,this.rowsValue-1)}getRowsText(e,r){try{const i=this.terminal.buffer?.active;if(!i||typeof i.getLine!="function")return"";const[o,c]=e<=r?[e,r]:[r,e],h=typeof i.viewportY=="number"?i.viewportY:0,l=[];for(let f=o;f<=c;f++){const u=i.getLine(h+f);l.push(typeof u?.translateToString=="function"?u.translateToString(!0):"")}return l.join(`
|
|
4
|
+
`)}catch{return""}}selectRows(e,r){try{if(typeof this.terminal?.selectLines!="function")return;const i=this.terminal.buffer?.active,o=typeof i?.viewportY=="number"?i.viewportY:0,[c,h]=e<=r?[e,r]:[r,e];this.terminal.selectLines(o+c,o+h)}catch{}}selectCells(e,r,i,o){try{const c=this.terminal.buffer?.active,h=typeof c?.viewportY=="number"?c.viewportY:0,l=Math.min(r,o),f=Math.max(r,o);if(l===f){if(typeof this.terminal?.select!="function"){this.selectRows(l,f);return}const u=Math.min(e,i),x=Math.max(e,i);this.terminal.select(u,h+l,x-u+1)}else this.selectRows(l,f)}catch{this.selectRows(r,o)}}getCellsText(e,r,i,o){try{const c=this.terminal.buffer?.active;if(!c||typeof c.getLine!="function")return this.getRowsText(r,o);const h=typeof c.viewportY=="number"?c.viewportY:0,l=Math.min(r,o),f=Math.max(r,o),u=r<o?e:r>o?i:Math.min(e,i),x=r<o?i:r>o?e:Math.max(e,i),v=[];for(let p=l;p<=f;p++){const d=c.getLine(h+p);if(!d){v.push("");continue}const T=p===l?u:0,S=p===f?x:this.colsValue-1;let M="";if(typeof d.getCell=="function")for(let L=T;L<=S;L++){const C=d.getCell(L);C&&(M+=typeof C.getChars=="function"?C.getChars():"")}else M=typeof d.translateToString=="function"?d.translateToString(!1):"";v.push(M.replace(/\s+$/,""))}return v.join(`
|
|
5
|
+
`)}catch{return this.getRowsText(r,o)}}getSelection(){try{if(typeof this.terminal?.getSelection=="function")return this.terminal.getSelection()}catch{}return""}clearSelection(){try{typeof this.terminal?.clearSelection=="function"&&this.terminal.clearSelection()}catch{}}hasSelectionSupport(){return typeof this.terminal?.selectLines=="function"}updateCellMetrics(e=!1){const r=this.container.querySelector("canvas");if(r instanceof HTMLElement&&r.offsetWidth>0&&r.offsetHeight>0&&this.colsValue>0&&this.rowsValue>0){const i=r.offsetWidth/this.colsValue,o=r.offsetHeight/this.rowsValue;(e||!this.charW||!this.charH)&&(this.charW=i,this.charH=o)}(!this.charW||!this.charH)&&(this.charW=9,this.charH=18)}}function lt(a){const e=a.getBoundingClientRect(),r=window.visualViewport;return r?{width:Math.min(e.width,r.width),height:Math.max(0,Math.min(e.height,r.height-Math.max(0,e.top)))}:e}function Bt(a,e,r){return a.innerHTML="",a.classList.add("terminal-pending"),(async()=>{let i;if(r.renderer==="ghostty")try{i=await $.create(a,r.scrollback,r.theme)}catch{console.error("[tmux-web] ghostty-web failed; falling back to xterm.js"),i=await q.create(a,r.scrollback,r.theme)}else i=await q.create(a,r.scrollback,r.theme);let o,c=0,h,l=null,f=0,u="connecting",x=0,v=!1,p=[],d="",T=!1,S=1e3;const M=location.protocol==="https:"?"wss:":"ws:",L=r.wsBase||"/ws",C=M+"//"+location.host+L+"/"+encodeURIComponent(e),ct="/api/session/"+encodeURIComponent(e)+"/upload",ut=/^((?!chrome|android|crios|fxios|edgios).)*safari/i.test(navigator.userAgent);function ft(){return p.join("")+d}async function ht(t,n=0){const s=t?i.viewportY():0,g=t?i.baseY():0,m=K(ft());if(i.reset(),!m){t||i.scrollToBottom();return}await i.write(m),t?i.scrollToLine(g+s+n):i.scrollToBottom()}function Y(t){o?.readyState===WebSocket.OPEN&&o.send(JSON.stringify(t))}function mt(t){let n;try{n=JSON.parse(t)}catch{u==="live"&&(d+=t,i.write(K(t)));return}if(n.type==="auth.required"){const s=localStorage.getItem("tmux-web-token");s?Y({type:"auth.token",token:s}):location.href="/login?returnTo="+encodeURIComponent(location.pathname+location.search);return}if(n.type==="attach_failed"&&typeof n.message=="string"){V=!0,u="dead",i.reset(),i.write(`\r
|
|
6
|
+
\x1B[31m`+K(n.message)+`\x1B[0m\r
|
|
7
|
+
`).then(()=>{O();try{o?.close()}catch{}});return}if(n.type==="auth.ok"){n.token&&localStorage.setItem("tmux-web-token",n.token),S=1e3,k(),Y({type:"resize",cols:i.cols,rows:i.rows}),y();return}if(n.type==="auth.failed"){if(n.permanentLock||n.retryAfterMs&&n.retryAfterMs>6e4){localStorage.removeItem("tmux-web-token"),location.href="/login?error="+encodeURIComponent(n.message);return}return}if(n.type==="snapshot"&&typeof n.data=="string"){const s=K(n.data);p=[s],d="",x=typeof n.lines=="number"?n.lines:r.terminal.initialLines,u="live",i.reset(),i.write(s).then(()=>i.scrollToBottom());return}if(n.type==="window_changed"&&typeof n.activeIndex=="number"){const s=new URL(location.href);s.searchParams.get("window")!==String(n.activeIndex)&&(s.searchParams.set("window",String(n.activeIndex)),history.replaceState(history.state,"",s)),window.dispatchEvent(new CustomEvent("tmux:windows",{detail:n.windows}));return}if(n.type==="history"&&typeof n.data=="string"){v=!1,n.lines>0&&n.data&&(p.unshift(n.data),x+=n.lines,ht(!0,n.lines));return}if(n.type==="data"&&typeof n.data=="string"){const s=K(n.data);if(u==="connecting"){u="live",d=s,i.write(s);return}u==="live"&&(d+=s,i.write(s))}}let V=!1;function Q(){if(V)return;let t=C;const n=localStorage.getItem("tmux-web-token");n&&(t+=(t.includes("?")?"&":"?")+"token="+encodeURIComponent(n)),o=new WebSocket(t),o.onopen=()=>{u="connecting",x=0,v=!1,p=[],d="",i.reset(),S=1e3},o.onmessage=s=>{typeof s.data=="string"&&mt(s.data)},o.onclose=()=>{T||(u="connecting",!V&&setTimeout(()=>{S=Math.min(S*2,1e4),!T&&!V&&Q()},S))},o.onerror=()=>o?.close()}function W(t){Y({type:"input",data:t})}function k(){return i.fit()}function O(){a.classList.remove("terminal-pending")}function y(){c&&cancelAnimationFrame(c),h&&clearTimeout(h),k(),c=requestAnimationFrame(()=>{c=0,k()&&O()}),h=setTimeout(()=>{k()&&O()},120)}function pt(){y(),setTimeout(y,50),setTimeout(y,150),setTimeout(y,300)}function Z(t){return typeof t=="string"&&t.startsWith("image/")}function R(t){return t?.files?.length?t.files[0]??null:null}function dt(t){if(!t?.items)return null;for(let n=0;n<t.items.length;n++){const s=t.items[n];if(s?.kind==="file"&&Z(s.type))return s.getAsFile()}return null}async function gt(t){const n=new FormData,s=t instanceof File&&t.name?t.name:"upload";n.append("file",t,s);const g=localStorage.getItem("tmux-web-token"),m={};g&&(m.Authorization="Bearer "+g);const I=await fetch(ct,{method:"POST",body:n,headers:m});if(!I.ok){let st="upload failed";try{const at=await I.json();at.error&&(st=at.error)}catch{}throw new Error(st)}const U=await I.json();if(!U.path)throw new Error("no path in response");return U.path}async function N(t){try{const n=await gt(t);W(n)}catch{}}i.onData(t=>W(t)),i.onResize(({cols:t,rows:n})=>Y({type:"resize",cols:t,rows:n})),i.onScroll(()=>{u!=="live"||v||!i.isNearScrollbackTop()||(v=!0,Y({type:"load_history",before:x}))});let P=!1,F=!1,w=null,b=null;const B=document.createElement("div");B.className="terminal-copy-banner",B.innerHTML='<strong>Copy mode</strong><span class="hint">drag to select \xB7 Alt+C copies \xB7 Esc exits</span>',B.hidden=!0,a.appendChild(B);const E=document.createElement("div");E.className="terminal-copy-banner terminal-copy-toast",E.textContent="Copied",E.hidden=!0,a.appendChild(E);function tt(t,n){const s=a.querySelector(".xterm-screen, canvas"),m=(s&&s.getBoundingClientRect().width>0?s:a).getBoundingClientRect(),I=m.height>0&&i.rows>0?m.height/i.rows:18,U=m.width>0&&i.cols>0?m.width/i.cols:9;return{row:Math.max(0,Math.min(i.rows-1,Math.floor((n-m.top)/I))),col:Math.max(0,Math.min(i.cols-1,Math.floor((t-m.left)/U)))}}async function _(t){if(!t)return;try{if(navigator.clipboard?.writeText){await navigator.clipboard.writeText(t);return}}catch{}const n=document.createElement("textarea");n.value=t,n.style.position="fixed",n.style.opacity="0",n.style.pointerEvents="none",document.body.appendChild(n),n.focus(),n.select();try{document.execCommand("copy")}catch{}n.remove()}let z;function X(){E.hidden=!1,z&&clearTimeout(z),z=setTimeout(()=>{E.hidden=!0},1e3)}function D(t){P=t,B.hidden=!t,a.classList.toggle("terminal-copy-mode-active",t),t&&i.focus()}function et(){D(!P)}function yt(t){T||t.button!==0||F||(P||t.shiftKey)&&(t.preventDefault(),t.stopPropagation(),F=!0,w=tt(t.clientX,t.clientY),b=w,i.selectCells(w.col,w.row,b.col,b.row),document.addEventListener("mousemove",J,!0),document.addEventListener("mouseup",G,!0))}function J(t){T||!F||!w||(t.preventDefault(),t.stopPropagation(),b=tt(t.clientX,t.clientY),i.selectCells(w.col,w.row,b.col,b.row))}function G(t){T||!F||!w||!b||(t.preventDefault(),t.stopPropagation(),document.removeEventListener("mousemove",J,!0),document.removeEventListener("mouseup",G,!0),F=!1,D(!1),E.textContent="\u5DF2\u9009\u4E2D \xB7 Alt+C \u590D\u5236",X(),i.focus())}a.addEventListener("mousedown",yt,!0),document.addEventListener("keydown",wt,!0);function wt(t){if(!(T||!i.isFocused()||t.defaultPrevented||t.isComposing)){if(P){if(t.key==="Escape"){t.preventDefault(),t.stopPropagation(),w=null,b=null,i.clearSelection(),D(!1);return}if(t.key==="Enter"||(t.ctrlKey||t.metaKey)&&t.code==="KeyC"){t.preventDefault(),t.stopPropagation(),_(i.getScreenText()).then(X),D(!1);return}}if(t.altKey&&t.code==="KeyC"&&!t.ctrlKey&&!t.metaKey){if(t.preventDefault(),t.stopPropagation(),w&&b){const n=i.getCellsText(w.col,w.row,b.col,b.row);w=null,b=null,i.clearSelection(),D(!1),n&&(E.textContent="Copied",_(n).then(X))}else{const n=i.getSelection();n?(i.clearSelection(),E.textContent="Copied",_(n).then(X)):et()}return}if((t.ctrlKey||t.metaKey)&&t.code==="KeyV"){t.preventDefault(),t.stopPropagation(),(async()=>{try{if(navigator.clipboard?.read){const n=await navigator.clipboard.read();for(const s of n)for(const g of s.types)if(Z(g)){const m=await s.getType(g);await N(m);return}}}catch{}try{const n=await navigator.clipboard?.readText();n&&i.pasteText(nt(n))}catch{}})();return}}}let j=0;function nt(t){return t.split(`\r
|
|
6
8
|
`).join(`
|
|
7
9
|
`).split(`
|
|
8
|
-
`).join("\r")}async function vt(t){const
|
|
10
|
+
`).join("\r")}async function vt(t){const n=dt(t.clipboardData);if(n){t.preventDefault(),t.stopPropagation();const m=Date.now();if(m-j<50)return;j=m,await N(n);return}const s=t.clipboardData?.getData("text/plain");if(!s)return;t.preventDefault(),t.stopPropagation();const g=Date.now();g-j<50||(j=g,i.pasteText(nt(s)))}let H=0;function bt(t){t.preventDefault(),H++,R(t.dataTransfer)&&a.classList.add("terminal-drag-over")}function Tt(t){t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="copy")}function xt(t){t.preventDefault(),H--,H<=0&&(H=0,a.classList.remove("terminal-drag-over"))}async function St(t){t.preventDefault(),H=0,a.classList.remove("terminal-drag-over");const n=R(t.dataTransfer);n&&await N(n)}function it(t){!ut||t.key!=="Escape"||P||t.defaultPrevented||t.repeat||t.metaKey||t.ctrlKey||t.altKey||i.isFocused()&&(t.preventDefault(),t.stopPropagation(),W("\x1B"))}a.addEventListener("paste",vt),a.addEventListener("dragenter",bt),a.addEventListener("dragover",Tt),a.addEventListener("dragleave",xt),a.addEventListener("drop",St),document.addEventListener("keydown",it,!0);function Lt(t){if(t.touches.length!==1){l=null;return}const n=t.touches[0];n&&(l={startX:n.clientX,startY:n.clientY,lastX:n.clientX,lastY:n.clientY,scrolling:!1},t.stopPropagation())}function Et(t){if(!l||t.touches.length!==1)return;const n=t.touches[0];if(!n)return;const s=n.clientY-l.startY,g=n.clientX-l.startX;if(!l.scrolling){if(Math.abs(s)<8||Math.abs(s)<Math.abs(g))return;l.scrolling=!0,f=Date.now()+500}t.preventDefault(),t.stopPropagation(),Yt(-(n.clientY-l.lastY),n.clientX,n.clientY),l.lastX=n.clientX,l.lastY=n.clientY}function Mt(t){if(!l)return;const n=l.scrolling;l=null,t.stopPropagation(),n?(f=Date.now()+500,t.preventDefault()):i.focus()}function Ct(t){l=null,t.stopPropagation()}function Dt(t){t.pointerType==="touch"&&Date.now()<f&&(t.preventDefault(),t.stopPropagation())}function Yt(t,n,s){(a.querySelector(".xterm-screen")??a).dispatchEvent(new WheelEvent("wheel",{deltaY:t,deltaMode:WheelEvent.DOM_DELTA_PIXEL,clientX:n,clientY:s,bubbles:!0,cancelable:!0}))}a.addEventListener("touchstart",Lt,{passive:!0,capture:!0}),a.addEventListener("touchmove",Et,{passive:!1,capture:!0}),a.addEventListener("touchend",Mt,{passive:!1,capture:!0}),a.addEventListener("touchcancel",Ct,{passive:!0,capture:!0}),a.addEventListener("pointerup",Dt,!0);function rt(){y()}window.addEventListener("resize",rt),window.visualViewport?.addEventListener("resize",y),window.visualViewport?.addEventListener("scroll",y);const ot=new ResizeObserver(()=>y());return ot.observe(a),document.fonts?.ready.then(()=>{y(),setTimeout(y,50),setTimeout(y,200)}),a.addEventListener("focusin",pt,!0),requestAnimationFrame(()=>{k()&&O(),Q(),y()}),{destroy(){if(T=!0,D(!1),z&&clearTimeout(z),document.removeEventListener("mousemove",J,!0),document.removeEventListener("mouseup",G,!0),o){try{o.close(1e3,"session switch")}catch{}o=void 0}a.innerHTML="",a.classList.remove("terminal-pending"),window.removeEventListener("resize",rt),ot.disconnect(),document.removeEventListener("keydown",it,!0)},focus(){i.focus()},sendInput(t){W(t)},toggleCopyMode(){et()}}})()}export{Bt as initTerminal};
|