tmux-weblink 2.2.19 → 2.2.21
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,30 +1,30 @@
|
|
|
1
|
-
var mn=/\x1b\](?:10|11|110|111|104)(?:;[^\x07\x1b]*)?\x1b?(?:\\|\x07)/g;function Xe(e){return e.replace(/\x1b\[\?1049[hl]/g,"")}function pe(e){return e.replace(mn,"")}var
|
|
2
|
-
`)}selectRows(t,n){let s=this.terminal.buffer.active,[l,r]=t<=n?[t,n]:[n,t];this.terminal.selectLines(s.viewportY+l,s.viewportY+r)}selectCells(t,n,s,l){let r=this.terminal.buffer.active,c=Math.min(n,l),a=Math.max(n,l);if(c===a){let u=Math.min(t,s),f=Math.max(t,s);this.terminal.select(u,r.viewportY+c,f-u+1)}else this.terminal.selectLines(r.viewportY+c,r.viewportY+a)}getCellsText(t,n,s,l){let r=this.terminal.buffer.active,c=Math.min(n,l),a=Math.max(n,l),u=n<l?t:n>l?s:Math.min(t,s),f=n<l?s:n>l?t:Math.max(t,s),S=r.viewportY,L=[];for(let F=c;F<=a;F++){let M=r.getLine(S+F);if(!M){L.push("");continue}let b=F===c?u:0,O=F===a?f:this.terminal.cols-1,
|
|
3
|
-
`)}getSelection(){return this.terminal.getSelection()}clearSelection(){this.terminal.clearSelection()}hasSelectionSupport(){return!0}};function gn(e){let t=e.getBoundingClientRect(),n=window.visualViewport;return n?{width:Math.min(t.width,n.width),height:Math.max(0,Math.min(t.height,n.height-Math.max(0,t.top)))}:t}function yn(e,t,n){return e.innerHTML="",e.classList.add("terminal-pending"),(async()=>{let s=await vn.create(e,n.scrollback,n.theme),l,r=0,c,a=null,u=0,f=0,S=.2,L=10,F=.95,M=.04,b=null,O=null;function
|
|
1
|
+
var mn=/\x1b\](?:10|11|110|111|104)(?:;[^\x07\x1b]*)?\x1b?(?:\\|\x07)/g;function Xe(e){return e.replace(/\x1b\[\?1049[hl]/g,"")}function pe(e){return e.replace(mn,"")}var Ae;function hn(){return Ae||(document.querySelector("link[data-tmux-web-xterm-css]")?Ae=Promise.resolve():(Ae=new Promise(e=>{let t=document.createElement("link");t.rel="stylesheet",t.href="/assets/xterm.css",t.setAttribute("data-tmux-web-xterm-css",""),t.addEventListener("load",()=>e(),{once:!0}),t.addEventListener("error",()=>e(),{once:!0}),document.head.appendChild(t)}),Ae))}var vn=class jt{terminal;fitAddon;container;constructor(t,n,s){this.container=t,this.terminal=n,this.fitAddon=s,this.terminal.loadAddon(this.fitAddon),this.terminal.open(t)}static async create(t,n,s){let[{Terminal:l},{FitAddon:r}]=await Promise.all([import("./xterm-BXEES47M.js"),import("./addon-fit-D5N335P2.js"),hn()]),c=new l({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:n,convertEol:!1,smoothScrollDuration:120,theme:s});return new jt(t,c,new r)}get cols(){return this.terminal.cols}get rows(){return this.terminal.rows}write(t){return new Promise(n=>this.terminal.write(t,n))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom()}scrollToLine(t,n=!1){this.terminal.scrollToLine(Math.max(0,t),n)}scrollLines(t){let n=this.terminal.buffer?.active;this.terminal.scrollLines(t)}isNearScrollbackTop(){return this.terminal.buffer.active.viewportY<=1}viewportY(){return this.terminal.buffer.active.viewportY}baseY(){return this.terminal.buffer.active.baseY}fit(){let t=gn(this.container);if(t.width<=0||t.height<=0)return!1;let n=this.terminal._core?._renderService?.dimensions?.css?.cell;if(!n?.width||!n?.height)return this.fitAddon.fit(),!0;let s=n.width,l=n.height,r=this.terminal.element?.querySelector(".xterm-viewport"),c=r?Math.max(0,r.offsetWidth-r.clientWidth):0,a=Math.max(2,Math.floor((t.width-c)/s)),u=Math.max(2,Math.floor(t.height/l));return(a!==this.terminal.cols||u!==this.terminal.rows)&&this.terminal.resize(a,u),!0}focus(){this.terminal.focus()}pasteText(t){this.terminal.paste(t)}input(t){this.terminal.input(t,!1)}onData(t){this.terminal.onData(t),this.terminal.onBinary(t)}onResize(t){this.terminal.onResize(t)}onScroll(t){this.terminal.onScroll(t)}attachCustomKeyEventHandler(t){this.terminal.attachCustomKeyEventHandler(t)}isFocused(){let t=document.activeElement;return t?t===this.container||t===this.terminal.textarea||this.container.contains(t)||!!t.closest?.(".xterm"):!1}getScreenText(){return this.getRowsText(0,this.terminal.rows-1)}getRowsText(t,n){let s=this.terminal.buffer.active,[l,r]=t<=n?[t,n]:[n,t],c=s.viewportY,a=[];for(let u=l;u<=r;u++){let f=s.getLine(c+u);a.push(f?f.translateToString(!0):"")}return a.join(`
|
|
2
|
+
`)}selectRows(t,n){let s=this.terminal.buffer.active,[l,r]=t<=n?[t,n]:[n,t];this.terminal.selectLines(s.viewportY+l,s.viewportY+r)}selectCells(t,n,s,l){let r=this.terminal.buffer.active,c=Math.min(n,l),a=Math.max(n,l);if(c===a){let u=Math.min(t,s),f=Math.max(t,s);this.terminal.select(u,r.viewportY+c,f-u+1)}else this.terminal.selectLines(r.viewportY+c,r.viewportY+a)}getCellsText(t,n,s,l){let r=this.terminal.buffer.active,c=Math.min(n,l),a=Math.max(n,l),u=n<l?t:n>l?s:Math.min(t,s),f=n<l?s:n>l?t:Math.max(t,s),S=r.viewportY,L=[];for(let F=c;F<=a;F++){let M=r.getLine(S+F);if(!M){L.push("");continue}let b=F===c?u:0,O=F===a?f:this.terminal.cols-1,se="";for(let Ce=b;Ce<=O;Ce++){let W=M.getCell(Ce);W&&(se+=W.getChars())}L.push(se.replace(/\s+$/,""))}return L.join(`
|
|
3
|
+
`)}getSelection(){return this.terminal.getSelection()}clearSelection(){this.terminal.clearSelection()}hasSelectionSupport(){return!0}};function gn(e){let t=e.getBoundingClientRect(),n=window.visualViewport;return n?{width:Math.min(t.width,n.width),height:Math.max(0,Math.min(t.height,n.height-Math.max(0,t.top)))}:t}function yn(e,t,n){return e.innerHTML="",e.classList.add("terminal-pending"),(async()=>{let s=await vn.create(e,n.scrollback,n.theme),l,r=0,c,a=null,u=0,f=0,S=.2,L=10,F=.95,M=.04,b=null,O=null;function se(i){b||(b=document.createElement("div"),b.style.cssText=["position:absolute","left:0","width:40%","padding:10px 0","text-align:center","font:600 14px/1.4 system-ui, -apple-system, sans-serif","color:rgba(255,255,255,0.95)","background:rgba(20,30,50,0.55)","border:1px solid rgba(255,255,255,0.25)","border-radius:10px","pointer-events:none","opacity:0","transition:opacity 0.15s ease","z-index:6"].join(";"),e.appendChild(b)),b.textContent=i?"\u2191 \u4E0A\u7FFB\u4E00\u9875 (PgUp)":"\u2193 \u4E0B\u7FFB\u4E00\u9875 (PgDn)",b.style.top=i?"10%":"auto",b.style.bottom=i?"auto":"10%",b.style.opacity="1",O&&clearTimeout(O),O=setTimeout(()=>{b&&(b.style.opacity="0")},900)}function Ce(){O&&clearTimeout(O),b&&(b.style.opacity="0")}function W(){u&&(cancelAnimationFrame(u),u=0),f=0}function Ut(i){if(W(),Math.abs(i)<S)return;f=Math.max(-L,Math.min(L,i));let o=()=>{if(j){u=0;return}let d=e.querySelector(".xterm-rows > div"),p=d?d.getBoundingClientRect().height:16,v=p>0?Math.round(f*16/p):f>0?1:-1;v===0&&(v=f>0?1:-1);let A=s.viewportY()-v,V=s.baseY(),ue=Math.max(0,Math.min(A,V));if(s.scrollToLine(ue,!0),f*=F,ue!==A){u=0;return}if(Math.abs(f)<M){u=0;return}u=requestAnimationFrame(o)};u=requestAnimationFrame(o)}let ke=0,R="connecting",Se=0,ie=!1,Te=[],G="",j=!1,ae=1e3,_t=location.protocol==="https:"?"wss:":"ws:",Yt=n.wsBase||"/ws",Ot=_t+"//"+location.host+Yt+"/"+encodeURIComponent(t),Wt="/api/session/"+encodeURIComponent(t)+"/upload",qt=/^((?!chrome|android|crios|fxios|edgios).)*safari/i.test(navigator.userAgent);function Kt(){return Te.join("")+G}async function Vt(i,o=0){let d=i?s.viewportY():0,p=pe(Kt());if(s.reset(),!p){i||s.scrollToBottom();return}await s.write(p),i?s.scrollToLine(o+d):s.scrollToBottom()}function q(i){l?.readyState===WebSocket.OPEN&&l.send(JSON.stringify(i))}function Xt(i){let o;try{o=JSON.parse(i)}catch{R==="live"&&(G+=i,s.write(pe(i)));return}if(o.type==="auth.required"){let d=localStorage.getItem("tmux-web-token");d?q({type:"auth.token",token:d}):location.href="/login?returnTo="+encodeURIComponent(location.pathname+location.search);return}if(o.type==="attach_failed"&&typeof o.message=="string"){Be=!0,R="dead",s.reset(),s.write(`\r
|
|
4
4
|
\x1B[31m`+pe(o.message)+`\x1B[0m\r
|
|
5
|
-
`).then(()=>{
|
|
5
|
+
`).then(()=>{Me();try{l?.close()}catch{}});return}if(o.type==="auth.ok"){o.token&&localStorage.setItem("tmux-web-token",o.token),ae=1e3,K(),q({type:"resize",cols:s.cols,rows:s.rows}),T();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 d=Xe(pe(o.data));Te=[d],G="",Se=typeof o.lines=="number"?o.lines:n.terminal.initialLines,R="live",s.reset(),K(),q({type:"resize",cols:s.cols,rows:s.rows}),s.write(d).then(()=>s.scrollToBottom());return}if(o.type==="window_changed"&&typeof o.activeIndex=="number"){let d=new URL(location.href);d.searchParams.get("window")!==String(o.activeIndex)&&(d.searchParams.set("window",String(o.activeIndex)),history.replaceState(history.state,"",d)),window.dispatchEvent(new CustomEvent("tmux:windows",{detail:o.windows}));return}if(o.type==="history"&&typeof o.data=="string"){o.lines>0&&o.data?(Te.unshift(Xe(o.data)),Se+=o.lines,Vt(!0,o.lines).finally(()=>{ie=!1})):ie=!1;return}if(o.type==="data"&&typeof o.data=="string"){let d=Xe(pe(o.data));if(R==="connecting"){R="live",G=d,s.write(d);return}R==="live"&&(G+=d,s.write(d))}}let Be=!1;function ot(){if(Be)return;let i=Ot,o=localStorage.getItem("tmux-web-token");o&&(i+=(i.includes("?")?"&":"?")+"token="+encodeURIComponent(o)),i+=(i.includes("?")?"&":"?")+"cols="+s.cols+"&rows="+s.rows,l=new WebSocket(i),l.onopen=()=>{R="connecting",Se=0,ie=!1,Te=[],G="",s.reset(),ae=1e3},l.onmessage=d=>{typeof d.data=="string"&&Xt(d.data)},l.onclose=()=>{j||(R="connecting",!Be&&setTimeout(()=>{ae=Math.min(ae*2,1e4),!j&&!Be&&ot()},ae))},l.onerror=()=>l?.close()}function Q(i){q({type:"input",data:i})}function K(){return s.fit()}function Me(){e.classList.remove("terminal-pending")}function T(){r&&cancelAnimationFrame(r),c&&clearTimeout(c),K(),r=requestAnimationFrame(()=>{r=0,K()&&Me()}),c=setTimeout(()=>{K()&&Me()},120)}function Jt(){T(),setTimeout(T,50),setTimeout(T,150),setTimeout(T,300)}function lt(i){return typeof i=="string"&&i.startsWith("image/")}function rt(i){return i?.files?.length?i.files[0]??null:null}function Zt(i){if(!i?.items)return null;for(let o=0;o<i.items.length;o++){let d=i.items[o];if(d?.kind==="file"&<(d.type))return d.getAsFile()}return null}async function Gt(i){let o=new FormData,d=i instanceof File&&i.name?i.name:"upload";o.append("file",i,d);let p=localStorage.getItem("tmux-web-token"),v={};p&&(v.Authorization="Bearer "+p);let A=await fetch(Wt,{method:"POST",body:o,headers:v});if(!A.ok){let ue="upload failed";try{let ht=await A.json();ht.error&&(ue=ht.error)}catch{}throw new Error(ue)}let V=await A.json();if(!V.path)throw new Error("no path in response");return V.path}async function qe(i){try{let o=await Gt(i);Q(o)}catch{}}s.onData(i=>Q(i)),s.onResize(({cols:i,rows:o})=>q({type:"resize",cols:i,rows:o})),s.onScroll(()=>{R!=="live"||ie||!s.isNearScrollbackTop()||(ie=!0,q({type:"load_history",before:Se}))});let oe=!1,le=!1,E=null,x=null,re=document.createElement("div");re.className="terminal-copy-banner",re.innerHTML='<strong>Copy mode</strong><span class="hint">drag to copy \xB7 Esc exits</span>',re.hidden=!0,e.appendChild(re);let $=document.createElement("div");$.className="terminal-copy-banner terminal-copy-toast",$.textContent="Copied",$.hidden=!0,e.appendChild($);function ct(i,o){let d=e.querySelector(".xterm-screen, canvas"),p=(d&&d.getBoundingClientRect().width>0?d:e).getBoundingClientRect(),v=p.height>0&&s.rows>0?p.height/s.rows:18,A=p.width>0&&s.cols>0?p.width/s.cols:9;return{row:Math.max(0,Math.min(s.rows-1,Math.floor((o-p.top)/v))),col:Math.max(0,Math.min(s.cols-1,Math.floor((i-p.left)/A)))}}async function Ie(i){if(!i)return;try{if(navigator.clipboard?.writeText){await navigator.clipboard.writeText(i);return}}catch{}let o=document.createElement("textarea");o.value=i,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 ce;function De(){$.hidden=!1,ce&&clearTimeout(ce),ce=setTimeout(()=>{$.hidden=!0},1e3)}function ee(i){oe=i,re.hidden=!i,e.classList.toggle("terminal-copy-mode-active",i),i&&s.focus()}function dt(){ee(!oe)}function Qt(i){j||i.button!==0||le||(oe||i.shiftKey)&&(i.preventDefault(),i.stopPropagation(),le=!0,E=ct(i.clientX,i.clientY),x=E,s.selectCells(E.col,E.row,x.col,x.row),document.addEventListener("mousemove",Ke,!0),document.addEventListener("mouseup",Ve,!0))}function Ke(i){j||!le||!E||(i.preventDefault(),i.stopPropagation(),x=ct(i.clientX,i.clientY),s.selectCells(E.col,E.row,x.col,x.row))}function Ve(i){if(j||!le||!E||!x)return;i.preventDefault(),i.stopPropagation(),document.removeEventListener("mousemove",Ke,!0),document.removeEventListener("mouseup",Ve,!0),le=!1;let o=s.getCellsText(E.col,E.row,x.col,x.row);E=null,x=null,s.clearSelection(),ee(!1),o&&($.textContent="\u5DF2\u590D\u5236",Ie(o).then(De)),s.focus()}e.addEventListener("mousedown",Qt,!0),document.addEventListener("keydown",en,!0);function en(i){if(!(j||!s.isFocused()||i.defaultPrevented||i.isComposing)){if(oe){if(i.key==="Escape"){i.preventDefault(),i.stopPropagation(),E=null,x=null,s.clearSelection(),ee(!1);return}if(i.key==="Enter"||(i.ctrlKey||i.metaKey)&&i.code==="KeyC"){i.preventDefault(),i.stopPropagation(),Ie(s.getScreenText()).then(De),ee(!1);return}}if(i.altKey&&i.code==="KeyC"&&!i.ctrlKey&&!i.metaKey){if(i.preventDefault(),i.stopPropagation(),E&&x){let o=s.getCellsText(E.col,E.row,x.col,x.row);E=null,x=null,s.clearSelection(),ee(!1),o&&($.textContent="Copied",Ie(o).then(De))}else{let o=s.getSelection();o?(s.clearSelection(),$.textContent="Copied",Ie(o).then(De)):dt()}return}if((i.ctrlKey||i.metaKey)&&i.code==="KeyV"){i.preventDefault(),i.stopPropagation(),(async()=>{try{if(navigator.clipboard?.read){let o=await navigator.clipboard.read();for(let d of o)for(let p of d.types)if(lt(p)){let v=await d.getType(p);await qe(v);return}}}catch{}try{let o=await navigator.clipboard?.readText();o&&s.pasteText(ut(o))}catch{}})();return}}}let Fe=0;function ut(i){return i.split(`\r
|
|
6
6
|
`).join(`
|
|
7
7
|
`).split(`
|
|
8
|
-
`).join("\r")}async function tn(i){let o=Zt(i.clipboardData);if(o){i.preventDefault(),i.stopPropagation();let
|
|
9
|
-
<span>${h(e.name)}</span>${n?"":'<span class="meta">offline</span>'}`,n&&s.addEventListener("click",l=>{l.target.closest(".session-edit-btn")||ge(e.name,t)}),s}function Tn(e){let t=document.createElement("div");t.className="session-item"+(e.name===
|
|
8
|
+
`).join("\r")}async function tn(i){let o=Zt(i.clipboardData);if(o){i.preventDefault(),i.stopPropagation();let v=Date.now();if(v-Fe<50)return;Fe=v,await qe(o);return}let d=i.clipboardData?.getData("text/plain");if(!d)return;i.preventDefault(),i.stopPropagation();let p=Date.now();p-Fe<50||(Fe=p,s.pasteText(ut(d)))}let de=0;function nn(i){i.preventDefault(),de++,rt(i.dataTransfer)&&e.classList.add("terminal-drag-over")}function sn(i){i.preventDefault(),i.dataTransfer&&(i.dataTransfer.dropEffect="copy")}function an(i){i.preventDefault(),de--,de<=0&&(de=0,e.classList.remove("terminal-drag-over"))}async function on(i){i.preventDefault(),de=0,e.classList.remove("terminal-drag-over");let o=rt(i.dataTransfer);o&&await qe(o)}function pt(i){!qt||i.key!=="Escape"||oe||i.defaultPrevented||i.repeat||i.metaKey||i.ctrlKey||i.altKey||s.isFocused()&&(i.preventDefault(),i.stopPropagation(),Q("\x1B"))}e.addEventListener("paste",tn),e.addEventListener("dragenter",nn),e.addEventListener("dragover",sn),e.addEventListener("dragleave",an),e.addEventListener("drop",on),document.addEventListener("keydown",pt,!0);function ln(i){if(i.touches.length!==1){a=null;return}let o=i.touches[0];if(!o)return;W();let d=e.getBoundingClientRect(),p=o.clientX-d.left<d.width*.4?"tui":"history",v=o.clientY-d.top<d.height*.5;a={startX:o.clientX,startY:o.clientY,lastX:o.clientX,lastY:o.clientY,lastT:performance.now(),velocity:0,scrolling:!1,zone:p,tuiUp:v,sent:!1},i.stopPropagation()}function rn(i){if(!a||i.touches.length!==1)return;let o=i.touches[0];if(!o)return;let d=o.clientY-a.startY,p=o.clientX-a.startX;if(!a.scrolling){if(Math.abs(d)<8||Math.abs(d)<Math.abs(p))return;a.scrolling=!0,ke=Date.now()+500}i.preventDefault(),i.stopPropagation();let v=performance.now(),A=o.clientY-a.lastY;if(a.zone==="tui"){a.sent||(a.sent=!0,Q(a.tuiUp?"\x1B[5~":"\x1B[6~"),se(a.tuiUp)),a.lastX=o.clientX,a.lastY=o.clientY,a.lastT=v;return}let V=v-a.lastT;V>0&&(a.velocity=A/V),pn(-A),a.lastX=o.clientX,a.lastY=o.clientY,a.lastT=v}function cn(i){if(!a)return;let o=a.scrolling,d=a.zone,p=a.tuiUp,v=a.velocity;if(a=null,i.stopPropagation(),d==="tui"){o||(Q(p?"\x1B[5~":"\x1B[6~"),se(p),ke=Date.now()+500,i.preventDefault());return}if(!o){s.focus();return}ke=Date.now()+500,i.preventDefault(),v&&Ut(v)}function dn(i){a=null,W(),i.stopPropagation()}function un(i){i.pointerType==="touch"&&Date.now()<ke&&(i.preventDefault(),i.stopPropagation())}function pn(i){let o=e.querySelector(".xterm-rows > div"),d=o?o.getBoundingClientRect().height:16,p=d>0?Math.round(i/d):i>0?1:-1;p===0&&(p=i>0?1:-1),s.scrollLines(p)}e.addEventListener("touchstart",ln,{passive:!0,capture:!0}),e.addEventListener("touchmove",rn,{passive:!1,capture:!0}),e.addEventListener("touchend",cn,{passive:!1,capture:!0}),e.addEventListener("touchcancel",dn,{passive:!0,capture:!0}),e.addEventListener("pointerup",un,!0);function ft(){T()}window.addEventListener("resize",ft),window.visualViewport?.addEventListener("resize",T),window.visualViewport?.addEventListener("scroll",T);let mt=new ResizeObserver(()=>T());mt.observe(e),document.fonts?.ready.then(()=>{T(),setTimeout(T,50),setTimeout(T,200)}),e.addEventListener("focusin",Jt,!0);async function fn(){if(document.fonts?.ready)try{await Promise.race([document.fonts.ready,new Promise(i=>setTimeout(i,1e3))])}catch{}}return requestAnimationFrame(()=>{K()&&Me(),(async()=>(await fn(),K()&&q({type:"resize",cols:s.cols,rows:s.rows}),ot(),T()))()}),{destroy(){if(j=!0,W(),ee(!1),ce&&clearTimeout(ce),document.removeEventListener("mousemove",Ke,!0),document.removeEventListener("mouseup",Ve,!0),l){try{l.close(1e3,"session switch")}catch{}l=void 0}e.innerHTML="",e.classList.remove("terminal-pending"),window.removeEventListener("resize",ft),mt.disconnect(),document.removeEventListener("keydown",pt,!0)},focus(){s.focus()},sendInput(i){Q(i)},toggleCopyMode(){dt()}}})()}var fe=window.__TMUX_WEB_SHELL__,g=null,y=null,me=typeof window.__TMUX_WEB_SCOPE__?.agentId=="string"?window.__TMUX_WEB_SCOPE__.agentId:null,B=me;window.__tmuxWebScopeAgent=me;var Je="sessions",U="",He="",Pe="",vt="";function C(e){return B?"/a/"+encodeURIComponent(B)+e:e}var m=document.getElementById("sidebar-content"),X=document.getElementById("main-placeholder"),I=document.getElementById("terminal-container"),he=document.getElementById("file-editor"),wn=document.getElementById("fe-path"),H=document.getElementById("fe-status"),ve=document.getElementById("fe-content"),J=document.getElementById("fe-save"),bn=document.getElementById("fe-delete"),En=document.getElementById("fe-back"),gt=document.getElementById("fe-new-name"),Ln=document.getElementById("fe-new-btn"),Ze=document.getElementById("settings-backdrop"),yt=document.getElementById("settings-popover"),wt=document.querySelector(".sidebar");function xn(){return window.matchMedia("(max-width: 640px)").matches}function Ge(){xn()&&wt.classList.add("collapsed")}function bt(){wt.classList.remove("collapsed")}document.getElementById("mode-sessions").addEventListener("click",()=>{bt(),Et("sessions")}),document.getElementById("mode-files").addEventListener("click",()=>{bt(),Et("files")});function Et(e){Je=e,document.querySelectorAll(".mode-btn").forEach(n=>n.classList.remove("active"));let t=document.getElementById(e==="sessions"?"mode-sessions":"mode-files");t&&t.classList.add("active"),e==="sessions"?(Qe="",_()):Rn()}var Qe="";async function _(){if(Je!=="sessions")return;try{let t=await(await fetch("/api/sidebar/sessions")).json(),n=JSON.stringify({recent:t.recent,agents:t.agents,tombstones:t.tombstones});if(n===Qe)return;Qe=n,Bn(t)}catch{m.innerHTML+='<div class="file-tree-empty">Failed to load sessions</div>'}let e=document.getElementById("ns-btn");e&&e.addEventListener("click",()=>{let t=window.__openNewSessionModal;typeof t=="function"?t():document.getElementById("new-session-modal")?.classList.add("open")}),at()}var Lt="tmux-web-sidebar-group-collapsed";function xt(){try{return new Set(JSON.parse(localStorage.getItem(Lt)||"[]"))}catch{return new Set}}function Cn(e){try{localStorage.setItem(Lt,JSON.stringify([...e]))}catch{}}function kn(e,t,n){if(!e)return"\u2026";let s=n&&(e===n||e.startsWith(n+"/"))?"~"+e.slice(n.length):e,l=s.split("/").filter(Boolean);if(l.length===0)return e;for(let r=1;r<=l.length;r++){let c=l.slice(-r).join("/");if(!t.some(a=>!a||a===e?!1:(n&&(a===n||a.startsWith(n+"/"))?"~"+a.slice(n.length):a).split("/").filter(Boolean).slice(-r).join("/")===c))return c}return s}function Ct(e,t,n,s=!0){let l=new Map;for(let a of e){let u=a.path||"";l.has(u)||l.set(u,[]),l.get(u).push(a)}let r=[...l.keys()],c=xt();for(let[a,u]of l){let f=kn(a,r,t),S=c.has(a),L=document.createElement("div");L.className="session-group-header"+(S?" collapsed":""),L.title=a||"No working directory",L.innerHTML=`<span class="sg-folder">📁</span><span class="sg-label">${h(f)}</span>`,L.addEventListener("click",()=>{let M=xt(),b=L.nextElementSibling;M.has(a)?(M.delete(a),L.classList.remove("collapsed"),b?.classList.remove("collapsed")):(M.add(a),L.classList.add("collapsed"),b?.classList.add("collapsed")),Cn(M)});let F=document.createElement("div");F.className="session-group-body"+(S?" collapsed":"");for(let M of u)F.appendChild(n?Sn(M,n,s):Tn(M));m.appendChild(L),m.appendChild(F)}}function Sn(e,t,n){let s=document.createElement("div");return s.className="session-item"+(e.name===y&&B===t?" active":"")+(n?"":" session-offline"),s.setAttribute("data-session",e.name),s.setAttribute("data-agent",t),s.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="${e.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>
|
|
9
|
+
<span>${h(e.name)}</span>${n?"":'<span class="meta">offline</span>'}`,n&&s.addEventListener("click",l=>{l.target.closest(".session-edit-btn")||ge(e.name,t)}),s}function Tn(e){let t=document.createElement("div");t.className="session-item"+(e.name===y&&!B?" active":""),t.setAttribute("data-session",e.name),t.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="${e.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>
|
|
10
10
|
<span>${h(e.name)}</span>
|
|
11
11
|
<button class="session-edit-btn" data-session="${h(e.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>
|
|
12
12
|
`,t.addEventListener("click",s=>{s.target.closest(".session-edit-btn")||ge(e.name)});let n=t.querySelector(".session-edit-btn");return n&&n.addEventListener("click",s=>{s.stopPropagation(),Pt(e.name,n)}),t}function Bn(e){m.innerHTML='<button class="new-session-sidebar-btn" id="ns-btn">+ New Session</button>';let t=e.recent||[],n=document.createElement("div");n.className="sidebar-section-label"+(me?" clickable":""),n.textContent=me?"\u2190 \u8FD4\u56DE\u672C\u673A":"\u672C\u673A",me&&(n.title="Back to hub",n.addEventListener("click",()=>{window.location.href="/"})),m.appendChild(n),Ct(t,e.home);let s=e.agents||[];for(let r of s){if(!r.sessions||r.sessions.length===0)continue;let c=r.agentId===B,a=document.createElement("div");a.className="sidebar-section-label machine-label"+(r.online?"":" agent-offline-label")+(!c&&r.online?" clickable":""),a.textContent=r.agentName+(r.online?"":" (offline)"),!c&&r.online&&(a.title="\u6253\u5F00 "+r.agentName,a.addEventListener("click",()=>{window.location.href="/a/"+encodeURIComponent(r.agentId)+"/"})),m.appendChild(a),Ct(r.sessions,e.home,r.agentId,r.online)}let l=e.tombstones||[];if(l.length>0){let r=document.createElement("div");r.className="sidebar-section-label tombstone-label",r.textContent="\u5931\u6548\u4F1A\u8BDD",m.appendChild(r);for(let c of l){let a=document.createElement("div");a.className="session-item session-tombstone",a.setAttribute("data-session",c.name),c.agentId&&a.setAttribute("data-agent",c.agentId);let u=c.agentId?c.agentOnline?" (agent)":" (agent \u79BB\u7EBF)":"";a.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="M4 6h16v2H4V6zm0 5h16v2H4v-2zm0 5h16v2H4v-2z"></svg>
|
|
13
13
|
<span>${h(c.name)}</span><span class="meta">\u5931\u6548${u}</span>
|
|
14
|
-
<button class="session-edit-btn" data-session="${h(c.name)}" title="\u6062\u590D\u4F1A\u8BDD"><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>`;let f=a.querySelector(".session-edit-btn");f&&f.addEventListener("click",S=>{S.stopPropagation(),Pt(c.name,f,{tombstone:!0,agentId:c.agentId})}),m.appendChild(a)}}}function h(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}async function ge(e,t){if(!(
|
|
14
|
+
<button class="session-edit-btn" data-session="${h(c.name)}" title="\u6062\u590D\u4F1A\u8BDD"><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>`;let f=a.querySelector(".session-edit-btn");f&&f.addEventListener("click",S=>{S.stopPropagation(),Pt(c.name,f,{tombstone:!0,agentId:c.agentId})}),m.appendChild(a)}}}function h(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}async function ge(e,t){if(!(y===e&&g&&B===(t||null))){he.style.display="none",X.style.display="none",I.style.display="",I.classList.add("terminal-pending"),Ge(),g&&(Ye(),g.destroy(),g=null),y=e,B=t||null,window.__tmuxWebScopeAgent=B,window.__tmuxWebCurrentSession=y,Xn(e,t);for(let n of m.querySelectorAll(".session-item"))n.classList.toggle("active",n.getAttribute("data-session")===e&&(n.getAttribute("data-agent")||null)===B);try{g=await yn(I,e,{terminal:fe.terminal,scrollback:fe.scrollback,theme:fe.theme,wsBase:B?"/ws/a/"+encodeURIComponent(B):fe.wsBase||"/ws"}),Ht()}catch(n){console.error("[shell] terminal init failed:",n);let s=n&&typeof n=="object"&&"message"in n?n.message:String(n);I.textContent="Failed to open terminal for "+e+": "+s,I.classList.remove("terminal-pending")}}}var Ne=[],w=null,kt=!1;function Mn(e){if(!w||!w.files.length)return null;let t=w.repoRoot;if(!t||!e.startsWith(t))return null;let n=e.slice(t.length+1);for(let s of w.files)if(s.path===n)return s.status;return null}async function In(e){kt=!0;try{let t=await fetch(C("/api/git/status?path="+encodeURIComponent(e)));t.ok?w=await t.json():w=null}catch{w=null}finally{kt=!1}}function Dn(){if(!w||!w.branch)return"";let{branch:e,linesAdded:t,linesRemoved:n}=w,s=`<div class="sidebar-git"><div class="git-branch-badge">
|
|
15
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>
|
|
16
|
-
${h(e)}</div>`;return(t>0||n>0)&&(s+=`<div class="git-diff-stats">+<span class="add">${t}</span> <span class="del">-${n}</span></div>`),s+"</div>"}m.addEventListener("click",e=>{e.target.closest(".sidebar-git")&&
|
|
16
|
+
${h(e)}</div>`;return(t>0||n>0)&&(s+=`<div class="git-diff-stats">+<span class="add">${t}</span> <span class="del">-${n}</span></div>`),s+"</div>"}m.addEventListener("click",e=>{e.target.closest(".sidebar-git")&&te&&w&&(e.stopPropagation(),It())});var ye=document.getElementById("header-git"),St=document.getElementById("git-diff-view"),Tt=document.getElementById("gd-path"),Re=document.getElementById("gd-status"),$e=document.getElementById("gd-content"),Fn=document.getElementById("gd-back"),te=null;function we(e){if(!e||!e.branch){ye.style.display="none",te=null;return}te=e.repoRoot;let{branch:t,linesAdded:n,linesRemoved:s}=e,l=`<span class="branch">${h(t)}</span>`;(n>0||s>0)&&(l+=`<span class="sep">\xB7</span>+<span class="diff-add">${n}</span> <span class="diff-del">-${s}</span>`),ye.innerHTML=l,ye.style.display="block"}ye.addEventListener("click",e=>{te&&w&&(e.stopPropagation(),It())});var k=document.getElementById("git-popover"),ze=document.getElementById("git-popover-backdrop");function et(){let e=ye.getBoundingClientRect();k.style.top=e.bottom+4+"px",k.style.left=Math.max(8,Math.min(e.left,window.innerWidth-400))+"px"}function Bt(){let e=te,t=document.getElementById("git-popover-browse");t&&t.addEventListener("click",()=>{if(Ue(),e){Je="files",document.querySelectorAll(".mode-btn").forEach(s=>s.classList.remove("active"));let n=document.getElementById("mode-files");n&&n.classList.add("active"),Y(e)}})}var Mt="";function It(){if(!w)return;let e=w.files||[];if(!e.length)k.innerHTML=`<div class="git-popover-header">No changes \u2014 clean working tree</div>
|
|
17
17
|
<div class="git-popover-footer"><button id="git-popover-browse">Browse repository \u2192</button></div>`;else{let t=`<div class="git-popover-header">${e.length} file${e.length>1?"s":""} changed</div>`;for(let n=0;n<e.length;n++){let s=e[n],l=s.additions||0,r=s.deletions||0,c="";switch(s.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}t+=`<div class="git-popover-item" data-idx="${n}">
|
|
18
18
|
${c}<span class="file-path">${h(s.path)}</span>
|
|
19
19
|
<span class="file-add">${l>0?"+"+l:""}</span>
|
|
20
20
|
<span class="file-del">${r>0?"-"+r:""}</span>
|
|
21
|
-
</div>`}t+='<div class="git-popover-footer"><button id="git-popover-browse">Browse repository \u2192</button></div>',Mt=t,k.innerHTML=t,k.querySelectorAll(".git-popover-item").forEach(n=>{let s=parseInt(n.dataset.idx||"0",10),l=e[s];!l||l.status==="D"||(n.classList.add("clickable"),n.style.cursor="pointer",n.addEventListener("click",()=>Ft(l.path)))})}et(),k.classList.add("open")
|
|
21
|
+
</div>`}t+='<div class="git-popover-footer"><button id="git-popover-browse">Browse repository \u2192</button></div>',Mt=t,k.innerHTML=t,k.querySelectorAll(".git-popover-item").forEach(n=>{let s=parseInt(n.dataset.idx||"0",10),l=e[s];!l||l.status==="D"||(n.classList.add("clickable"),n.style.cursor="pointer",n.addEventListener("click",()=>Ft(l.path)))})}et(),k.classList.add("open"),ze.classList.add("open"),Bt()}function An(){return window.innerWidth>=1024}function Dt(e,t){let n=(e+(t&&e?`
|
|
22
22
|
`:"")+t).split(`
|
|
23
|
-
`),s="",l=0,r=0;for(let c of n){let a=c;if(a.startsWith("@@")){let u=a.match(/@@\s+-(\d+)[^+]*\+(\d+)/);u&&(l=parseInt(u[1],10)-1,r=parseInt(u[2],10)-1),s+=`<div class="diff-line hunk"><span class="ln-body">${h(a)}</span></div>`;continue}if(a.startsWith("diff --git")||a.startsWith("index ")||a.startsWith("--- ")||a.startsWith("+++ ")||a.startsWith("new file")||a.startsWith("deleted file")){a.startsWith("diff --git")&&(s+=`<div class="diff-line header"><span class="ln-body">${h(a)}</span></div>`);continue}if(a.startsWith("+"))r++,s+=`<div class="diff-line add"><span class="ln-no">${r}</span><span class="ln-body">${h(a)}</span></div>`;else if(a.startsWith("-"))l++,s+=`<div class="diff-line del"><span class="ln-no">${l}</span><span class="ln-body">${h(a)}</span></div>`;else if(a.startsWith("\\"))s+=`<div class="diff-line"><span class="ln-body">${h(a)}</span></div>`;else{if(!a&&!l&&!r)continue;l++,r++,s+=`<div class="diff-line"><span class="ln-no">${l}</span><span class="ln-no" style="margin-right:12px">${r}</span><span class="ln-body">${h(a)}</span></div>`}}return{html:s,lineCount:n.length}}var
|
|
23
|
+
`),s="",l=0,r=0;for(let c of n){let a=c;if(a.startsWith("@@")){let u=a.match(/@@\s+-(\d+)[^+]*\+(\d+)/);u&&(l=parseInt(u[1],10)-1,r=parseInt(u[2],10)-1),s+=`<div class="diff-line hunk"><span class="ln-body">${h(a)}</span></div>`;continue}if(a.startsWith("diff --git")||a.startsWith("index ")||a.startsWith("--- ")||a.startsWith("+++ ")||a.startsWith("new file")||a.startsWith("deleted file")){a.startsWith("diff --git")&&(s+=`<div class="diff-line header"><span class="ln-body">${h(a)}</span></div>`);continue}if(a.startsWith("+"))r++,s+=`<div class="diff-line add"><span class="ln-no">${r}</span><span class="ln-body">${h(a)}</span></div>`;else if(a.startsWith("-"))l++,s+=`<div class="diff-line del"><span class="ln-no">${l}</span><span class="ln-body">${h(a)}</span></div>`;else if(a.startsWith("\\"))s+=`<div class="diff-line"><span class="ln-body">${h(a)}</span></div>`;else{if(!a&&!l&&!r)continue;l++,r++,s+=`<div class="diff-line"><span class="ln-no">${l}</span><span class="ln-no" style="margin-right:12px">${r}</span><span class="ln-body">${h(a)}</span></div>`}}return{html:s,lineCount:n.length}}var je=null;async function Ft(e){let t=te;if(t)if(Ue(),An()){I.style.display="none",g&&(Ye(),g.destroy(),g=null,je=y,y=null),we(null),he.style.display="none",X.style.display="none",St.style.display="flex",Tt.textContent=e,Re.textContent="Loading\u2026",$e.innerHTML="";try{let n=await fetch(C("/api/git/diff?path="+encodeURIComponent(t)+"&file="+encodeURIComponent(e)));if(!n.ok)throw new Error(await n.text());let s=await n.json();Pn(e,s.diff,s.stagedDiff)}catch(n){let s=n instanceof Error?n.message:String(n);Re.textContent="Error",$e.innerHTML=`<div class="diff-empty" style="padding:24px;text-align:center;color:var(--panel-muted)">Error: ${h(s)}</div>`}}else{k.innerHTML=`<div class="git-diff-view"><div class="diff-header">
|
|
24
24
|
<button class="diff-back">\u2190 Back</button>
|
|
25
25
|
<span class="diff-filename">${h(e)}</span>
|
|
26
26
|
<span class="diff-loading">Loading\u2026</span>
|
|
27
|
-
</div></div>`,et(),k.classList.add("open")
|
|
27
|
+
</div></div>`,et(),k.classList.add("open"),ze.classList.add("open");try{let n=await fetch(C("/api/git/diff?path="+encodeURIComponent(t)+"&file="+encodeURIComponent(e)));if(!n.ok)throw new Error(await n.text());let s=await n.json();Hn(e,s.diff,s.stagedDiff)}catch(n){let s=n instanceof Error?n.message:String(n);k.innerHTML=`<div class="git-diff-view"><div class="diff-header">
|
|
28
28
|
<button class="diff-back">\u2190 Back</button>
|
|
29
29
|
<span class="diff-filename">${h(e)}</span>
|
|
30
30
|
</div><div class="diff-empty">Error loading diff: ${h(s)}</div></div>`}}}function Hn(e,t,n){if(!t&&!n){k.innerHTML=`<div class="git-diff-view"><div class="diff-header">
|
|
@@ -34,7 +34,7 @@ var mn=/\x1b\](?:10|11|110|111|104)(?:;[^\x07\x1b]*)?\x1b?(?:\\|\x07)/g;function
|
|
|
34
34
|
<button class="diff-back">\u2190 Back</button>
|
|
35
35
|
<span class="diff-filename">${h(e)}</span>
|
|
36
36
|
<span class="diff-filesize">${l} lines</span>
|
|
37
|
-
</div><div class="diff-content">${s}</div></div>`,k.querySelector(".diff-back")?.addEventListener("click",()=>{k.innerHTML=Mt,et(),w&&k.querySelectorAll(".git-popover-item").forEach(r=>{let c=parseInt(r.dataset.idx||"0",10),a=w.files[c];!a||a.status==="D"||(r.style.cursor="pointer",r.addEventListener("click",()=>Ft(a.path)))}),Bt()})}function Pn(e,t,n){if(!t&&!n){Re.textContent="No diff"
|
|
37
|
+
</div><div class="diff-content">${s}</div></div>`,k.querySelector(".diff-back")?.addEventListener("click",()=>{k.innerHTML=Mt,et(),w&&k.querySelectorAll(".git-popover-item").forEach(r=>{let c=parseInt(r.dataset.idx||"0",10),a=w.files[c];!a||a.status==="D"||(r.style.cursor="pointer",r.addEventListener("click",()=>Ft(a.path)))}),Bt()})}function Pn(e,t,n){if(!t&&!n){Re.textContent="No diff",$e.innerHTML='<div class="diff-empty" style="padding:24px;text-align:center;color:var(--panel-muted)">No diff content available</div>';return}let{html:s,lineCount:l}=Dt(t,n);Tt.textContent=e,Re.textContent=l+" lines",$e.innerHTML=s}function Nn(){St.style.display="none",je?(I.style.display="",I.classList.add("terminal-pending"),ge(je),je=null):y?(I.style.display="",I.classList.add("terminal-pending"),Ht()):X.style.display="flex"}Fn.addEventListener("click",Nn);function Ue(){k.classList.remove("open"),ze.classList.remove("open")}ze.addEventListener("click",Ue),document.addEventListener("keydown",e=>{e.key==="Escape"&&(Ue(),We())});async function At(e){try{let t=await(await fetch("/api/fs/session-path?session="+encodeURIComponent(e))).json();if(t.path){let n=await fetch("/api/git/status?path="+encodeURIComponent(t.path));if(n.ok){let s=await n.json();w=s,we(s);return}}}catch{}w=null,we(null)}var _e=null;function Ht(){Ye(),y&&(At(y),_e=setInterval(()=>{y&&At(y)},3e4))}function Ye(){_e&&(clearInterval(_e),_e=null)}function Rn(){if(Ne=fe.fsRoots||[],Ne.length===0){if(y){$n(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 e of Ne){let t=document.createElement("div");t.className="file-tree-item",t.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> ${h(e)}`,t.addEventListener("click",()=>Y(e)),m.appendChild(t)}}async function $n(e){m.innerHTML='<div class="file-tree-empty">Loading...</div>';try{let t=await(await fetch(C("/api/fs/session-path?session="+encodeURIComponent(e)))).json();t.path?Y(t.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 Y(e){U=e,m.innerHTML='<div class="file-tree-empty">Loading...</div>';let t=In(e);try{let n=await(await fetch(C("/api/fs/list?path="+encodeURIComponent(e)))).json();await t,m.innerHTML="",we(w),m.innerHTML+=Dn();let s=zn(e);if(s&&!Ne.some(r=>e===r)){let r=document.createElement("div");r.className="file-tree-item",r.innerHTML="..",r.addEventListener("click",()=>Y(s)),m.appendChild(r)}if(n.dirs)for(let r of n.dirs){let c=r.split("/").pop()||r.split("\\").pop(),a=document.createElement("div");a.className="file-tree-item",a.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> ${h(c)}`,a.addEventListener("click",()=>Y(r)),m.appendChild(a)}else m.innerHTML="";let l=n.files||[];for(let r of l){let c=r.split("/").pop()||r.split("\\").pop(),a=Mn(r),u="",f="";if(a)switch(a){case"M":u="git-mod",f='<span class="git-file-status M">M</span>';break;case"A":u="git-add",f='<span class="git-file-status A">A</span>';break;case"D":u="git-del",f='<span class="git-file-status D">D</span>';break;case"?":u="git-untracked",f='<span class="git-file-status ?">?</span>';break;case"R":u="git-mod",f='<span class="git-file-status R">R</span>';break}let S=document.createElement("div");S.className="file-tree-item file"+(u?" "+u:""),S.innerHTML=`<span class="file-icon">\u{1F4C4}</span> ${f}${h(c)}`,S.addEventListener("click",()=>jn(r)),m.appendChild(S)}}catch{m.innerHTML='<div class="file-tree-error">Failed to load directory</div>'}}function zn(e){let t=e.lastIndexOf("/");return t<=0?null:e.substring(0,t)}async function jn(e){He=e,I.style.display="none",g&&(Ye(),g.destroy(),g=null,y=null),we(null),Ge(),X.style.display="none",he.style.display="flex",wn.textContent=e,H.textContent="Loading...",J.style.display="none";try{let t=await fetch(C("/api/file?path="+encodeURIComponent(e)));if(!t.ok){let s=await t.json();H.textContent=s.error||"Failed to load",ve.value="";return}let n=await t.json();ve.value=n.content,Pe=n.content,vt=n.content,H.textContent=n.size+" bytes",J.style.display=""}catch{H.textContent="Failed to load",ve.value=""}}ve.addEventListener("input",()=>{Pe=ve.value}),J.addEventListener("click",async()=>{J.textContent="Saving...",J.disabled=!0;try{let e=await fetch(C("/api/file"),{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:He,content:Pe})});if(!e.ok){let t=await e.json();H.textContent=t.error||"Save failed";return}vt=Pe,H.textContent="Saved"}catch{H.textContent="Save failed"}finally{J.disabled=!1,J.textContent="Save"}}),bn.addEventListener("click",async()=>{if(confirm("Delete "+He+"?"))try{let e=await fetch(C("/api/file/delete"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:He})});if(!e.ok){let t=await e.json();H.textContent=t.error||"Delete failed";return}he.style.display="none",X.style.display="flex",U&&Y(U)}catch{H.textContent="Delete failed"}}),En.addEventListener("click",()=>{he.style.display="none",X.style.display="flex",U&&Y(U)}),Ln.addEventListener("click",async()=>{let e=gt.value.trim();if(!e)return;let t=U+"/"+e;try{let n=await fetch(C("/api/file/touch"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:t})});if(!n.ok){let s=await n.json();H.textContent=s.error||"Create failed";return}gt.value="",U&&Y(U)}catch{H.textContent="Create failed"}}),document.getElementById("mode-settings").addEventListener("click",()=>{let e=yt.classList.toggle("open");Ze.classList.toggle("open",e)}),Ze.addEventListener("click",()=>{yt.classList.remove("open"),Ze.classList.remove("open")});var D="",z=!1,Oe,be=document.createElement("div");be.className="session-popover-backdrop",document.body.appendChild(be);var P=document.createElement("div");P.id="session-popover",P.className="session-popover",P.style.display="none",P.innerHTML=`<div class="sp-field">
|
|
38
38
|
<label>Rename session</label>
|
|
39
39
|
<input type="text" id="sp-name" />
|
|
40
40
|
</div>
|
|
@@ -44,5 +44,5 @@ var mn=/\x1b\](?:10|11|110|111|104)(?:;[^\x07\x1b]*)?\x1b?(?:\\|\x07)/g;function
|
|
|
44
44
|
</div>
|
|
45
45
|
<hr class="sp-divider" />
|
|
46
46
|
<button class="btn primary" id="sp-rebuild" style="display:none">\u91CD\u5EFA\u540C\u540D\u540C\u8DEF\u5F84 session</button>
|
|
47
|
-
<button class="btn danger" id="sp-delete">Delete session</button>`,document.body.appendChild(P);function
|
|
48
|
-
`).length;
|
|
47
|
+
<button class="btn danger" id="sp-delete">Delete session</button>`,document.body.appendChild(P);function Un(e){let t=e.getBoundingClientRect();P.style.top=t.bottom+4+"px",P.style.left=Math.max(8,Math.min(t.left,window.innerWidth-240))+"px"}function Pt(e,t,n){D=e,z=!!n?.tombstone,Oe=n?.agentId;let s=document.getElementById("sp-name");s.value=e;let l=P.querySelector(".sp-field label");l.textContent=z?"\u91CD\u547D\u540D (\u4EC5\u8BB0\u5F55\uFF0C\u4E0D\u91CD\u5EFA)":"Rename session";let r=document.getElementById("sp-rebuild");r.style.display=z?"":"none";let c=document.getElementById("sp-delete");c.textContent=z?"\u5220\u9664\u5931\u6548\u8BB0\u5F55 (\u5893\u7891\u6D88\u5931)":"Delete session";let a=document.getElementById("sp-save");a.textContent=z?"\u91CD\u547D\u540D":"Save",be.classList.add("open"),P.style.display="block",Un(t),setTimeout(()=>s.focus(),50)}function Z(){be.classList.remove("open"),P.style.display="none"}be.addEventListener("click",Z),document.getElementById("sp-save").addEventListener("click",async()=>{let e=document.getElementById("sp-name").value.trim();if(!e||e===D){Z();return}try{let t=z?{oldName:D,newName:e,agentId:Oe}:{oldName:D,newName:e};if(!(await fetch(C(z?"/api/sessions/rename-tombstone":"/api/sessions/rename"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})).ok)return;Z(),_(),!z&&y===D&&ge(e)}catch{}}),document.getElementById("sp-rebuild").addEventListener("click",async()=>{if(confirm('\u91CD\u5EFA\u4F1A\u8BDD "'+D+'" (\u540C\u540D\u540C\u8DEF\u5F84\uFF0C\u5185\u5BB9\u4E3A\u7A7A)\uFF1F'))try{let e=await fetch(C("/api/sessions/rebuild"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:D,agentId:Oe})});if(!e.ok){let t=await e.json();alert(t.error||"\u91CD\u5EFA\u5931\u8D25");return}Z(),_()}catch{}}),document.getElementById("sp-delete").addEventListener("click",async()=>{if(z){if(!confirm('\u5220\u9664\u5931\u6548\u8BB0\u5F55 "'+D+'"\uFF1F'))return;try{if(!(await fetch(C("/api/sessions/dismiss"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:D,agentId:Oe})})).ok)return;Z(),_()}catch{}return}if(confirm('Delete session "'+D+'"?'))try{if(!(await fetch(C("/api/sessions/kill"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:D})})).ok)return;Z(),y===D&&(g&&(g.destroy(),g=null),y=null,I.style.display="none",X.style.display="flex"),_()}catch{}}),document.getElementById("sp-cancel").addEventListener("click",Z);var _n={esc:"\x1B",tab:" ","s-tab":"\x1B[Z",up:"\x1B[A",down:"\x1B[B",left:"\x1B[D",right:"\x1B[C",space:" ",enter:"\r","ctrl-r":"","ctrl-c":"",btw:"/btw ",yes:"yes\r"};document.getElementById("mobile-keys").addEventListener("click",e=>{let t=e.target.closest("button[data-key]");if(!t||!g)return;let n=_n[t.dataset.key];n&&(g.sendInput(n),g.focus())});var N=document.getElementById("mk-input"),Nt=document.getElementById("mk-send");function Rt(){if(!N||!g)return;let e=N.value;e&&(g.sendInput(e+"\r"),N.value="",N.rows=1,g.focus())}if(N&&(N.addEventListener("input",()=>{N.rows=1;let e=N.value.split(`
|
|
48
|
+
`).length;N.rows=Math.min(e,4)}),N.addEventListener("keydown",e=>{e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),Rt())})),Nt&&Nt.addEventListener("click",Rt),window.visualViewport){let e=document.querySelector(".app-layout"),t=()=>{e&&(e.style.height=window.visualViewport.height+"px"),window.scrollTo(0,0),document.documentElement.scrollTop=0,document.body.scrollTop=0};window.visualViewport.addEventListener("resize",t),window.addEventListener("orientationchange",()=>setTimeout(t,100)),document.addEventListener("touchstart",()=>{(window.scrollY>0||document.documentElement.scrollTop>0)&&window.scrollTo(0,0)},{passive:!0})}var tt=document.getElementById("process-panel"),Ee=document.getElementById("proc-list"),Yn=document.getElementById("proc-close"),nt=document.getElementById("proc-backdrop"),On=document.getElementById("header-ram");function Wn(){Ee.innerHTML='<div class="proc-empty">Loading\u2026</div>',fetch(C("/api/system/processes")).then(e=>e.json()).then(e=>{if(!Array.isArray(e)||!e.length){Ee.innerHTML='<div class="proc-empty">No processes</div>';return}let t="";for(let n of e){let s=n.rss,l=s<1048576?(s/1024).toFixed(0)+"K":(s/1048576).toFixed(1)+"M";t+='<div class="proc-row" data-pid="'+n.pid+'"><span class="proc-mem">'+n.mem+'%</span><span class="proc-rss">'+l+'</span><span class="proc-cmd" title="'+h(n.command)+'">'+h(n.command)+'</span><button class="proc-kill" title="Kill PID '+n.pid+'">×</button></div>'}Ee.innerHTML=t;for(let n of Ee.querySelectorAll(".proc-row")){let s=n.querySelector(".proc-kill");s&&s.addEventListener("click",l=>{let r=l.target.closest(".proc-row");!r||!confirm("Kill PID "+r.dataset.pid+"?")||fetch(C("/api/system/kill"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({pid:parseInt(r.dataset.pid,10)})}).then(c=>c.json()).then(c=>{c.ok?r.style.opacity="0.3":alert("Failed: "+(c.error||"unknown"))}).catch(()=>alert("Network error"))})}}).catch(()=>{Ee.innerHTML='<div class="proc-empty">Failed to load</div>'})}function qn(){tt.classList.add("open"),nt.classList.add("open"),Wn()}function We(){tt.classList.remove("open"),nt.classList.remove("open")}On.addEventListener("click",e=>{e.stopPropagation(),tt.classList.contains("open")?We():qn()}),Yn.addEventListener("click",We),nt.addEventListener("click",We);var Kn=2e3,Le=null,st=null,ne=new Map,xe=new Map;function $t(e,t){return(t?"a:"+t+":":"l:")+e}function Vn(e,t,n){let s=$t(e,t),l=xe.get(s),r=e===y&&(t??null)===B,c=n==="idle"&&l?.state==="working";xe.set(s,{session:e,agentId:t,state:n,doneUntil:c?Date.now()+Kn:void 0,unread:c?!r:!1});let a=t?'.session-item[data-agent="'+CSS.escape(t)+'"][data-session="'+CSS.escape(e)+'"]':'.session-item[data-session="'+CSS.escape(e)+'"]:not([data-agent])',u=m.querySelector(a);u&&it(u,s,xe.get(s))}function it(e,t,n){let s=ne.get(t);s&&(clearTimeout(s),ne.delete(t)),e.classList.remove("working","just-done");let l=n.session===y&&(n.agentId??null)===B;n.state==="working"?e.classList.add("working"):l&&n.doneUntil&&Date.now()<n.doneUntil?(e.classList.add("just-done"),ne.set(t,setTimeout(()=>{e.classList.remove("just-done"),ne.delete(t)},Math.max(0,n.doneUntil-Date.now())))):!l&&n.unread&&e.classList.add("just-done")}function at(){for(let[e,t]of xe){let n=t.agentId?'.session-item[data-agent="'+CSS.escape(t.agentId)+'"][data-session="'+CSS.escape(t.session)+'"]':'.session-item[data-session="'+CSS.escape(t.session)+'"]:not([data-agent])',s=m.querySelector(n);s&&it(s,e,t)}}function Xn(e,t){let n=$t(e,t),s=xe.get(n);if(!s)return;let l=ne.get(n);l&&(clearTimeout(l),ne.delete(n)),s.doneUntil=void 0,s.unread=!1;let r=t?'.session-item[data-agent="'+CSS.escape(t)+'"][data-session="'+CSS.escape(e)+'"]':'.session-item[data-session="'+CSS.escape(e)+'"]:not([data-agent])',c=m.querySelector(r);c&&it(c,n,s)}function zt(){if(Le||st)return;let e=localStorage.getItem("tmux-web-token"),t=(location.protocol==="https:"?"wss:":"ws:")+"//"+location.host+"/ws/activity";e&&(t+="?token="+encodeURIComponent(e));try{let n=new WebSocket(t);Le=n,n.onmessage=s=>{try{let l=JSON.parse(String(s.data));l&&l.type==="session.activity"&&typeof l.session=="string"&&Vn(l.session,l.agentId||void 0,l.state==="working"?"working":"idle")}catch{}},n.onclose=()=>{Le===n&&(Le=null,st=setTimeout(()=>{st=null,zt()},5e3))},n.onerror=()=>{try{n.close()}catch{}}}catch{Le=null}}window.__openSession=ge,window.__refreshSidebar=_,_(),Ge(),at(),zt(),document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&at()}),setInterval(()=>{document.visibilityState==="visible"&&_()},1e4);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const Ht=/\x1b\](?:10|11|110|111|104)(?:;[^\x07\x1b]*)?\x1b?(?:\\|\x07)/g;function rt(
|
|
2
|
-
`)}selectRows(o,r){const n=this.terminal.buffer.active,[l,d]=o<=r?[o,r]:[r,o];this.terminal.selectLines(n.viewportY+l,n.viewportY+d)}selectCells(o,r,n,l){const d=this.terminal.buffer.active,m=Math.min(r,l),
|
|
3
|
-
`)}getSelection(){return this.terminal.getSelection()}clearSelection(){this.terminal.clearSelection()}hasSelectionSupport(){return!0}}function _t(
|
|
1
|
+
const Ht=/\x1b\](?:10|11|110|111|104)(?:;[^\x07\x1b]*)?\x1b?(?:\\|\x07)/g;function rt(a){return a.replace(/\x1b\[\?1049[hl]/g,"")}function H(a){return a.replace(Ht,"")}let N;function Nt(){return N||(document.querySelector("link[data-tmux-web-xterm-css]")?N=Promise.resolve():(N=new Promise(o=>{const r=document.createElement("link");r.rel="stylesheet",r.href="/assets/xterm.css",r.setAttribute("data-tmux-web-xterm-css",""),r.addEventListener("load",()=>o(),{once:!0}),r.addEventListener("error",()=>o(),{once:!0}),document.head.appendChild(r)}),N))}class st{terminal;fitAddon;container;constructor(o,r,n){this.container=o,this.terminal=r,this.fitAddon=n,this.terminal.loadAddon(this.fitAddon),this.terminal.open(o)}static async create(o,r,n){const[{Terminal:l},{FitAddon:d}]=await Promise.all([import("@xterm/xterm"),import("@xterm/addon-fit"),Nt()]),m=new l({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:r,convertEol:!1,smoothScrollDuration:120,theme:n});return new st(o,m,new d)}get cols(){return this.terminal.cols}get rows(){return this.terminal.rows}write(o){return new Promise(r=>this.terminal.write(o,r))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom()}scrollToLine(o,r=!1){this.terminal.scrollToLine(Math.max(0,o),r)}scrollLines(o){const r=this.terminal.buffer?.active;this.terminal.scrollLines(o)}isNearScrollbackTop(){return this.terminal.buffer.active.viewportY<=1}viewportY(){return this.terminal.buffer.active.viewportY}baseY(){return this.terminal.buffer.active.baseY}fit(){const o=_t(this.container);if(o.width<=0||o.height<=0)return!1;const n=this.terminal._core?._renderService?.dimensions?.css?.cell;if(!n?.width||!n?.height)return this.fitAddon.fit(),!0;const l=n.width,d=n.height,m=this.terminal.element?.querySelector(".xterm-viewport"),s=m?Math.max(0,m.offsetWidth-m.clientWidth):0,f=Math.max(2,Math.floor((o.width-s)/l)),p=Math.max(2,Math.floor(o.height/d));return(f!==this.terminal.cols||p!==this.terminal.rows)&&this.terminal.resize(f,p),!0}focus(){this.terminal.focus()}pasteText(o){this.terminal.paste(o)}input(o){this.terminal.input(o,!1)}onData(o){this.terminal.onData(o),this.terminal.onBinary(o)}onResize(o){this.terminal.onResize(o)}onScroll(o){this.terminal.onScroll(o)}attachCustomKeyEventHandler(o){this.terminal.attachCustomKeyEventHandler(o)}isFocused(){const o=document.activeElement;return o?o===this.container||o===this.terminal.textarea||this.container.contains(o)||!!o.closest?.(".xterm"):!1}getScreenText(){return this.getRowsText(0,this.terminal.rows-1)}getRowsText(o,r){const n=this.terminal.buffer.active,[l,d]=o<=r?[o,r]:[r,o],m=n.viewportY,s=[];for(let f=l;f<=d;f++){const p=n.getLine(m+f);s.push(p?p.translateToString(!0):"")}return s.join(`
|
|
2
|
+
`)}selectRows(o,r){const n=this.terminal.buffer.active,[l,d]=o<=r?[o,r]:[r,o];this.terminal.selectLines(n.viewportY+l,n.viewportY+d)}selectCells(o,r,n,l){const d=this.terminal.buffer.active,m=Math.min(r,l),s=Math.max(r,l);if(m===s){const f=Math.min(o,n),p=Math.max(o,n);this.terminal.select(f,d.viewportY+m,p-f+1)}else this.terminal.selectLines(d.viewportY+m,d.viewportY+s)}getCellsText(o,r,n,l){const d=this.terminal.buffer.active,m=Math.min(r,l),s=Math.max(r,l),f=r<l?o:r>l?n:Math.min(o,n),p=r<l?n:r>l?o:Math.max(o,n),et=d.viewportY,P=[];for(let L=m;L<=s;L++){const _=d.getLine(et+L);if(!_){P.push("");continue}const w=L===m?f:0,M=L===s?p:this.terminal.cols-1;let F="";for(let q=w;q<=M;q++){const C=_.getCell(q);C&&(F+=C.getChars())}P.push(F.replace(/\s+$/,""))}return P.join(`
|
|
3
|
+
`)}getSelection(){return this.terminal.getSelection()}clearSelection(){this.terminal.clearSelection()}hasSelectionSupport(){return!0}}function _t(a){const o=a.getBoundingClientRect(),r=window.visualViewport;return r?{width:Math.min(o.width,r.width),height:Math.max(0,Math.min(o.height,r.height-Math.max(0,o.top)))}:o}function qt(a,o,r){return a.innerHTML="",a.classList.add("terminal-pending"),(async()=>{const n=await st.create(a,r.scrollback,r.theme);let l,d=0,m,s=null,f=0,p=0;const et=.2,P=10,L=.95,_=.04;let w=null,M=null;function F(t){w||(w=document.createElement("div"),w.style.cssText=["position:absolute","left:0","width:40%","padding:10px 0","text-align:center","font:600 14px/1.4 system-ui, -apple-system, sans-serif","color:rgba(255,255,255,0.95)","background:rgba(20,30,50,0.55)","border:1px solid rgba(255,255,255,0.25)","border-radius:10px","pointer-events:none","opacity:0","transition:opacity 0.15s ease","z-index:6"].join(";"),a.appendChild(w)),w.textContent=t?"\u2191 \u4E0A\u7FFB\u4E00\u9875 (PgUp)":"\u2193 \u4E0B\u7FFB\u4E00\u9875 (PgDn)",w.style.top=t?"10%":"auto",w.style.bottom=t?"auto":"10%",w.style.opacity="1",M&&clearTimeout(M),M=setTimeout(()=>{w&&(w.style.opacity="0")},900)}function q(){M&&clearTimeout(M),w&&(w.style.opacity="0")}function C(){f&&(cancelAnimationFrame(f),f=0),p=0}function gt(t){if(C(),Math.abs(t)<et)return;p=Math.max(-P,Math.min(P,t));const e=()=>{if(E){f=0;return}const i=a.querySelector(".xterm-rows > div"),u=i?i.getBoundingClientRect().height:16;let c=u>0?Math.round(p*16/u):p>0?1:-1;c===0&&(c=p>0?1:-1);const v=n.viewportY()-c,tt=n.baseY(),R=Math.max(0,Math.min(v,tt));if(n.scrollToLine(R,!0),p*=L,R!==v){f=0;return}if(Math.abs(p)<_){f=0;return}f=requestAnimationFrame(e)};f=requestAnimationFrame(e)}let j=0,x="connecting",V=0,A=!1,W=[],k="",E=!1,z=1e3;const wt=location.protocol==="https:"?"wss:":"ws:",yt=r.wsBase||"/ws",vt=wt+"//"+location.host+yt+"/"+encodeURIComponent(o),xt="/api/session/"+encodeURIComponent(o)+"/upload",Tt=/^((?!chrome|android|crios|fxios|edgios).)*safari/i.test(navigator.userAgent);function bt(){return W.join("")+k}async function Et(t,e=0){const i=t?n.viewportY():0,u=H(bt());if(n.reset(),!u){t||n.scrollToBottom();return}await n.write(u),t?n.scrollToLine(e+i):n.scrollToBottom()}function S(t){l?.readyState===WebSocket.OPEN&&l.send(JSON.stringify(t))}function Lt(t){let e;try{e=JSON.parse(t)}catch{x==="live"&&(k+=t,n.write(H(t)));return}if(e.type==="auth.required"){const i=localStorage.getItem("tmux-web-token");i?S({type:"auth.token",token:i}):location.href="/login?returnTo="+encodeURIComponent(location.pathname+location.search);return}if(e.type==="attach_failed"&&typeof e.message=="string"){J=!0,x="dead",n.reset(),n.write(`\r
|
|
4
4
|
\x1B[31m`+H(e.message)+`\x1B[0m\r
|
|
5
|
-
`).then(()=>{
|
|
5
|
+
`).then(()=>{G();try{l?.close()}catch{}});return}if(e.type==="auth.ok"){e.token&&localStorage.setItem("tmux-web-token",e.token),z=1e3,D(),S({type:"resize",cols:n.cols,rows:n.rows}),y();return}if(e.type==="auth.failed"){if(e.permanentLock||e.retryAfterMs&&e.retryAfterMs>6e4){localStorage.removeItem("tmux-web-token"),location.href="/login?error="+encodeURIComponent(e.message);return}return}if(e.type==="snapshot"&&typeof e.data=="string"){const i=rt(H(e.data));W=[i],k="",V=typeof e.lines=="number"?e.lines:r.terminal.initialLines,x="live",n.reset(),D(),S({type:"resize",cols:n.cols,rows:n.rows}),n.write(i).then(()=>n.scrollToBottom());return}if(e.type==="window_changed"&&typeof e.activeIndex=="number"){const i=new URL(location.href);i.searchParams.get("window")!==String(e.activeIndex)&&(i.searchParams.set("window",String(e.activeIndex)),history.replaceState(history.state,"",i)),window.dispatchEvent(new CustomEvent("tmux:windows",{detail:e.windows}));return}if(e.type==="history"&&typeof e.data=="string"){e.lines>0&&e.data?(W.unshift(rt(e.data)),V+=e.lines,Et(!0,e.lines).finally(()=>{A=!1})):A=!1;return}if(e.type==="data"&&typeof e.data=="string"){const i=rt(H(e.data));if(x==="connecting"){x="live",k=i,n.write(i);return}x==="live"&&(k+=i,n.write(i))}}let J=!1;function at(){if(J)return;let t=vt;const e=localStorage.getItem("tmux-web-token");e&&(t+=(t.includes("?")?"&":"?")+"token="+encodeURIComponent(e)),t+=(t.includes("?")?"&":"?")+"cols="+n.cols+"&rows="+n.rows,l=new WebSocket(t),l.onopen=()=>{x="connecting",V=0,A=!1,W=[],k="",n.reset(),z=1e3},l.onmessage=i=>{typeof i.data=="string"&&Lt(i.data)},l.onclose=()=>{E||(x="connecting",!J&&setTimeout(()=>{z=Math.min(z*2,1e4),!E&&!J&&at()},z))},l.onerror=()=>l?.close()}function I(t){S({type:"input",data:t})}function D(){return n.fit()}function G(){a.classList.remove("terminal-pending")}function y(){d&&cancelAnimationFrame(d),m&&clearTimeout(m),D(),d=requestAnimationFrame(()=>{d=0,D()&&G()}),m=setTimeout(()=>{D()&&G()},120)}function Mt(){y(),setTimeout(y,50),setTimeout(y,150),setTimeout(y,300)}function lt(t){return typeof t=="string"&&t.startsWith("image/")}function ct(t){return t?.files?.length?t.files[0]??null:null}function Ct(t){if(!t?.items)return null;for(let e=0;e<t.items.length;e++){const i=t.items[e];if(i?.kind==="file"&<(i.type))return i.getAsFile()}return null}async function St(t){const e=new FormData,i=t instanceof File&&t.name?t.name:"upload";e.append("file",t,i);const u=localStorage.getItem("tmux-web-token"),c={};u&&(c.Authorization="Bearer "+u);const b=await fetch(xt,{method:"POST",body:e,headers:c});if(!b.ok){let tt="upload failed";try{const R=await b.json();R.error&&(tt=R.error)}catch{}throw new Error(tt)}const v=await b.json();if(!v.path)throw new Error("no path in response");return v.path}async function nt(t){try{const e=await St(t);I(e)}catch{}}n.onData(t=>I(t)),n.onResize(({cols:t,rows:e})=>S({type:"resize",cols:t,rows:e})),n.onScroll(()=>{x!=="live"||A||!n.isNearScrollbackTop()||(A=!0,S({type:"load_history",before:V}))});let B=!1,K=!1,h=null,g=null;const U=document.createElement("div");U.className="terminal-copy-banner",U.innerHTML='<strong>Copy mode</strong><span class="hint">drag to copy \xB7 Esc exits</span>',U.hidden=!0,a.appendChild(U);const T=document.createElement("div");T.className="terminal-copy-banner terminal-copy-toast",T.textContent="Copied",T.hidden=!0,a.appendChild(T);function ut(t,e){const i=a.querySelector(".xterm-screen, canvas"),c=(i&&i.getBoundingClientRect().width>0?i:a).getBoundingClientRect(),b=c.height>0&&n.rows>0?c.height/n.rows:18,v=c.width>0&&n.cols>0?c.width/n.cols:9;return{row:Math.max(0,Math.min(n.rows-1,Math.floor((e-c.top)/b))),col:Math.max(0,Math.min(n.cols-1,Math.floor((t-c.left)/v)))}}async function $(t){if(!t)return;try{if(navigator.clipboard?.writeText){await navigator.clipboard.writeText(t);return}}catch{}const e=document.createElement("textarea");e.value=t,e.style.position="fixed",e.style.opacity="0",e.style.pointerEvents="none",document.body.appendChild(e),e.focus(),e.select();try{document.execCommand("copy")}catch{}e.remove()}let X;function Q(){T.hidden=!1,X&&clearTimeout(X),X=setTimeout(()=>{T.hidden=!0},1e3)}function Y(t){B=t,U.hidden=!t,a.classList.toggle("terminal-copy-mode-active",t),t&&n.focus()}function ft(){Y(!B)}function Dt(t){E||t.button!==0||K||(B||t.shiftKey)&&(t.preventDefault(),t.stopPropagation(),K=!0,h=ut(t.clientX,t.clientY),g=h,n.selectCells(h.col,h.row,g.col,g.row),document.addEventListener("mousemove",ot,!0),document.addEventListener("mouseup",it,!0))}function ot(t){E||!K||!h||(t.preventDefault(),t.stopPropagation(),g=ut(t.clientX,t.clientY),n.selectCells(h.col,h.row,g.col,g.row))}function it(t){if(E||!K||!h||!g)return;t.preventDefault(),t.stopPropagation(),document.removeEventListener("mousemove",ot,!0),document.removeEventListener("mouseup",it,!0),K=!1;const e=n.getCellsText(h.col,h.row,g.col,g.row);h=null,g=null,n.clearSelection(),Y(!1),e&&(T.textContent="\u5DF2\u590D\u5236",$(e).then(Q)),n.focus()}a.addEventListener("mousedown",Dt,!0),document.addEventListener("keydown",Pt,!0);function Pt(t){if(!(E||!n.isFocused()||t.defaultPrevented||t.isComposing)){if(B){if(t.key==="Escape"){t.preventDefault(),t.stopPropagation(),h=null,g=null,n.clearSelection(),Y(!1);return}if(t.key==="Enter"||(t.ctrlKey||t.metaKey)&&t.code==="KeyC"){t.preventDefault(),t.stopPropagation(),$(n.getScreenText()).then(Q),Y(!1);return}}if(t.altKey&&t.code==="KeyC"&&!t.ctrlKey&&!t.metaKey){if(t.preventDefault(),t.stopPropagation(),h&&g){const e=n.getCellsText(h.col,h.row,g.col,g.row);h=null,g=null,n.clearSelection(),Y(!1),e&&(T.textContent="Copied",$(e).then(Q))}else{const e=n.getSelection();e?(n.clearSelection(),T.textContent="Copied",$(e).then(Q)):ft()}return}if((t.ctrlKey||t.metaKey)&&t.code==="KeyV"){t.preventDefault(),t.stopPropagation(),(async()=>{try{if(navigator.clipboard?.read){const e=await navigator.clipboard.read();for(const i of e)for(const u of i.types)if(lt(u)){const c=await i.getType(u);await nt(c);return}}}catch{}try{const e=await navigator.clipboard?.readText();e&&n.pasteText(dt(e))}catch{}})();return}}}let Z=0;function dt(t){return t.split(`\r
|
|
6
6
|
`).join(`
|
|
7
7
|
`).split(`
|
|
8
|
-
`).join("\r")}async function kt(t){const e=Ct(t.clipboardData);if(e){t.preventDefault(),t.stopPropagation();const
|
|
8
|
+
`).join("\r")}async function kt(t){const e=Ct(t.clipboardData);if(e){t.preventDefault(),t.stopPropagation();const c=Date.now();if(c-Z<50)return;Z=c,await nt(e);return}const i=t.clipboardData?.getData("text/plain");if(!i)return;t.preventDefault(),t.stopPropagation();const u=Date.now();u-Z<50||(Z=u,n.pasteText(dt(i)))}let O=0;function It(t){t.preventDefault(),O++,ct(t.dataTransfer)&&a.classList.add("terminal-drag-over")}function Yt(t){t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="copy")}function Ft(t){t.preventDefault(),O--,O<=0&&(O=0,a.classList.remove("terminal-drag-over"))}async function At(t){t.preventDefault(),O=0,a.classList.remove("terminal-drag-over");const e=ct(t.dataTransfer);e&&await nt(e)}function mt(t){!Tt||t.key!=="Escape"||B||t.defaultPrevented||t.repeat||t.metaKey||t.ctrlKey||t.altKey||n.isFocused()&&(t.preventDefault(),t.stopPropagation(),I("\x1B"))}a.addEventListener("paste",kt),a.addEventListener("dragenter",It),a.addEventListener("dragover",Yt),a.addEventListener("dragleave",Ft),a.addEventListener("drop",At),document.addEventListener("keydown",mt,!0);function zt(t){if(t.touches.length!==1){s=null;return}const e=t.touches[0];if(!e)return;C();const i=a.getBoundingClientRect(),u=e.clientX-i.left<i.width*.4?"tui":"history",c=e.clientY-i.top<i.height*.5;s={startX:e.clientX,startY:e.clientY,lastX:e.clientX,lastY:e.clientY,lastT:performance.now(),velocity:0,scrolling:!1,zone:u,tuiUp:c,sent:!1},t.stopPropagation()}function Bt(t){if(!s||t.touches.length!==1)return;const e=t.touches[0];if(!e)return;const i=e.clientY-s.startY,u=e.clientX-s.startX;if(!s.scrolling){if(Math.abs(i)<8||Math.abs(i)<Math.abs(u))return;s.scrolling=!0,j=Date.now()+500}t.preventDefault(),t.stopPropagation();const c=performance.now(),b=e.clientY-s.lastY;if(s.zone==="tui"){s.sent||(s.sent=!0,I(s.tuiUp?"\x1B[5~":"\x1B[6~"),F(s.tuiUp)),s.lastX=e.clientX,s.lastY=e.clientY,s.lastT=c;return}const v=c-s.lastT;v>0&&(s.velocity=b/v),Ot(-b),s.lastX=e.clientX,s.lastY=e.clientY,s.lastT=c}function Kt(t){if(!s)return;const e=s.scrolling,i=s.zone,u=s.tuiUp,c=s.velocity;if(s=null,t.stopPropagation(),i==="tui"){e||(I(u?"\x1B[5~":"\x1B[6~"),F(u),j=Date.now()+500,t.preventDefault());return}if(!e){n.focus();return}j=Date.now()+500,t.preventDefault(),c&>(c)}function Ut(t){s=null,C(),t.stopPropagation()}function Xt(t){t.pointerType==="touch"&&Date.now()<j&&(t.preventDefault(),t.stopPropagation())}function Ot(t){const e=a.querySelector(".xterm-rows > div"),i=e?e.getBoundingClientRect().height:16;let u=i>0?Math.round(t/i):t>0?1:-1;u===0&&(u=t>0?1:-1),n.scrollLines(u)}a.addEventListener("touchstart",zt,{passive:!0,capture:!0}),a.addEventListener("touchmove",Bt,{passive:!1,capture:!0}),a.addEventListener("touchend",Kt,{passive:!1,capture:!0}),a.addEventListener("touchcancel",Ut,{passive:!0,capture:!0}),a.addEventListener("pointerup",Xt,!0);function pt(){y()}window.addEventListener("resize",pt),window.visualViewport?.addEventListener("resize",y),window.visualViewport?.addEventListener("scroll",y);const ht=new ResizeObserver(()=>y());ht.observe(a),document.fonts?.ready.then(()=>{y(),setTimeout(y,50),setTimeout(y,200)}),a.addEventListener("focusin",Mt,!0);async function Rt(){if(document.fonts?.ready)try{await Promise.race([document.fonts.ready,new Promise(t=>setTimeout(t,1e3))])}catch{}}return requestAnimationFrame(()=>{D()&&G(),(async()=>(await Rt(),D()&&S({type:"resize",cols:n.cols,rows:n.rows}),at(),y()))()}),{destroy(){if(E=!0,C(),Y(!1),X&&clearTimeout(X),document.removeEventListener("mousemove",ot,!0),document.removeEventListener("mouseup",it,!0),l){try{l.close(1e3,"session switch")}catch{}l=void 0}a.innerHTML="",a.classList.remove("terminal-pending"),window.removeEventListener("resize",pt),ht.disconnect(),document.removeEventListener("keydown",mt,!0)},focus(){n.focus()},sendInput(t){I(t)},toggleCopyMode(){ft()}}})()}export{qt as initTerminal,rt as stripAltScreenSequences};
|