@3sln/trove 0.0.19 → 0.0.20
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.
- package/README.md +38 -0
- package/package.json +1 -1
- package/packages/core/src/index.js +3 -0
- package/packages/core/src/sqlite-d1.js +6 -0
- package/packages/core/src/sqlite-do.js +182 -0
- package/packages/server/src/adapters/worker.js +25 -6
- package/packages/web/dist/assets/main-6tn55drx.js +742 -0
- package/packages/web/dist/assets/{main-axerf2vw.js.map → main-6tn55drx.js.map} +15 -15
- package/packages/web/dist/assets/{styles-hskanqc0.css → styles-15b7sgsm.css} +1 -1
- package/packages/web/dist/index.html +2 -2
- package/packages/web/dist/sw.js +1 -1
- package/packages/web/src/bl/actions.js +100 -7
- package/packages/web/src/bl/commands.js +3 -1
- package/packages/web/src/bl/fileType.js +31 -0
- package/packages/web/src/bl/launcher.js +17 -4
- package/packages/web/src/bl/openers.js +16 -0
- package/packages/web/src/bl/state.js +4 -0
- package/packages/web/src/styles.css +27 -0
- package/packages/web/src/ui/components/launcher.js +3 -1
- package/packages/web/src/ui/components/overlays.js +20 -1
- package/packages/web/src/ui/components/statusBar.js +20 -6
- package/packages/web/src/ui/components/views/grid.js +4 -4
- package/packages/web/src/ui/components/views/list.js +4 -4
- package/packages/web/src/ui/components/views/parts.js +47 -2
- package/packages/web/src/ui/compositions/workbench.js +3 -1
- package/packages/web/dist/assets/main-axerf2vw.js +0 -742
|
@@ -1,742 +0,0 @@
|
|
|
1
|
-
import{a as RH,c as z1,d as MH}from"./chunk-4xqbzebh.js";var fB={};z1(fB,{wbr:()=>kG,video:()=>fG,vdom:()=>P0,ul:()=>YG,u:()=>xG,track:()=>vG,tr:()=>J6,title:()=>_1,time:()=>TG,thead:()=>E6,th:()=>C6,tfoot:()=>B6,textarea:()=>R6,template:()=>N6,td:()=>Q6,tbody:()=>A6,table:()=>eG,svg:()=>nG,sup:()=>_G,summary:()=>q6,sub:()=>SG,style:()=>k1,strong:()=>wG,special:()=>j1,span:()=>jG,source:()=>aG,small:()=>OG,slot:()=>z6,settings:()=>S1,select:()=>I6,section:()=>o1,script:()=>g1,schedule:()=>P6,samp:()=>PG,s:()=>NG,reconcile:()=>w1,q:()=>zG,progress:()=>F6,pre:()=>LG,portal:()=>dG,picture:()=>cG,param:()=>lG,p:()=>KG,output:()=>U6,option:()=>W6,optgroup:()=>Z6,ol:()=>JG,object:()=>pG,noscript:()=>y1,nav:()=>s1,meter:()=>D6,meta:()=>T1,math:()=>sG,mark:()=>qG,map:()=>bG,main:()=>n1,link:()=>x1,li:()=>EG,legend:()=>$6,label:()=>H6,kbd:()=>VG,ins:()=>MG,input:()=>G6,img:()=>hG,iframe:()=>mG,i:()=>RG,html:()=>wC,hr:()=>CG,header:()=>u1,h6:()=>a1,h5:()=>d1,h4:()=>c1,h3:()=>l1,h2:()=>p1,h1:()=>m1,h:()=>P1,form:()=>X6,footer:()=>f1,flush:()=>O6,figure:()=>BG,figcaption:()=>QG,fieldset:()=>Y6,embed:()=>uG,em:()=>IG,dt:()=>AG,dodo:()=>sK,dl:()=>e1,div:()=>t1,dialog:()=>V6,dfn:()=>FG,details:()=>M6,del:()=>UG,dd:()=>r1,datalist:()=>L6,data:()=>WG,colgroup:()=>tG,col:()=>rG,code:()=>ZG,clear:()=>j6,cite:()=>DG,caption:()=>iG,canvas:()=>oG,button:()=>K6,br:()=>$G,blockquote:()=>i1,b:()=>HG,audio:()=>yG,aside:()=>v1,article:()=>b1,area:()=>gG,alias:()=>O1,address:()=>h1,abbr:()=>GG,a:()=>XG});var sQ=Symbol("ELEMENT_NODE"),jC=Symbol("ALIAS_NODE"),$B=Symbol("SPECIAL_NODE"),vB=Symbol("OPAQUE_NODE"),_A=Symbol("NODE_STATE");var D1=new Set(["__proto__","constructor","prototype"]),dK=(A,Q)=>Object.prototype.hasOwnProperty.call(A,Q);function Z1(A,Q){return typeof Q==="string"&&A.toLowerCase()===Q.toLowerCase()}class DB{constructor(A,Q,B){this.type=A,this.tag=Q,this.args=B}key(A){return this.k=A,this}on(A){return this.hooks=A,this}opaque(){if(this.type!==sQ)throw Error(".opaque() can only be used on element nodes (h).");return this.type=vB,this}}function W1(A,Q){if(A===Q)return!1;if(A&&Q&&typeof A==="object"&&typeof Q==="object"){if(A.constructor!==Q.constructor)return!0;if(Array.isArray(A)){if(A.length!==Q.length)return!0;for(let B=0;B<A.length;B++)if(A[B]!==Q[B])return!0;return!1}if(A.constructor===Object){let B=Object.keys(A);if(B.length!==Object.keys(Q).length)return!0;for(let C of B)if(!dK(Q,C)||A[C]!==Q[C])return!0;return!1}}return!0}function U1(A){return Array.isArray(A)||A!=null&&typeof A[Symbol.iterator]==="function"&&typeof A!=="string"}function F1(A){return(...Q)=>new DB(jC,A,Q)}function I1(A){return(...Q)=>new DB($B,A,Q)}function R1(A,Q){if(A.namespaceURI==="http://www.w3.org/1999/xhtml")switch(Q){case"svg":return"http://www.w3.org/2000/svg";case"math":return"http://www.w3.org/1998/Math/MathML"}return A.namespaceURI??A.host?.namespaceURI??"http://www.w3.org/1999/xhtml"}function aK(A){return{originalProps:Object.create(null),newVdom:A}}function N0(A,Q,B){let C=A.ownerDocument.createElementNS(R1(A,Q),Q);return C[_A]=aK(B),C}var nK=new WeakMap;function M1(A){let Q=[],B=A;while(B)if(Q.push(B),B.parentElement)B=B.parentElement;else B=B.getRootNode()?.host;return Q}function cK(A,Q){for(let B of Q)A.add(B)}function V1(A,Q){let B=Q??A?.defaultView??globalThis;return B.Node?.prototype??B.Element?.prototype}function q1(A){let Q=new Set;return A.addEventListener("focusin",(B)=>{Q.clear(),cK(Q,B.composedPath())}),A.addEventListener("focusout",(B)=>{if(!B.relatedTarget)Q.clear()}),cK(Q,M1(A.activeElement)),nK.set(A,Q),Q}var P0=(A)=>{let Q=A?.shouldUpdate??W1,B=A?.isMap??(($)=>$?.constructor===Object),C=A?.mapIter??(($)=>Object.entries($)),E=A?.mapGet??(($,W)=>$[W]),J=A?.mapMerge??((...$)=>Object.assign({},...$)),K=A?.newMap??(($)=>({...$})),L=A?.mapPut??(($,W,Z)=>{return $[W]=Z,$}),Y=A?.isSeq??U1,X=A?.seqIter??(($)=>$),H=A?.convertName??(($)=>$),G=A?.convertTagName??H,D=A?.convertPropName??H,U=A?.convertStyleName??H,I=A?.convertDataName??H,R=A?.convertClassName??H,V=A?.convertHookName??H,_=A?.listenerKey??"listener",m=A?.captureKey??"capture",b=A?.passiveKey??"passive",q=K({});function p($){if($==null)return[][Symbol.iterator]();if(typeof $[Symbol.iterator]==="function")return $[Symbol.iterator]();if(typeof $.next==="function")return $;return[$][Symbol.iterator]()}function k($,W,Z,j,x){if($==null)return;for(let S in $)if(dK($,S))W(S,$[S],Z,j,x)}function v($,W,Z,j,x){if($==null)return;let S=p(C($)),n;while(!(n=S.next()).done){let GA=n.value;W(GA[0],GA[1],Z,j,x)}}let O=A?.mapEach??(A?.mapIter?v:k);function g($){return $===null||$===void 0||$===!1}function e($,W,Z){let j=p(X(W)),x;while(!(x=j.next()).done){let S=x.value;if(Z&&g(S))continue;if(!Y(S))$.push(S);else e($,S,Z)}}function AA($,W){let Z=[];return e(Z,$,W),Z}let QA=A?.flattenSeq??AA;function QQ($,W){let Z=[];for(let j=W;j<$.length;j++){let x=$[j];if(g(x))continue;if(!Y(x))Z.push(x);else e(Z,x,!0)}return Z}function FA($){return g($)?"":String($)}function IA($,W,...Z){if(!B(W)){if(W!==null&&W!==void 0)Z.unshift(W);W=q}return new DB(sQ,G($),[W,...Z])}function YA($,W,Z){Z.setProperty(U($),W)}function t($,W,Z,j){if(E(j,$)!==void 0)return;Z.removeProperty(U($))}function WA($,W,Z){let j=$.style;O(Z,YA,j),O(W,t,j,Z)}function XA($,W,Z){Z.setAttribute(D($),W)}function aQ($,W,Z,j){if(E(j,$)!==void 0)return;Z.removeAttribute(D($))}function OA($,W,Z){O(Z,XA,$),O(W,aQ,$,Z)}function iA($,W,Z){Z.dataset[I($)]=W}function jA($,W,Z,j){if(E(j,$)!==void 0)return;delete Z.dataset[I($)]}function RA($,W,Z){O(Z,iA,$),O(W,jA,$,Z)}function r($,W,Z){let j=new Set;for(let x of QA(W,!0)){let S=R(x);if(S)j.add(S)}for(let x of QA(Z,!0)){let S=R(x);if(!S)continue;j.delete(S),$.classList.add(S)}for(let x of j)$.classList.remove(x)}function pA($,W,Z,j){if(D1.has(Z)){console.error(`Refusing to assign unsafe prop name '${Z}' to a DOM node.`);return}let x=W.originalProps;if(!(Z in x))x[Z]=$[Z];$[Z]=j===void 0?x[Z]:j}function PQ($,W,Z){let j=W.originalProps;if(Z in j)$[Z]=j[Z],delete j[Z]}function OQ($,W,Z,j,x){let S=D($),n=E(j,$);if(Object.is(W,n))return;switch(S){case"$styling":{if(!B(W))throw Error("invalid value for styling prop");WA(Z,n??q,W??q);break}case"$classes":{if(!Y(W))throw Error("invalid value for classes prop");r(Z,n??[],W??[]);break}case"$attrs":{if(!B(W))throw Error("invalid value for attrs prop");OA(Z,n??q,W??q);break}case"$dataset":{if(!B(W))throw Error("invalid value for dataset prop");RA(Z,n??q,W??q);break}default:{if(x)pA(Z,Z[_A],S,W);else if(W===void 0)Z.removeAttribute(S);else Z.setAttribute(S,W);break}}}function YB($,W,Z,j,x){if(E(j,$)!==void 0)return;let S=D($);switch(S){case"$styling":WA(Z,W??q,q);break;case"$classes":r(Z,W??[],[]);break;case"$attrs":OA(Z,W??q,q);break;case"$dataset":RA(Z,W??q,q);break;default:{if(x)PQ(Z,Z[_A],S);else Z.removeAttribute(S);break}}}function jQ($,W){let Z=$[_A],j=$.namespaceURI==="http://www.w3.org/1999/xhtml",x=Z.vdom?.args[0]??q;O(W,OQ,$,x,j),O(x,YB,$,W,j)}function wQ($,W,Z){if(typeof Z==="function")$.addEventListener(W,Z);else if(Z!=null)$.addEventListener(W,E(Z,_),{capture:!!E(Z,m),passive:!!E(Z,b)})}function SQ($,W,Z){if(typeof Z==="function")$.removeEventListener(W,Z);else if(Z!=null)$.removeEventListener(W,E(Z,_),!!E(Z,m))}function _Q($,W,Z){let j=V($);if(j[0]==="$")return;wQ(Z,j,W)}function hB($,W,Z,j){let x=V($);if(x[0]==="$")return;let S=E(j,$);if(W===S)return;SQ(Z,x,S),wQ(Z,x,W)}function E1($,W,Z,j){let x=V($);if(x[0]==="$"||E(j,$)!==void 0)return;SQ(Z,x,W)}function fK($,W){let Z=$[_A],j=W??q;if(!Z.vdom){O(j,_Q,$);return}let x=Z.vdom.hooks??q;O(j,hB,$,x),O(x,E1,$,j)}function z0($){let W=$[_A],Z=W.newVdom,j=W.vdom,x=Z.args;switch(Z.type){case sQ:{jQ($,x[0]),bB($,QQ(x,1));break}case vB:{jQ($,x[0]);break}case jC:{let S=Z.tag.apply($,Z.args);if(g(S))bB($,[]);else if(Y(S))bB($,QA(S,!0));else bB($,[S]);break}case $B:{try{Z.tag.update?.($,Z.args,j?.args)}catch(S){console.error(S)}break}}if(Z.hooks||j?.hooks)fK($,Z.hooks??q);try{Z.hooks?.$update?.($,Z,j)}catch(S){console.error(S)}W.vdom=Z,delete W.newVdom}function J1($,W){if(typeof W!=="object"||W===null)return $.ownerDocument.createTextNode(FA(W));let Z;switch(W.type){case sQ:case vB:Z=N0($,W.tag,W);break;case jC:Z=N0($,"udom-alias",W),Z.style.display="contents";break;case $B:Z=N0($,"udom-special",W),Z.style.display="contents";break;default:throw Error("Invalid VDOM node")}return Z}function uK($){if($.children)for(let W of $.children)OC(W)}function OC($){let W=$[_A];if(!W)return;let{vdom:Z}=W;if(!Z){delete $[_A];return}if(Z.hooks)fK($,q);if(Z.type===sQ||Z.type===vB)jQ($,q);if(Z.type===sQ||Z.type===jC)uK($);delete $[_A];try{if(Z.type===$B)Z.tag.detach?.($);Z.hooks?.$detach?.($)}catch(j){console.error(j)}}function K1($,W){let Z=$[_A];if(Q(Z.vdom.args,W.args)||Q(Z.vdom.hooks,W.hooks))Z.newVdom=W;return $}function L1($){let W=new Map,Z={nodes:[],cursor:0};for(let j of $.childNodes){if(j.nodeType===3){Z.nodes.push(j);continue}let x=j[_A],S=x?.vdom;if(S===void 0){if(x?.newVdom)throw Error("Attempt to reconcile against a target while already working on a reconciliation against that same target, this is not allowed");continue}let n=W.get(S.tag);if(!n)n={nodesForKey:null,nodesWithoutKey:{nodes:[],cursor:0}},W.set(S.tag,n);if(S.k!==void 0){if(!n.nodesForKey)n.nodesForKey=new Map;let GA=n.nodesForKey.get(S.k);if(GA)GA.nodes.push(j);else n.nodesForKey.set(S.k,{nodes:[j],cursor:0})}else n.nodesWithoutKey.nodes.push(j)}return{byTag:W,textNodes:Z}}function mK($){if(!$||$.cursor>=$.nodes.length)return;return $.nodes[$.cursor++]}function Y1($,W,Z,j){let x=$.firstChild;for(let S=0;S<W.length;S++){let n=W[S];if(n===x){x=x.nextSibling;continue}(j&&n.isConnected?j:Z).call($,n,x)}}function X1($,W,Z,j){let x=W[j],S=x;for(let GA=j-1;GA>=0;GA--){let FQ=W[GA];if(FQ!==S.previousSibling)Z.call($,FQ,S);S=FQ}let n=x.nextSibling;for(let GA=j+1;GA<W.length;GA++){let FQ=W[GA];if(FQ===n)n=n.nextSibling;else Z.call($,FQ,n)}}function G1($,W){for(let Z=0;Z<$.length;Z++)if(W.has($[Z]))return Z;return-1}function H1($){let W=$[_A];if(!W?.newVdom)return;if(!W.vdom)try{if(W.newVdom.hooks?.$attach?.($),W.newVdom.type===$B)W.newVdom.tag.attach?.($)}catch(Z){console.error(Z)}z0($)}function bB($,W){let Z=$.firstChild?new Set($.childNodes):null,{byTag:j,textNodes:x}=L1($),S=[];for(let MA of W){let nQ;if(MA instanceof DB){let GB=j.get(MA.tag),HB=GB?mK(MA.k!==void 0?GB.nodesForKey?.get(MA.k):GB.nodesWithoutKey):void 0;nQ=HB?K1(HB,MA):J1($,MA)}else{let GB=mK(x),HB=FA(MA);if(GB){if(nQ=GB,nQ.nodeValue!==HB)nQ.nodeValue=HB}else nQ=$.ownerDocument.createTextNode(HB)}Z?.delete(nQ),S.push(nQ)}if(Z)for(let MA of Z)OC(MA),$.removeChild(MA);if(S.length===0)return;let n=$.ownerDocument,GA=V1(n,A?.window),FQ=GA.insertBefore,pK=typeof GA.moveBefore==="function"?GA.moveBefore:null,lK=$.isConnected,XB=-1;if(lK&&!pK){let MA=nK.get(n)??q1(n);if(XB=G1(S,MA),XB!==-1&&S[XB].parentNode!==$)XB=-1}if(XB===-1)Y1($,S,FQ,lK?pK:null);else X1($,S,FQ,XB);for(let MA=0;MA<S.length;MA++)H1(S[MA])}function $1($,W){let Z=$[_A];if(W===null||W===void 0){if(Z)OC($);else uK($);$.replaceChildren();return}if(Y(W)){bB($,QA(W,!0));return}if(W instanceof DB){if(Z){if(Z.vdom.type===W.type&&Z.vdom.tag===W.tag){if(Q(Z.vdom.args,W.args)||Q(Z.vdom.hooks,W.hooks))Z.newVdom=W,z0($);return}OC($)}switch(W.type){case sQ:case vB:if(!Z1($.nodeName,G(W.tag)))throw Error("incompatible target for vdom");break}$[_A]=aK(W);try{if(W.hooks?.$attach?.($),W.type===$B)W.tag.attach?.($)}catch(j){console.error(j)}z0($);return}throw Error("invalid vdom")}return{h:IA,alias:F1,special:I1,reconcile:$1,settings:{shouldUpdate:Q,isMap:B,mapIter:C,mapEach:O,mapGet:E,mapMerge:J,newMap:K,mapPut:L,isSeq:Y,flattenSeq:QA,seqIter:X,convertTagName:G,convertPropName:D,convertStyleName:U,convertDataName:I,convertClassName:R,convertHookName:V,convertName:H,listenerKey:_,captureKey:m,passiveKey:b}}};function wC({h:A}){return{title:(...Q)=>A("title",...Q),meta:(Q)=>A("meta",Q),link:(Q)=>A("link",Q),style:(...Q)=>A("style",...Q),script:(...Q)=>A("script",...Q),noscript:(...Q)=>A("noscript",...Q),address:(...Q)=>A("address",...Q),article:(...Q)=>A("article",...Q),aside:(...Q)=>A("aside",...Q),footer:(...Q)=>A("footer",...Q),header:(...Q)=>A("header",...Q),h1:(...Q)=>A("h1",...Q),h2:(...Q)=>A("h2",...Q),h3:(...Q)=>A("h3",...Q),h4:(...Q)=>A("h4",...Q),h5:(...Q)=>A("h5",...Q),h6:(...Q)=>A("h6",...Q),main:(...Q)=>A("main",...Q),nav:(...Q)=>A("nav",...Q),section:(...Q)=>A("section",...Q),blockquote:(...Q)=>A("blockquote",...Q),dd:(...Q)=>A("dd",...Q),div:(...Q)=>A("div",...Q),dl:(...Q)=>A("dl",...Q),dt:(...Q)=>A("dt",...Q),figcaption:(...Q)=>A("figcaption",...Q),figure:(...Q)=>A("figure",...Q),hr:()=>A("hr"),li:(...Q)=>A("li",...Q),ol:(...Q)=>A("ol",...Q),p:(...Q)=>A("p",...Q),pre:(...Q)=>A("pre",...Q),ul:(...Q)=>A("ul",...Q),a:(...Q)=>A("a",...Q),abbr:(...Q)=>A("abbr",...Q),b:(...Q)=>A("b",...Q),br:()=>A("br"),cite:(...Q)=>A("cite",...Q),code:(...Q)=>A("code",...Q),data:(...Q)=>A("data",...Q),del:(...Q)=>A("del",...Q),dfn:(...Q)=>A("dfn",...Q),em:(...Q)=>A("em",...Q),i:(...Q)=>A("i",...Q),ins:(...Q)=>A("ins",...Q),kbd:(...Q)=>A("kbd",...Q),mark:(...Q)=>A("mark",...Q),q:(...Q)=>A("q",...Q),s:(...Q)=>A("s",...Q),samp:(...Q)=>A("samp",...Q),small:(...Q)=>A("small",...Q),span:(...Q)=>A("span",...Q),strong:(...Q)=>A("strong",...Q),sub:(...Q)=>A("sub",...Q),sup:(...Q)=>A("sup",...Q),time:(...Q)=>A("time",...Q),u:(...Q)=>A("u",...Q),wbr:()=>A("wbr"),area:(Q)=>A("area",Q),audio:(...Q)=>A("audio",...Q),img:(Q)=>A("img",Q),map:(...Q)=>A("map",...Q),track:(Q)=>A("track",Q),video:(...Q)=>A("video",...Q),embed:(Q)=>A("embed",Q),iframe:(...Q)=>A("iframe",...Q),object:(...Q)=>A("object",...Q),param:(Q)=>A("param",Q),picture:(...Q)=>A("picture",...Q),portal:(...Q)=>A("portal",...Q),source:(Q)=>A("source",Q),svg:(...Q)=>A("svg",...Q),math:(...Q)=>A("math",...Q),canvas:(...Q)=>A("canvas",...Q),caption:(...Q)=>A("caption",...Q),col:(Q)=>A("col",Q),colgroup:(...Q)=>A("colgroup",...Q),table:(...Q)=>A("table",...Q),tbody:(...Q)=>A("tbody",...Q),td:(...Q)=>A("td",...Q),tfoot:(...Q)=>A("tfoot",...Q),th:(...Q)=>A("th",...Q),thead:(...Q)=>A("thead",...Q),tr:(...Q)=>A("tr",...Q),button:(...Q)=>A("button",...Q),datalist:(...Q)=>A("datalist",...Q),fieldset:(...Q)=>A("fieldset",...Q),form:(...Q)=>A("form",...Q),input:(Q)=>A("input",Q),label:(...Q)=>A("label",...Q),legend:(...Q)=>A("legend",...Q),meter:(...Q)=>A("meter",...Q),optgroup:(...Q)=>A("optgroup",...Q),option:(...Q)=>A("option",...Q),output:(...Q)=>A("output",...Q),progress:(...Q)=>A("progress",...Q),select:(...Q)=>A("select",...Q),textarea:(...Q)=>A("textarea",...Q),details:(...Q)=>A("details",...Q),dialog:(...Q)=>A("dialog",...Q),summary:(...Q)=>A("summary",...Q),slot:(...Q)=>A("slot",...Q),template:(...Q)=>A("template",...Q)}}function O0({window:A}={}){let Q=!1,B=0,C=[];function E(){return A??globalThis}function J(U){let I=E().requestAnimationFrame;return typeof I==="function"?I.call(E(),U):setTimeout(U,16)}function K(U){let I=E().cancelAnimationFrame;if(typeof I==="function")I.call(E(),U);else clearTimeout(U)}function L(){return E().performance?.now()??Date.now()}function Y(U){for(let I of U)try{I()}catch(R){console.error("Error in scheduled function:",R)}}function X(){let U=L();B=0;while(C.length>0){let I=C.splice(0,100);if(Y(I),L()-U>10&&C.length>0){B=J(X);return}}Q=!1}function H(U,{signal:I}={}){if(I?.aborted)return;let R=U;if(I)R=()=>{if(!I.aborted)U()};if(C.push(R),!Q)Q=!0,B=J(X)}function G(){if(B)K(B),B=0;Q=!0;while(C.length>0){let U=C;C=[],Y(U)}Q=!1}function D(){if(B)K(B);C=[],Q=!1,B=0}return{schedule:H,flush:G,clear:D}}function sK(A){let Q=P0(A),B=wC(Q),C=A?.scheduler??O0(A);return{...Q,...B,...C}}var N1=sK();var{h:P1,alias:O1,special:j1,reconcile:w1,settings:S1,title:_1,meta:T1,link:x1,style:k1,script:g1,noscript:y1,address:h1,article:b1,aside:v1,footer:f1,header:u1,h1:m1,h2:p1,h3:l1,h4:c1,h5:d1,h6:a1,main:n1,nav:s1,section:o1,blockquote:i1,dd:r1,div:t1,dl:e1,dt:AG,figcaption:QG,figure:BG,hr:CG,li:EG,ol:JG,p:KG,pre:LG,ul:YG,a:XG,abbr:GG,b:HG,br:$G,cite:DG,code:ZG,data:WG,del:UG,dfn:FG,em:IG,i:RG,ins:MG,kbd:VG,mark:qG,q:zG,s:NG,samp:PG,small:OG,span:jG,strong:wG,sub:SG,sup:_G,time:TG,u:xG,wbr:kG,area:gG,audio:yG,img:hG,map:bG,track:vG,video:fG,embed:uG,iframe:mG,object:pG,param:lG,picture:cG,portal:dG,source:aG,svg:nG,math:sG,canvas:oG,caption:iG,col:rG,colgroup:tG,table:eG,tbody:A6,td:Q6,tfoot:B6,th:C6,thead:E6,tr:J6,button:K6,datalist:L6,fieldset:Y6,form:X6,input:G6,label:H6,legend:$6,meter:D6,optgroup:Z6,option:W6,output:U6,progress:F6,select:I6,textarea:R6,details:M6,dialog:V6,summary:q6,slot:z6,template:N6,schedule:P6,flush:O6,clear:j6}=N1;function w6(A,{signal:Q}={}){queueMicrotask(()=>{if(!Q?.aborted)A()})}function S6(A){return(Q)=>A("pre",{$styling:{"background-color":"#fdd",color:"#330",padding:"1em","white-space":"pre-wrap"}},A("strong",null,`Error: ${Q?.message??String(Q)}`),`
|
|
2
|
-
|
|
3
|
-
`,Q?.stack??"")}function oK(A){return A!=null&&typeof A.special==="function"&&typeof A.reconcile==="function"}function j0(A){let Q=oK(A)?{dodo:A}:A,B=Q?.dodo;if(!oK(B))throw Error("a dodo instance must be provided in settings, e.g. reactive({dodo})");return{schedule:typeof B.schedule==="function"?B.schedule:w6,renderError:S6(B.h),...Q,dodo:B,...B.settings}}var BQ=Symbol("dodo.reactive.PENDING"),VA=Symbol("dodo.reactive.NOTHING");function iQ(A){return A!=null&&typeof A.onDirty==="function"&&typeof A.getValue==="function"}function ZB(A){return iQ(A)?A.getValue():A}function _6(A){if(typeof A==="function")return A;if(A&&typeof A.unsubscribe==="function")return()=>A.unsubscribe();return()=>{}}function w0(){let A=new Set;return{listeners:A,notify(){for(let Q of Array.from(A))try{Q()}catch(B){console.error("Error in dodo cell listener:",B)}}}}function S0(A,Q){let{listeners:B,notify:C}=w0(),E=null;return{onDirty(J){if(B.add(J),B.size===1)try{E=_6(A(C))}catch(L){throw B.delete(J),L}let K=!1;return()=>{if(K)return;if(K=!0,B.delete(J),B.size===0&&E){let L=E;E=null,L()}}},getValue(){return Q()}}}function c(A){let Q=A,{listeners:B,notify:C}=w0();return{onDirty(E){return B.add(E),()=>B.delete(E)},getValue(){return Q},setValue(E){if(Object.is(E,Q))return;Q=E,C()},update(E){this.setValue(E(Q))}}}function iK(A){return{onDirty(){return()=>{}},getValue(){return A}}}function BA(A,Q){let B=Array.isArray(A)?A:[A],{listeners:C,notify:E}=w0(),J=null,K=VA,L=()=>{K=VA,E()},Y=()=>{let X=Array(B.length);for(let H=0;H<B.length;H++){let G=ZB(B[H]);if(G===BQ)return BQ;X[H]=G}return Q(...X)};return{onDirty(X){if(C.add(X),C.size===1)K=VA,J=B.map((G)=>iQ(G)?G.onDirty(L):null);let H=!1;return()=>{if(H)return;if(H=!0,C.delete(X),C.size===0&&J){for(let G of J)G?.();J=null,K=VA}}},getValue(){if(K===VA||!J)K=Y();return K}}}function SC(A,Q){return BA([A],Q)}function _C(A,{initial:Q=BQ}={}){return T6(A,{initial:Q},(B,C)=>B.subscribe({next:C.next,error:C.error,complete:C.complete}))}function T6(A,{initial:Q},B){let C=Q,E=VA;return S0((K)=>{return B(A,{next(Y){C=Y,E=VA,K()},error(Y){E=Y,K()},complete(){}})},()=>{if(E!==VA)throw E;return C})}function rK(A){return{subscribe(Q){let B=typeof Q==="function"?{next:Q}:Q??{},C=()=>{let J;try{J=ZB(A)}catch(K){B.error?.(K);return}if(J!==BQ)B.next?.(J)},E=iQ(A)?A.onDirty(C):()=>{};return C(),{unsubscribe:E}}}}function TQ(A,Q){let B=()=>{let E;try{E=ZB(A)}catch(J){console.error("Error reading cell in effect:",J);return}if(E===BQ)return;Q(E)},C=iQ(A)?A.onDirty(B):()=>{};return B(),C}var oQ=Symbol("dodo.reactive.watch");function TC(A){let Q=j0(A),{dodo:B,schedule:C,renderError:E}=Q,{special:J,reconcile:K}=B,L=Q.mapGet??((G,D)=>G[D]),Y=(G,D)=>G==null?void 0:L(G,D),X=Q.shouldUpdate??((G,D)=>G!==D);return{watch:J({attach(G){G[oQ]={source:VA,builder:null,placeholder:void 0,errorBuilder:void 0,unsubscribe:null,abortController:null,renderScheduled:!1,lastValue:VA,lastBuilder:VA}},update(G,[D,U,I]){let R=G[oQ];if(!R)return;if(R.builder=U,R.placeholder=Y(I,"placeholder"),R.errorBuilder=Y(I,"error"),R.source!==D){if(R.unsubscribe?.(),R.unsubscribe=null,R.abortController?.abort(),R.abortController=new AbortController,R.source=D,R.lastValue=VA,iQ(D))try{R.unsubscribe=D.onDirty(()=>this.invalidate(G))}catch(V){this.renderError(G,V);return}}this.render(G)},invalidate(G){let D=G[oQ];if(!D||D.renderScheduled)return;D.renderScheduled=!0,C(()=>this.render(G),{signal:D.abortController?.signal})},render(G){let D=G[oQ];if(!D)return;D.renderScheduled=!1;let U;try{U=ZB(D.source===VA?void 0:D.source)}catch(I){this.renderError(G,I);return}if(D.builder===D.lastBuilder&&D.lastValue!==VA&&!X(D.lastValue,U))return;D.lastValue=U,D.lastBuilder=D.builder;try{if(U===BQ)K(G,D.placeholder?[D.placeholder()]:[]);else K(G,[D.builder(U)])}catch(I){this.renderError(G,I)}},renderError(G,D){let U=G[oQ];if(!U)return;U.lastValue=VA,U.lastBuilder=VA,console.error("Error in watched cell:",D);try{K(G,[(U.errorBuilder??E)(D)])}catch(I){console.error("Error rendering the error view:",I)}},detach(G){let D=G[oQ];if(!D)return;D.unsubscribe?.(),D.abortController?.abort(),delete G[oQ],K(G,null)}})}}var{watch:CQ}=TC({dodo:fB});var T=fB;var tK={watch:CQ,cell:c,derive:BA,constant:iK,mapCell:SC,connectable:S0,fromObservable:_C,toObservable:rK,effect:TQ,isCell:iQ,readCell:ZB,PENDING:BQ};var f=Object.freeze({NOT_FOUND:"not_found",ALREADY_EXISTS:"already_exists",INVALID:"invalid",CONFLICT:"conflict",UNAUTHORIZED:"unauthorized",FORBIDDEN:"forbidden",UNSUPPORTED:"unsupported",QUOTA:"quota",TOO_LARGE:"too_large",BAD_RANGE:"bad_range",TRANSIENT:"transient",TIMEOUT:"timeout",ABORTED:"aborted",INTERNAL:"internal"}),x6=new Set([f.TRANSIENT,f.TIMEOUT,f.QUOTA]),k6={[f.NOT_FOUND]:404,[f.ALREADY_EXISTS]:409,[f.INVALID]:400,[f.CONFLICT]:412,[f.UNAUTHORIZED]:401,[f.FORBIDDEN]:403,[f.UNSUPPORTED]:501,[f.QUOTA]:429,[f.TOO_LARGE]:413,[f.BAD_RANGE]:416,[f.TRANSIENT]:503,[f.TIMEOUT]:504,[f.ABORTED]:499,[f.INTERNAL]:500};class z extends Error{constructor(A,Q,B={}){super(Q,B.cause!==void 0?{cause:B.cause}:void 0);if(this.name="TroveError",this.code=A||f.INTERNAL,this.retryable=B.retryable??x6.has(this.code),this.details=B.details??null,this.status=k6[this.code]??500,this.code===f.QUOTA&&!this.retryable)this.status=507}toJSON(){return{error:{code:this.code,message:this.message,retryable:this.retryable,...this.details?{details:this.details}:{}}}}static notFound(A,Q){return new z(f.NOT_FOUND,A?`${A} not found`:"Not found",Q)}static alreadyExists(A,Q){return new z(f.ALREADY_EXISTS,`${A} already exists`,Q)}static invalid(A,Q){return new z(f.INVALID,A,Q)}static conflict(A,Q){return new z(f.CONFLICT,A,Q)}static unsupported(A,Q){return new z(f.UNSUPPORTED,A,Q)}static transient(A,Q){return new z(f.TRANSIENT,A,{retryable:!0,...Q})}static timeout(A,Q){return new z(f.TIMEOUT,A,{retryable:!0,...Q})}static aborted(A="Operation aborted",Q){return new z(f.ABORTED,A,{retryable:!1,...Q})}static unauthorized(A="Unauthorized",Q){return new z(f.UNAUTHORIZED,A,Q)}static tooLarge(A="Too large",Q){return new z(f.TOO_LARGE,A,{retryable:!1,...Q})}static badRange(A="Range not satisfiable",Q){return new z(f.BAD_RANGE,A,{retryable:!1,...Q})}static forbidden(A="Forbidden",Q){return new z(f.FORBIDDEN,A,Q)}static rateLimited(A,Q){return new z(f.QUOTA,A,{retryable:!0,...Q})}static internal(A="Internal error",Q){return new z(f.INTERNAL,A,Q)}}function uB(A,Q="Unexpected error"){if(A instanceof z)return A;if(A?.name==="AbortError"||A?.code==="ABORT_ERR")return z.aborted(A.message||"Operation aborted",{cause:A});if(new Set(["ECONNRESET","ECONNREFUSED","ETIMEDOUT","EAI_AGAIN","EPIPE","ENOTFOUND","UND_ERR_SOCKET"]).has(A?.code)||A instanceof TypeError&&/fetch|network/i.test(A.message||""))return z.transient(A.message||"Network error",{cause:A});switch(A?.code){case"ENOENT":return z.notFound(null,{cause:A});case"EEXIST":return z.alreadyExists("Path",{cause:A});case"EACCES":case"EPERM":return new z(f.FORBIDDEN,"Permission denied",{cause:A});case"ENOSPC":return new z(f.QUOTA,"The storage volume is full — free some space and try again",{cause:A,retryable:!1});case"EDQUOT":return new z(f.QUOTA,"The storage quota for this volume has been reached",{cause:A,retryable:!1});case"EFBIG":return new z(f.QUOTA,"That file is larger than this filesystem can store",{cause:A,retryable:!1})}return z.internal(A?.message||Q,{cause:A})}function eK(A){if(A instanceof z)return A.retryable;return uB(A).retryable}function AL(A=""){let Q=(globalThis.crypto?.randomUUID?.()??g6()).replace(/-/g,"");return A?`${A}_${Q}`:Q}function g6(){let A="";for(let Q=0;Q<32;Q++)A+=Math.floor(Math.random()*16).toString(16);return A}function QL(A){let Q=String(A||"").lastIndexOf(".");return Q>0?String(A).slice(Q).toLowerCase():""}function xC(A,Q){if(!A||!Q)return!1;if(typeof A.match==="function")try{if(A.match(Q))return!0}catch{}let B=QL(Q.name||"");if(B&&(A.ext||[]).some((J)=>(J.startsWith(".")?J:"."+J).toLowerCase()===B))return!0;let C=Q.contentType||"";return(A.mime||A.contentType||[]).some((J)=>J.endsWith("/*")?C.startsWith(J.slice(0,-1)):C===J)}var WB="trove+contrib:",BL="core",y6=/^(?:core|[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)+)$/,h6=/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;function b6(A){return typeof A==="string"&&y6.test(A)}function kC(A){return typeof A==="string"&&h6.test(A)}function EQ(A){return gC(A),`${A.domain}/${A.name}`}function xQ(A,Q){if(!kC(Q))throw z.invalid(`Invalid contribution name "${Q}"`);return`${WB}${EQ(A)}/${Q}`}var v6="workbench";function CL(A){return`${WB}${BL}/${v6}/${A}`}function kQ(A){if(typeof A!=="string"||!A.startsWith(WB))return null;let Q=A.slice(WB.length),B=Q.indexOf("/"),C=Q.indexOf("/",B+1);if(B<0||C<0)return null;let E=Q.slice(0,B),J=Q.slice(B+1,C),K=Q.slice(C+1);if(!E||!J||!K)return null;return{domain:E,plugin:J,name:K,pluginId:`${E}/${J}`}}function EL(A,Q){let B=kQ(Q);return!!B&&B.pluginId===`${A.domain}/${A.name}`}function gC(A){if(!b6(A?.domain))throw z.invalid(`Plugin manifest needs a valid "domain" (got ${JSON.stringify(A?.domain)})`);if(!kC(A?.name))throw z.invalid(`Plugin manifest needs a valid "name" (got ${JSON.stringify(A?.name)})`);if(A.domain===BL)throw z.invalid('The "core" domain is reserved for built-in contributions')}var KL={command:{normalize:(A)=>({title:A.title||null,category:A.category||null,icon:A.icon||null,when:A.when||null,palette:A.palette!==!1,offline:!!A.offline})},opener:{needsEntry:!0,normalize:(A)=>({title:A.title||null,match:JL(A.match),priority:A.priority??50,when:A.when||null,offline:!!A.offline,dock:A.dock||null})},indexer:{needsEntry:!0,normalize:(A)=>({title:A.title||null,match:JL(A.match)})},statusItem:{normalize:(A)=>{let Q=A.slot==="left"?"left":"right",B=A.render||"html";if(B!=="html")throw z.invalid(`statusItem "render" must be "html" (got ${JSON.stringify(B)})`);return{slot:Q,render:B,order:A.order??0,when:A.when||null,offline:!!A.offline,command:A.command||null}}},register:{normalize:(A)=>({default:A.default??null,description:A.description||null})},keymap:{normalize:(A)=>{if(!A.path||typeof A.path!=="string")throw z.invalid('keymap contribution needs a "path" to a JSON file in the package');return{path:A.path}}}},_0=Object.keys(KL);function IQ(A){let Q=A?.contributes;if(Q==null)return[];if(typeof Q!=="object"||Array.isArray(Q))throw z.invalid('manifest "contributes" must be a map of name -> contribution');let B=[];for(let[C,E]of Object.entries(Q)){if(!E||typeof E!=="object")throw z.invalid(`Contribution "${C}" must be an object`);if(!kC(C))throw z.invalid(`Invalid contribution name "${C}"`);let J=KL[E.type];if(!J)throw z.invalid(`Contribution "${C}" has unknown type ${JSON.stringify(E.type)} (expected one of ${_0.join(", ")})`);let K=E.entry||A.entry;if(J.needsEntry&&!K)throw z.invalid(`Contribution "${C}" (${E.type}) needs an "entry" module`);B.push({name:C,uri:xQ(A,C),pluginId:EQ(A),type:E.type,...J.normalize(E),...J.needsEntry?{entry:K}:{}})}return B}function f6(A,Q){return IQ(A).filter((B)=>B.type===Q)}function T0(A){return f6(A,"indexer").map((Q)=>({id:Q.uri,name:Q.name,title:Q.title||Q.name,match:Q.match,entry:Q.entry}))}function LL(A){let Q;try{Q=JSON.parse(A)}catch(C){throw z.invalid("Keymap file is not valid JSON",{cause:C})}let B=Array.isArray(Q)?Q:Array.isArray(Q?.bindings)?Q.bindings:null;if(!B)throw z.invalid("Keymap file must be a JSON array of bindings");return B.filter((C)=>C&&typeof C.key==="string"&&typeof C.command==="string").map((C)=>({key:C.key,command:C.command,when:typeof C.when==="string"?C.when:null,args:Array.isArray(C.args)?C.args:void 0}))}function JL(A){if(!A||typeof A!=="object"||Array.isArray(A))return{};let Q=(J)=>J==null?void 0:(Array.isArray(J)?J:[J]).filter((K)=>typeof K==="string"),B={},C=Q(A.ext),E=Q(A.mime??A.contentType);if(C)B.ext=C;if(E)B.mime=E;if(typeof A.match==="function")B.match=A.match;return B}var u6=[..._0,"view"];function yC(A){return String(A).startsWith(WB)?A:CL(A)}class x0{constructor(){this.items=new Map,this.cell=c([])}#A(){this.cell.setValue([...this.items.values()])}register(A,Q){let B=Q?.type;if(!u6.includes(B))throw Error(`Unknown contribution type "${B}" for ${A}`);let C=yC(A),E=kQ(C);if(!E)throw Error(`Not a contribution URI: ${C}`);let J=Q.pluginId??(E.domain==="core"?null:E.pluginId),K={...Q,uri:C,type:B,id:E.domain==="core"?E.name:C,name:E.name,pluginId:J};return this.items.set(C,K),this.#A(),()=>this.unregister(C)}update(A,Q){let B=yC(A),C=this.items.get(B);if(!C)return!1;return this.items.set(B,{...C,...Q}),this.#A(),!0}unregister(A){if(this.items.delete(yC(A)))this.#A()}get(A){return A?this.items.get(yC(A))||null:null}all(){return[...this.items.values()]}ofType(A){return this.all().filter((Q)=>Q.type===A)}observe(){return this.cell}openersFor(A){return this.ofType("opener").filter((Q)=>xC(Q.match,A)).sort((Q,B)=>(B.priority??0)-(Q.priority??0))}keybindings(){return this.ofType("keymap").flatMap((A)=>(A.bindings||[]).map((Q)=>({...Q,keymap:A.uri,pluginId:A.pluginId})))}}var k0=new Map;function m6(A){if(!A)return()=>!0;if(k0.has(A))return k0.get(A);let Q;try{Q=new XL(A).parseExpression()}catch(B){console.warn(`Invalid when clause: "${A}" — ${B.message}`),Q=()=>!1}return k0.set(A,Q),Q}function YL(A,Q){return m6(A)(Q||{})}var hC=/\s*(=~|==|!=|>=|<=|&&|\|\||[()!<>]|trove\+contrib:[A-Za-z0-9_./-]+|\/(?:\\.|[^/])*\/[a-z]*|'(?:\\.|[^'])*'|"(?:\\.|[^"])*"|[A-Za-z0-9_.:-]+)/y;class XL{constructor(A){this.src=A,this.tokens=this.#A(A),this.pos=0}#A(A){let Q=[],B=0;hC.lastIndex=0;while(B<A.length){hC.lastIndex=B;let C=hC.exec(A);if(!C||C.index==null){if(!A.slice(B).trim())break;throw Error(`Unexpected "${A.slice(B)}"`)}Q.push(C[1]),B=hC.lastIndex}return Q}#Q(){return this.tokens[this.pos]}#B(){return this.tokens[this.pos++]}#C(A){if(this.#Q()!==A)throw Error(`Expected "${A}"`);this.pos++}parseExpression(){let A=this.#E();if(this.pos!==this.tokens.length)throw Error(`Trailing "${this.#Q()}"`);return A}#E(){let A=this.#J();while(this.#Q()==="||"){this.#B();let Q=this.#J(),B=A;A=(C)=>B(C)||Q(C)}return A}#J(){let A=this.#K();while(this.#Q()==="&&"){this.#B();let Q=this.#K(),B=A;A=(C)=>B(C)&&Q(C)}return A}#K(){if(this.#Q()==="!"){this.#B();let A=this.#K();return(Q)=>!A(Q)}return this.#L()}#L(){let A=this.#Y(),Q=this.#Q();if(["==","!=",">=","<=",">","<","=~"].includes(Q)){if(this.#B(),Q==="=~"){let C=this.#B(),E=p6(C);return(J)=>E.test(String(A(J)??""))}let B=this.#Y();return(C)=>c6(Q,A(C),B(C))}return(B)=>l6(A(B))}#Y(){let A=this.#B();if(A===void 0)throw Error("Unexpected end");if(A==="("){let Q=this.#E();return this.#C(")"),Q}if(A==="true")return()=>!0;if(A==="false")return()=>!1;if(/^-?\d+(\.\d+)?$/.test(A)){let Q=Number(A);return()=>Q}if(A[0]==="'"||A[0]==='"'){let Q=A.slice(1,-1).replace(/\\(.)/g,"$1");return()=>Q}return(Q)=>Q[A]}}function p6(A){let Q=/^\/((?:\\.|[^/])*)\/([a-z]*)$/.exec(A);if(!Q)throw Error(`Bad regex ${A}`);return new RegExp(Q[1],Q[2])}function l6(A){return!(A===void 0||A===null||A===!1||A===""||A===0)}function c6(A,Q,B){switch(A){case"==":return Q==B;case"!=":return Q!=B;case">":return Q>B;case"<":return Q<B;case">=":return Q>=B;case"<=":return Q<=B}return!1}var d6=(A)=>({onDirty:()=>()=>{},getValue:()=>A});class g0{#A=new Map;#Q=new Map;#B=c({});constructor(A={}){let Q={platform:GL(),isMac:/mac/i.test(GL()),...A};for(let[B,C]of Object.entries(Q))this.register(B,d6(C))}register(A,Q){if(this.#A.has(A))throw Error(`Context key "${A}" already has an owner`);return this.#A.set(A,Q),this.#Q.set(A,Q.onDirty(()=>this.#C(A))),this.#C(A),()=>this.unregister(A)}unregister(A){let Q=this.#Q.get(A);if(!Q)return;Q(),this.#Q.delete(A),this.#A.delete(A),this.#C(A)}#C(){this.#E()}own(A,Q=void 0){let B=c(Q),C=this.register(A,B);return{set:(E)=>B.setValue(E),dispose:C}}#E(){let A={};for(let[Q,B]of this.#A)A[Q]=B.getValue();this.#B.setValue(A)}snapshot(){return this.#B.getValue()}get(A){return this.#A.get(A)?.getValue()}observe(){return this.#B}evaluate(A){return YL(A,this.snapshot())}}function GL(){return typeof navigator<"u"?navigator.platform||navigator.userAgent||"":""}var lA=(A,Q)=>A.dispatch(Q).next(["complete","error","abort"]);class y0{constructor(A,Q,B){this.contributions=A,this.context=Q,this.notifications=B,this.handlers=new Map,this.dispatch=()=>{throw Error("CommandService has no dispatcher yet — see createApp")}}register(A,Q){let B=typeof A==="string"?{id:A,actions:Q}:A;if(B.actions)this.handlers.set(B.id,B.actions);let C=this.contributions.register(B.id,{type:"command",title:B.title??B.id,category:B.category,icon:B.icon,when:B.when,palette:B.palette??!0,pluginId:B.pluginId,offline:B.offline});return()=>{this.handlers.delete(B.id),C()}}isEnabled(A){let Q=this.contributions.get(A);if(Q?.when&&!this.context.evaluate(Q.when))return!1;return this.isAvailable(Q)}isAvailable(A){if(!A)return!0;return this.availability?this.availability(A):!0}async execute(A,...Q){let B=this.handlers.get(A);if(!B){this.notifications.error(`Command not found: ${A}`);return}let C=this.contributions.get(A);if(!this.isAvailable(C)){this.notifications.warn(`“${C?.title||A}” isn’t available right now.`);return}if(!this.isEnabled(A))return;try{let E=B(...Q);if(!E)return;for(let J of[].concat(E))if((await lA(this,J))?.type!=="complete")break}catch(E){throw console.error(`Command ${A} failed`,E),this.notifications.error(E?.message||`Command failed: ${A}`),E}}paletteCommands(){return this.contributions.ofType("command").filter((A)=>A.palette!==!1&&(!A.when||this.context.evaluate(A.when))).sort((A,Q)=>(A.category||"").localeCompare(Q.category||"")||A.title.localeCompare(Q.title))}}function h0(A){let Q=A.trim().toLowerCase().split("+").map((J)=>J.trim()),B=new Set,C="";for(let J of Q)if(["ctrl","control"].includes(J))B.add("ctrl");else if(["cmd","meta","super","win"].includes(J))B.add("meta");else if(J==="alt"||J==="option")B.add("alt");else if(J==="shift")B.add("shift");else if(["ctrlcmd","mod"].includes(J))B.add(HL()?"meta":"ctrl");else C=J;return[...["ctrl","meta","alt","shift"].filter((J)=>B.has(J)),C].filter(Boolean).join("+")}function b0(A){let Q=[];if(A.ctrlKey)Q.push("ctrl");if(A.metaKey)Q.push("meta");if(A.altKey)Q.push("alt");if(A.shiftKey)Q.push("shift");let B=A.key.toLowerCase();return B={" ":"space",escape:"escape",enter:"enter",arrowup:"up",arrowdown:"down",arrowleft:"left",arrowright:"right"}[B]||B,[...Q.filter((E)=>B!==E),B].join("+")}class UB{constructor(A,Q,B,C=null){this.contributions=A,this.commands=Q,this.context=B,this.settings=C,this.chordPrefix=null,this.chordTimer=null,this._onKeyDown=this.#B.bind(this)}install(A=window){return A.addEventListener("keydown",this._onKeyDown),()=>A.removeEventListener("keydown",this._onKeyDown)}overrides(){return this.settings?.get("keybindings.overrides")||{}}static bindingId(A){return`${A.command}\x00${h0(A.defaultKey||A.key)}`}rebind(A,Q){if(!this.settings)return;let B=typeof A==="string"?this.#A(A):UB.bindingId(A);if(!B)return;let C={...this.overrides()};if(Q)C[B]=Q;else delete C[B];this.settings.set("keybindings.overrides",C)}#A(A){let Q=this.contributions.keybindings().find((B)=>B?.command===A&&B.key);return Q?UB.bindingId({...Q,defaultKey:Q.key}):null}resolved(){let A=this.overrides();return this.contributions.keybindings().filter((Q)=>Q?.key&&Q.command).map((Q)=>{let B=h0(Q.key),C=UB.bindingId({command:Q.command,defaultKey:B});return{...Q,defaultKey:B,bindingId:C,key:h0(A[C]||Q.key)}})}#Q(A){let Q=this.context.snapshot(),B=this.resolved();for(let C=B.length-1;C>=0;C--){let E=B[C];if(E.key!==A)continue;if(E.when&&!this.context.evaluate(E.when))continue;return E}return null}#B(A){if(A.defaultPrevented)return;let Q=b0(A),B=A.ctrlKey||A.metaKey||A.altKey;if(a6(A.target)&&!B&&A.key!=="Escape"){this.#C();return}let E=this.chordPrefix?`${this.chordPrefix} ${Q}`:Q,J=this.#Q(E);if(J){A.preventDefault(),this.#C(),this.commands.execute(J.command,...J.args||[]);return}if(!this.chordPrefix&&this.resolved().some((K)=>K.key.startsWith(Q+" "))){A.preventDefault(),this.chordPrefix=Q,this.chordTimer=setTimeout(()=>this.#C(),1500);return}this.#C()}#C(){if(this.chordPrefix=null,this.chordTimer)clearTimeout(this.chordTimer);this.chordTimer=null}labelFor(A){let Q=this.resolved().find((B)=>B.command===A);return Q?v0(Q.key):null}}function a6(A){if(!A)return!1;let Q=A.tagName;return Q==="INPUT"||Q==="TEXTAREA"||Q==="SELECT"||A.isContentEditable}function HL(){return typeof navigator<"u"&&/mac/i.test(navigator.platform||navigator.userAgent||"")}function v0(A){let Q=HL(),B=Q?{ctrl:"⌃",meta:"⌘",alt:"⌥",shift:"⇧",enter:"↵",escape:"esc",up:"↑",down:"↓",left:"←",right:"→",space:"␣"}:{ctrl:"Ctrl",meta:"Win",alt:"Alt",shift:"Shift",enter:"Enter",escape:"Esc",up:"↑",down:"↓",left:"←",right:"→",space:"Space"};return A.split(" ").map((C)=>C.split("+").map((E)=>B[E]||(E.length===1?E.toUpperCase():E[0].toUpperCase()+E.slice(1))).join(Q?"":"+")).join(" ")}var DL="trove.settings";class f0{constructor(){this.schema=new Map,this.values=n6(),this.cell=c(this.effective())}register(A){for(let Q of[].concat(A))this.schema.set(Q.key,Q);return this.cell.setValue(this.effective()),()=>{for(let Q of[].concat(A))this.schema.delete(Q.key);this.cell.setValue(this.effective())}}get(A){if(A in this.values)return this.values[A];return this.schema.get(A)?.default}set(A,Q){let B=this.schema.get(A);if(B&&Q===B.default)delete this.values[A];else this.values[A]=Q;$L(this.values),this.cell.setValue(this.effective())}reset(A){delete this.values[A],$L(this.values),this.cell.setValue(this.effective())}effective(){let A={};for(let[Q,B]of this.schema)A[Q]=Q in this.values?this.values[Q]:B.default;for(let[Q,B]of Object.entries(this.values))if(!(Q in A))A[Q]=B;return A}observe(){return this.cell}grouped(){let A=new Map;for(let Q of[...this.schema.values()].sort((B,C)=>(B.order??0)-(C.order??0))){if(Q.hidden)continue;let B=Q.category||"General";if(!A.has(B))A.set(B,[]);A.get(B).push({...Q,value:this.get(Q.key)})}return[...A.entries()].map(([Q,B])=>({category:Q,items:B}))}scopedFor(A){let Q=`${A}.`;return{register:(B)=>this.register([].concat(B).map((C)=>({...C,key:Q+C.key,category:C.category||A}))),get:(B)=>this.get(Q+B),set:(B,C)=>this.set(Q+B,C)}}}function n6(){try{return JSON.parse(localStorage.getItem(DL))||{}}catch{return{}}}function $L(A){try{localStorage.setItem(DL,JSON.stringify(A))}catch{}}var s6=0;class u0{constructor(){this.items=[],this.cell=c([])}observe(){return this.cell}#A(A,Q,B={}){let C={id:++s6,level:A,message:Q,actions:B.actions||null,createdAt:Date.now(),sticky:B.sticky||A==="error"};if(this.items=[...this.items,C],this.cell.setValue(this.items),!C.sticky)setTimeout(()=>this.dismiss(C.id),B.timeout??4000);return C.id}info(A,Q){return this.#A("info",A,Q)}success(A,Q){return this.#A("success",A,Q)}warn(A,Q){return this.#A("warn",A,Q)}error(A,Q){return this.#A("error",A,Q)}update(A,Q){this.items=this.items.map((B)=>B.id===A?{...B,...Q}:B),this.cell.setValue(this.items)}dismiss(A){this.items=this.items.filter((Q)=>Q.id!==A),this.cell.setValue(this.items)}}var o6={retries:4,minDelayMs:250,maxDelayMs:8000,factor:2,jitter:!0};function i6(A,Q){return new Promise((B,C)=>{if(Q?.aborted)return C(z.aborted());let E=(L)=>(Y)=>{clearTimeout(J),Q?.removeEventListener("abort",K),L(Y)},J=setTimeout(()=>E(B)(),A),K=()=>E(C)(z.aborted());Q?.addEventListener("abort",K,{once:!0})})}async function FB(A,Q={}){let B={...o6,...Q},C=B.shouldRetry??eK,E=0;for(;;){if(B.signal?.aborted)throw z.aborted();try{return await A(E)}catch(J){let K=uB(J);if(!(E<B.retries&&C(K)&&K.code!=="aborted"))throw K;let Y=Math.min(B.maxDelayMs,B.minDelayMs*B.factor**E),X=B.jitter?Math.random()*Y:Y;B.onRetry?.({attempt:E+1,delayMs:X,error:K}),await i6(X,B.signal),E++}}}class m0{constructor({baseUrl:A="",fetch:Q=globalThis.fetch.bind(globalThis),token:B=null}={}){this.baseUrl=A.replace(/\/$/,""),this._fetch=Q,this._token=B}token(){return(typeof this._token==="function"?this._token():this._token)||null}authHeaders(){let A=this.token();return A?{authorization:`Bearer ${A}`}:{}}async request(A,Q,{body:B,query:C,signal:E,raw:J}={}){let K=this.baseUrl+Q+(C?"?"+new URLSearchParams(C):"");return FB(async()=>{let L=await this._fetch(K,{method:A,headers:{...this.authHeaders(),...B?{"content-type":"application/json"}:{}},body:B?JSON.stringify(B):void 0,signal:E});if(L.status===429||L.status>=500){if(!J){let H;try{let G=await L.text();H=(G?JSON.parse(G):null)?.error}catch{}if(H&&H.retryable===!1)throw new z(H.code,H.message,{retryable:!1,details:H.details});throw z.transient(H?.message||`Server ${L.status}`)}throw z.transient(`Server ${L.status}`)}if(J)return L;let Y=await L.text(),X=Y?JSON.parse(Y):null;if(!L.ok){let H=X?.error||{code:"internal",message:`Request failed (${L.status})`};throw new z(H.code,H.message,{retryable:H.retryable,details:H.details})}return X},{signal:E,retries:3})}capabilities(){return this.request("GET","/api/capabilities")}async reachable(A=4000){try{let Q=AbortSignal.timeout?AbortSignal.timeout(A):void 0;return(await this._fetch(this.baseUrl+"/api/capabilities",{method:"GET",signal:Q,headers:this.authHeaders()})).ok}catch{return!1}}list(A,Q={}){return this.request("GET",`${this.#A(A)}/items`,{query:Q})}stat(A,{collection:Q,...B}={}){let C=String(A).startsWith("trove:")?"uri":"id",E=Q?`${this.#A(Q)}/items/resolve`:"/api/items/resolve";return this.request("GET",E,{query:{[C]:A,...B}})}#A(A){if(!A)throw Error("This call is scoped to a collection — pass one");return`/api/collections/${encodeURIComponent(A)}`}backlinks(A,Q={}){return this.request("GET","/api/items/backlinks",{query:{id:A,...Q}})}rename(A,Q){return this.request("POST","/api/items/rename",{body:{id:A,newName:Q}})}remove(A){return this.request("POST","/api/items/delete",{body:{id:A}})}trash(A){return this.request("GET",`${this.#A(A)}/trash`)}restore(A){return this.request("POST","/api/trash/restore",{body:{id:A}})}purgeTrash({id:A,collection:Q}={}){return A?this.request("POST","/api/trash/purge",{body:{id:A}}):this.request("POST",`${this.#A(Q)}/trash/purge`)}search(A,{collection:Q,...B}={}){let C=Q?`${this.#A(Q)}/search`:"/api/search";return this.request("GET",C,{query:{q:A,...B}})}query(A,{collection:Q,...B}={}){let C=Q?`${this.#A(Q)}/query`:"/api/query";return this.request("POST",C,{body:{q:A,...B}})}tagSearch(A,Q,{collection:B,...C}={}){let E=B?`${this.#A(B)}/tags/search`:"/api/tags/search";return this.request("POST",E,{body:{filters:A,q:Q,...C}})}indexers(){return this.request("GET","/api/indexers")}tasks(){return this.request("GET","/api/tasks")}cancelTask(A){return this.request("POST",`/api/tasks/${encodeURIComponent(A)}/cancel`)}dismissTask(A){return this.request("DELETE",`/api/tasks/${encodeURIComponent(A)}`)}issues(){return this.request("GET","/api/issues")}retryIssue(A){return this.request("POST",`/api/issues/${encodeURIComponent(A)}/retry`)}dismissIssue(A){return this.request("DELETE",`/api/issues/${encodeURIComponent(A)}`)}reindex(){return this.request("POST","/api/reindex")}scanCollection(A){return this.request("POST",`/api/collections/${encodeURIComponent(A)}/scan`)}checkStorage(){return this.request("POST","/api/diagnostics/storage")}async installPlugin(A,Q){let B=Q&&Q.length?"?grants="+encodeURIComponent(Q.join(",")):"",C=await this._fetch(this.baseUrl+"/api/plugins/install"+B,{method:"POST",body:A,headers:this.authHeaders()}),E=await C.json().catch(()=>null);if(!C.ok){let J=E?.error||{code:"internal",message:`Install failed (${C.status})`};throw new z(J.code,J.message,{details:J.details})}return E.install}installedPlugins(){return this.request("GET","/api/plugins/installed")}async pluginPackage(A){let Q=await this._fetch(`${this.baseUrl}/api/plugins/${encodeURIComponent(A)}/package`,{headers:this.authHeaders()});if(!Q.ok)throw new z("not_found",`Package for "${A}" not found`);return new Uint8Array(await Q.arrayBuffer())}uninstallPluginServer(A){return this.request("DELETE",`/api/plugins/${encodeURIComponent(A)}/install`)}pushIndex(A,Q,B){return this.request("POST",`/api/index/${encodeURIComponent(A)}`,{body:{nodeId:Q,...B}})}me(){return this.request("GET","/api/me")}collections(){return this.request("GET","/api/collections")}createCollection(A){return this.request("POST","/api/collections",{body:A})}updateCollection(A,Q){return this.request("PATCH",`/api/collections/${encodeURIComponent(A)}`,{body:Q})}rotationEstimate(A){return this.request("GET",`/api/collections/${encodeURIComponent(A)}/rotate/estimate`)}collectionGrants(A){return this.request("GET",`/api/collections/${encodeURIComponent(A)}/grants`)}setCollectionGrant(A,Q){return this.request("POST",`/api/collections/${encodeURIComponent(A)}/grants`,{body:Q})}rotationState(A){return this.request("GET",`/api/collections/${encodeURIComponent(A)}/rotate`)}beginRotation(A){return this.request("POST",`/api/collections/${encodeURIComponent(A)}/rotate`)}cancelRotation(A){return this.request("DELETE",`/api/collections/${encodeURIComponent(A)}/rotate`)}sidecar(A){return this.request("GET",`/api/items/${encodeURIComponent(A)}/sidecar`)}addComment(A,{body:Q,parentId:B,mentions:C}={}){return this.request("POST",`/api/items/${encodeURIComponent(A)}/comments`,{body:{body:Q,parentId:B,mentions:C}})}editComment(A,Q,B){return this.request("POST",`/api/items/${encodeURIComponent(A)}/comments/${encodeURIComponent(Q)}/edit`,{body:{body:B}})}deleteComment(A,Q){return this.request("DELETE",`/api/items/${encodeURIComponent(A)}/comments/${encodeURIComponent(Q)}`)}reactComment(A,Q,B,C){return this.request("POST",`/api/items/${encodeURIComponent(A)}/comments/${encodeURIComponent(Q)}/react`,{body:{emoji:B,on:C}})}setTag(A,Q,B){return this.request("POST",`/api/items/${encodeURIComponent(A)}/tags`,{body:{name:Q,value:B}})}removeTag(A,Q){return this.request("DELETE",`/api/items/${encodeURIComponent(A)}/tags/${encodeURIComponent(Q)}`)}notifications(){return this.request("GET","/api/notifications")}markNotificationsRead(A){return this.request("POST","/api/notifications/read",{body:{ids:A}})}vapidKey(){return this.request("GET","/api/push/vapid")}apiKeys(){return this.request("GET","/api/keys")}mintApiKey({name:A,scopes:Q,expiresAt:B=null}){return this.request("POST","/api/keys",{body:{name:A,scopes:Q,expiresAt:B}})}revokeApiKey(A){return this.request("DELETE",`/api/keys/${encodeURIComponent(A)}`)}subscribePush(A){return this.request("POST","/api/push/subscribe",{body:{subscription:A}})}downloadUrl(A,{attachment:Q}={}){return`${this.baseUrl}/api/items/download?id=${encodeURIComponent(A)}${Q?"&disposition=attachment":""}`}mintUrls(A,Q="media"){return this.request("POST","/api/items/urls",{body:{ids:A,op:Q}})}async download(A,Q,{attachment:B=!0}={}){let C=this.downloadUrl(A,{attachment:B});if(!this.token())return{url:C,streamed:!0};let E=await this._fetch(C,{headers:this.authHeaders()});if(!E.ok)throw new z("internal",`Download failed (${E.status})`);return{url:URL.createObjectURL(await E.blob()),streamed:!1,revoke:!0}}async readBytes(A,{signal:Q}={}){let B=await this._fetch(this.downloadUrl(A),{signal:Q,headers:this.authHeaders()});if(!B.ok)throw new z("internal",`Download failed (${B.status})`);return new Uint8Array(await B.arrayBuffer())}async readText(A,Q){return new TextDecoder().decode(await this.readBytes(A,Q))}async readRange(A,{start:Q=0,end:B,signal:C}={}){let E=B==null?`bytes=${Q}-`:`bytes=${Q}-${B-1}`,J=await this._fetch(this.downloadUrl(A),{signal:C,headers:{...this.authHeaders(),range:E}});if(J.status===416)return{bytes:new Uint8Array(0),etag:J.headers.get("etag"),total:0};if(!J.ok&&J.status!==206)throw new z("internal",`Read failed (${J.status})`);let K=new Uint8Array(await J.arrayBuffer()),L=Number(/\/(\d+)$/.exec(J.headers.get("content-range")||"")?.[1])||(J.status===200?K.length:null);return{bytes:K,etag:J.headers.get("etag"),total:L}}async readTextCapped(A,{maxBytes:Q=524288,size:B=null,signal:C}={}){let E=B==null||B>Q,J=await this._fetch(this.downloadUrl(A),{signal:C,headers:{...this.authHeaders(),...E?{range:`bytes=0-${Q-1}`}:{}}});if(J.status===416)return{text:"",truncated:!1,total:0};if(!J.ok&&J.status!==206)throw new z("internal",`Download failed (${J.status})`);let K=new Uint8Array(await J.arrayBuffer()),L=Number(/\/(\d+)$/.exec(J.headers.get("content-range")||"")?.[1])||null,Y=K.length>=Q&&(L==null||L>K.length),X=new TextDecoder("utf-8",{fatal:!1}).decode(K);if(Y){let H=X.lastIndexOf(`
|
|
4
|
-
`);if(H>0)X=X.slice(0,H)}return{text:X,truncated:Y,total:L}}async upload(A,Q){let B=Q.name||A.name||"untitled",C=A.size,E=(k)=>FB(k,{signal:Q.signal,retries:4,onRetry:({attempt:v,delayMs:O,error:g})=>Q.onRetry?.({attempt:v,delayMs:O,message:g.message})}),J=await E(()=>this.request("POST",`${this.#A(Q.collection)}/uploads`,{body:{name:B,size:C,contentType:A.type||void 0},signal:Q.signal}));if(J.uploadId)Q.onStart?.(J.uploadId);let K=new ZL(C,Q.onProgress),L=J.transfer||{},Y=J.endpoints?.complete||`/api/uploads/${J.uploadId}/complete`;if(J.strategy==="single"){let k=A;return await E(()=>bC(L.url||J.url,k,{headers:L.requiredHeaders,signal:Q.signal,onProgress:(O)=>K.set("single",O)})),(await E(()=>this.request("POST",Y,{body:{},signal:Q.signal}))).node}if(J.strategy==="direct-single"){let k=A;return await E(()=>bC(this.baseUrl+this.#Q(J,1),k,{headers:{...this.authHeaders(),...L.authHeaders},signal:Q.signal,onProgress:(O)=>K.set(1,O)})),(await E(()=>this.request("POST",Y,{body:{},signal:Q.signal}))).node}let X=J.partSize,H=J.partCount??Math.ceil(C/X),G=new Set;try{let k=J.endpoints?.status||`/api/uploads/${J.uploadId}/status`,v=await this.request("GET",k,{signal:Q.signal});G=new Set(v.received||[])}catch{}let D=[],U=[];for(let k=1;k<=H;k++){let v=(k-1)*X,O=A.slice(v,Math.min(v+X,C));U.push({n:k,blob:O})}let I=Array(H),R=Math.min(Q.concurrency??4,U.length),V=0,_=new AbortController,m=()=>_.abort();if(Q.signal)if(Q.signal.aborted)_.abort();else Q.signal.addEventListener("abort",m,{once:!0});let b=async()=>{while(V<U.length){if(_.signal.aborted)return;let{n:k,blob:v}=U[V++];if(G.has(k)){K.set(k,v.size);continue}let O=await FB(()=>this.#B(J,k,v,{signal:_.signal,onProgress:(g)=>K.set(k,g)}),{signal:_.signal,retries:4,onRetry:({attempt:g,delayMs:e,error:AA})=>Q.onRetry?.({attempt:g,delayMs:e,part:k,message:AA.message})});I[k-1]={partNumber:k,etag:O}}};try{await Promise.all(Array.from({length:R},b))}catch(k){throw _.abort(),k}finally{Q.signal?.removeEventListener("abort",m)}let q=I.filter(Boolean);return(await E(()=>this.request("POST",Y,{body:{parts:q},signal:Q.signal}))).node}#Q(A,Q){return(A.transfer?.partUrl||`/api/uploads/${A.uploadId}/parts/{partNumber}`).replace("{partNumber}",String(Q))}async#B(A,Q,B,{signal:C,onProgress:E}){let J=A.transfer||{};if(A.strategy==="presign"){let Y=(J.parts||A.parts)?.find((D)=>D.partNumber===Q)?.url;if(!Y){let D=A.endpoints?.sign||`/api/uploads/${A.uploadId}/parts/{partNumber}/sign`;Y=(await this.request("POST",D.replace("{partNumber}",String(Q)),{signal:C})).url}let H=(await bC(Y,B,{signal:C,onProgress:E,wantEtag:!0})).etag,G=A.endpoints?.report||`/api/uploads/${A.uploadId}/parts/{partNumber}/report`;return await this.request("POST",G.replace("{partNumber}",String(Q)),{body:{etag:H},signal:C}),H}return(await bC(this.baseUrl+this.#Q(A,Q),B,{headers:{...this.authHeaders(),...J.authHeaders},signal:C,onProgress:E,wantJson:!0})).json?.etag}async abortUpload(A){return this.request("DELETE",`/api/uploads/${A}`)}}class ZL{constructor(A,Q){this.total=A,this.cb=Q,this.parts=new Map}set(A,Q){let B=this.parts.get(A)||0;if(Q<B)return;if(this.parts.set(A,Q),!this.cb)return;let C=0;for(let J of this.parts.values())C+=J;let E=Math.min(C,this.total);this.cb({loaded:E,total:this.total,ratio:this.total?E/this.total:1})}}function bC(A,Q,{signal:B,onProgress:C,wantEtag:E,wantJson:J,headers:K}={}){return new Promise((L,Y)=>{let X=new XMLHttpRequest;X.open("PUT",A,!0);for(let[H,G]of Object.entries(K||{}))try{X.setRequestHeader(H,G)}catch{}if(B){if(B.aborted)return X.abort(),Y(z.aborted());B.addEventListener("abort",()=>X.abort(),{once:!0})}X.upload.onprogress=(H)=>C?.(H.loaded),X.onload=()=>{if(X.status>=200&&X.status<300){let H={status:X.status};if(E)H.etag=X.getResponseHeader("ETag")||X.getResponseHeader("etag");if(J)try{H.json=JSON.parse(X.responseText)}catch{}L(H)}else if(X.status===429||X.status>=500)Y(z.transient(`Upload part failed (${X.status})`));else Y(new z("internal",`Upload failed (${X.status})`))},X.onerror=()=>Y(z.transient("Network error during upload")),X.onabort=()=>Y(z.aborted()),X.send(Q)})}var CA=Uint8Array,gA=Uint16Array,t0=Int32Array,vC=new CA([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),fC=new CA([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),a0=new CA([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),VL=function(A,Q){var B=new gA(31);for(var C=0;C<31;++C)B[C]=Q+=1<<A[C-1];var E=new t0(B[30]);for(var C=1;C<30;++C)for(var J=B[C];J<B[C+1];++J)E[J]=J-B[C]<<5|C;return{b:B,r:E}},qL=VL(vC,2),zL=qL.b,n0=qL.r;zL[28]=258,n0[258]=28;var NL=VL(fC,0),r6=NL.b,WL=NL.r,s0=new gA(32768);for(u=0;u<32768;++u)JQ=(u&43690)>>1|(u&21845)<<1,JQ=(JQ&52428)>>2|(JQ&13107)<<2,JQ=(JQ&61680)>>4|(JQ&3855)<<4,s0[u]=((JQ&65280)>>8|(JQ&255)<<8)>>1;var JQ,u,LQ=function(A,Q,B){var C=A.length,E=0,J=new gA(Q);for(;E<C;++E)if(A[E])++J[A[E]-1];var K=new gA(Q);for(E=1;E<Q;++E)K[E]=K[E-1]+J[E-1]<<1;var L;if(B){L=new gA(1<<Q);var Y=15-Q;for(E=0;E<C;++E)if(A[E]){var X=E<<4|A[E],H=Q-A[E],G=K[A[E]-1]++<<H;for(var D=G|(1<<H)-1;G<=D;++G)L[s0[G]>>Y]=X}}else{L=new gA(C);for(E=0;E<C;++E)if(A[E])L[E]=s0[K[A[E]-1]++]>>15-A[E]}return L},gQ=new CA(288);for(u=0;u<144;++u)gQ[u]=8;var u;for(u=144;u<256;++u)gQ[u]=9;var u;for(u=256;u<280;++u)gQ[u]=7;var u;for(u=280;u<288;++u)gQ[u]=8;var u,lB=new CA(32);for(u=0;u<32;++u)lB[u]=5;var u,t6=LQ(gQ,9,0),e6=LQ(gQ,9,1),AH=LQ(lB,5,0),QH=LQ(lB,5,1),p0=function(A){var Q=A[0];for(var B=1;B<A.length;++B)if(A[B]>Q)Q=A[B];return Q},rA=function(A,Q,B){var C=Q/8|0;return(A[C]|A[C+1]<<8)>>(Q&7)&B},l0=function(A,Q){var B=Q/8|0;return(A[B]|A[B+1]<<8|A[B+2]<<16)>>(Q&7)},e0=function(A){return(A+7)/8|0},cB=function(A,Q,B){if(Q==null||Q<0)Q=0;if(B==null||B>A.length)B=A.length;return new CA(A.subarray(Q,B))};var BH=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"],qA=function(A,Q,B){var C=Error(Q||BH[A]);if(C.code=A,Error.captureStackTrace)Error.captureStackTrace(C,qA);if(!B)throw C;return C},CH=function(A,Q,B,C){var E=A.length,J=C?C.length:0;if(!E||Q.f&&!Q.l)return B||new CA(0);var K=!B,L=K||Q.i!=2,Y=Q.i;if(K)B=new CA(E*3);var X=function(wQ){var SQ=B.length;if(wQ>SQ){var _Q=new CA(Math.max(SQ*2,wQ));_Q.set(B),B=_Q}},H=Q.f||0,G=Q.p||0,D=Q.b||0,U=Q.l,I=Q.d,R=Q.m,V=Q.n,_=E*8;do{if(!U){H=rA(A,G,1);var m=rA(A,G+1,3);if(G+=3,!m){var b=e0(G)+4,q=A[b-4]|A[b-3]<<8,p=b+q;if(p>E){if(Y)qA(0);break}if(L)X(D+q);B.set(A.subarray(b,p),D),Q.b=D+=q,Q.p=G=p*8,Q.f=H;continue}else if(m==1)U=e6,I=QH,R=9,V=5;else if(m==2){var k=rA(A,G,31)+257,v=rA(A,G+10,15)+4,O=k+rA(A,G+5,31)+1;G+=14;var g=new CA(O),e=new CA(19);for(var AA=0;AA<v;++AA)e[a0[AA]]=rA(A,G+AA*3,7);G+=v*3;var QA=p0(e),QQ=(1<<QA)-1,FA=LQ(e,QA,1);for(var AA=0;AA<O;){var IA=FA[rA(A,G,QQ)];G+=IA&15;var b=IA>>4;if(b<16)g[AA++]=b;else{var YA=0,t=0;if(b==16)t=3+rA(A,G,3),G+=2,YA=g[AA-1];else if(b==17)t=3+rA(A,G,7),G+=3;else if(b==18)t=11+rA(A,G,127),G+=7;while(t--)g[AA++]=YA}}var WA=g.subarray(0,k),XA=g.subarray(k);R=p0(WA),V=p0(XA),U=LQ(WA,R,1),I=LQ(XA,V,1)}else qA(1);if(G>_){if(Y)qA(0);break}}if(L)X(D+131072);var aQ=(1<<R)-1,OA=(1<<V)-1,iA=G;for(;;iA=G){var YA=U[l0(A,G)&aQ],jA=YA>>4;if(G+=YA&15,G>_){if(Y)qA(0);break}if(!YA)qA(2);if(jA<256)B[D++]=jA;else if(jA==256){iA=G,U=null;break}else{var RA=jA-254;if(jA>264){var AA=jA-257,r=vC[AA];RA=rA(A,G,(1<<r)-1)+zL[AA],G+=r}var pA=I[l0(A,G)&OA],PQ=pA>>4;if(!pA)qA(3);G+=pA&15;var XA=r6[PQ];if(PQ>3){var r=fC[PQ];XA+=l0(A,G)&(1<<r)-1,G+=r}if(G>_){if(Y)qA(0);break}if(L)X(D+131072);var OQ=D+RA;if(D<XA){var YB=J-XA,jQ=Math.min(XA,OQ);if(YB+D<0)qA(3);for(;D<jQ;++D)B[D]=C[YB+D]}for(;D<OQ;++D)B[D]=B[D-XA]}}if(Q.l=U,Q.p=iA,Q.b=D,Q.f=H,U)H=1,Q.m=R,Q.d=I,Q.n=V}while(!H);return D!=B.length&&K?cB(B,0,D):B.subarray(0,D)},RQ=function(A,Q,B){B<<=Q&7;var C=Q/8|0;A[C]|=B,A[C+1]|=B>>8},mB=function(A,Q,B){B<<=Q&7;var C=Q/8|0;A[C]|=B,A[C+1]|=B>>8,A[C+2]|=B>>16},c0=function(A,Q){var B=[];for(var C=0;C<A.length;++C)if(A[C])B.push({s:C,f:A[C]});var E=B.length,J=B.slice();if(!E)return{t:OL,l:0};if(E==1){var K=new CA(B[0].s+1);return K[B[0].s]=1,{t:K,l:1}}B.sort(function(p,k){return p.f-k.f}),B.push({s:-1,f:25001});var L=B[0],Y=B[1],X=0,H=1,G=2;B[0]={s:-1,f:L.f+Y.f,l:L,r:Y};while(H!=E-1)L=B[B[X].f<B[G].f?X++:G++],Y=B[X!=H&&B[X].f<B[G].f?X++:G++],B[H++]={s:-1,f:L.f+Y.f,l:L,r:Y};var D=J[0].s;for(var C=1;C<E;++C)if(J[C].s>D)D=J[C].s;var U=new gA(D+1),I=o0(B[H-1],U,0);if(I>Q){var C=0,R=0,V=I-Q,_=1<<V;J.sort(function(k,v){return U[v.s]-U[k.s]||k.f-v.f});for(;C<E;++C){var m=J[C].s;if(U[m]>Q)R+=_-(1<<I-U[m]),U[m]=Q;else break}R>>=V;while(R>0){var b=J[C].s;if(U[b]<Q)R-=1<<Q-U[b]++-1;else++C}for(;C>=0&&R;--C){var q=J[C].s;if(U[q]==Q)--U[q],++R}I=Q}return{t:new CA(U),l:I}},o0=function(A,Q,B){return A.s==-1?Math.max(o0(A.l,Q,B+1),o0(A.r,Q,B+1)):Q[A.s]=B},UL=function(A){var Q=A.length;while(Q&&!A[--Q]);var B=new gA(++Q),C=0,E=A[0],J=1,K=function(Y){B[C++]=Y};for(var L=1;L<=Q;++L)if(A[L]==E&&L!=Q)++J;else{if(!E&&J>2){for(;J>138;J-=138)K(32754);if(J>2)K(J>10?J-11<<5|28690:J-3<<5|12305),J=0}else if(J>3){K(E),--J;for(;J>6;J-=6)K(8304);if(J>2)K(J-3<<5|8208),J=0}while(J--)K(E);J=1,E=A[L]}return{c:B.subarray(0,C),n:Q}},pB=function(A,Q){var B=0;for(var C=0;C<Q.length;++C)B+=A[C]*Q[C];return B},PL=function(A,Q,B){var C=B.length,E=e0(Q+2);A[E]=C&255,A[E+1]=C>>8,A[E+2]=A[E]^255,A[E+3]=A[E+1]^255;for(var J=0;J<C;++J)A[E+J+4]=B[J];return(E+4+C)*8},FL=function(A,Q,B,C,E,J,K,L,Y,X,H){RQ(Q,H++,B),++E[256];var G=c0(E,15),D=G.t,U=G.l,I=c0(J,15),R=I.t,V=I.l,_=UL(D),m=_.c,b=_.n,q=UL(R),p=q.c,k=q.n,v=new gA(19);for(var O=0;O<m.length;++O)++v[m[O]&31];for(var O=0;O<p.length;++O)++v[p[O]&31];var g=c0(v,7),e=g.t,AA=g.l,QA=19;for(;QA>4&&!e[a0[QA-1]];--QA);var QQ=X+5<<3,FA=pB(E,gQ)+pB(J,lB)+K,IA=pB(E,D)+pB(J,R)+K+14+3*QA+pB(v,e)+2*v[16]+3*v[17]+7*v[18];if(Y>=0&&QQ<=FA&&QQ<=IA)return PL(Q,H,A.subarray(Y,Y+X));var YA,t,WA,XA;if(RQ(Q,H,1+(IA<FA)),H+=2,IA<FA){YA=LQ(D,U,0),t=D,WA=LQ(R,V,0),XA=R;var aQ=LQ(e,AA,0);RQ(Q,H,b-257),RQ(Q,H+5,k-1),RQ(Q,H+10,QA-4),H+=14;for(var O=0;O<QA;++O)RQ(Q,H+3*O,e[a0[O]]);H+=3*QA;var OA=[m,p];for(var iA=0;iA<2;++iA){var jA=OA[iA];for(var O=0;O<jA.length;++O){var RA=jA[O]&31;if(RQ(Q,H,aQ[RA]),H+=e[RA],RA>15)RQ(Q,H,jA[O]>>5&127),H+=jA[O]>>12}}}else YA=t6,t=gQ,WA=AH,XA=lB;for(var O=0;O<L;++O){var r=C[O];if(r>255){var RA=r>>18&31;if(mB(Q,H,YA[RA+257]),H+=t[RA+257],RA>7)RQ(Q,H,r>>23&31),H+=vC[RA];var pA=r&31;if(mB(Q,H,WA[pA]),H+=XA[pA],pA>3)mB(Q,H,r>>5&8191),H+=fC[pA]}else mB(Q,H,YA[r]),H+=t[r]}return mB(Q,H,YA[256]),H+t[256]},EH=new t0([65540,131080,131088,131104,262176,1048704,1048832,2114560,2117632]),OL=new CA(0),JH=function(A,Q,B,C,E,J){var K=J.z||A.length,L=new CA(C+K+5*(1+Math.ceil(K/7000))+E),Y=L.subarray(C,L.length-E),X=J.l,H=(J.r||0)&7;if(Q){if(H)Y[0]=J.r>>3;var G=EH[Q-1],D=G>>13,U=G&8191,I=(1<<B)-1,R=J.p||new gA(32768),V=J.h||new gA(I+1),_=Math.ceil(B/3),m=2*_,b=function(hB){return(A[hB]^A[hB+1]<<_^A[hB+2]<<m)&I},q=new t0(25000),p=new gA(288),k=new gA(32),v=0,O=0,g=J.i||0,e=0,AA=J.w||0,QA=0;for(;g+2<K;++g){var QQ=b(g),FA=g&32767,IA=V[QQ];if(R[FA]=IA,V[QQ]=FA,AA<=g){var YA=K-g;if((v>7000||e>24576)&&(YA>423||!X)){H=FL(A,Y,0,q,p,k,O,e,QA,g-QA,H),e=v=O=0,QA=g;for(var t=0;t<286;++t)p[t]=0;for(var t=0;t<30;++t)k[t]=0}var WA=2,XA=0,aQ=U,OA=FA-IA&32767;if(YA>2&&QQ==b(g-OA)){var iA=Math.min(D,YA)-1,jA=Math.min(32767,g),RA=Math.min(258,YA);while(OA<=jA&&--aQ&&FA!=IA){if(A[g+WA]==A[g+WA-OA]){var r=0;for(;r<RA&&A[g+r]==A[g+r-OA];++r);if(r>WA){if(WA=r,XA=OA,r>iA)break;var pA=Math.min(OA,r-2),PQ=0;for(var t=0;t<pA;++t){var OQ=g-OA+t&32767,YB=R[OQ],jQ=OQ-YB&32767;if(jQ>PQ)PQ=jQ,IA=OQ}}}FA=IA,IA=R[FA],OA+=FA-IA&32767}}if(XA){q[e++]=268435456|n0[WA]<<18|WL[XA];var wQ=n0[WA]&31,SQ=WL[XA]&31;O+=vC[wQ]+fC[SQ],++p[257+wQ],++k[SQ],AA=g+WA,++v}else q[e++]=A[g],++p[A[g]]}}for(g=Math.max(g,AA);g<K;++g)q[e++]=A[g],++p[A[g]];if(H=FL(A,Y,X,q,p,k,O,e,QA,g-QA,H),!X)J.r=H&7|Y[H/8|0]<<3,H-=7,J.h=V,J.p=R,J.i=g,J.w=AA}else{for(var g=J.w||0;g<K+X;g+=65535){var _Q=g+65535;if(_Q>=K)Y[H/8|0]=X,_Q=K;H=PL(Y,H+1,A.subarray(g,_Q))}J.i=K}return cB(L,0,C+e0(H)+E)},KH=function(){var A=new Int32Array(256);for(var Q=0;Q<256;++Q){var B=Q,C=9;while(--C)B=(B&1&&-306674912)^B>>>1;A[Q]=B}return A}(),LH=function(){var A=-1;return{p:function(Q){var B=A;for(var C=0;C<Q.length;++C)B=KH[B&255^Q[C]]^B>>>8;A=B},d:function(){return~A}}};var YH=function(A,Q,B,C,E){if(!E){if(E={l:1},Q.dictionary){var J=Q.dictionary.subarray(-32768),K=new CA(J.length+A.length);K.set(J),K.set(A,J.length),A=K,E.w=J.length}}return JH(A,Q.level==null?6:Q.level,Q.mem==null?E.l?Math.ceil(Math.max(8,Math.min(13,Math.log(A.length)))*1.5):20:12+Q.mem,B,C,E)},jL=function(A,Q){var B={};for(var C in A)B[C]=A[C];for(var C in Q)B[C]=Q[C];return B};var KQ=function(A,Q){return A[Q]|A[Q+1]<<8},cA=function(A,Q){return(A[Q]|A[Q+1]<<8|A[Q+2]<<16|A[Q+3]<<24)>>>0},d0=function(A,Q){return cA(A,Q)+cA(A,Q+4)*4294967296},UA=function(A,Q,B){for(;B;++Q)A[Q]=B,B>>>=8};function XH(A,Q){return YH(A,Q||{},0,0)}function GH(A,Q){return CH(A,{i:2},Q&&Q.out,Q&&Q.dictionary)}var wL=function(A,Q,B,C){for(var E in A){var J=A[E],K=Q+E,L=C;if(Array.isArray(J))L=jL(C,J[1]),J=J[0];if(ArrayBuffer.isView(J))B[K]=[J,L];else B[K+="/"]=[new CA(0),L],wL(J,K,B,C)}},IL=typeof TextEncoder<"u"&&new TextEncoder,i0=typeof TextDecoder<"u"&&new TextDecoder,HH=0;try{i0.decode(OL,{stream:!0}),HH=1}catch(A){}var $H=function(A){for(var Q="",B=0;;){var C=A[B++],E=(C>127)+(C>223)+(C>239);if(B+E>A.length)return{s:Q,r:cB(A,B-1)};if(!E)Q+=String.fromCharCode(C);else if(E==3)C=((C&15)<<18|(A[B++]&63)<<12|(A[B++]&63)<<6|A[B++]&63)-65536,Q+=String.fromCharCode(55296|C>>10,56320|C&1023);else if(E&1)Q+=String.fromCharCode((C&31)<<6|A[B++]&63);else Q+=String.fromCharCode((C&15)<<12|(A[B++]&63)<<6|A[B++]&63)}};function RL(A,Q){if(Q){var B=new CA(A.length);for(var C=0;C<A.length;++C)B[C]=A.charCodeAt(C);return B}if(IL)return IL.encode(A);var E=A.length,J=new CA(A.length+(A.length>>1)),K=0,L=function(H){J[K++]=H};for(var C=0;C<E;++C){if(K+5>J.length){var Y=new CA(K+8+(E-C<<1));Y.set(J),J=Y}var X=A.charCodeAt(C);if(X<128||Q)L(X);else if(X<2048)L(192|X>>6),L(128|X&63);else if(X>55295&&X<57344)X=65536+(X&1047552)|A.charCodeAt(++C)&1023,L(240|X>>18),L(128|X>>12&63),L(128|X>>6&63),L(128|X&63);else L(224|X>>12),L(128|X>>6&63),L(128|X&63)}return cB(J,0,K)}function DH(A,Q){if(Q){var B="";for(var C=0;C<A.length;C+=16384)B+=String.fromCharCode.apply(null,A.subarray(C,C+16384));return B}else if(i0)return i0.decode(A);else{var E=$H(A),J=E.s,B=E.r;if(B.length)qA(8);return J}}var ZH=function(A,Q){return Q+30+KQ(A,Q+26)+KQ(A,Q+28)},WH=function(A,Q,B){var C=KQ(A,Q+28),E=KQ(A,Q+30),J=DH(A.subarray(Q+46,Q+46+C),!(KQ(A,Q+8)&2048)),K=Q+46+C,L=UH(A,K,E,B,cA(A,Q+20),cA(A,Q+24),cA(A,Q+42)),Y=L[0],X=L[1],H=L[2];return[KQ(A,Q+10),Y,X,J,K+E+KQ(A,Q+32),H]},UH=function(A,Q,B,C,E,J,K){var L=E==4294967295,Y=J==4294967295,X=K==4294967295,H=Q+B,G=L+Y+X;if(C&&G){for(;Q+4<H;Q+=4+KQ(A,Q+2))if(KQ(A,Q)==1)return[L?d0(A,Q+4+8*Y):E,Y?d0(A,Q+4):J,X?d0(A,Q+4+8*(Y+L)):K,1];if(C<2)qA(13)}return[E,J,K,0]},r0=function(A){var Q=0;if(A)for(var B in A){var C=A[B].length;if(C>65535)qA(9);Q+=C+4}return Q},ML=function(A,Q,B,C,E,J,K,L){var Y=C.length,X=B.extra,H=L&&L.length,G=r0(X);if(UA(A,Q,K!=null?33639248:67324752),Q+=4,K!=null)A[Q++]=20,A[Q++]=B.os;A[Q]=20,Q+=2,A[Q++]=B.flag<<1|(J<0&&8),A[Q++]=E&&8,A[Q++]=B.compression&255,A[Q++]=B.compression>>8;var D=new Date(B.mtime==null?Date.now():B.mtime),U=D.getFullYear()-1980;if(U<0||U>119)qA(10);if(UA(A,Q,U<<25|D.getMonth()+1<<21|D.getDate()<<16|D.getHours()<<11|D.getMinutes()<<5|D.getSeconds()>>1),Q+=4,J!=-1)UA(A,Q,B.crc),UA(A,Q+4,J<0?-J-2:J),UA(A,Q+8,B.size);if(UA(A,Q+12,Y),UA(A,Q+14,G),Q+=16,K!=null)UA(A,Q,H),UA(A,Q+6,B.attrs),UA(A,Q+10,K),Q+=14;if(A.set(C,Q),Q+=Y,G)for(var I in X){var R=X[I],V=R.length;UA(A,Q,+I),UA(A,Q+2,V),A.set(R,Q+4),Q+=4+V}if(H)A.set(L,Q),Q+=H;return Q},FH=function(A,Q,B,C,E){UA(A,Q,101010256),UA(A,Q+8,B),UA(A,Q+10,B),UA(A,Q+12,C),UA(A,Q+16,E)};function SL(A,Q){if(!Q)Q={};var B={},C=[];wL(A,"",B,Q);var E=0,J=0;for(var K in B){var L=B[K],Y=L[0],X=L[1],H=X.level==0?0:8,G=RL(K),D=G.length,U=X.comment,I=U&&RL(U),R=I&&I.length,V=r0(X.extra);if(D>65535)qA(11);var _=H?XH(Y,X):Y,m=_.length,b=LH();b.p(Y),C.push(jL(X,{size:Y.length,crc:b.d(),c:_,f:G,m:I,u:D!=K.length||I&&U.length!=R,o:E,compression:H})),E+=30+D+V+m,J+=76+2*(D+V)+(R||0)+m}var q=new CA(J+22),p=E,k=J-E;for(var v=0;v<C.length;++v){var G=C[v];ML(q,G.o,G,G.f,G.u,G.c.length);var O=30+G.f.length+r0(G.extra);q.set(G.c,G.o+O),ML(q,E,G,G.f,G.u,G.c.length,G.o,G.m),E+=16+O+(G.m?G.m.length:0)}return FH(q,E,C.length,k,p),q}function _L(A,Q){var B={},C=A.length-22;for(;cA(A,C)!=101010256;--C)if(!C||A.length-C>65558)qA(13);var E=KQ(A,C+8);if(!E)return{};var J=cA(A,C+16),K=cA(A,C-20)==117853008;if(K){var L=cA(A,C-12);if(K=cA(A,L)==101075792,K)E=cA(A,L+32),J=cA(A,L+48)}var Y=Q&&Q.filter;for(var X=0;X<E;++X){var H=WH(A,J,K),G=H[0],D=H[1],U=H[2],I=H[3],R=H[4],V=H[5],_=ZH(A,V);if(J=R,!Y||Y({name:I,size:D,originalSize:U,compression:G}))if(!G)B[I]=cB(A,_,_+D);else if(G==8)B[I]=GH(A.subarray(_,_+D),{out:new CA(U)});else qA(14,"unknown compression type "+G)}return B}function IH(){return new Promise((A,Q)=>{let B=indexedDB.open("trove-plugins",1);B.onupgradeneeded=()=>{let C=B.result;if(!C.objectStoreNames.contains("installs"))C.createObjectStore("installs",{keyPath:"id"})},B.onsuccess=()=>A(B.result),B.onerror=()=>Q(B.error)})}function uC(A,Q,B){return new Promise((C,E)=>{let J=A.transaction("installs",Q),K=J.objectStore("installs"),L;Promise.resolve(B(K)).then((Y)=>L=Y),J.oncomplete=()=>C(L),J.onerror=()=>E(J.error)})}var TL=(A)=>new Promise((Q,B)=>{A.onsuccess=()=>Q(A.result),A.onerror=()=>B(A.error)});class AE{constructor(){this._db=null}async#A(){return this._db??=await IH()}async save(A){let Q=await this.#A();return await uC(Q,"readwrite",(B)=>B.put(A)),A}async get(A){let Q=await this.#A();return uC(Q,"readonly",(B)=>TL(B.get(A)))}async list(){let A=await this.#A();return uC(A,"readonly",(Q)=>TL(Q.getAll()))}async remove(A){let Q=await this.#A();await uC(Q,"readwrite",(B)=>B.delete(A))}async patch(A,Q){let B=await this.get(A);if(!B)return null;let C={...B,...Q};return await this.save(C),C}}var mC=null;function VH(){if(!mC)mC=import("./chunk-h05bxfbs.js").then((m)=>RH(m.default,1)).then((A)=>(A.default||A)({locateFile:()=>"/sql-wasm.wasm"})).catch((A)=>{throw mC=null,A});return mC}var qH="trove-plugin-clientdb",pC="dbs";function zH(){return new Promise((A,Q)=>{let B=indexedDB.open(qH,1);B.onupgradeneeded=()=>{let C=B.result;if(!C.objectStoreNames.contains(pC))C.createObjectStore(pC)},B.onsuccess=()=>A(B.result),B.onerror=()=>Q(B.error)})}function QE(A,Q){return zH().then((B)=>new Promise((C,E)=>{let J=B.transaction(pC,A),K;Promise.resolve(Q(J.objectStore(pC))).then((L)=>K=L),J.oncomplete=()=>{B.close(),C(K)},J.onerror=()=>{B.close(),E(J.error)}}))}var NH=(A)=>new Promise((Q,B)=>{A.onsuccess=()=>Q(A.result),A.onerror=()=>B(A.error)}),PH=(A)=>QE("readonly",(Q)=>NH(Q.get(A))),OH=(A,Q)=>QE("readwrite",(B)=>B.put(Q,A)),jH=(A)=>QE("readwrite",(Q)=>Q.delete(A));class xL{constructor(A,Q){this.key=A,this.db=Q,this._saveTimer=null}#A(){clearTimeout(this._saveTimer),this._saveTimer=setTimeout(()=>{this.flush().catch((A)=>{console.error(`persisting plugin storage "${this.key}" failed`,A),this.onError?.(A,this.key)})},150)}async flush(){clearTimeout(this._saveTimer),this._saveTimer=null,await OH(this.key,this.db.export())}async exec(A){return this.db.exec(A),this.#A(),{ok:!0}}async run(A,...Q){return this.db.run(A,Q),this.#A(),{ok:!0}}async get(A,...Q){let B=this.db.prepare(A);try{return B.bind(Q),B.step()?B.getAsObject():null}finally{B.free()}}async all(A,...Q){let B=this.db.prepare(A),C=[];try{B.bind(Q);while(B.step())C.push(B.getAsObject())}finally{B.free()}return C}async batch(A=[]){this.db.run("BEGIN");try{for(let{sql:Q,params:B=[]}of A)this.db.run(Q,B);this.db.run("COMMIT")}catch(Q){try{this.db.run("ROLLBACK")}catch{}throw Q}return this.#A(),{ok:!0}}close(){clearTimeout(this._saveTimer),this.db.close()}}class BE{constructor({onError:A}={}){this._pool=new Map,this.onError=A||null}async obtain(A){let Q=this._pool.get(A);if(!Q){let B=await VH(),C=await PH(A);Q=new xL(A,new B.Database(C||void 0)),Q.onError=this.onError,this._pool.set(A,Q)}return Q}async drop(A){let Q=this._pool.get(A);if(Q)Q.close(),this._pool.delete(A);await jH(A)}}var kL=new TextEncoder;function CE(A){let Q=atob(A.replace(/-/g,"+").replace(/_/g,"/")),B=new Uint8Array(Q.length);for(let C=0;C<Q.length;C++)B[C]=Q.charCodeAt(C);return B}function gL(A){let Q=new Uint8Array(A),B="";for(let C=0;C<Q.length;C++)B+=Q[C].toString(16).padStart(2,"0");return B}async function yL(A){return new Uint8Array(await crypto.subtle.digest("SHA-256",A))}function wH(A){let Q={...A};return delete Q.signature,JSON.stringify(EE(Q))}function EE(A){if(Array.isArray(A))return A.map(EE);if(A&&typeof A==="object"){let Q={};for(let B of Object.keys(A).sort())Q[B]=EE(A[B]);return Q}return A}async function SH(A){let Q=[...A.keys()].filter((K)=>K!=="manifest.json").sort(),B=[];for(let K of Q){let L=A.get(K),Y=kL.encode(K),X=new Uint8Array(4);new DataView(X.buffer).setUint32(0,L.length),B.push(Y,new Uint8Array([0]),X,L)}let C=B.reduce((K,L)=>K+L.length,0),E=new Uint8Array(C),J=0;for(let K of B)E.set(K,J),J+=K.length;return gL(await yL(E))}async function _H(A){return gL(await yL(CE(A)))}async function TH({manifest:A,files:Q}){if(!A.signature||!A.publicKey)return{signed:!1,valid:!1};let B=await SH(Q);if(A.contentHash&&A.contentHash!==B)return{signed:!0,valid:!1,reason:"File contents do not match the manifest hash"};try{let C=await crypto.subtle.importKey("spki",CE(A.publicKey),{name:"ECDSA",namedCurve:"P-256"},!1,["verify"]);if(!await crypto.subtle.verify({name:"ECDSA",hash:"SHA-256"},C,CE(A.signature),kL.encode(wH(A))))return{signed:!0,valid:!1,reason:"Signature does not verify"};return{signed:!0,valid:!0,fingerprint:await _H(A.publicKey)}}catch(C){return{signed:!0,valid:!1,reason:"Bad key/signature: "+C.message}}}function xH(A,Q,B){let C=(K)=>(K||"").toLowerCase().replace(/:/g,""),E=C(Q),J=[B.name,`${B.domain}/${B.name}`];for(let K of A?.keys||[]){if(C(K.fingerprint)!==E)continue;if((K.plugins||[]).some((L)=>L==="*"||J.includes(L)))return!0}return!1}async function hL({manifest:A,files:Q},B){let C=await TH({manifest:A,files:Q});if(!C.signed)return{status:"unverified",reason:"Package is not signed"};if(!C.valid)return{status:"invalid",reason:C.reason||"Invalid signature — the package may have been tampered with"};let E=null;try{E=await B(A.domain)}catch{}if(E&&xH(E,C.fingerprint,A))return{status:"verified",domain:A.domain,fingerprint:C.fingerprint};return{status:"signed",domain:A.domain,fingerprint:C.fingerprint,reason:E?"Domain does not list this key":"Could not reach the domain"}}function JE(A){let Q=/^([a-z][a-z0-9+.-]*:\/\/)\*\.(.+)$/i.exec(A),B=!!Q,C;try{C=new URL(B?Q[1]+Q[2]:A)}catch{throw Error(`Invalid network endpoint "${A}" (must be an absolute http(s) URL)`)}if(C.protocol!=="http:"&&C.protocol!=="https:")throw Error(`Network endpoint "${A}" must use http or https`);let E=C.hostname.toLowerCase();if(!E)throw Error(`Network endpoint "${A}" has no host`);return{scheme:C.protocol,host:E,wildcard:B,port:C.port,pathPrefix:C.pathname||"/",raw:A}}function bL(A){let Q=[];for(let B of A||[])try{Q.push(JE(B))}catch{}return Q}function kH(A,Q){let B;try{B=new URL(Q)}catch{return!1}if(B.protocol!==A.scheme)return!1;let C=B.hostname.toLowerCase();if(A.wildcard){if(C!==A.host&&!C.endsWith("."+A.host))return!1}else if(C!==A.host)return!1;if(B.port!==A.port)return!1;return B.pathname.startsWith(A.pathPrefix)}function lC(A,Q){return bL(A).some((B)=>kH(B,Q))}function cC(A){return bL(A).map((Q)=>({scheme:Q.scheme.replace(":",""),host:(Q.wildcard?"*.":"")+Q.host+(Q.port?":"+Q.port:""),path:Q.pathPrefix==="/"?"":Q.pathPrefix,raw:Q.raw}))}var gH={files:"Read your files, folders, and search index (via the host).",storage:"Keep its own SQLite database(s) — on the server and/or on this device.",ui:"Show a popup panel and toasts.",commands:"Add commands to the palette, and run the specific host commands it lists.",opener:"Preview/open file types.",indexer:"Add searchable content to your files.",network:"Connect to the internet — only the endpoints it declares (shown below).",media:"Show playback controls on your lock screen and notifications while it plays media.",dock:"Keep its viewer in a small floating window when you navigate away."},KE=new Set;function vL(A){let Q=YE(A,"storage");if(!Q)return{plugin:!1,domain:!1};if(Q===!0||typeof Q==="object"&&!("plugin"in Q)&&!("domain"in Q))return{plugin:!0,domain:!1};return{plugin:!!Q.plugin,domain:!!Q.domain}}function yH(A){return gH[A]||A}function fL(A){let Q=A&&A.capabilities,B={};if(Array.isArray(Q)){for(let C of Q)if(C)B[C]={}}else if(Q&&typeof Q==="object")for(let[C,E]of Object.entries(Q)){if(E===!1||E==null)continue;B[C]=E===!0?{}:E}return B}function LE(A){return Object.keys(fL(A))}function YE(A,Q){let B=fL(A);return Object.prototype.hasOwnProperty.call(B,Q)?B[Q]:null}function rQ(A){let Q=YE(A,"network");if(Q){if(Array.isArray(Q))return Q;if(Array.isArray(Q.endpoints))return Q.endpoints;if(Array.isArray(Q.prefixes))return Q.prefixes}if(Array.isArray(A.network))return A.network;return[]}function dA(A){let Q=A?.displayName??A?.name;return typeof Q==="string"&&Q.trim()?Q:"Plugin"}function uL(A){let Q=YE(A,"commands");if(!Q)return[];if(Array.isArray(Q))return Q.filter(Boolean);if(Array.isArray(Q.execute))return Q.execute.filter(Boolean);return[]}function dC(A,Q,B){if(!Q)return!1;if(kQ(Q)&&EL(A,Q))return!0;return uL(A).includes(Q)}function tQ(A){let Q;try{Q=_L(A instanceof Uint8Array?A:new Uint8Array(A))}catch(J){throw Error("Not a valid zip archive: "+J.message)}let B=new Map;for(let[J,K]of Object.entries(Q))if(!J.endsWith("/"))B.set(J.replace(/^\.?\//,""),K);let C=B.get("manifest.json");if(!C)throw Error("Package is missing manifest.json");let E;try{E=JSON.parse(new TextDecoder().decode(C))}catch(J){throw Error("manifest.json is not valid JSON: "+J.message)}return hH(E,B),{manifest:E,files:B,raw:A}}function hH(A,Q){let B=(C,E)=>{if(!C)throw Error(E)};if(gC(A),B(A.entry,"manifest.entry (path to the plugin script) is required"),B(Q.has(A.entry),`entry "${A.entry}" is not in the package`),A.capabilities!=null)B(Array.isArray(A.capabilities)||typeof A.capabilities==="object","capabilities must be an object of { capability: options } (or an array of ids)");if(A.icon)B(Q.has(A.icon),`icon "${A.icon}" is not in the package`);for(let C of IQ(A)){if(C.entry)B(Q.has(C.entry),`contribution "${C.name}" points at "${C.entry}", which is not in the package`);if(C.type==="keymap")B(Q.has(C.path),`keymap "${C.name}" points at "${C.path}", which is not in the package`)}for(let C of rQ(A))JE(C)}async function mL(A,Q=globalThis.fetch.bind(globalThis)){let B;try{B=await Q(A)}catch(E){throw Error("Could not fetch the plugin: "+E.message)}if(!B.ok)throw Error(`Could not fetch the plugin (HTTP ${B.status})`);let C=new Uint8Array(await B.arrayBuffer());return tQ(C)}function pL(A,Q){let B=A.manifest,C=IQ(B).map((K)=>({kind:K.type,name:K.name,uri:K.uri,title:K.title||K.name,detail:K.type==="opener"||K.type==="indexer"?bH(K.match):K.type==="statusItem"?`${K.slot} of the status bar${K.command?` — runs ${K.command}`:""}`:K.type==="keymap"?K.path:"",offline:!!K.offline})),E=Q?.status==="verified",J=vL(B);return{id:EQ(B),name:dA(B),version:B.version||"0.0.0",description:B.description||"",author:B.author||"Unknown",domain:B.domain,capabilities:LE(B).map((K)=>({id:K,description:yH(K),adminOnly:KE.has(K)})),contributions:C,settings:(B.settings||[]).map((K)=>({key:K.key,title:K.title||K.key,type:K.type,secret:!!K.secret})),network:cC(rQ(B)),commands:uL(B),storage:J.plugin||J.domain?{plugin:J.plugin,domain:J.domain,domainBlocked:J.domain&&!E}:null,fileCount:A.files.size,sizeBytes:[...A.files.values()].reduce((K,L)=>K+L.length,0),trust:Q}}function XE(A,Q){let B=vL(A);return{plugin:B.plugin,domain:B.domain&&Q?.status==="verified"}}function bH(A){if(!A)return"";let Q=[];if(A.ext?.length)Q.push(A.ext.join(", "));if(A.mime?.length)Q.push(A.mime.join(", "));return Q.join(" · ")}class GE{constructor(){this.owner=null}#A(){return typeof navigator<"u"?navigator.mediaSession:null}apply(A,Q,B={}){let C=this.#A();if(!C)return{ok:!1};if(A&&Q!=="clear")this.owner=A,A.mediaOwner=!0;try{if(Q==="metadata")C.metadata=typeof MediaMetadata<"u"?new MediaMetadata({title:B.title||"",artist:B.artist||"",album:B.album||"",artwork:B.artwork||[]}):C.metadata;else if(Q==="playbackState")C.playbackState=B.state||"none";else if(Q==="position"&&C.setPositionState)C.setPositionState({duration:B.duration||0,position:B.position||0,playbackRate:B.playbackRate||1});else if(Q==="action"){if(C.setActionHandler?.(B.action,B.on?()=>A?.channel?.emit("media:action",{action:B.action}):null),A)A.mediaActions||=new Set,B.on?A.mediaActions.add(B.action):A.mediaActions.delete(B.action)}else if(Q==="clear"){if(A&&this.owner&&this.owner!==A)return{ok:!0};this.releaseActions(A),C.metadata=null,C.playbackState="none",this.owner=null}}catch{}return{ok:!0}}releaseActions(A){let Q=this.#A();if(!Q||!A?.mediaActions)return;for(let B of A.mediaActions)try{Q.setActionHandler?.(B,null)}catch{}A.mediaActions.clear()}releaseFrame(A){if(this.owner===A)this.owner=null,this.apply(A,"clear",{});this.releaseActions(A)}}class HE{constructor({destroyFrame:A,openFile:Q,onChange:B}={}){this.destroyFrame=A,this.openFile=Q,this.onChange=B||(()=>{}),this.docked=null,this.el=null}place(A,Q,B,C=""){this.stopPlace(A);let E=A.iframe;E.style.cssText=`position:fixed;border:0;visibility:visible;display:block;background:transparent;z-index:${B};margin:0;padding:0;border-radius:${C};`;let J=()=>{let Y=Q.getBoundingClientRect(),X=Y.width>0&&Y.height>0&&document.contains(Q);E.style.left=`${Y.left}px`,E.style.top=`${Y.top}px`,E.style.width=`${Y.width}px`,E.style.height=`${Y.height}px`,E.style.visibility=X?"visible":"hidden"};J();let K=typeof ResizeObserver<"u"?new ResizeObserver(J):null;if(K?.observe(Q),document.body)K?.observe(document.body);let L=typeof IntersectionObserver<"u"?new IntersectionObserver(J,{threshold:[0,1]}):null;L?.observe(Q),window.addEventListener("scroll",J,!0),window.addEventListener("resize",J),A.place={target:Q,stop:()=>{K?.disconnect(),L?.disconnect(),window.removeEventListener("scroll",J,!0),window.removeEventListener("resize",J)}}}stopPlace(A){if(A.place)A.place.stop(),A.place=null}hide(A){this.stopPlace(A),A.iframe.style.cssText="position:fixed;left:0;top:0;width:0;height:0;border:0;visibility:hidden;"}releaseFrame(A){if(this.stopPlace(A),this.docked===A)this.docked=null,this.#A()}#A(){if(this.el)this.el.style.display="none"}dock(A){if(this.docked&&this.docked!==A)this.closeDock(this.docked);let Q=A.dock?.minSize||{width:300,height:90},B=this.#Q();B.style.width=`${lL(Q.width,200,480)}px`,B.style.height=`${lL(Q.height,56,360)+26}px`,B.querySelector(".vd-title").textContent=A.node?.name||(A.record.manifest.displayName||A.record.manifest.name),B.style.display="flex",this.place(A,B.querySelector(".vd-body"),61,"0 0 11px 11px"),this.docked=A,A.channel?.emit("dock:state",{docked:!0}),this.onChange()}undock(A){if(this.#A(),this.docked===A)this.docked=null;A.channel?.emit("dock:state",{docked:!1})}closeDock(A){if(this.#A(),this.docked===A)this.docked=null;A.channel?.emit("dock:state",{docked:!1,closed:!0}),this.destroyFrame?.(A),this.onChange()}#Q(){if(this.el)return this.el;let A=document.createElement("div");return A.className="viewer-dock",A.innerHTML='<div class="vd-bar"><span class="vd-title"></span><button class="vd-expand" title="Reopen">↗</button><button class="vd-close" title="Close">✕</button></div><div class="vd-body"></div>',A.querySelector(".vd-expand").addEventListener("click",()=>{let Q=this.docked;if(Q?.node)this.openFile?.(Q.node,Q.openerId)}),A.querySelector(".vd-close").addEventListener("click",()=>{if(this.docked)this.closeDock(this.docked)}),document.body.appendChild(A),this.el=A,A}}function lL(A,Q,B){return Math.max(Q,Math.min(B,A||Q))}function yA(A){console.error(A)}var IB="The provider has been disposed";class l{static deps=[];async obtain(A={}){throw Error("obtain() not implemented")}release(A,Q={}){}async flush(){}static fromSingleton(A,{dispose:Q,deps:B=[]}={}){return class extends l{static deps=B;#A;#Q=!1;constructor(E={}){super();this.#A=E}async obtain(){return A}release(){}async dispose(){if(this.#Q)return;if(this.#Q=!0,typeof Q==="function")await Q(A,this.#A)}}}static fromPool(A,Q,{size:B=1,deps:C=[]}={}){if(!Number.isInteger(B)||B<1)throw RangeError("fromPool() requires an integer size of at least 1");return class extends l{static deps=C;#A;#Q=[];#B=new Set;#C=[];#E=0;#J=!1;constructor(J={}){super();this.#A=J}async#K(J){try{await Q(J,this.#A)}catch(K){yA(K)}}#L(){while(this.#C.length>0){if(this.#Q.length>0){let K=this.#Q.shift();this.#B.add(K),this.#C.shift().resolve(K);continue}if(this.#E>=B)return;let J=this.#C.shift();this.#E++,Promise.resolve().then(()=>A(this.#A)).then((K)=>{if(this.#J){this.#E--,this.#K(K),J.reject(Error(IB));return}this.#B.add(K),J.resolve(K)},(K)=>{this.#E--,J.reject(K),this.#L()})}}async obtain(){if(this.#J)throw Error(IB);let J=Promise.withResolvers();return this.#C.push(J),this.#L(),await J.promise}release(J){if(!this.#B.delete(J))return;if(this.#J){this.#E--,this.#K(J);return}this.#Q.push(J),this.#L()}async dispose(){if(this.#J)return;this.#J=!0;let J=this.#C.splice(0);for(let{reject:L}of J)L(Error(IB));let K=this.#Q.splice(0);this.#E-=K.length,await Promise.all(K.map((L)=>this.#K(L)))}}}static fromLazySingleton(A,Q,{deps:B=[]}={}){return class extends l{static deps=B;#A;#Q=null;#B=null;#C=!1;constructor(E={}){super();this.#A=E}async obtain(){if(this.#C)throw Error(IB);this.#Q??=Promise.resolve().then(()=>A(this.#A));try{return this.#B=await this.#Q,this.#B}catch(E){throw this.#Q=null,this.#B=null,E}}release(){}async dispose(){if(this.#C)return;if(this.#C=!0,!this.#Q||typeof Q!=="function")return;let E=this.#B??await this.#Q.catch(()=>null);if(E!=null)await Q(E,this.#A)}}}static fromRefCounted(A,Q,{deps:B=[]}={}){return class extends l{static deps=B;#A;#Q=0;#B=null;#C=null;#E=null;#J=!1;constructor(E={}){super();this.#A=E}async obtain(){if(this.#J)throw Error(IB);this.#Q++;while(this.#E)await this.#E;if(this.#J)throw this.#Q--,Error(IB);if(!this.#B)this.#B=Promise.resolve().then(()=>A(this.#A));try{return this.#C=await this.#B,this.#C}catch(E){if(this.#Q--,this.#Q<=0)this.#Q=0,this.#B=null,this.#C=null;throw E}}async release(){if(this.#Q<=0)return;if(this.#Q--,this.#Q>0)return;let E=this.#C,J=this.#B;if(this.#C=null,this.#B=null,!J)return;this.#E=(async()=>{try{let K=E??await J.catch(()=>null);if(K!=null)await Q(K,this.#A)}catch(K){yA(K)}finally{this.#E=null}})(),await this.#E}async dispose(){if(this.#J=!0,this.#Q>0)this.#Q=1,await this.release();while(this.#E)await this.#E}}}}class $E{#A;#Q=!1;constructor(A,Q){this.resources=A,this.#A=Q}get released(){return this.#Q}async release(){if(this.#Q)return;this.#Q=!0;for(let{name:A,provider:Q,options:B}of this.#A)try{await Q.release(this.resources[A],B)}catch(C){yA(C)}this.#A=[]}}class yQ{#A=new Map;#Q=new WeakMap;#B;#C=!1;constructor({providers:A,feed:Q}={}){if(this.#B=Q??new EventTarget,!A)return;let B=(C,E)=>{if(this.#A.has(C))return this.#A.get(C);let J=A[C];if(!J)throw Error(`Dependency not found: ${C}`);let K=[...E,C];if(E.includes(C))throw Error(`Cyclic dependency detected: ${K.join(" -> ")}`);let L={};for(let X of J.deps??[])L[X]=B(X,K);let Y=new J(L,{engineFeed:this.#B,container:this});return this.#A.set(C,Y),Y};for(let C of Object.keys(A))B(C,[])}get feed(){return this.#B}get disposed(){return this.#C}has(A){return this.#A.has(A)}get(A){let Q=this.#A.get(A);if(!Q)throw Error(`Dependency not found: ${A}`);return Q}resolve(A){if(!A)return{};let Q=this.#Q.get(A);if(Q)return Q;let B={};if(Array.isArray(A))for(let C of A)B[C]={provider:this.get(C),options:void 0};else for(let C of Object.keys(A))B[C]={provider:this.get(C),options:A[C]};return this.#Q.set(A,B),B}resolveAll(...A){let Q=A.filter(Boolean);if(Q.length===1)return this.resolve(Q[0]);return Object.assign({},...Q.map((B)=>this.resolve(B)))}async lease(...A){if(this.#C)throw Error("The container has been disposed");let Q=this.resolveAll(...A),B={},C=[];try{for(let[E,{provider:J,options:K}]of Object.entries(Q))B[E]=await J.obtain(K),C.push({name:E,provider:J,options:K})}catch(E){throw await new $E(B,C).release(),E}return new $E(B,C)}async use(A,Q){let B=await this.lease(A);try{return await Q(B.resources)}finally{await B.release()}}async dispose(){if(this.#C)return;this.#C=!0;let A=[...this.#A.values()].reverse();for(let Q of A)try{await Q.flush?.()}catch(B){yA(B)}for(let Q of A)try{await Q.dispose?.()}catch(B){yA(B)}}}var vH=typeof ErrorEvent==="function"?ErrorEvent:class extends Event{constructor(Q,{error:B,message:C=""}={}){super(Q);this.error=B,this.message=C}};function fH(A){return A&&typeof A.message==="string"?A.message:String(A)}class aL extends Event{constructor({reason:A,error:Q=null}={}){super("abort");this.reason=A,this.error=Q}}var cL=["complete","error","abort"];function uH(){return typeof DOMException==="function"?new DOMException("The dispatch was aborted","AbortError"):Object.assign(Error("The dispatch was aborted"),{name:"AbortError"})}class P{execute(){throw Error("execute() not implemented")}}class DE extends EventTarget{#A=new AbortController;#Q;#B=null;constructor(){super();for(let A of cL)this.addEventListener(A,(Q)=>{this.#B??={type:A,event:Q}},{once:!0})}get signal(){return this.#A.signal}get settled(){return this.#B?.type??null}get reason(){return this.#Q}abort(A){if(this.#A.signal.aborted)return;this.#Q=A??uH(),this.#A.abort(this.#Q)}next(A,{signal:Q}={}){let B=new Set(Array.isArray(A)?A:[A]);if(B.size===0)throw TypeError("next() requires at least one event name");let C=B.has("abort");return new Promise((E,J)=>{if(Q?.aborted){J(Q.reason);return}if(this.#A.signal.aborted&&!C&&!this.#B){J(this.#Q);return}if(this.#B){this.#C(E,J,this.#B,B);return}let K=new AbortController,L={signal:K.signal},Y=(X)=>(H)=>{K.abort(),X(H)};for(let X of B)this.addEventListener(X,Y(E),L);for(let X of cL){if(B.has(X))continue;this.addEventListener(X,(H)=>Y(J)(dL(X,H,B)),L)}if(!C)this.#A.signal.addEventListener("abort",()=>Y(J)(this.#Q),L);Q?.addEventListener("abort",()=>Y(J)(Q.reason),L)})}#C(A,Q,B,C){if(C.has(B.type))A(B.event);else Q(dL(B.type,B.event,C))}}function dL(A,Q,B){if(A==="error")return Q.error;if(A==="abort")return Q.reason;return mH(B)}function mH(A){return Error(`The dispatch completed without emitting ${[...A].map((Q)=>`'${Q}'`).join(" or ")}`)}class aC{#A;#Q;constructor({container:A,interceptors:Q}={}){this.#A=A??new yQ,this.#Q=Q?[...Q]:[]}get container(){return this.#A}get feed(){return this.#A.feed}dispatch(A){if(!(A instanceof P))throw TypeError("dispatch() requires an instance of Action");let Q=this.#A,B=this.#Q,C=Q.feed,E=new DE;return setTimeout(async()=>{let J=[],K={},L=null,Y=(X)=>{if(X!==void 0)K=X};try{for(let H of B){if(J.push(H),!H.enter)continue;Y(await Q.use(H.deps,(G)=>H.enter(G,{dispatchFeed:E,engineFeed:C,signal:E.signal,state:K,action:A})))}let X=await Q.lease(A.constructor.deps,A.deps);try{await A.execute(X.resources,{dispatchFeed:E,engineFeed:C,signal:E.signal,state:K})}finally{await X.release()}}catch(X){L=X}finally{for(let X=J.length-1;X>=0;X--){let H=J[X],G=E.signal.aborted;try{if(G&&H.abort)Y(await Q.use(H.deps,(D)=>H.abort(D,{dispatchFeed:E,engineFeed:C,signal:E.signal,action:A,state:K,reason:E.reason,error:L})));else if(L&&H.error){let D={dispatchFeed:E,engineFeed:C,signal:E.signal,action:A,state:K,error:L,handled:()=>{L=null}};Y(await Q.use(H.deps,(U)=>H.error(U,D)))}else if(!L&&H.leave)Y(await Q.use(H.deps,(D)=>H.leave(D,{dispatchFeed:E,engineFeed:C,signal:E.signal,state:K,action:A})))}catch(D){L=D}}if(E.signal.aborted)E.dispatchEvent(new aL({reason:E.reason,error:L}));else if(L)E.dispatchEvent(new vH("error",{error:L,message:fH(L)}));else E.dispatchEvent(new Event("complete"))}}),E}}class YQ{boot(){throw Error("boot() not implemented, and no fetch() to fall back to")}kill(){}}class nL{#A;#Q;#B=null;#C=null;#E=!1;#J=null;#K=Promise.withResolvers();#L=!1;#Y=void 0;#X=!1;#G=void 0;#$=void 0;observers=new Set;constructor(A,Q){this.#A=A,this.#Q=Q,this.notify=this.notify.bind(this)}get hasValue(){return this.#L}get currentValue(){return this.#Y}get received(){return this.#K.promise}get bootFeed(){return this.#G}get killFeed(){return this.#$}#Z(A,Q){let B=this.#A._dispatch(A);return B.addEventListener("error",(C)=>{yA(Error(`${this.#Q.constructor.name} ${Q} (${A.constructor.name}) failed`,{cause:C.error}))},{once:!0}),B}notify(A){if(this.#X)return;if(this.#Y=A,!this.#L)this.#L=!0,this.#K.resolve(!0);for(let Q of[...this.observers])try{Q.next?.(A)}catch(B){yA(B)}}boot(){if(this.#C)return this.#C;return this.#C=(async()=>{try{if(this.#Q.bootAction)this.#G=this.#Z(this.#Q.bootAction,"bootAction");this.#B=await this.#A._container.lease(this.#Q.constructor.deps,this.#Q.deps);let A={notify:this.notify,engineFeed:this.#A._container.feed,bootFeed:this.#G};if(this.#Q.boot===YQ.prototype.boot){if(typeof this.#Q.fetch!=="function")throw Error(`${this.#Q.constructor.name} implements neither boot() nor fetch()`);this.notify(await this.#Q.fetch(this.#B.resources,A)),await this.#D()}else await this.#Q.boot(this.#B.resources,A)}catch(A){yA(A),await this.#D(A)}finally{this.#E=!0}})(),this.#C}kill(){if(this.#J)return this.#J;return this.#J=this.#E?this.#H():Promise.resolve(this.#C).then(()=>this.#H()),this.#J}async#H(){if(this.#X)return;try{if(this.#Q.killAction)this.#$=this.#Z(this.#Q.killAction,"killAction");if(this.#Q.kill)await this.#Q.kill(this.#B?.resources??{},{bootFeed:this.#G,killFeed:this.#$,engineFeed:this.#A._container.feed,notify:this.notify})}catch(A){yA(A)}finally{await this.#D()}}async#D(A){if(this.#X)return;this.#X=!0,this.#A._evict(this.#Q,this);let Q=[...this.observers];this.observers.clear();for(let C of Q)try{if(A!==void 0&&C.error)C.error(A);else C.complete?.()}catch(E){yA(E)}if(!this.#L)this.#K.resolve(!1);let B=this.#B;if(this.#B=null,B)await B.release()}}class nC{#A;#Q;#B;#C=!1;constructor({container:A,dispatcher:Q,createControllerMap:B}={}){this.#A=A??new yQ,this.#Q=Q??null,this.#B=B?.()??new Map}get container(){return this.#A}get feed(){return this.#A.feed}get _container(){return this.#A}_dispatch(A){if(!this.#Q)throw Error("A query declared a bootAction/killAction but no dispatcher was given to QueryStore");return this.#Q.dispatch(A)}_evict(A,Q){if(this.#B.get(A)===Q)this.#B.delete(A)}#E(A){return[A.constructor.deps,A.deps]}query(A){if(!(A instanceof YQ))throw TypeError("query() requires an instance of Query");return{subscribe:(Q)=>{if(this.#C)throw Error("The query store has been disposed");let B=typeof Q==="function"?{next:Q}:Q||{},C=this.#B.get(A);if(C){if(C.observers.add(B),C.hasValue)try{B.next?.(C.currentValue)}catch(J){yA(J)}}else C=new nL(this,A),this.#B.set(A,C),C.observers.add(B),C.boot();let E=!1;return{get closed(){return E},unsubscribe:()=>{if(E)return;if(E=!0,C.observers.delete(B),C.observers.size===0)this._evict(A,C),C.kill()}}},peek:async()=>{let Q=this.#B.get(A);if(Q&&await Q.received)return Q.currentValue;if(typeof A.fetch!=="function")throw TypeError(`${A.constructor.name} is not active and does not implement fetch()`);let B=await this.#A.lease(...this.#E(A));try{return await A.fetch(B.resources,{engineFeed:this.#A.feed,bootFeed:Q?.bootFeed,killFeed:Q?.killFeed})}finally{await B.release()}}}}async dispose(){if(this.#C)return;this.#C=!0;for(let A of[...this.#B.values?.()??[]])await A.kill()}}class sC{#A;#Q;#B;#C=!1;constructor({providers:A,interceptors:Q,hooks:B,container:C,dispatcher:E,queries:J}={}){this.#A=C??new yQ({providers:A}),this.#Q=E??new aC({container:this.#A,interceptors:Q}),this.#B=J??new nC({container:this.#A,dispatcher:this.#Q,createControllerMap:B?.createQueryControllersMap})}get container(){return this.#A}get dispatcher(){return this.#Q}get queries(){return this.#B}get feed(){return this.#A.feed}dispatch(A){return this.#Q.dispatch(A)}query(A){return this.#B.query(A)}async dispose(){if(this.#C)return;this.#C=!0,await this.#B.dispose(),await this.#A.dispose()}}function oC(A,Q,B,C){let E=A?.[Q];return E&&E.ref===B?E:{ref:B,...C}}var dB="promptValue",aB="pluginReview";function sL(A,Q){let B=A?.[dB];return B&&B.ref===Q?B.value:Q?.value??""}function oL(A){let Q=nB(A);if(Q.status==="invalid")return{status:Q.status,allowed:!1,requiresAcknowledgement:!1,headline:"This package has been altered",detail:`${Q.explanation}. It was signed, and the signature does not match its contents — so it is not what its author published. Trove will not install it.`};if(Q.status==="unverified")return{status:Q.status,allowed:!0,requiresAcknowledgement:!0,headline:"Unsigned — for development only",detail:"Nobody has signed this package, so there is no way to tell who wrote it or whether it has been altered since. Install it only if you built it yourself or you trust wherever you got it from."};if(Q.status==="signed")return{status:Q.status,allowed:!0,requiresAcknowledgement:!1,headline:"Signed, but the domain does not vouch for the key",detail:`${Q.explanation}. The signature is real; what is unproven is that ${Q.domain||"the publisher"} authorised it.`};return{status:Q.status,allowed:!0,requiresAcknowledgement:!1,headline:null,detail:null}}function nB(A){let Q=A||{};switch(Q.status){case"verified":return{status:"verified",tone:"verified",icon:"check",domain:Q.domain||null,explanation:Q.domain?`Signed by a key published at ${Q.domain}`:"Signed by a key the publishing domain vouches for",severity:0};case"signed":return{status:"signed",tone:"signed",icon:"info",domain:Q.domain||null,explanation:Q.reason||"Signed, but the domain does not vouch for the key",severity:1};case"invalid":return{status:"invalid",tone:"invalid",icon:"warn",domain:Q.domain||null,explanation:Q.reason||"The signature did not verify — this package may have been altered",severity:3};default:return{status:"unverified",tone:"unverified",icon:"warn",domain:Q.domain||null,explanation:Q.reason||"This plugin is not signed",severity:2}}}async function iL(A,Q){try{let B=new Uint8Array(await Q.arrayBuffer());await tL(A,tQ(B))}catch(B){A.notifications.error(`Couldn't read the plugin: ${B.message}`)}}async function rL(A,Q){try{let B=await mL(Q,(C,E)=>fetch(C,E));await tL(A,B)}catch(B){A.notifications.error(`Couldn't fetch the plugin: ${B.message}`)}}async function tL({notifications:A,overlay:Q,plugins:B,social:C,workbench:E},J){let K=dA(J.manifest);if(B.plugins.has(EQ(J.manifest))){A.warn(`“${K}” is already installed.`);return}let L={status:"unverified"};try{L=await B.assessTrust(J)}catch{}let Y=oL(L);if(!Y.allowed){A.error(`“${K}” was not installed. ${Y.detail}`,{sticky:!0});return}Q.set({dialog:{kind:"plugin-review",summary:pL(J,L),policy:Y,isAdmin:!!C.get().admin,installActions:[new ZE(J,L,K)]}})}function pH(A,Q=null){return{...A?.meta||{},...Q||A?.tags||{}}}function lH(A,Q){if(Q.present)return A!=null&&A!==!1&&A!=="";if(A==null)return!1;let B=Number(A),C=Number(Q.value),E=A!==""&&A!==!0&&A!==!1&&Q.value!==""&&Q.value!=null&&!Number.isNaN(B)&&!Number.isNaN(C),J=E?B:String(A).toLowerCase(),K=E?C:String(Q.value).toLowerCase();switch(Q.op){case"!=":return J!==K;case"<":return J<K;case"<=":return J<=K;case">":return J>K;case">=":return J>=K;default:return J===K}}function eL(A,Q,B=null){let C=pH(A,B);return(Q||[]).every((E)=>lH(C[E.key],E))}var cH=/#([\w.-]+)(?::(<=|>=|!=|=|<|>)?("[^"]*"|[^#\s]+)?)?/g;function sB(A){let Q=[],B=A;for(let C of A.matchAll(cH)){let[,E,J,K]=C,L=K&&K.startsWith('"')?K.slice(1,-1):K;Q.push(L==null||L===""?{key:E,present:!0}:{key:E,op:J||"=",value:L,present:!1}),B=B.replace(C[0]," ")}return{text:B.replace(/\s+/g," ").trim(),filters:Q}}function A8(A,Q){if(!Q||!Q.length)return!0;return eL(A,Q)}function iC(A){return A.present?`#${A.key}`:`#${A.key}:${A.op}${A.value}`}function oB(A){let Q=(A?.name||"").toLowerCase();return Q.includes(".")?Q.slice(Q.lastIndexOf(".")):""}var Q8=[{kind:"audio",icon:"file-audio",mime:["audio/"],ext:[".mp3",".flac",".wav",".opus",".ogg",".m4a",".m4b"]},{kind:"image",icon:"file-image",mime:["image/"],ext:[".png",".jpg",".jpeg",".gif",".webp",".svg",".avif"]},{kind:"video",icon:"file-video",mime:["video/"],ext:[".mp4",".webm",".mkv",".mov"]},{kind:"text",icon:"file-text",mime:["text/","application/json"],ext:[".txt",".md",".markdown",".json",".js",".mjs",".ts",".jsx",".tsx",".css",".html",".xml",".yaml",".yml",".toml",".ini",".log",".csv",".py",".rb",".go",".rs",".sh",".c",".h",".cpp",".java"]}];function dH(A,Q,B){if(A.ext.includes(Q))return!0;return A.mime.some((C)=>C.endsWith("/")?B.startsWith(C):B===C)}function B8(A){let Q=oB(A),B=A?.contentType||"";for(let C of Q8)if(dH(C,Q,B))return C.kind;return"file"}var aH={...Object.fromEntries(Q8.map((A)=>[A.kind,A.icon])),file:"file"};function MQ(A){return aH[B8(A)]||"file"}var nH="thumbnail";function RB(A){let Q=A?.thumbnail;if(typeof Q?.src==="string"&&Q.src)return Q;if(Number.isFinite(Q?.range?.start)&&Number.isFinite(Q?.range?.end))return Q;let B=A?.contributions;if(!B)return null;for(let C of Object.values(B)){let E=C?.metadata?.[nH];if(typeof E?.src==="string"&&E.src)return E;if(Number.isFinite(E?.range?.start)&&Number.isFinite(E?.range?.end))return E}return null}function C8(A){return B8(A)==="text"}var MB="openers.associations";function WE(A,Q){return{id:A.id,title:A.title??A.name??A.id,match:A.match??null,priority:A.priority??0,pluginId:A.pluginId??null,source:A.pluginId?Q?.plugins?.get(A.pluginId)?.manifest?.displayName||A.pluginId:"Built-in"}}function E8(A,Q){return(A||[]).filter((B)=>xC(B.match,Q))}function J8(A){return oB(A)||A?.contentType||""}function K8(A){let Q=oB(A);if(Q)return`${Q} files`;let B=A?.contentType||"";return B?`${B} files`:"this file type"}function L8(A,Q){return A.contributions.openersFor(Q).filter((B)=>(!B.when||A.context.evaluate(B.when))&&A.plugins.isAvailable(B)).sort((B,C)=>(C.priority??0)-(B.priority??0)).map((B)=>WE(B,A.plugins))}function Y8(A,Q){let B=A.settings.get(MB)||{},C=oB(Q),E=Q?.contentType||"",J=E.includes("/")?`${E.slice(0,E.indexOf("/")+1)}*`:"";return C&&B[C]||E&&B[E]||J&&B[J]||null}function X8(A,Q,B){let C={...A||{}};if(B)C[Q]=B;else delete C[Q];return C}var H8="trove:",$8=255;var D8=/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;function rC(A){if(typeof A!=="string"||!A.toLowerCase().startsWith(H8))return null;let Q;try{Q=new URL(A)}catch{return null}let B=Q.pathname,C=B.indexOf("/"),E=C<0?B:B.slice(0,C);if(!D8.test(E))return null;let J=Q.searchParams.get("id"),K=Q.searchParams.get("name"),L="";if(C>=0)try{L=decodeURIComponent(B.slice(C+1))}catch{return null}if(J!=null&&(K!=null||L))return null;let Y=J!=null?"id":"name",X=J!=null?J:K!=null?K:L;if(!X||X.length>$8)return null;return{collection:E,by:Y,value:X}}function G8({collection:A,by:Q,value:B}){return`${H8}${A}?${Q}=${encodeURIComponent(B)}`}function iB(A,Q="name"){let B=A?.collectionId||"default";if(Q==="id"){if(!A?.id)throw z.invalid("trove: link by id needs a node id");return G8({collection:B,by:"id",value:A.id})}if(!A?.name)throw z.invalid("trove: link by name needs a node name");return G8({collection:B,by:"name",value:A.name})}var sH="/c";function Z8(A,Q="",B="name"){if(!A?.collectionId)throw z.invalid("An item needs a collection to be linked to");let C=B==="id"?`id:${A.id}`:encodeURIComponent(A.name);if(!C||B==="id"&&!A.id)throw z.invalid("Nothing to link to");let E=`${sH}/${encodeURIComponent(A.collectionId)}/i/${C}`;return Q?`${String(Q).replace(/\/$/,"")}${E}`:E}function W8(A){let Q;try{Q=A.startsWith("/")?A:new URL(A).pathname}catch{return null}let B=/^\/c\/([^/]+)\/i\/(.+)$/.exec(Q);if(!B)return null;let C,E;try{C=decodeURIComponent(B[1]),E=decodeURIComponent(B[2])}catch{return null}if(!D8.test(C))return null;let J=E.startsWith("id:"),K=J?E.slice(3):E;if(!K||K.length>$8)return null;return{collection:C,by:J?"id":"name",value:K}}function rB(A){let Q=A?.selection||[],B=A?.selectionNodes;if(B?.length)return B.filter((C)=>Q.includes(C.id));return(A?.items||[]).filter((C)=>Q.includes(C.id))}class UE{#A;constructor(A=null){this.#A={items:[]},this.cell=c(this.#A),this._controllers=new Map,this.activity=A,this._tasks=new Map,this._retries=new Map}get(){return this.#A}observe(){return this.cell}#Q(){this.cell.setValue(this.#A)}start(A,Q,B,C,{retry:E=null}={}){if(this._controllers.set(A,C),E)this._retries.set(A,E);this.#A={items:[...this.#A.items,{id:A,name:Q,direction:"up",ratio:0,loaded:0,total:B,status:"active",error:null,retryable:!!E}]},this.#Q(),this.#B(A,Q,B)}#B(A,Q,B){let C=this.activity?.start({kind:"transfer",title:`Uploading ${Q}`,total:B||null,unit:"bytes",onCancel:()=>this.cancel(A)});if(C)this._tasks.set(A,C)}retry(A){let Q=this._retries.get(A);if(!Q)return null;let B=this.#A.items.find((C)=>C.id===A);if(!B||B.status==="active")return null;return Q()}restart(A,Q){this._controllers.set(A,Q);let B=this.#A.items.find((C)=>C.id===A);this.#A={items:this.#A.items.map((C)=>C.id===A?{...C,status:"active",error:null,ratio:0,loaded:0}:C)},this.#Q(),this.#B(A,B?.name||"file",B?.total||null)}progress(A,{loaded:Q,total:B,ratio:C}){this.#A={items:this.#A.items.map((E)=>E.id===A?{...E,loaded:Q,total:B,ratio:C}:E)},this.#Q(),this._tasks.get(A)?.progress({done:Q,total:B||null})}finish(A,Q="done",B=null){this.#A={items:this.#A.items.map((E)=>E.id===A?{...E,status:Q,error:B,ratio:Q==="done"?1:E.ratio}:E)},this._controllers.delete(A),this.#Q();let C=this._tasks.get(A);if(C){if(Q==="done")C.succeed();else if(Q==="cancelled")C.cancel();else C.fail(B||Error("Upload failed"));this._tasks.delete(A)}if(Q==="done")setTimeout(()=>this.dismiss(A),4000)}cancel(A){this._controllers.get(A)?.abort(),this.finish(A,"cancelled")}dismiss(A){this.#A={items:this.#A.items.filter((Q)=>Q.id!==A)},this._retries.delete(A),this.#Q()}clearDone(){let A=this.#A.items.filter((B)=>B.status==="active"),Q=new Set(A.map((B)=>B.id));for(let B of[...this._retries.keys()])if(!Q.has(B))this._retries.delete(B);this.#A={items:A},this.#Q()}}function tC(A){let Q=A?.draft?.caps||{},B=Object.entries(Q).filter(([,C])=>C.length).map(([C,E])=>({collectionId:C,capabilities:E}));return B.length?B:null}function U8(A,{open:Q,scan:B,rotate:C,create:E,access:J}){let K=A?.collectionId;return{rows:(A?.collections||[]).map((Y)=>({id:Y.id,name:Y.name||Y.id,driver:Y.driver||"unknown",system:!!Y.system,current:Y.id===K,fingerprint:Y.encryption?.fingerprint||null,encrypted:!!Y.encryption,capabilities:Y.capabilities||[],actions:{open:[Q(Y.id)],scan:[Q(Y.id),B()],rotate:Y.encryption?[Q(Y.id),C()]:null,access:Y.capabilities?.includes("admin")?[J(Y.id)]:null}})),canCreate:!!A?.canCreateCollection,create:[E()]}}function eC(A,Q,B){let C=A?.collectionId,E=(A?.collections||[]).map((J)=>({label:J.name||J.id,icon:J.id===C?"check":"files",actions:[Q(J.id)]}));if(A?.canCreateCollection){if(E.length)E.push({sep:!0});E.push({label:"New collection…",icon:"plus",actions:[B()]})}return E}function F8(A){return new Promise((Q)=>{let B=document.createElement("input");B.type="file",A(B),B.style.display="none",document.body.appendChild(B);let C=(J)=>{Q(J),B.remove(),window.removeEventListener("focus",E)},E=()=>setTimeout(()=>{if(!B.files.length)C(null)},300);B.addEventListener("change",()=>C(B.files),{once:!0}),window.addEventListener("focus",E),B.click()})}function I8(){return F8((A)=>{A.multiple=!0})}function R8(){return F8((A)=>{A.accept=".zip,application/zip"}).then((A)=>A?.[0]??null)}function M8(A,Q){let B=document.createElement("a");B.href=A,B.download=Q||"",document.body.appendChild(B),B.click(),B.remove()}function hQ(A={}){let Q=c(A);return{observe:()=>Q,get:()=>Q.getValue(),set:(B)=>Q.setValue({...Q.getValue(),...B})}}var V8=(A)=>hQ({items:[],loading:!1,error:null,selection:[],sort:A.get("explorer.sort"),order:A.get("explorer.sortOrder"),collectionId:null,collections:[],canCreateCollection:!1,gate:null,stats:null,usage:null,nextCursor:null,loadingMore:!1,trash:null,selectionNodes:null}),q8=()=>hQ({query:"",mode:"hybrid",results:[],loading:!1,error:null,ran:!1,paletteFiles:[],paletteQuery:"",paletteLoading:!1,paletteError:null,filtered:!1,offline:!1,resolved:null}),z8=()=>hQ({keys:[],loading:!1,loaded:!1,error:null,minted:null,busy:null,draft:null,forbidden:!1}),N8=()=>hQ({}),P8=()=>hQ({palette:null,dialog:null,contextMenu:null,pluginPanel:null,activityPanel:!1}),O8=()=>hQ({activity:"home",sidebarVisible:!0,launch:{query:"",index:0},aclFor:null,searchModal:!1,sheet:null,infoPanel:!1});function FE(A,Q,B){return(A+Q+B)%B}var j8=()=>hQ({collectionId:null,grants:[],admins:[],loading:!1,error:null,busy:!1}),w8=()=>hQ({collectionId:null,rotation:null,estimate:null,loading:!1,error:null,busy:!1});class hA extends P{static deps=["api","explorer","notifications","settings"];constructor(A){super();this.collectionId=A}async execute(A){let{api:Q,explorer:B,notifications:C,settings:E}=A,J=this.collectionId||B.get().collectionId;if(!J){B.set({loading:!1,gate:"choose"});return}let K=J!==B.get().collectionId;B.set({loading:!0,error:null,collectionId:J,...K?{trash:null}:{}});try{let L=E.get("explorer.sort"),Y=E.get("explorer.sortOrder"),X=await Q.list(J,{sort:L,order:Y});B.set({items:X.items,loading:!1,selection:[],sort:L,order:Y,collectionId:X.collectionId||J,stats:X.stats||null,usage:X.usage||null,nextCursor:X.nextCursor||null}),E.set("explorer.lastCollection",J),B.set({gate:null})}catch(L){B.set({loading:!1,error:L.message}),C.error(`Couldn't load this collection: ${L.message}`)}}}class IE extends P{static deps=["api","explorer"];async execute(A){try{let Q=await A.api.collections(),B=Q.collections||[];return A.explorer.set({collections:B,canCreateCollection:!!Q.canCreate}),B}catch{return[]}}}class RE extends P{static deps=["api","engine","explorer","notifications","settings"];async execute(A){let Q=W8(typeof location<"u"?location.pathname:"");if(Q)return this.#A(A,Q);let B=[],C=!1;try{let K=await A.api.collections();B=K.collections||[],C=!!K.canCreate,A.explorer.set({collections:B,canCreateCollection:C})}catch(K){A.explorer.set({loading:!1,error:`Couldn't load your collections: ${K.message}`});return}let E=B.map((K)=>K.id),J=A.settings.get("explorer.lastCollection");if(!E.length){A.explorer.set({loading:!1,items:[],collections:[],gate:C?"create":null,error:C?null:"You do not have access to any collections yet. Ask an administrator to grant you one."});return}if(!J||!E.includes(J)){A.explorer.set({loading:!1,items:[],gate:"choose",error:null});return}return A.explorer.set({gate:null}),A.engine.dispatch(new hA(J))}async#A(A,Q){let{api:B,engine:C,explorer:E,notifications:J}=A;if(typeof history<"u")history.replaceState(null,"","/");let K=[];try{let Y=await B.collections();K=Y.collections||[],E.set({collections:K,canCreateCollection:!!Y.canCreate})}catch(Y){E.set({loading:!1,error:`Couldn’t load your collections: ${Y.message}`});return}if(!K.some((Y)=>Y.id===Q.collection)){E.set({loading:!1,items:[],gate:null,error:`This link points at a collection you do not have access to (“${Q.collection}”). Ask whoever shared it to grant you access.`});return}E.set({gate:null}),await lA(C,new hA(Q.collection));let L;try{L=(Q.by==="id"?await B.stat(Q.value):await B.stat(Q.value,{collection:Q.collection}))?.node||null}catch{L=null}if(!L?.id){J.warn(Q.by==="name"?`“${Q.value}” is not in this collection any more — it may have been renamed or removed.`:"That item no longer exists.");return}C.dispatch(new aA(L,{reset:!0}))}}class N extends P{static deps=["commands"];constructor(A,...Q){super();this.id=A,this.args=Q}async execute({commands:A}){return A.execute(this.id,...this.args)}}class ME extends P{static deps=["notifications","plugins"];constructor(A){super();this.pluginId=A}async execute(A){try{await A.plugins.uninstall(this.pluginId)}catch(Q){A.notifications.error(`Couldn’t uninstall: ${Q.message}`)}}}class S8 extends P{static deps=["api","engine","notifications"];constructor(A){super();this.record=A}async execute(A){try{let Q=await A.api.createCollection(this.record);A.notifications.success(`Created collection “${Q.collection.name}”`),await lA(A.engine,new IE),A.engine.dispatch(new hA(Q.collection.id))}catch(Q){A.notifications.error(`Couldn’t create collection: ${Q.message}`)}}}class VE extends P{static deps=["api","explorer","notifications"];async execute(A){let{api:Q,explorer:B,notifications:C}=A,E=B.get().nextCursor;if(!E||B.get().loadingMore)return;B.set({loadingMore:!0});try{let J=await Q.list(B.get().collectionId,{sort:B.get().sort,order:B.get().order,cursor:E});B.set({items:[...B.get().items,...J.items],nextCursor:J.nextCursor||null,loadingMore:!1})}catch(J){B.set({loadingMore:!1}),C.error(`Couldn't load more: ${J.message}`)}}}class tB extends P{static deps=["engine","explorer"];async execute(A){return A.engine.dispatch(new hA(A.explorer.get().collectionId))}}class eQ extends P{static deps=["api","engine","explorer","notifications"];constructor(A="list",Q=null){super();this.op=A,this.id=Q}async execute(A){let{api:Q,explorer:B,notifications:C}=A,E=B.get().collectionId;if(this.op==="hide"){B.set({trash:null});return}try{if(this.op==="restore"){let{node:K}=await Q.restore(this.id);C.success(`Restored “${K.name}”`)}else if(this.op==="purge")await Q.purgeTrash({id:this.id});else if(this.op==="empty"){let{purged:K}=await Q.purgeTrash({collection:E});C.success(`Deleted ${K} item${K===1?"":"s"} for good`)}let{items:J}=await Q.trash(E);if(B.set({trash:J}),this.op!=="list")A.engine.dispatch(new hA(E))}catch(J){C.error(`Trash: ${J.message}`)}}}class _8 extends P{static deps=["api","engine","navigation","notifications"];constructor(A){super();this.ids=A}async execute(A){try{for(let Q of this.ids)await A.api.remove(Q);A.notifications.info(`Deleted ${this.ids.length} item${this.ids.length>1?"s":""}`);for(let Q of this.ids)A.navigation.forget(Q)}catch(Q){A.notifications.error(`Couldn’t delete: ${Q.message}`)}A.engine.dispatch(new tB)}}class T8 extends P{static deps=["api","engine","navigation","notifications"];constructor(A,Q){super();this.id=A,this.newName=Q}async execute(A){try{let Q=await A.api.rename(this.id,this.newName);A.navigation.updateTabNode(Q.node),A.engine.dispatch(new tB)}catch(Q){A.notifications.error(`Couldn’t rename: ${Q.message}`)}}}class aA extends P{static deps=["context","contributions","engine","plugins","settings"];constructor(A,Q={}){super();this.node=A,this.opts=Q}async execute(A){if(!this.node)return;let Q=(E)=>A.engine.dispatch(new GQ(this.node,E,{reset:!!this.opts.reset}));if(this.opts.openerId)return Q(this.opts.openerId);let B=L8(A,this.node),C=Y8(A,this.node);if(C&&B.some((E)=>E.id===C))return Q(C);if(B.length>1)return A.engine.dispatch(new sA({kind:"opener-chooser",node:this.node,openers:B,reset:!!this.opts.reset}));Q(B[0]?.id||"core.fallback")}}class eB extends P{static deps=["api","engine","explorer","notifications","settings","transfers"];constructor(A,Q){super();this.files=A,this.collectionId=Q}async execute(A){let Q=this.collectionId||A.explorer.get().collectionId;if(!Q){A.notifications.error("Open a collection before uploading");return}let B=A.settings.get("uploads.concurrency"),C=[...this.files].map((E)=>this.#A(A,E,Q,B));await Promise.allSettled(C),A.engine.dispatch(new hA(Q))}async#A(A,Q,B,C,E=null){let{api:J,notifications:K,transfers:L}=A,Y=E||AL("xfer"),X=new AbortController;if(E)L.restart(Y,X);else L.start(Y,Q.name,Q.size,X,{retry:()=>this.#A(A,Q,B,C,Y)});let H=null;try{let G=await J.upload(Q,{collection:B,concurrency:C,signal:X.signal,onStart:(D)=>{H=D},onProgress:(D)=>L.progress(Y,D)});if(L.finish(Y,"done"),G?.name&&G.name!==Q.name)K.info(`"${Q.name}" already existed — saved as "${G.name}".`)}catch(G){if(H)J.abortUpload(H).catch(()=>{});if(G.code==="aborted")L.finish(Y,"cancelled");else L.finish(Y,"error",G.message),K.error(`Upload failed: ${Q.name} — ${G.message}. Retry it from the transfers tray.`)}}}class VB extends P{static deps=["api","explorer","offline","search"];constructor(A,Q){super();this.filters=A||[],this.text=Q||""}async execute(A){let{api:Q,search:B}=A;if(!this.filters.length){B.set({results:[],ran:!1,filtered:!1});return}if(B.set({query:this.text,loading:!0,error:null,filtered:!0}),A.offline&&!A.offline.get().online){let C=(A.explorer.get().items||[]).filter((E)=>A8(E,this.filters));B.set({results:C.map((E)=>({node:E})),loading:!1,ran:!0,filtered:!0,offline:!0});return}try{let C=await Q.tagSearch(this.filters,this.text.trim()||void 0,{limit:100});B.set({results:(C.items||[]).map((E)=>({node:E})),loading:!1,ran:!0,filtered:!0,offline:!1})}catch(C){B.set({loading:!1,error:C.message,ran:!0,filtered:!0})}}}class qE extends P{static deps=["api","overlay","search"];constructor(A){super();this.query=A}async execute(A){let{api:Q,overlay:B,search:C}=A;if(B.get().palette?.mode!=="files")return;let E=(this.query||"").trim();if(!E){C.set({paletteFiles:[],paletteQuery:"",paletteError:null,paletteLoading:!1});return}C.set({paletteQuery:E,paletteLoading:!0,paletteError:null});try{let J=await Q.search(E,{mode:"keyword",limit:30});if(C.get().paletteQuery!==E)return;C.set({paletteFiles:J.results||[],paletteLoading:!1})}catch(J){if(C.get().paletteQuery!==E)return;C.set({paletteFiles:[],paletteLoading:!1,paletteError:J?.message||"Search failed"})}}}class VQ extends P{static deps=["api","contributions","offline","search","settings"];constructor(A,Q){super();this.query=A,this.mode=Q}async execute(A){let{api:Q,contributions:B,search:C,settings:E}=A,J=this.query.trim();if(!J){C.set({query:"",results:[],ran:!1,error:null,resolved:null});return}let K=this.mode||E.get("search.mode");C.set({query:this.query,mode:K,loading:!0,error:null,resolved:null,filtered:!1});let L=()=>C.get().query!==this.query,Y=A.offline;if(Y&&!Y.get().online){try{let X=await Y.searchOffline(J,{limit:40});if(L())return;C.set({results:X,loading:!1,ran:!0,offline:!0,resolved:null})}catch(X){if(L())return;C.set({results:[],loading:!1,ran:!0,offline:!0,error:X.message})}return}try{let X=B.ofType("view").map((G)=>({id:G.id,title:G.title||G.id})),H=await Q.query(J,{mode:K,limit:40,views:X});if(L())return;C.set({results:H.results,resolved:H.resolved||null,loading:!1,ran:!0,offline:!1})}catch(X){if(L())return;if(Y){let H=await Y.searchOffline(J,{limit:40});if(L())return;C.set({results:H,loading:!1,ran:!0,offline:!0,error:H.length?null:X.message})}else C.set({loading:!1,error:X.message,ran:!0})}}}class AC extends P{static deps=["api","apiKeys"];async execute(A){A.apiKeys.set({loading:!0,error:null});try{let Q=await A.api.apiKeys();A.apiKeys.set({keys:Q.keys||[],loading:!1,loaded:!0,error:null})}catch(Q){if(Q?.status===403||Q?.code==="forbidden"){A.apiKeys.set({keys:[],loading:!1,loaded:!0,error:null,forbidden:!0});return}A.apiKeys.set({loading:!1,error:Q?.message||"Could not load API keys"})}}}class x8 extends P{static deps=["api","apiKeys","notifications"];constructor(A){super();this.spec=A}async execute(A){A.apiKeys.set({busy:"mint",error:null});try{let{key:Q,secret:B}=await A.api.mintApiKey(this.spec);A.apiKeys.set({minted:{key:Q,secret:B},busy:null});let C=await A.api.apiKeys().catch(()=>null);if(C)A.apiKeys.set({keys:C.keys||[]});return Q}catch(Q){return A.apiKeys.set({busy:null,error:Q?.message||"Could not create the key"}),A.notifications.error(Q?.message||"Could not create the key"),null}}}class zE extends P{static deps=["api","apiKeys","notifications"];constructor(A){super();this.id=A}async execute(A){A.apiKeys.set({busy:this.id,error:null});try{await A.api.revokeApiKey(this.id);let Q=await A.api.apiKeys().catch(()=>null);A.apiKeys.set({busy:null,...Q?{keys:Q.keys||[]}:{}}),A.notifications.success("Key revoked")}catch(Q){A.apiKeys.set({busy:null}),A.notifications.error(Q?.message||"Could not revoke the key")}}}class NE extends P{static deps=["keybindings"];constructor(A,Q){super();this.bindingId=A,this.key=Q}async execute({keybindings:A}){let Q=A.resolved().find((B)=>B.bindingId===this.bindingId);if(!Q)return;A.rebind(Q,this.key)}}class tA extends P{static deps=["notifications"];constructor(A,Q="Copied"){super();this.text=A,this.label=Q}async execute({notifications:A}){try{await navigator.clipboard.writeText(this.text),A.success(this.label)}catch{A.info(this.text,{sticky:!0})}}}class PE extends P{static deps=["notifications"];constructor(A){super();this.id=A}async execute({notifications:A}){A.dismiss(this.id)}}class XQ extends P{static deps=["workbench"];async execute({workbench:A}){this.apply(A)}}class bA extends P{static deps=["overlay"];async execute({overlay:A}){this.apply(A)}}class k8 extends P{static deps=["navigation"];async execute({navigation:A}){this.apply(A)}}class TA extends bA{apply(A){A.set({dialog:null})}}class QC extends bA{constructor(A){super();this.patch=A}apply(A){let Q=A.get().dialog;if(Q)A.set({dialog:{...Q,...this.patch}})}}class qB extends bA{apply(A){A.set({contextMenu:null})}}class BC extends bA{apply(A){A.set({palette:null})}}class OE extends bA{constructor(A){super();this.query=A}apply(A){let Q=A.get().palette;if(Q)A.set({palette:{...Q,query:this.query,index:0}})}}class jE extends bA{constructor(A){super();this.index=A}apply(A){let Q=A.get().palette;if(Q)A.set({palette:{...Q,index:this.index}})}}class A0 extends bA{constructor(A,Q){super();this.delta=A,this.count=Q}apply(A){let Q=A.get().palette;if(!Q||!this.count)return;A.set({palette:{...Q,index:FE(Q.index,this.delta,this.count)}})}}class wE extends XQ{apply(A){A.set({searchModal:!0,launch:{query:"",index:0}})}}class zB extends XQ{apply(A){A.set({searchModal:!1})}}class SE extends XQ{constructor(A){super();this.collectionId=A}apply(A){A.set({aclFor:A.get().aclFor===this.collectionId?null:this.collectionId})}}class AB extends XQ{constructor(A){super();this.query=A}apply(A){A.set({launch:{query:this.query,index:0}})}}class _E extends XQ{constructor(A){super();this.index=A}apply(A){A.set({launch:{...A.get().launch,index:this.index}})}}class Q0 extends XQ{constructor(A){super();this.which=A}apply(A){A.set({sheet:A.get().sheet===this.which?null:this.which})}}class nA extends XQ{apply(A){A.set({sheet:null})}}class CC extends XQ{constructor(A){super();this.open=A}apply(A){A.set({infoPanel:this.open??!A.get().infoPanel})}}class EC extends bA{constructor(A){super();this.pluginId=A}apply(A){A.set({pluginPanel:this.pluginId})}}class TE extends bA{apply(A){A.set({pluginPanel:null})}}class GQ extends P{static deps=["navigation","workbench"];constructor(A,Q,B={}){super();this.node=A,this.openerId=Q,this.opts=B}async execute({navigation:A,workbench:Q}){Q.set({activity:"home",searchModal:!1}),A.openFile(this.node,this.openerId,this.opts)}}class JC extends P{static deps=["activity"];async execute(A){this.apply(A.activity)}}class wA extends P{static deps=["activity","overlay"];constructor(A){super();this.which=A}async execute({activity:A,overlay:Q}){let B=this.which??!Q.get().activityPanel;if(Q.set({activityPanel:B}),B)await A.refresh()}}class xE extends JC{constructor(A){super();this.id=A}apply(A){A.cancel(this.id)}}class kE extends JC{constructor(A){super();this.id=A}apply(A){A.dismiss(this.id)}}class gE extends JC{constructor(A){super();this.id=A}apply(A){A.retryIssue(this.id)}}class yE extends JC{constructor(A){super();this.id=A}apply(A){A.dismissIssue(this.id)}}class KC extends P{static deps=["transfers"];async execute(A){this.apply(A.transfers)}}class LC extends KC{constructor(A){super();this.id=A}apply(A){A.cancel(this.id)}}class hE extends KC{constructor(A){super();this.id=A}apply(A){A.retry(this.id)}}class bE extends KC{constructor(A){super();this.id=A}apply(A){A.dismiss(this.id)}}class vE extends KC{apply(A){A.clearDone()}}class HQ extends P{static deps=["social"];async execute(A){return this.apply(A.social)}}class qQ extends HQ{constructor(A){super();this.open=A}apply(A){A.toggleInbox(this.open)}}class YC extends HQ{apply(A){return A.enablePush()}}class B0 extends HQ{constructor(A){super();this.body=A}apply(A){return A.comment(this.body)}}class fE extends HQ{constructor(A){super();this.commentId=A}apply(A){return A.deleteComment(this.commentId)}}class uE extends HQ{constructor(A,Q){super();this.commentId=A,this.emoji=Q}apply(A){return A.react(this.commentId,this.emoji)}}class C0 extends HQ{constructor(A){super();this.target=A}apply(A){A.setReplyTo(this.target)}}class mE extends HQ{constructor(A,Q){super();this.name=A,this.value=Q}apply(A){A.addTag(this.name,this.value)}}class pE extends HQ{constructor(A){super();this.name=A}apply(A){A.removeTag(this.name)}}class XC extends HQ{constructor(A){super();this.nodeId=A}apply(A){A.loadSidecar(this.nodeId)}}class NB extends P{static deps=["apiKeys"];async execute(A){this.apply(A.apiKeys)}}class E0 extends NB{constructor(A){super();this.patch=A}apply(A){let Q=A.get().draft;if(Q)A.set({draft:{...Q,...this.patch}})}}class lE extends NB{constructor(A,Q){super();this.collectionId=A,this.capability=Q}apply(A){let Q=A.get().draft;if(!Q)return;let B={...Q.caps},C=new Set(B[this.collectionId]||[]);if(C.has(this.capability))C.delete(this.capability);else C.add(this.capability);if(C.size)B[this.collectionId]=[...C];else delete B[this.collectionId];A.set({draft:{...Q,caps:B}})}}class cE extends P{static deps=["explorer","workbench"];constructor(A,Q){super();this.delta=A,this.nodes=Q}async execute({workbench:A,explorer:Q}){let B=this.nodes.length;if(!B)return;let C=FE(A.get().launch.index,this.delta,B);A.set({launch:{...A.get().launch,index:C}}),g8(Q,this.nodes[C])}}class dE extends P{static deps=["explorer","workbench"];constructor(A,Q){super();this.index=A,this.node=Q}async execute({workbench:A,explorer:Q}){A.set({launch:{...A.get().launch,index:this.index}}),g8(Q,this.node)}}function g8(A,Q){let B=Q?.id?[Q.id]:[],C=A.get().selection;if(B.length===C.length&&B.every((E,J)=>E===C[J]))return;A.set({selection:B,selectionNodes:Q?[Q]:null})}class QB extends P{static deps=["viewState"];constructor(A,Q){super();this.key=A,this.value=Q}async execute({viewState:A}){A.set({[this.key]:this.value})}}class $Q extends bA{constructor(A,Q=null){super();this.items=A,this.at=Q?.rect?{prefer:Q.prefer||"down",rect:{left:Q.rect.left,top:Q.rect.top,right:Q.rect.right,bottom:Q.rect.bottom}}:Q?{x:Q.x,y:Q.y}:null}apply(A){A.set({contextMenu:{items:this.items,at:this.at}})}}class sA extends bA{constructor(A){super();this.dialog=A}apply(A){A.set({dialog:this.dialog})}}class bQ extends P{static deps=["settings"];constructor(A,Q){super();this.key=A,this.value=Q}async execute({settings:A}){A.set(this.key,this.value)}}class GC extends P{static deps=["settings"];constructor(A,Q){super();this.typeKey=A,this.openerId=Q}async execute({settings:A}){if(!this.typeKey)return;A.set(MB,X8(A.get(MB),this.typeKey,this.openerId))}}class aE extends k8{apply(A){A.back()}}class vQ extends P{static deps=["navigation","workbench"];async execute({navigation:A,workbench:Q}){Q.set({activity:"home",searchModal:!1}),A.reset()}}class nE extends P{static deps=["plugins"];constructor(A){super();this.pluginId=A}async execute({plugins:A}){return A.refresh(this.pluginId)}}class sE extends P{static deps=["plugins"];constructor(A,Q,B){super();this.pluginId=A,this.key=Q,this.value=B}async execute({plugins:A}){return A.setSecret(this.pluginId,this.key,this.value)}}class oE extends P{static deps=["api","engine","notifications","workbench"];constructor(A){super();this.nodeId=A}async execute({api:A,engine:Q,notifications:B,workbench:C}){let E;try{({node:E}=await A.stat(this.nodeId))}catch(J){B.warn(J?.status===403||J?.code==="forbidden"?"You no longer have access to that item.":"That item no longer exists.");return}await lA(Q,new aA(E)),C.set({infoPanel:!0})}}class iE extends P{static deps=["overlay","viewState"];async execute(A){let B=(A.viewState.get()[dB]?.value??"").trim();if(A.overlay.set({dialog:null}),B)await this.withValue(B,A)}}class y8 extends iE{static deps=["engine","overlay","viewState"];constructor(A){super();this.node=A}async withValue(A,{engine:Q}){if(A!==this.node.name)Q.dispatch(new T8(this.node.id,A))}}class ZE extends P{static deps=["notifications","overlay","plugins","viewState","workbench"];constructor(A,Q,B){super();this.pkg=A,this.trust=Q,this.label=B}async execute({notifications:A,overlay:Q,plugins:B,viewState:C,workbench:E}){let J=[...C.get()[aB]?.grants||[]];Q.set({dialog:null}),E.set({activity:"plugins",sidebarVisible:!0});let K=A.info(`Installing “${this.label}”…`,{sticky:!0});try{await B.install(this.pkg,{grants:J,trust:this.trust}),A.dismiss(K),A.success(`Installed “${this.label}”`)}catch(L){A.dismiss(K),A.error(`Install failed: ${L.message}`)}}}class rE extends iE{static deps=["notifications","overlay","plugins","social","viewState","workbench"];async withValue(A,Q){await rL(Q,A)}}class tE extends P{static deps=["engine","overlay"];constructor(A){super();this.record=A}async execute({engine:A,overlay:Q}){if(Q.set({dialog:null}),this.record)A.dispatch(new S8(this.record))}}class eE extends P{static deps=["viewState"];constructor(A,Q,B,C={}){super();this.key=A,this.ref=Q,this.patch=B,this.fallback=C}async execute({viewState:A}){let Q=A.get()[this.key],B=Q&&Q.ref===this.ref?Q.form:this.fallback;A.set({[this.key]:{ref:this.ref,form:{...B,...this.patch}}})}}function HC({explorer:A,navigation:Q,notifications:B},C=null){let E=C||rB(A.get())[0]||Q.activeTab()?.node;if(!E)B.info("Pick a file first — highlight one in the list, or open it.");return E}class J0 extends bA{constructor(A="commands",Q=""){super();this.mode=A,this.query=Q}apply(A){A.set({palette:{mode:this.mode,query:this.query,index:0}})}}class $C extends XQ{constructor(A){super();this.activity=A}apply(A){A.set({activity:this.activity,sidebarVisible:!0})}}class AJ extends P{static deps=["navigation","overlay","workbench"];async execute({navigation:A,overlay:Q,workbench:B}){let C=Q.get(),E=B.get();if(C.contextMenu)return Q.set({contextMenu:null});if(C.dialog)return Q.set({dialog:null});if(E.sheet)return B.set({sheet:null});if(E.searchModal)return B.set({searchModal:!1});if(C.palette)return Q.set({palette:null});if(C.pluginPanel)return Q.set({pluginPanel:null});if(C.activityPanel)return Q.set({activityPanel:!1});if(A.get().stack.length>1)A.back()}}class QJ extends P{static deps=["engine","voice"];async execute({engine:A,voice:Q}){await Q.run({onText:(B,{final:C})=>{if(!B)return;if(A.dispatch(new AB(B)),C)A.dispatch(new VQ(B))}})}}class BJ extends P{static deps=["activity","api","engine","notifications"];async execute({activity:A,api:Q,engine:B,notifications:C}){try{let E=await Q.reindex();if(await A.refreshTasks(),B.dispatch(new wA(!0)),E.alreadyRunning)C.info("A rebuild is already running")}catch(E){C.error(`Couldn't rebuild the index: ${E.message}`)}}}class CJ extends P{static deps=["activity","api","engine","explorer","notifications"];async execute({activity:A,api:Q,engine:B,explorer:C,notifications:E}){let J=C.get().collectionId;if(!J)return E.info("Open a collection first — a scan is per collection.");try{let K=await Q.scanCollection(J);if(await A.refreshTasks(),B.dispatch(new wA(!0)),K.alreadyRunning)E.info("A scan of this collection is already running");A.followUp()}catch(K){E.error(`Couldn't scan “${J}”: ${K.message}`)}}}class EJ extends P{static deps=["activity","api","engine","notifications"];async execute({activity:A,api:Q,engine:B,notifications:C}){try{let E=await Q.checkStorage();await A.refresh(),B.dispatch(new wA(!0));let J=(E.results||[]).reduce((K,L)=>K+(L.findings?.length||0),0);if(J)C.warn(`Found ${J} storage problem${J===1?"":"s"} — see Activity`);else if(!E.checked)C.info("There are no collections to check yet");else if(!E.corsChecked)C.info("Stores are reachable. Browser access was not checked — this drive has no public URL configured.");else C.success("Stores are reachable and allow browser access")}catch(E){C.error(`Couldn't check the stores: ${E.message}`)}}}class JJ extends P{static deps=["engine","explorer"];async execute({engine:A,explorer:Q}){let B=Q.get().collectionId,C=await I8();if(C?.length)await lA(A,new eB(C,B))}}class K0 extends P{static deps=["engine","explorer","navigation","notifications"];constructor(A="trove",Q=null){super();this.kind=A,this.node=Q}async execute(A){let Q=HC(A,this.node);if(!Q)return;return A.engine.dispatch(this.kind==="share"?new tA(Z8(Q,location.origin),"Link copied — anyone with access to this collection can open it"):new tA(iB(Q),`Copied ${iB(Q)}`))}}class KJ extends P{static deps=["engine","explorer","navigation","notifications"];constructor(A=null){super();this.node=A}async execute(A){let Q=HC(A,this.node);if(!Q)return;A.engine.dispatch(new sA({kind:"prompt",title:"Rename",label:"New name",value:Q.name,confirmLabel:"Rename",confirmActions:[new y8(Q)]}))}}class LJ extends P{static deps=["engine","explorer","navigation","notifications","settings"];async execute(A){let Q=rB(A.explorer.get()),B=Q.length?null:A.navigation.activeTab()?.node;if(B)Q.push(B);if(!Q.length){A.notifications.info("Pick a file first — highlight one in the list, or open it.");return}let C=new _8(Q.map((E)=>E.id));if(!A.settings.get("explorer.confirmDelete"))return A.engine.dispatch(C);A.engine.dispatch(new sA({kind:"confirm",title:`Move ${Q.length} item${Q.length>1?"s":""} to the trash?`,body:Q.length===1?`"${Q[0].name}" leaves the drive but is kept, and can be restored from the trash.`:"They leave the drive but are kept, and can be restored from the trash.",confirmLabel:"Move to trash",confirmActions:[C]}))}}class YJ extends P{static deps=["engine"];async execute({engine:A}){A.dispatch(new eQ("list")),A.dispatch(new vQ)}}class XJ extends P{static deps=["engine","explorer","navigation","notifications"];constructor(A=null){super();this.node=A}async execute(A){let Q=HC(A,this.node);if(Q)return A.engine.dispatch(new aA(Q))}}class GJ extends P{static deps=["api","explorer","navigation","notifications"];constructor(A=null){super();this.node=A}async execute(A){let Q=HC(A,this.node);if(!Q?.id)return;try{let{url:B,revoke:C}=await A.api.download(Q.id,Q.name);if(M8(B,Q.name),C)setTimeout(()=>URL.revokeObjectURL(B),60000)}catch(B){A.notifications.error(`Couldn't download ${Q.name}: ${B.message}`)}}}class L0 extends P{static deps=["explorer","navigation","notifications","offline"];constructor(A=null,Q=!0){super();this.node=A,this.pinned=Q}async execute(A){let Q=HC(A,this.node);if(!Q?.id)return;return this.pinned?A.offline.pin(Q):A.offline.unpin(Q.id)}}class HJ extends NB{apply(A){A.set({draft:{name:"",expiresInDays:"",caps:{}},error:null})}}class $J extends NB{apply(A){A.set({draft:null})}}class DJ extends NB{apply(A){if(A.get().minted)A.set({minted:null})}}class ZJ extends P{static deps=["apiKeys","engine"];async execute({apiKeys:A,engine:Q}){let B=A.get().draft,C=tC(A.get());if(!B?.name?.trim()||!C)return;let E=Number(B.expiresInDays),J=B.expiresInDays!==""&&Number.isFinite(E)&&E>0?Date.now()+E*86400000:null;return A.set({draft:null}),Q.dispatch(new x8({name:B.name.trim(),scopes:C,expiresAt:J}))}}class WJ extends P{static deps=["engine","explorer","notifications"];constructor(A=null){super();this.collectionId=A}async execute({engine:A,explorer:Q,notifications:B}){if(this.collectionId){A.dispatch(new hA(this.collectionId)),A.dispatch(new vQ);return}let C=eC(Q.get(),(E)=>new N("collections.switch",E),()=>new N("collections.create"));if(!C.length)return B.info("This drive has one collection.");A.dispatch(new $Q(C))}}class UJ extends P{static deps=["navigation","notifications","workbench"];async execute({navigation:A,notifications:Q,workbench:B}){if(!A.activeTab()){Q.info("Open a file to see its details and conversation.");return}B.set({infoPanel:!B.get().infoPanel})}}class FJ extends P{static deps=["notifications","overlay","plugins","social","workbench"];async execute(A){let Q=await R8();if(Q)await iL(A,Q)}}class IJ extends P{static deps=["plugins"];constructor(A,Q,B=[]){super();this.pluginId=A,this.name=Q,this.args=B}async execute({plugins:A}){return A.invokeCommand(this.pluginId,this.name,this.args)}}class RJ extends P{static deps=["social"];constructor(A){super();this.nodeId=A}async execute({social:A}){if(A.get().sidecar?.nodeId===this.nodeId)A.loadSidecar(null)}}class Y0 extends P{static deps=["acl","api","notifications"];constructor(A){super();this.collectionId=A}async execute({acl:A,api:Q,notifications:B}){let C=this.collectionId;if(!C)return;A.set({collectionId:C,loading:!0,error:null});try{let E=await Q.collectionGrants(C);A.set({grants:E?.grants||[],admins:E?.admins||[],loading:!1})}catch(E){if(A.set({loading:!1,error:E?.message||"Could not read the access list"}),E?.status!==403)B.error?.(E?.message||"Could not read the access list")}}}class MJ extends P{static deps=["acl","api","engine","notifications"];constructor(A,Q){super();this.collectionId=A,this.grant=Q}async execute({acl:A,api:Q,engine:B,notifications:C}){A.set({busy:!0});try{await Q.setCollectionGrant(this.collectionId,this.grant);let E=this.grant.type==="anyone"?"everyone":this.grant.subject;C.success?.(this.grant.capabilities?.length?`Access for ${E} updated`:`Access for ${E} removed`)}catch(E){C.error?.(E?.message||"Could not change access")}finally{A.set({busy:!1}),await lA(B,new Y0(this.collectionId))}}}class PB extends P{static deps=["api","explorer","notifications","rotation"];constructor(A=null){super();this.collectionId=A}async execute({api:A,explorer:Q,notifications:B,rotation:C}){let E=this.collectionId||Q.get().collectionId;if(!E)return;let J=C.get().collectionId!==E;C.set(J?{collectionId:E,rotation:null,estimate:null,loading:!0,error:null}:{collectionId:E,loading:!0,error:null});try{let[K,L]=await Promise.all([A.rotationState(E),A.rotationEstimate(E).catch(()=>null)]);C.set({rotation:K?.rotation??null,estimate:L??null,loading:!1})}catch(K){if(C.set({loading:!1,error:K?.message||"Could not read the rotation state"}),K?.status!==403)B.error?.(K?.message||"Could not read the rotation state")}}}class VJ extends P{static deps=["api","engine","explorer","notifications","rotation"];async execute({api:A,engine:Q,explorer:B,notifications:C,rotation:E}){let J=B.get().collectionId;if(!J)return;E.set({busy:!0});try{let K=await A.beginRotation(J);E.set({rotation:K?.rotation??null,busy:!1}),Q.dispatch(new IE),C.info("Key rotation started. It runs in the background and survives a reload.")}catch(K){E.set({busy:!1}),C.error(K?.message||"Could not start the rotation")}return Q.dispatch(new PB)}}class qJ extends P{static deps=["api","engine","explorer","notifications","rotation"];async execute({api:A,engine:Q,explorer:B,notifications:C,rotation:E}){let J=B.get().collectionId;if(!J)return;E.set({busy:!0});try{await A.cancelRotation(J),C.info("Rotation stopped. Files already moved stay on the new key.")}catch(K){C.error(K?.message||"Could not stop the rotation")}return E.set({busy:!1}),Q.dispatch(new PB)}}class zJ{constructor(A,Q={}){if(this.port=A,this.onCall=Q.onCall,this.onEvent=Q.onEvent,this.targetOrigin=Q.targetOrigin,this.seq=0,this.pending=new Map,this._listener=(B)=>this._receive(B.data,B),typeof A.addEventListener==="function")A.addEventListener("message",this._listener);else A.onmessage=this._listener;A.start?.()}_post(A,Q){if(this.targetOrigin)this.port.postMessage(A,this.targetOrigin,Q);else this.port.postMessage(A,Q)}call(A,Q,{timeout:B=30000,transfer:C}={}){let E=++this.seq;return new Promise((J,K)=>{let L=B?setTimeout(()=>{this.pending.delete(E),K(Error(`RPC timeout: ${A}`))},B):null;this.pending.set(E,{resolve:J,reject:K,timer:L}),this._post({__trove:"req",id:E,method:A,params:Q},C)})}emit(A,Q,B){this._post({__trove:"event",method:A,params:Q},B)}async _receive(A,Q){if(!A||A.__trove==null)return;if(A.__trove==="res"){let B=this.pending.get(A.id);if(!B)return;if(this.pending.delete(A.id),B.timer)clearTimeout(B.timer);if(A.error)B.reject(Object.assign(Error(A.error.message),A.error));else B.resolve(A.result);return}if(A.__trove==="event"){try{await this.onEvent?.(A.method,A.params,Q)}catch(B){console.error("rpc event handler error",B)}return}if(A.__trove==="req"){let B,C;try{B=await this.onCall?.(A.method,A.params,Q)}catch(E){C={message:E?.message||String(E),code:E?.code||"error"}}this._post({__trove:"res",id:A.id,result:B,error:C})}}dispose(){if(typeof this.port.removeEventListener==="function")this.port.removeEventListener("message",this._listener);for(let A of this.pending.values()){if(A.timer)clearTimeout(A.timer);A.reject(Error("RPC channel disposed"))}this.pending.clear(),this.port.close?.()}}var NJ=`// Injectable browser build of the Trove plugin SDK — a single self-contained IIFE
|
|
5
|
-
// with NO imports, so the host can inline it into a sandboxed iframe's srcdoc
|
|
6
|
-
// alongside the plugin's entry script. The iframe runs on an opaque origin
|
|
7
|
-
// (sandbox="allow-scripts", no allow-same-origin), so it can't fetch its own
|
|
8
|
-
// package files; instead it reaches everything — resources, files, settings,
|
|
9
|
-
// storage — through the host over a transferred MessagePort. Package resources
|
|
10
|
-
// are handed back as raw bytes (or iframe-local blob: URLs), never host URLs, so
|
|
11
|
-
// the plugin only ever holds opaque handles.
|
|
12
|
-
//
|
|
13
|
-
// Plugins use it as: trove.activate(async (ctx) => { ... })
|
|
14
|
-
(function () {
|
|
15
|
-
'use strict';
|
|
16
|
-
// Wire-protocol version this SDK speaks. MUST equal PROTOCOL_VERSION in
|
|
17
|
-
// protocol.js — this file is injected as text and cannot import it, so
|
|
18
|
-
// protocol.test.js asserts the two stay in step.
|
|
19
|
-
const SDK_PROTOCOL_VERSION = '1.0';
|
|
20
|
-
|
|
21
|
-
// --- events -----------------------------------------------------------------
|
|
22
|
-
//
|
|
23
|
-
// Every hook here used to be one assignment — \`onDeactivate = fn\`, \`onDock = fn\`,
|
|
24
|
-
// \`mediaHandlers[action] = fn\`. Register twice and the first silently vanished, with
|
|
25
|
-
// nothing to report it: the symptom is a timer or an object URL outliving its viewer,
|
|
26
|
-
// noticed much later as a leak. The audiobook player was losing one of two teardowns
|
|
27
|
-
// exactly that way.
|
|
28
|
-
//
|
|
29
|
-
// So the SDK's nodes are EventTargets and handlers are listeners. Registrations
|
|
30
|
-
// accumulate, removal is \`removeEventListener\`, and a plugin can compose without
|
|
31
|
-
// knowing what else is listening.
|
|
32
|
-
//
|
|
33
|
-
// Inlined rather than imported because this file is injected as TEXT into a sandboxed
|
|
34
|
-
// frame and has no module loader — see the header.
|
|
35
|
-
//
|
|
36
|
-
// Two things a plain CustomEvent cannot express, both needed:
|
|
37
|
-
//
|
|
38
|
-
// waitUntil(p) The host awaits some of these. \`opener:open\` must not resolve until
|
|
39
|
-
// the viewer has drawn, or "Opening…" is hidden over a blank frame.
|
|
40
|
-
// respondWith(v) A command has a return value that crosses back over the port. First
|
|
41
|
-
// answer wins; a second is a bug in the plugin, not something to pick
|
|
42
|
-
// between silently.
|
|
43
|
-
class TroveEvent extends Event {
|
|
44
|
-
constructor(type, detail) {
|
|
45
|
-
super(type, { cancelable: true });
|
|
46
|
-
this.detail = detail;
|
|
47
|
-
this._waits = [];
|
|
48
|
-
this._answered = false;
|
|
49
|
-
this._answer = undefined;
|
|
50
|
-
}
|
|
51
|
-
waitUntil(p) { this._waits.push(Promise.resolve(p)); }
|
|
52
|
-
respondWith(value) {
|
|
53
|
-
if (this._answered) return;
|
|
54
|
-
this._answered = true;
|
|
55
|
-
this._answer = value;
|
|
56
|
-
if (value && typeof value.then === 'function') this._waits.push(Promise.resolve(value).then((v) => { this._answer = v; }));
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Dispatch, then wait for every \`waitUntil\`, then answer.
|
|
62
|
-
*
|
|
63
|
-
* A listener that throws is reported and does not stop the others — dispatch is where
|
|
64
|
-
* resources are released, and one bad handler must not strand the rest.
|
|
65
|
-
*/
|
|
66
|
-
async function fire(target, type, detail) {
|
|
67
|
-
const ev = new TroveEvent(type, detail);
|
|
68
|
-
target.dispatchEvent(ev);
|
|
69
|
-
for (const r of await Promise.allSettled(ev._waits)) {
|
|
70
|
-
if (r.status === 'rejected') console.error('[trove] a "' + type + '" handler failed', r.reason);
|
|
71
|
-
}
|
|
72
|
-
return ev._answer;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* An EventTarget that knows what is listening.
|
|
77
|
-
*
|
|
78
|
-
* The host needs that: it is how the manifest reports which commands a plugin actually
|
|
79
|
-
* implements, and how media claims an OS control on the first listener and releases it
|
|
80
|
-
* on the last.
|
|
81
|
-
*/
|
|
82
|
-
function makeTarget(onFirst, onLast) {
|
|
83
|
-
const counts = new Map();
|
|
84
|
-
const target = new EventTarget();
|
|
85
|
-
const add = target.addEventListener.bind(target);
|
|
86
|
-
const remove = target.removeEventListener.bind(target);
|
|
87
|
-
target.types = () => [...counts.entries()].filter(([, n]) => n > 0).map(([t]) => t);
|
|
88
|
-
target.listening = (type) => (counts.get(type) || 0) > 0;
|
|
89
|
-
target.addEventListener = (type, fn, opts) => {
|
|
90
|
-
const n = (counts.get(type) || 0) + 1;
|
|
91
|
-
counts.set(type, n);
|
|
92
|
-
if (n === 1 && onFirst) onFirst(type);
|
|
93
|
-
return add(type, fn, opts);
|
|
94
|
-
};
|
|
95
|
-
target.removeEventListener = (type, fn, opts) => {
|
|
96
|
-
const n = Math.max(0, (counts.get(type) || 0) - 1);
|
|
97
|
-
counts.set(type, n);
|
|
98
|
-
if (n === 0 && onLast) onLast(type);
|
|
99
|
-
return remove(type, fn, opts);
|
|
100
|
-
};
|
|
101
|
-
return target;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* \`onThing(fn)\` written over \`addEventListener\`.
|
|
106
|
-
*
|
|
107
|
-
* Kept because it reads well for the common case and is what every existing plugin
|
|
108
|
-
* says. What changed is that it no longer REPLACES: two calls mean two listeners, and
|
|
109
|
-
* it returns a disposer. A handler that returns a promise keeps the host waiting; one
|
|
110
|
-
* that returns a value answers.
|
|
111
|
-
*/
|
|
112
|
-
function hook(target, type, args = (e) => [e.detail]) {
|
|
113
|
-
return (fn) => {
|
|
114
|
-
if (typeof fn !== 'function') return () => {};
|
|
115
|
-
const listener = (e) => {
|
|
116
|
-
// GUARDED here rather than relying on the host's EventTarget to isolate a throw.
|
|
117
|
-
// Browsers do report an uncaught listener error and carry on, but that is not
|
|
118
|
-
// uniform — Bun stops dispatch — and teardown is the one place where "the rest
|
|
119
|
-
// still ran" has to be a guarantee rather than a hope.
|
|
120
|
-
let out;
|
|
121
|
-
try {
|
|
122
|
-
out = fn(...args(e));
|
|
123
|
-
} catch (err) {
|
|
124
|
-
console.error('[trove] a "' + e.type + '" handler threw', err);
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
if (out && typeof out.then === 'function') e.waitUntil(out);
|
|
128
|
-
if (out !== undefined) e.respondWith(out);
|
|
129
|
-
};
|
|
130
|
-
target.addEventListener(type, listener);
|
|
131
|
-
return () => target.removeEventListener(type, listener);
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
let port = null, manifest = null, capabilities = [], storageScopes = {}, online = true, seq = 0, role = 'primary';
|
|
135
|
-
const pending = new Map();
|
|
136
|
-
// EVERY hook is an EventTarget registration — see above for why. \`ctx\` itself is
|
|
137
|
-
// the target for lifecycle and connectivity; commands, openers and media each get their
|
|
138
|
-
// own so an event type can be a command name or an action without colliding.
|
|
139
|
-
const bus = makeTarget(); // deactivate | connectivity | settingschange | dockchange
|
|
140
|
-
const commandTarget = makeTarget(); // type = the command's short name
|
|
141
|
-
const openerTarget = makeTarget(); // type = the opener's name, or '*'
|
|
142
|
-
// Media tells the HOST which actions to claim from the OS, so registration is observed:
|
|
143
|
-
// the first listener for an action claims it, the last one to go releases it.
|
|
144
|
-
const mediaTarget = makeTarget(
|
|
145
|
-
(action) => { call('media:action', { action, on: true }).catch(() => {}); },
|
|
146
|
-
(action) => { call('media:action', { action, on: false }).catch(() => {}); },
|
|
147
|
-
);
|
|
148
|
-
// A LIST. It was one slot — \`onDeactivate = fn\` — so a second registration silently
|
|
149
|
-
// discarded the first, and the plugin that lost one had no way to notice: the symptom
|
|
150
|
-
// is a timer or an object URL that outlives the viewer. The audiobook player has two
|
|
151
|
-
// teardowns (a download poller and the transport), which is not exotic; anything with
|
|
152
|
-
// more than one resource has more than one.
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
const now = () => { try { return Date.now(); } catch { return 0; } };
|
|
156
|
-
|
|
157
|
-
// The HOST times its own calls out; this side did not, and \`pending\` was never
|
|
158
|
-
// rejected — not on a dropped reply, not on port close. A plugin awaiting one hung
|
|
159
|
-
// forever with no way to find out, and the entry leaked with it.
|
|
160
|
-
const CALL_TIMEOUT_MS = 30_000;
|
|
161
|
-
|
|
162
|
-
function call(method, params, transfer) {
|
|
163
|
-
const id = ++seq;
|
|
164
|
-
return new Promise((resolve, reject) => {
|
|
165
|
-
const timer = setTimeout(() => {
|
|
166
|
-
pending.delete(id);
|
|
167
|
-
reject(new Error(\`Timed out waiting for the host to answer "\${method}"\`));
|
|
168
|
-
}, CALL_TIMEOUT_MS);
|
|
169
|
-
if (timer && timer.unref) timer.unref();
|
|
170
|
-
pending.set(id, { resolve, reject, timer });
|
|
171
|
-
port.postMessage({ __trove: 'req', id, method, params }, transfer || []);
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
const emit = (method, params) => port.postMessage({ __trove: 'event', method, params });
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* A file's bytes, addressable without holding them.
|
|
178
|
-
*
|
|
179
|
-
* \`Blob\` is already the browser's interface for exactly that — \`slice()\` is free,
|
|
180
|
-
* \`stream()\` is a reader, and everything that eats bytes eats a Blob — so a range reader
|
|
181
|
-
* wears the interface that exists rather than inventing a parallel vocabulary.
|
|
182
|
-
*
|
|
183
|
-
* THE SHARP EDGE, and it is sharp: a Blob SUBCLASS only overrides what JavaScript calls.
|
|
184
|
-
* Anything reading the blob's internal bytes — \`URL.createObjectURL\`, \`new
|
|
185
|
-
* Response(blob)\`, \`fetch(url, {body})\`, and structured clone through \`postMessage\` —
|
|
186
|
-
* bypasses every override here and sees the empty blob passed to \`super()\`. Two
|
|
187
|
-
* consequences the design is built around:
|
|
188
|
-
*
|
|
189
|
-
* 1. A RemoteBlob cannot be posted INTO this frame from the host; it would arrive as a
|
|
190
|
-
* plain, empty Blob. It is constructed here, in the frame that uses it.
|
|
191
|
-
* 2. \`local()\` is the escape hatch for all of them. A realized Blob really does hold
|
|
192
|
-
* its bytes, so it works with \`createObjectURL\` — which is the download-then-play
|
|
193
|
-
* path for anything that cannot be streamed.
|
|
194
|
-
*/
|
|
195
|
-
class RemoteBlob extends Blob {
|
|
196
|
-
constructor(id, { size = 0, type = '', etag = null, start = 0, end = null } = {}) {
|
|
197
|
-
super();
|
|
198
|
-
this.id = id;
|
|
199
|
-
// \`_type\`, and a getter below. \`Blob.prototype.type\` is an accessor with no setter,
|
|
200
|
-
// so \`this.type = …\` THROWS in strict mode — which every module is. That one line
|
|
201
|
-
// meant \`ctx.files.blob()\` rejected on construction for every plugin that ever
|
|
202
|
-
// called it: no cover art, no container parsing, no streaming, and an error message
|
|
203
|
-
// ("Cannot set property type of #<Blob> which has only a getter") that never left
|
|
204
|
-
// the sandboxed frame it was thrown in.
|
|
205
|
-
this._type = type;
|
|
206
|
-
this.etag = etag;
|
|
207
|
-
// A window on the source. \`size\` is this window's length, which is what makes
|
|
208
|
-
// \`slice()\` of a slice behave the way a caller expects.
|
|
209
|
-
this._start = start;
|
|
210
|
-
this._end = end == null ? size : end;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
get size() { return Math.max(0, this._end - this._start); }
|
|
214
|
-
get type() { return this._type; }
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* A window on the same source. No bytes move and none need to exist yet.
|
|
218
|
-
*
|
|
219
|
-
* Negative indices count from the end, as \`Blob.slice\` does — which is what makes
|
|
220
|
-
* "the last 64 KiB" expressible, and reading the tail of a file is half of what a
|
|
221
|
-
* container parser does.
|
|
222
|
-
*/
|
|
223
|
-
slice(begin = 0, finish = this.size, type = this.type) {
|
|
224
|
-
const len = this.size;
|
|
225
|
-
const from = begin < 0 ? Math.max(0, len + begin) : Math.min(begin, len);
|
|
226
|
-
const to = finish < 0 ? Math.max(0, len + finish) : Math.min(finish, len);
|
|
227
|
-
const win = new RemoteBlob(this.id, {
|
|
228
|
-
type, etag: this.etag,
|
|
229
|
-
start: this._start + from,
|
|
230
|
-
end: this._start + Math.max(from, to),
|
|
231
|
-
});
|
|
232
|
-
return win;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* The bytes of this window.
|
|
237
|
-
*
|
|
238
|
-
* A \`signal\` is checked BEFORE the call and not during it: an in-flight request over
|
|
239
|
-
* the port cannot be recalled, so the honest granularity is per read. \`chunks()\` is
|
|
240
|
-
* where cancelling actually bites, because there the reads are small and there are
|
|
241
|
-
* many of them.
|
|
242
|
-
*/
|
|
243
|
-
async bytes({ signal } = {}) {
|
|
244
|
-
if (signal && signal.aborted) throw new Error('Aborted');
|
|
245
|
-
const r = await call('files:bytes', { id: this.id, start: this._start, end: this._end });
|
|
246
|
-
// Every read refreshes the etag, because a file overwritten in place keeps its id
|
|
247
|
-
// and anything cached off these bytes has to notice.
|
|
248
|
-
if (r.etag) this.etag = r.etag;
|
|
249
|
-
return new Uint8Array(r.bytes);
|
|
250
|
-
}
|
|
251
|
-
async arrayBuffer() { return (await this.bytes()).buffer; }
|
|
252
|
-
async text() { return new TextDecoder().decode(await this.bytes()); }
|
|
253
|
-
|
|
254
|
-
/** One window at a time, so a caller can walk a large file without holding it. */
|
|
255
|
-
async *chunks({ size = 4 * 1024 * 1024, signal } = {}) {
|
|
256
|
-
for (let at = 0; at < this.size; at += size) {
|
|
257
|
-
yield this.slice(at, Math.min(at + size, this.size)).bytes({ signal });
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
stream() {
|
|
262
|
-
const iter = this.chunks();
|
|
263
|
-
return new ReadableStream({
|
|
264
|
-
async pull(controller) {
|
|
265
|
-
const { value, done } = await iter.next();
|
|
266
|
-
if (done) controller.close();
|
|
267
|
-
else controller.enqueue(value);
|
|
268
|
-
},
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
/**
|
|
273
|
-
* REALIZE the bytes into an ordinary Blob.
|
|
274
|
-
*
|
|
275
|
-
* The escape hatch named above, and the download half of "this book cannot be
|
|
276
|
-
* streamed, here is a Download button". \`onProgress\` fires once with \`loaded: 0\`
|
|
277
|
-
* BEFORE the first chunk, so a bar appears at 0% instead of jumping in partway.
|
|
278
|
-
*/
|
|
279
|
-
async local({ onProgress, signal, chunkSize = 4 * 1024 * 1024 } = {}) {
|
|
280
|
-
const total = this.size;
|
|
281
|
-
const parts = [];
|
|
282
|
-
let loaded = 0;
|
|
283
|
-
if (onProgress) onProgress({ loaded: 0, total, ratio: 0 });
|
|
284
|
-
for await (const chunk of this.chunks({ size: chunkSize, signal })) {
|
|
285
|
-
parts.push(chunk);
|
|
286
|
-
loaded += chunk.length;
|
|
287
|
-
if (onProgress) onProgress({ loaded, total, ratio: total ? loaded / total : 0 });
|
|
288
|
-
}
|
|
289
|
-
return new Blob(parts, { type: this.type });
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// What this frame reports about itself on every heartbeat. Contributions are the
|
|
294
|
-
// host's own manifest reading — all the plugin can usefully say is which of its
|
|
295
|
-
// declared contributions it actually bound a handler to, plus whether it thinks
|
|
296
|
-
// it's online.
|
|
297
|
-
function buildManifest() {
|
|
298
|
-
return {
|
|
299
|
-
domain: manifest && manifest.domain, name: manifest && manifest.name,
|
|
300
|
-
online, role, ts: now(),
|
|
301
|
-
handlers: commandTarget.types(),
|
|
302
|
-
};
|
|
303
|
-
}
|
|
304
|
-
const announce = () => port && emit('manifest', buildManifest());
|
|
305
|
-
|
|
306
|
-
function onPort(e) {
|
|
307
|
-
const m = e.data;
|
|
308
|
-
if (!m || m.__trove == null) return;
|
|
309
|
-
if (m.__trove === 'res') {
|
|
310
|
-
const p = pending.get(m.id);
|
|
311
|
-
if (!p) return;
|
|
312
|
-
clearTimeout(p.timer);
|
|
313
|
-
pending.delete(m.id);
|
|
314
|
-
m.error ? p.reject(Object.assign(new Error(m.error.message), m.error)) : p.resolve(m.result);
|
|
315
|
-
} else if (m.__trove === 'req') {
|
|
316
|
-
Promise.resolve().then(() => dispatch(m.method, m.params))
|
|
317
|
-
.then((result) => port.postMessage({ __trove: 'res', id: m.id, result }))
|
|
318
|
-
.catch((err) => port.postMessage({ __trove: 'res', id: m.id, error: { message: err.message } }));
|
|
319
|
-
} else if (m.__trove === 'event') {
|
|
320
|
-
dispatchEvent(m.method, m.params);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
function dispatch(method, params) {
|
|
325
|
-
if (method === 'command:execute') {
|
|
326
|
-
// Throw rather than resolve \`undefined\` for an id nobody implements: that told the
|
|
327
|
-
// host the command had RUN when nothing had.
|
|
328
|
-
if (!commandTarget.listening(params.id)) throw new Error(\`No handler registered for command "\${params.id}"\`);
|
|
329
|
-
return fire(commandTarget, params.id, { args: params.args || [] });
|
|
330
|
-
}
|
|
331
|
-
if (method === 'opener:open') {
|
|
332
|
-
// An opener frame boots at that opener's entry module and runs exactly one
|
|
333
|
-
// opener, so an unkeyed onOpen(fn) handler is the normal case.
|
|
334
|
-
const type = openerTarget.listening(params.openerId) ? params.openerId
|
|
335
|
-
: openerTarget.listening('*') ? '*' : null;
|
|
336
|
-
if (!type) throw new Error('no opener ' + params.openerId);
|
|
337
|
-
// AWAITED, and that is what \`waitUntil\` is for: \`opener:open\` must not resolve until
|
|
338
|
-
// the viewer has drawn, or the host hides "Opening…" over a blank frame.
|
|
339
|
-
return fire(openerTarget, type, { file: params.file, context: params.context, openerId: params.openerId });
|
|
340
|
-
}
|
|
341
|
-
if (method === 'manifest') return buildManifest();
|
|
342
|
-
throw new Error('Unknown host call ' + method);
|
|
343
|
-
}
|
|
344
|
-
async function dispatchEvent(method, params) {
|
|
345
|
-
if (method === 'deactivate') return fire(bus, 'deactivate', {});
|
|
346
|
-
if (method === 'connectivity') { online = !!params.online; await fire(bus, 'connectivity', { online }); announce(); }
|
|
347
|
-
if (method === 'settings:changed') return fire(bus, 'settingschange', { key: params.key, value: params.value });
|
|
348
|
-
// The OS/host fired a media transport control (play/pause/next/seek…).
|
|
349
|
-
if (method === 'media:action') return fire(mediaTarget, params.action, params);
|
|
350
|
-
// The host docked or undocked this viewer (see ctx.dock).
|
|
351
|
-
if (method === 'dock:state') return fire(bus, 'dockchange', params);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
function requireCap(cap) { if (!capabilities.includes(cap)) throw new Error('Plugin lacks capability "' + cap + '"'); }
|
|
355
|
-
|
|
356
|
-
// Storage: one async SQL handle (mirrors the host SqliteDatabase interface) per
|
|
357
|
-
// scope+side, over RPC. Only granted scopes are exposed on ctx.storage.
|
|
358
|
-
function sqlHandle(scope, side) {
|
|
359
|
-
var send = function (op, extra) { return call('storage:sql', Object.assign({ scope: scope, side: side, op: op }, extra)); };
|
|
360
|
-
return {
|
|
361
|
-
exec: function (sql) { return send('exec', { sql: sql }); },
|
|
362
|
-
run: function (sql) { return send('run', { sql: sql, params: [].slice.call(arguments, 1) }); },
|
|
363
|
-
get: function (sql) { return send('get', { sql: sql, params: [].slice.call(arguments, 1) }); },
|
|
364
|
-
all: function (sql) { return send('all', { sql: sql, params: [].slice.call(arguments, 1) }); },
|
|
365
|
-
batch: function (statements) { return send('batch', { statements: statements }); },
|
|
366
|
-
};
|
|
367
|
-
}
|
|
368
|
-
function scopeHandle(scope) {
|
|
369
|
-
return { server: sqlHandle(scope, 'server'), client: sqlHandle(scope, 'client') };
|
|
370
|
-
}
|
|
371
|
-
function makeStorage() {
|
|
372
|
-
var s = {};
|
|
373
|
-
if (storageScopes.plugin) s.plugin = scopeHandle('plugin');
|
|
374
|
-
if (storageScopes.domain) s.domain = scopeHandle('domain');
|
|
375
|
-
return s;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
function hasHeader(h, name) { name = name.toLowerCase(); for (var k in h) if (k.toLowerCase() === name) return true; return false; }
|
|
379
|
-
// Wrap the host's brokered-fetch result in a minimal Response-like object.
|
|
380
|
-
function makeResponse(r) {
|
|
381
|
-
var bytes = new Uint8Array(r.bytes || new ArrayBuffer(0));
|
|
382
|
-
var decode = function () { return new TextDecoder().decode(bytes); };
|
|
383
|
-
return {
|
|
384
|
-
ok: r.ok, status: r.status, statusText: r.statusText, url: r.url, headers: r.headers || {},
|
|
385
|
-
arrayBuffer: function () { return Promise.resolve(bytes.slice().buffer); },
|
|
386
|
-
bytes: function () { return Promise.resolve(bytes); },
|
|
387
|
-
text: function () { return Promise.resolve(decode()); },
|
|
388
|
-
json: function () { return Promise.resolve(JSON.parse(decode())); },
|
|
389
|
-
};
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
function makeContext() {
|
|
393
|
-
return {
|
|
394
|
-
manifest, capabilities,
|
|
395
|
-
// Which instance this is: 'primary' is the plugin's single background frame
|
|
396
|
-
// (register commands/indexers, do one-time setup here); 'viewer' is a
|
|
397
|
-
// per-open frame hosting an opener for one file (drive media/dock from here).
|
|
398
|
-
role,
|
|
399
|
-
get online() { return online; },
|
|
400
|
-
// Contributions are DECLARED IN THE MANIFEST (openers, indexers, commands,
|
|
401
|
-
// statusItems, keybindings). The host registers them before this code runs, so
|
|
402
|
-
// a plugin never registers anything at runtime — it only supplies the behaviour
|
|
403
|
-
// for what it declared, addressed by id.
|
|
404
|
-
commands: {
|
|
405
|
-
/** Implement a command this plugin's manifest declares, by its short name. */
|
|
406
|
-
/** Implement a command this plugin's manifest declares, by its short name. */
|
|
407
|
-
handle(name, handler) { hook(commandTarget, name, (e) => e.detail.args)(handler); return this; },
|
|
408
|
-
addEventListener: (...a) => commandTarget.addEventListener(...a),
|
|
409
|
-
removeEventListener: (...a) => commandTarget.removeEventListener(...a),
|
|
410
|
-
/**
|
|
411
|
-
* Run a command. Its OWN commands by short name; anyone else's by full address
|
|
412
|
-
* (a built-in like 'explorer.download', or a \`trove+contrib:\` URI) — and only
|
|
413
|
-
* if the manifest's \`commands\` capability lists it.
|
|
414
|
-
*/
|
|
415
|
-
execute(id) { const a = [].slice.call(arguments, 1); return call('command:execute', { id, args: a }); },
|
|
416
|
-
},
|
|
417
|
-
/** Implement the opener this frame was booted for (its entry module). The id is
|
|
418
|
-
* optional — an opener frame runs exactly one opener. */
|
|
419
|
-
onOpen(idOrHandler, maybeHandler) {
|
|
420
|
-
const [id, handler] = typeof idOrHandler === 'function' ? ['*', idOrHandler] : [idOrHandler, maybeHandler];
|
|
421
|
-
// A handler returning a promise keeps the host waiting — which is what holds
|
|
422
|
-
// "Opening…" on screen until the viewer has actually drawn. See \`hook\`.
|
|
423
|
-
hook(openerTarget, id, (e) => [e.detail.file, e.detail.context])(handler);
|
|
424
|
-
return this;
|
|
425
|
-
},
|
|
426
|
-
/** The opener target, for \`addEventListener('*', e => e.waitUntil(…))\`. */
|
|
427
|
-
openers: openerTarget,
|
|
428
|
-
// NOTE: there is no onIndex(). Indexers run on the SERVER (in its isolate
|
|
429
|
-
// runtime), not in this sandbox — indexing has to happen once per upload for the
|
|
430
|
-
// drive, not in whichever tab is open. An indexer's entry module is plain ESM
|
|
431
|
-
// exporting \`index(node, ctx)\`; it doesn't use this SDK at all. What a plugin can
|
|
432
|
-
// do from here is PUSH contributions for a node via ctx.files.index (the
|
|
433
|
-
// \`indexer\` capability).
|
|
434
|
-
// Package resources — opaque handles. read() copies bytes into the iframe;
|
|
435
|
-
// url() wraps them in an iframe-local blob: URL.
|
|
436
|
-
resources: {
|
|
437
|
-
list() { return call('resources:list', {}); },
|
|
438
|
-
async read(path) { const r = await call('resources:read', { path }); return new Uint8Array(r.bytes); },
|
|
439
|
-
async text(path) { return new TextDecoder().decode(await this.read(path)); },
|
|
440
|
-
async url(path, type) {
|
|
441
|
-
const bytes = await this.read(path);
|
|
442
|
-
return URL.createObjectURL(new Blob([bytes], { type: type || 'application/octet-stream' }));
|
|
443
|
-
},
|
|
444
|
-
},
|
|
445
|
-
ui: {
|
|
446
|
-
toast: (text, opts) => emit('ui:toast', Object.assign({ text }, opts)),
|
|
447
|
-
showPanel: () => call('ui:showPanel', {}),
|
|
448
|
-
setBadge: (text) => emit('ui:badge', { text }),
|
|
449
|
-
/**
|
|
450
|
-
* Drive a status-bar slot this plugin's manifest declares. \`html\` is sanitized
|
|
451
|
-
* by the host down to a small inline-formatting allowlist before it renders.
|
|
452
|
-
* ctx.ui.status('sync').set('<b>3</b> queued')
|
|
453
|
-
* ctx.ui.status('sync').hide()
|
|
454
|
-
*/
|
|
455
|
-
status(name) {
|
|
456
|
-
return {
|
|
457
|
-
set: (html, opts) => call('ui:status', Object.assign({ name, html, visible: true }, opts || {})),
|
|
458
|
-
show: () => call('ui:status', { name, visible: true }),
|
|
459
|
-
hide: () => call('ui:status', { name, visible: false }),
|
|
460
|
-
};
|
|
461
|
-
},
|
|
462
|
-
},
|
|
463
|
-
/**
|
|
464
|
-
* Registers — context value slots this plugin's manifest declares, which
|
|
465
|
-
* when-clauses (its own keymap's, its commands') read by contribution URI.
|
|
466
|
-
* ctx.registers.set('busy', true)
|
|
467
|
-
*/
|
|
468
|
-
registers: {
|
|
469
|
-
set: (name, value) => call('context:setRegister', { name, value }),
|
|
470
|
-
},
|
|
471
|
-
// Media session — surfaces this viewer's playback to the OS (lock-screen /
|
|
472
|
-
// notification transport controls, so phones can play/pause/seek). The host
|
|
473
|
-
// owns navigator.mediaSession; action handlers are called back over RPC.
|
|
474
|
-
media: {
|
|
475
|
-
setMetadata: (m) => (requireCap('media'), call('media:metadata', m || {})),
|
|
476
|
-
setPlaybackState: (state) => (requireCap('media'), call('media:playbackState', { state })),
|
|
477
|
-
setPositionState: (p) => (requireCap('media'), call('media:position', p || {})),
|
|
478
|
-
/**
|
|
479
|
-
* @deprecated use \`ctx.media.addEventListener(action, …)\`.
|
|
480
|
-
*
|
|
481
|
-
* Additive now, and the RPC that claims the OS control moves with it: the first
|
|
482
|
-
* listener for an action claims it, the last one to go releases it. Passing null
|
|
483
|
-
* removes nothing in particular, so it is a no-op rather than a silent surprise.
|
|
484
|
-
*/
|
|
485
|
-
setActionHandler: (action, handler) => {
|
|
486
|
-
requireCap('media');
|
|
487
|
-
if (!handler) return Promise.resolve({ ok: true });
|
|
488
|
-
hook(mediaTarget, action)(handler);
|
|
489
|
-
return Promise.resolve({ ok: true });
|
|
490
|
-
},
|
|
491
|
-
addEventListener: (...a) => (requireCap('media'), mediaTarget.addEventListener(...a)),
|
|
492
|
-
removeEventListener: (...a) => mediaTarget.removeEventListener(...a),
|
|
493
|
-
clear: () => call('media:clear', {}),
|
|
494
|
-
},
|
|
495
|
-
// Dock — register this viewer to persist as a small floating frame when the
|
|
496
|
-
// user navigates away (a docked video = picture-in-picture; docked audio = a
|
|
497
|
-
// mini transport). Enable while playing/active, disable otherwise. \`minSize\`/
|
|
498
|
-
// \`maxSize\` are {width,height} constraints. onDock is notified on (un)dock.
|
|
499
|
-
dock: {
|
|
500
|
-
enable: (opts) => (requireCap('dock'), call('dock:enable', opts || {})),
|
|
501
|
-
disable: () => (requireCap('dock'), call('dock:disable', {})),
|
|
502
|
-
close: () => call('dock:close', {}),
|
|
503
|
-
/** @deprecated use \`ctx.addEventListener('dockchange', …)\`. Now additive. */
|
|
504
|
-
onChange: hook(bus, 'dockchange'),
|
|
505
|
-
addEventListener: (...a) => bus.addEventListener(...a),
|
|
506
|
-
removeEventListener: (...a) => bus.removeEventListener(...a),
|
|
507
|
-
},
|
|
508
|
-
// Network — there is no direct fetch in the sandbox; the host performs the
|
|
509
|
-
// request, but ONLY to endpoints declared in the manifest's \`network\` list
|
|
510
|
-
// (and only with the "network" capability). Returns a Response-like object.
|
|
511
|
-
net: {
|
|
512
|
-
fetch(url, opts) {
|
|
513
|
-
requireCap('network');
|
|
514
|
-
opts = opts || {};
|
|
515
|
-
var body = opts.body;
|
|
516
|
-
var headers = Object.assign({}, opts.headers);
|
|
517
|
-
if (body && typeof body === 'object' && !(body instanceof ArrayBuffer) && !(body instanceof Uint8Array)) {
|
|
518
|
-
body = JSON.stringify(body);
|
|
519
|
-
if (!hasHeader(headers, 'content-type')) headers['Content-Type'] = 'application/json';
|
|
520
|
-
}
|
|
521
|
-
// \`.buffer\` ignores byteOffset/byteLength, so any view produced by \`subarray\` or
|
|
522
|
-
// \`slice\` — or a view into a pooled buffer — sent the WHOLE backing store: the wrong
|
|
523
|
-
// payload, and an out-of-band leak of whatever else was in it.
|
|
524
|
-
if (ArrayBuffer.isView(body)) {
|
|
525
|
-
body = body.buffer.slice(body.byteOffset, body.byteOffset + body.byteLength);
|
|
526
|
-
}
|
|
527
|
-
return call('net:fetch', { url: String(url), method: opts.method || 'GET', headers: headers, body: body })
|
|
528
|
-
.then(makeResponse);
|
|
529
|
-
},
|
|
530
|
-
},
|
|
531
|
-
files: {
|
|
532
|
-
read: (id, opts) => (requireCap('files'), call('files:read', Object.assign({ id }, opts))),
|
|
533
|
-
list: (pathOrId, opts) => (requireCap('files'), call('files:list', Object.assign({ pathOrId }, opts))),
|
|
534
|
-
stat: (id) => (requireCap('files'), call('files:stat', { id })),
|
|
535
|
-
downloadUrl: (id) => (requireCap('files'), call('files:downloadUrl', { id })),
|
|
536
|
-
|
|
537
|
-
/**
|
|
538
|
-
* A file's bytes as a Blob you can slice, stream and realize — see RemoteBlob.
|
|
539
|
-
*
|
|
540
|
-
* \`stat\` first, because a Blob has to know its own size before \`slice\` means
|
|
541
|
-
* anything. One round trip, and every later read is a range.
|
|
542
|
-
*/
|
|
543
|
-
async blob(id) {
|
|
544
|
-
requireCap('files');
|
|
545
|
-
const { node } = await call('files:stat', { id });
|
|
546
|
-
return new RemoteBlob(id, { size: node.size || 0, type: node.contentType || '', etag: node.etag || null });
|
|
547
|
-
},
|
|
548
|
-
|
|
549
|
-
/**
|
|
550
|
-
* A URL a media element can load by itself, for streaming.
|
|
551
|
-
*
|
|
552
|
-
* It is MINTED — it carries its own grant and expires — which is the one place a
|
|
553
|
-
* host URL deliberately reaches a plugin. \`<audio src>\` is the only way to play a
|
|
554
|
-
* progressive MP4 without a fragmenter: MSE refuses one, and a Blob has to be
|
|
555
|
-
* whole before it can become an object URL. Use \`blob(id)\` for the parsing (a
|
|
556
|
-
* container's chapters are a few kilobytes out of a few hundred megabytes) and
|
|
557
|
-
* this for the playing.
|
|
558
|
-
*/
|
|
559
|
-
mediaUrl: (id, opts) => (requireCap('files'), call('files:mediaUrl', Object.assign({ id }, opts))),
|
|
560
|
-
|
|
561
|
-
/**
|
|
562
|
-
* A file's own key/value data, for THIS plugin.
|
|
563
|
-
*
|
|
564
|
-
* The third kind of state a viewer has, and the one there was nowhere to put. A
|
|
565
|
-
* contribution is derived from the file and is rewritten whenever it is
|
|
566
|
-
* re-indexed. A setting is per-device, so a listening position kept there does
|
|
567
|
-
* not follow you to your phone — which is the moment people notice. This is the
|
|
568
|
-
* other thing: state about a user's use of an item.
|
|
569
|
-
*
|
|
570
|
-
* ONE INTERFACE, and it deliberately does not say where the bytes are. A write
|
|
571
|
-
* lands locally at once and reaches the server when there is a server to reach;
|
|
572
|
-
* a read is the merge of both. Two devices that each wrote while apart converge,
|
|
573
|
-
* later write winning, because the sidecar underneath is a CRDT — see
|
|
574
|
-
* core/sidecar/document.js.
|
|
575
|
-
*
|
|
576
|
-
* Scoped to this plugin by the HOST, from the plugin it authenticated. There is
|
|
577
|
-
* no parameter for the scope because there is no version of this where a plugin
|
|
578
|
-
* chooses whose data it is writing.
|
|
579
|
-
*/
|
|
580
|
-
data: (id) => ({
|
|
581
|
-
all: () => (requireCap('files'), call('items:data:get', { id })),
|
|
582
|
-
get: async (key) => (requireCap('files'), (await call('items:data:get', { id }))[key]),
|
|
583
|
-
set: (key, value) => (requireCap('files'), call('items:data:set', { id, key, value })),
|
|
584
|
-
remove: (key) => (requireCap('files'), call('items:data:remove', { id, key })),
|
|
585
|
-
}),
|
|
586
|
-
|
|
587
|
-
/**
|
|
588
|
-
* Is the whole file already in this browser?
|
|
589
|
-
*
|
|
590
|
-
* Cheap — it reads bookkeeping, not bytes — so ask it before deciding what to
|
|
591
|
-
* draw. \`{ local, loaded, total, ratio, filling }\`: enough to show a progress
|
|
592
|
-
* bar for a download already under way instead of offering to start it again.
|
|
593
|
-
*/
|
|
594
|
-
hasLocal: (id) => (requireCap('files'), call('files:hasLocal', { id })),
|
|
595
|
-
|
|
596
|
-
/**
|
|
597
|
-
* The whole file as a Blob, or null when it is not stored locally.
|
|
598
|
-
*
|
|
599
|
-
* THE WAY MEDIA WORKS IN HERE. This frame's CSP is \`connect-src 'none'\` and
|
|
600
|
-
* \`media-src blob: data:\` — deliberately, so a plugin cannot reach the network
|
|
601
|
-
* and cannot be an exfiltration side-channel. An \`<audio src="https://…">\` is
|
|
602
|
-
* therefore blocked outright, and no amount of URL minting changes that. A Blob
|
|
603
|
-
* is allowed, so a downloaded file plays by being handed over.
|
|
604
|
-
*
|
|
605
|
-
* Null when the file is incomplete rather than a partial Blob: half an MP4 is
|
|
606
|
-
* not a shorter MP4, and a caller handed one would fail like a decoder bug
|
|
607
|
-
* instead of like a missing download. Pair it with \`offline.start\` and
|
|
608
|
-
* \`hasLocal\` to get from "not here" to "here".
|
|
609
|
-
*/
|
|
610
|
-
localBlob: async (id) => {
|
|
611
|
-
requireCap('files');
|
|
612
|
-
const { blob } = await call('files:localBlob', { id });
|
|
613
|
-
return blob || null;
|
|
614
|
-
},
|
|
615
|
-
|
|
616
|
-
/**
|
|
617
|
-
* Keeping a file, which is a DIFFERENT act from reading one.
|
|
618
|
-
*
|
|
619
|
-
* Ranging over a file stores nothing. \`start(id)\` is someone asking to have it
|
|
620
|
-
* offline, and from then on every chunk a read fetches is kept and the background
|
|
621
|
-
* filler skips it — so a book listened straight through downloads itself exactly
|
|
622
|
-
* once, and a book skipped around in fills its gaps.
|
|
623
|
-
*/
|
|
624
|
-
offline: {
|
|
625
|
-
start: (id) => (requireCap('files'), call('files:offline:start', { id })),
|
|
626
|
-
status: (id) => (requireCap('files'), call('files:offline:status', { id })),
|
|
627
|
-
cancel: (id) => (requireCap('files'), call('files:offline:cancel', { id })),
|
|
628
|
-
remove: (id) => (requireCap('files'), call('files:offline:remove', { id })),
|
|
629
|
-
},
|
|
630
|
-
// index(indexerId, nodeId, contribution) where contribution is
|
|
631
|
-
// { semanticTexts?, tags?, metadata? }. Legacy (indexerId, nodeId, documents[], facet)
|
|
632
|
-
// is still accepted when the 3rd arg is an array of documents.
|
|
633
|
-
//
|
|
634
|
-
// "Contribution" here is per-node ENRICHMENT — what an indexer says ABOUT a file,
|
|
635
|
-
// addressed by contributorId. It is a different noun from the \`contributes\` map in
|
|
636
|
-
// your manifest, which declares extension points addressed by URI. A plugin
|
|
637
|
-
// declares an \`indexer\` contribution (that sense) and it produces contributions
|
|
638
|
-
// (this sense).
|
|
639
|
-
index: (indexerId, nodeId, contribution, facet) => {
|
|
640
|
-
requireCap('indexer');
|
|
641
|
-
var payload = Array.isArray(contribution) ? { documents: contribution, facet: facet } : (contribution || {});
|
|
642
|
-
return call('files:index', Object.assign({ indexerId: indexerId, nodeId: nodeId }, payload));
|
|
643
|
-
},
|
|
644
|
-
},
|
|
645
|
-
// Persistent storage: an isolated SQLite database per granted scope. \`plugin\`
|
|
646
|
-
// is private to this plugin; \`domain\` (verified packages only) is shared with
|
|
647
|
-
// the vendor's other plugins. Each scope exposes a \`.server\` handle (and, from
|
|
648
|
-
// Stage 3, an on-device \`.client\` handle) with the same async SQL surface.
|
|
649
|
-
storage: makeStorage(),
|
|
650
|
-
// The plugin's own settings (declared in the manifest). getSecret reads a
|
|
651
|
-
// secret-typed value the host stores separately.
|
|
652
|
-
settings: {
|
|
653
|
-
get: (key) => call('settings:get', { key }),
|
|
654
|
-
getSecret: (key) => call('settings:getSecret', { key }),
|
|
655
|
-
set: (key, value) => call('settings:set', { key, value }),
|
|
656
|
-
/** @deprecated use \`ctx.addEventListener('settingschange', …)\`. Now additive. */
|
|
657
|
-
onChange: hook(bus, 'settingschange', (e) => [e.detail.key, e.detail.value]),
|
|
658
|
-
},
|
|
659
|
-
/** @deprecated use \`ctx.addEventListener('connectivity', …)\`. Now additive. */
|
|
660
|
-
onConnectivity: hook(bus, 'connectivity'),
|
|
661
|
-
announce,
|
|
662
|
-
/**
|
|
663
|
-
* @deprecated use \`ctx.addEventListener('deactivate', …)\`.
|
|
664
|
-
*
|
|
665
|
-
* Kept, and now additive: registering twice used to discard the first, which is
|
|
666
|
-
* how a viewer ended up leaking one of its two teardowns. Returns a disposer.
|
|
667
|
-
*/
|
|
668
|
-
onDeactivate: hook(bus, 'deactivate'),
|
|
669
|
-
|
|
670
|
-
// The bus itself. \`deactivate\`, \`connectivity\`, \`settingschange\`, \`dockchange\` —
|
|
671
|
-
// and every one of them composes, which the \`onX\` forms above now do too because
|
|
672
|
-
// they are written over this.
|
|
673
|
-
addEventListener: (...a) => bus.addEventListener(...a),
|
|
674
|
-
removeEventListener: (...a) => bus.removeEventListener(...a),
|
|
675
|
-
dispatchEvent: (...a) => bus.dispatchEvent(...a),
|
|
676
|
-
};
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
async function activate(setup) {
|
|
680
|
-
await new Promise((resolve) => {
|
|
681
|
-
function onInit(e) {
|
|
682
|
-
if (!e.data || e.data.__trove !== 'init') return;
|
|
683
|
-
window.removeEventListener('message', onInit);
|
|
684
|
-
manifest = e.data.manifest; capabilities = e.data.capabilities || []; storageScopes = e.data.storage || {}; online = e.data.online != null ? e.data.online : true; role = e.data.role || 'primary';
|
|
685
|
-
port = e.ports[0];
|
|
686
|
-
port.onmessage = onPort;
|
|
687
|
-
resolve();
|
|
688
|
-
}
|
|
689
|
-
window.addEventListener('message', onInit);
|
|
690
|
-
parent.postMessage({ __trove: 'ready', protocolVersion: SDK_PROTOCOL_VERSION }, '*');
|
|
691
|
-
});
|
|
692
|
-
const ctx = makeContext();
|
|
693
|
-
try {
|
|
694
|
-
await setup(ctx);
|
|
695
|
-
await call('activated', { ok: true });
|
|
696
|
-
announce();
|
|
697
|
-
} catch (err) {
|
|
698
|
-
await call('activated', { ok: false, error: err && err.message });
|
|
699
|
-
throw err;
|
|
700
|
-
}
|
|
701
|
-
return ctx;
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
globalThis.trove = { activate };
|
|
705
|
-
})();
|
|
706
|
-
`;var PJ="1.0";function h8(A){return String(A||"").split(".")[0]||"0"}function b8(A){if(!A)return!0;return h8(A)===h8("1.0")}var v8;(function(A){A[A.Static=1]="Static",A[A.Dynamic=2]="Dynamic",A[A.ImportMeta=3]="ImportMeta",A[A.StaticSourcePhase=4]="StaticSourcePhase",A[A.DynamicSourcePhase=5]="DynamicSourcePhase",A[A.StaticDeferPhase=6]="StaticDeferPhase",A[A.DynamicDeferPhase=7]="DynamicDeferPhase"})(v8||(v8={}));var iH=new Uint8Array(new Uint16Array([1]).buffer)[0]===1;function OJ(A,Q="@"){if(!o)return jJ.then(()=>OJ(A));let B=A.length+1,C=(o.__heap_base.value||o.__heap_base)+4*B-o.memory.buffer.byteLength;C>0&&o.memory.grow(Math.ceil(C/65536));let E=o.sa(B-1);if((iH?tH:rH)(A,new Uint16Array(o.memory.buffer,E,B)),!o.parse())throw Object.assign(Error(`Parse error ${Q}:${A.slice(0,o.e()).split(`
|
|
707
|
-
`).length}:${o.e()-A.lastIndexOf(`
|
|
708
|
-
`,o.e()-1)}`),{idx:o.e()});let J=[],K=[];for(;o.ri();){let Y=o.is(),X=o.ie(),H=o.it(),G=o.ai(),D=o.id(),U=o.ss(),I=o.se(),R;o.ip()&&(R=L(A.slice(D===-1?Y-1:Y,D===-1?X+1:X))),J.push({n:R,t:H,s:Y,e:X,ss:U,se:I,d:D,a:G})}for(;o.re();){let Y=o.es(),X=o.ee(),H=o.els(),G=o.ele(),D=A.slice(Y,X),U=D[0],I=H<0?void 0:A.slice(H,G),R=I?I[0]:"";K.push({s:Y,e:X,ls:H,le:G,n:U==='"'||U==="'"?L(D):D,ln:R==='"'||R==="'"?L(I):I})}function L(Y){try{return(0,eval)(Y)}catch(X){}}return[J,K,!!o.f(),!!o.ms()]}function rH(A,Q){let B=A.length,C=0;for(;C<B;){let E=A.charCodeAt(C);Q[C++]=(255&E)<<8|E>>>8}}function tH(A,Q){let B=A.length,C=0;for(;C<B;)Q[C]=A.charCodeAt(C++)}var o,eH=()=>{return A="AGFzbQEAAAABKwhgAX8Bf2AEf39/fwBgAAF/YAAAYAF/AGADf39/AX9gAn9/AX9gA39/fwADMTAAAQECAgICAgICAgICAgICAgICAgIAAwMDBAQAAAUAAAAAAAMDAwAGAAAABwAGAgUEBQFwAQEBBQMBAAEGDwJ/AUHA8gALfwBBwPIACwd6FQZtZW1vcnkCAAJzYQAAAWUAAwJpcwAEAmllAAUCc3MABgJzZQAHAml0AAgCYWkACQJpZAAKAmlwAAsCZXMADAJlZQANA2VscwAOA2VsZQAPAnJpABACcmUAEQFmABICbXMAEwVwYXJzZQAUC19faGVhcF9iYXNlAwEKzkQwaAEBf0EAIAA2AoAKQQAoAtwJIgEgAEEBdGoiAEEAOwEAQQAgAEECaiIANgKECkEAIAA2AogKQQBBADYC4AlBAEEANgLwCUEAQQA2AugJQQBBADYC5AlBAEEANgL4CUEAQQA2AuwJIAEL0wEBA39BACgC8AkhBEEAQQAoAogKIgU2AvAJQQAgBDYC9AlBACAFQSRqNgKICiAEQSBqQeAJIAQbIAU2AgBBACgC1AkhBEEAKALQCSEGIAUgATYCACAFIAA2AgggBSACIAJBAmpBACAGIANGIgAbIAQgA0YiBBs2AgwgBSADNgIUIAVBADYCECAFIAI2AgQgBUEANgIgIAVBA0EBQQIgABsgBBs2AhwgBUEAKALQCSADRiICOgAYAkACQCACDQBBACgC1AkgA0cNAQtBAEEBOgCMCgsLXgEBf0EAKAL4CSIEQRBqQeQJIAQbQQAoAogKIgQ2AgBBACAENgL4CUEAIARBFGo2AogKQQBBAToAjAogBEEANgIQIAQgAzYCDCAEIAI2AgggBCABNgIEIAQgADYCAAsIAEEAKAKQCgsVAEEAKALoCSgCAEEAKALcCWtBAXULHgEBf0EAKALoCSgCBCIAQQAoAtwJa0EBdUF/IAAbCxUAQQAoAugJKAIIQQAoAtwJa0EBdQseAQF/QQAoAugJKAIMIgBBACgC3AlrQQF1QX8gABsLCwBBACgC6AkoAhwLHgEBf0EAKALoCSgCECIAQQAoAtwJa0EBdUF/IAAbCzsBAX8CQEEAKALoCSgCFCIAQQAoAtAJRw0AQX8PCwJAIABBACgC1AlHDQBBfg8LIABBACgC3AlrQQF1CwsAQQAoAugJLQAYCxUAQQAoAuwJKAIAQQAoAtwJa0EBdQsVAEEAKALsCSgCBEEAKALcCWtBAXULHgEBf0EAKALsCSgCCCIAQQAoAtwJa0EBdUF/IAAbCx4BAX9BACgC7AkoAgwiAEEAKALcCWtBAXVBfyAAGwslAQF/QQBBACgC6AkiAEEgakHgCSAAGygCACIANgLoCSAAQQBHCyUBAX9BAEEAKALsCSIAQRBqQeQJIAAbKAIAIgA2AuwJIABBAEcLCABBAC0AlAoLCABBAC0AjAoL3Q0BBX8jAEGA0ABrIgAkAEEAQQE6AJQKQQBBACgC2Ak2ApwKQQBBACgC3AlBfmoiATYCsApBACABQQAoAoAKQQF0aiICNgK0CkEAQQA6AIwKQQBBADsBlgpBAEEAOwGYCkEAQQA6AKAKQQBBADYCkApBAEEAOgD8CUEAIABBgBBqNgKkCkEAIAA2AqgKQQBBADoArAoCQAJAAkACQANAQQAgAUECaiIDNgKwCiABIAJPDQECQCADLwEAIgJBd2pBBUkNAAJAAkACQAJAAkAgAkGbf2oOBQEICAgCAAsgAkEgRg0EIAJBL0YNAyACQTtGDQIMBwtBAC8BmAoNASADEBVFDQEgAUEEakGCCEEKEC8NARAWQQAtAJQKDQFBAEEAKAKwCiIBNgKcCgwHCyADEBVFDQAgAUEEakGMCEEKEC8NABAXC0EAQQAoArAKNgKcCgwBCwJAIAEvAQQiA0EqRg0AIANBL0cNBBAYDAELQQEQGQtBACgCtAohAkEAKAKwCiEBDAALC0EAIQIgAyEBQQAtAPwJDQIMAQtBACABNgKwCkEAQQA6AJQKCwNAQQAgAUECaiIDNgKwCgJAAkACQAJAAkACQAJAIAFBACgCtApPDQAgAy8BACICQXdqQQVJDQYCQAJAAkACQAJAAkACQAJAAkACQCACQWBqDgoQDwYPDw8PBQECAAsCQAJAAkACQCACQaB/ag4KCxISAxIBEhISAgALIAJBhX9qDgMFEQYJC0EALwGYCg0QIAMQFUUNECABQQRqQYIIQQoQLw0QEBYMEAsgAxAVRQ0PIAFBBGpBjAhBChAvDQ8QFwwPCyADEBVFDQ4gASkABELsgISDsI7AOVINDiABLwEMIgNBd2oiAUEXSw0MQQEgAXRBn4CABHFFDQwMDQtBAEEALwGYCiIBQQFqOwGYCkEAKAKkCiABQQN0aiIBQQE2AgAgAUEAKAKcCjYCBAwNC0EALwGYCiIDRQ0JQQAgA0F/aiIDOwGYCkEALwGWCiICRQ0MQQAoAqQKIANB//8DcUEDdGooAgBBBUcNDAJAIAJBAnRBACgCqApqQXxqKAIAIgMoAgQNACADQQAoApwKQQJqNgIEC0EAIAJBf2o7AZYKIAMgAUEEajYCDAwMCwJAQQAoApwKIgEvAQBBKUcNAEEAKALwCSIDRQ0AIAMoAgQgAUcNAEEAQQAoAvQJIgM2AvAJAkAgA0UNACADQQA2AiAMAQtBAEEANgLgCQtBAEEALwGYCiIDQQFqOwGYCkEAKAKkCiADQQN0aiIDQQZBAkEALQCsChs2AgAgAyABNgIEQQBBADoArAoMCwtBAC8BmAoiAUUNB0EAIAFBf2oiATsBmApBACgCpAogAUH//wNxQQN0aigCAEEERg0EDAoLQScQGgwJC0EiEBoMCAsgAkEvRw0HAkACQCABLwEEIgFBKkYNACABQS9HDQEQGAwKC0EBEBkMCQsCQAJAAkACQEEAKAKcCiIBLwEAIgMQG0UNAAJAAkAgA0FVag4EAAkBAwkLIAFBfmovAQBBK0YNAwwICyABQX5qLwEAQS1GDQIMBwsgA0EpRw0BQQAoAqQKQQAvAZgKIgJBA3RqKAIEEBxFDQIMBgsgAUF+ai8BAEFQakH//wNxQQpPDQULQQAvAZgKIQILAkACQCACQf//A3EiAkUNACADQeYARw0AQQAoAqQKIAJBf2pBA3RqIgQoAgBBAUcNACABQX5qLwEAQe8ARw0BIAQoAgRBlghBAxAdRQ0BDAULIANB/QBHDQBBACgCpAogAkEDdGoiAigCBBAeDQQgAigCAEEGRg0ECyABEB8NAyADRQ0DIANBL0ZBAC0AoApBAEdxDQMCQEEAKAL4CSICRQ0AIAEgAigCAEkNACABIAIoAgRNDQQLIAFBfmohAUEAKALcCSECAkADQCABQQJqIgQgAk0NAUEAIAE2ApwKIAEvAQAhAyABQX5qIgQhASADECBFDQALIARBAmohBAsCQCADQf//A3EQIUUNACAEQX5qIQECQANAIAFBAmoiAyACTQ0BQQAgATYCnAogAS8BACEDIAFBfmoiBCEBIAMQIQ0ACyAEQQJqIQMLIAMQIg0EC0EAQQE6AKAKDAcLQQAoAqQKQQAvAZgKIgFBA3QiA2pBACgCnAo2AgRBACABQQFqOwGYCkEAKAKkCiADakEDNgIACxAjDAULQQAtAPwJQQAvAZYKQQAvAZgKcnJFIQIMBwsQJEEAQQA6AKAKDAMLECVBACECDAULIANBoAFHDQELQQBBAToArAoLQQBBACgCsAo2ApwKC0EAKAKwCiEBDAALCyAAQYDQAGokACACCxoAAkBBACgC3AkgAEcNAEEBDwsgAEF+ahAmC/4KAQZ/QQBBACgCsAoiAEEMaiIBNgKwCkEAKAL4CSECQQEQKSEDAkACQAJAAkACQAJAAkACQAJAQQAoArAKIgQgAUcNACADEChFDQELAkACQAJAAkACQAJAAkAgA0EqRg0AIANB+wBHDQFBACAEQQJqNgKwCkEBECkhA0EAKAKwCiEEA0ACQAJAIANB//8DcSIDQSJGDQAgA0EnRg0AIAMQLBpBACgCsAohAwwBCyADEBpBAEEAKAKwCkECaiIDNgKwCgtBARApGgJAIAQgAxAtIgNBLEcNAEEAQQAoArAKQQJqNgKwCkEBECkhAwsgA0H9AEYNA0EAKAKwCiIFIARGDQ8gBSEEIAVBACgCtApNDQAMDwsLQQAgBEECajYCsApBARApGkEAKAKwCiIDIAMQLRoMAgtBAEEAOgCUCgJAAkACQAJAAkACQCADQZ9/ag4MAgsEAQsDCwsLCwsFAAsgA0H2AEYNBAwKC0EAIARBDmoiAzYCsAoCQAJAAkBBARApQZ9/ag4GABICEhIBEgtBACgCsAoiBSkAAkLzgOSD4I3AMVINESAFLwEKECFFDRFBACAFQQpqNgKwCkEAECkaC0EAKAKwCiIFQQJqQbIIQQ4QLw0QIAUvARAiAkF3aiIBQRdLDQ1BASABdEGfgIAEcUUNDQwOC0EAKAKwCiIFKQACQuyAhIOwjsA5Ug0PIAUvAQoiAkF3aiIBQRdNDQYMCgtBACAEQQpqNgKwCkEAECkaQQAoArAKIQQLQQAgBEEQajYCsAoCQEEBECkiBEEqRw0AQQBBACgCsApBAmo2ArAKQQEQKSEEC0EAKAKwCiEDIAQQLBogA0EAKAKwCiIEIAMgBBACQQBBACgCsApBfmo2ArAKDwsCQCAEKQACQuyAhIOwjsA5Ug0AIAQvAQoQIEUNAEEAIARBCmo2ArAKQQEQKSEEQQAoArAKIQMgBBAsGiADQQAoArAKIgQgAyAEEAJBAEEAKAKwCkF+ajYCsAoPC0EAIARBBGoiBDYCsAoLQQAgBEEGajYCsApBAEEAOgCUCkEBECkhBEEAKAKwCiEDIAQQLCEEQQAoArAKIQIgBEHf/wNxIgFB2wBHDQNBACACQQJqNgKwCkEBECkhBUEAKAKwCiEDQQAhBAwEC0EAQQE6AIwKQQBBACgCsApBAmo2ArAKC0EBECkhBEEAKAKwCiEDAkAgBEHmAEcNACADQQJqQawIQQYQLw0AQQAgA0EIajYCsAogAEEBEClBABArIAJBEGpB5AkgAhshAwNAIAMoAgAiA0UNBSADQgA3AgggA0EQaiEDDAALC0EAIANBfmo2ArAKDAMLQQEgAXRBn4CABHFFDQMMBAtBASEECwNAAkACQCAEDgIAAQELIAVB//8DcRAsGkEBIQQMAQsCQAJAQQAoArAKIgQgA0YNACADIAQgAyAEEAJBARApIQQCQCABQdsARw0AIARBIHJB/QBGDQQLQQAoArAKIQMCQCAEQSxHDQBBACADQQJqNgKwCkEBECkhBUEAKAKwCiEDIAVBIHJB+wBHDQILQQAgA0F+ajYCsAoLIAFB2wBHDQJBACACQX5qNgKwCg8LQQAhBAwACwsPCyACQaABRg0AIAJB+wBHDQQLQQAgBUEKajYCsApBARApIgVB+wBGDQMMAgsCQCACQVhqDgMBAwEACyACQaABRw0CC0EAIAVBEGo2ArAKAkBBARApIgVBKkcNAEEAQQAoArAKQQJqNgKwCkEBECkhBQsgBUEoRg0BC0EAKAKwCiEBIAUQLBpBACgCsAoiBSABTQ0AIAQgAyABIAUQAkEAQQAoArAKQX5qNgKwCg8LIAQgA0EAQQAQAkEAIARBDGo2ArAKDwsQJQuFDAEKf0EAQQAoArAKIgBBDGoiATYCsApBARApIQJBACgCsAohAwJAAkACQAJAAkACQAJAAkAgAkEuRw0AQQAgA0ECajYCsAoCQEEBECkiAkHkAEYNAAJAIAJB8wBGDQAgAkHtAEcNB0EAKAKwCiICQQJqQZwIQQYQLw0HAkBBACgCnAoiAxAqDQAgAy8BAEEuRg0ICyAAIAAgAkEIakEAKALUCRABDwtBACgCsAoiAkECakGiCEEKEC8NBgJAQQAoApwKIgMQKg0AIAMvAQBBLkYNBwtBACEEQQAgAkEMajYCsApBASEFQQUhBkEBECkhAkEAIQdBASEIDAILQQAoArAKIgIpAAJC5YCYg9CMgDlSDQUCQEEAKAKcCiIDECoNACADLwEAQS5GDQYLQQAhBEEAIAJBCmo2ArAKQQIhCEEHIQZBASEHQQEQKSECQQEhBQwBCwJAAkACQAJAIAJB8wBHDQAgAyABTQ0AIANBAmpBoghBChAvDQACQCADLwEMIgRBd2oiB0EXSw0AQQEgB3RBn4CABHENAgsgBEGgAUYNAQtBACEHQQchBkEBIQQgAkHkAEYNAQwCC0EAIQRBACADQQxqIgI2ArAKQQEhBUEBECkhCQJAQQAoArAKIgYgAkYNAEHmACECAkAgCUHmAEYNAEEFIQZBACEHQQEhCCAJIQIMBAtBACEHQQEhCCAGQQJqQawIQQYQLw0EIAYvAQgQIEUNBAtBACEHQQAgAzYCsApBByEGQQEhBEEAIQVBACEIIAkhAgwCCyADIABBCmpNDQBBACEIQeQAIQICQCADKQACQuWAmIPQjIA5Ug0AAkACQCADLwEKIgRBd2oiB0EXSw0AQQEgB3RBn4CABHENAQtBACEIIARBoAFHDQELQQAhBUEAIANBCmo2ArAKQSohAkEBIQdBAiEIQQEQKSIJQSpGDQRBACADNgKwCkEBIQRBACEHQQAhCCAJIQIMAgsgAyEGQQAhBwwCC0EAIQVBACEICwJAIAJBKEcNAEEAKAKkCkEALwGYCiICQQN0aiIDQQAoArAKNgIEQQAgAkEBajsBmAogA0EFNgIAQQAoApwKLwEAQS5GDQRBAEEAKAKwCiIDQQJqNgKwCkEBECkhAiAAQQAoArAKQQAgAxABAkACQCAFDQBBACgC8AkhAQwBC0EAKALwCSIBIAY2AhwLQQBBAC8BlgoiA0EBajsBlgpBACgCqAogA0ECdGogATYCAAJAIAJBIkYNACACQSdGDQBBAEEAKAKwCkF+ajYCsAoPCyACEBpBAEEAKAKwCkECaiICNgKwCgJAAkACQEEBEClBV2oOBAECAgACC0EAQQAoArAKQQJqNgKwCkEBECkaQQAoAvAJIgMgAjYCBCADQQE6ABggA0EAKAKwCiICNgIQQQAgAkF+ajYCsAoPC0EAKALwCSIDIAI2AgQgA0EBOgAYQQBBAC8BmApBf2o7AZgKIANBACgCsApBAmo2AgxBAEEALwGWCkF/ajsBlgoPC0EAQQAoArAKQX5qNgKwCg8LAkAgBEEBcyACQfsAR3INAEEAKAKwCiECQQAvAZgKDQUDQAJAAkACQCACQQAoArQKTw0AQQEQKSICQSJGDQEgAkEnRg0BIAJB/QBHDQJBAEEAKAKwCkECajYCsAoLQQEQKSEDQQAoArAKIQICQCADQeYARw0AIAJBAmpBrAhBBhAvDQcLQQAgAkEIajYCsAoCQEEBECkiAkEiRg0AIAJBJ0cNBwsgACACQQAQKw8LIAIQGgtBAEEAKAKwCkECaiICNgKwCgwACwsCQAJAIAJBWWoOBAMBAQMACyACQSJGDQILQQAoArAKIQYLIAYgAUcNAEEAIABBCmo2ArAKDwsgAkEqRyAHcQ0DQQAvAZgKQf//A3ENA0EAKAKwCiECQQAoArQKIQEDQCACIAFPDQECQAJAIAIvAQAiA0EnRg0AIANBIkcNAQsgACADIAgQKw8LQQAgAkECaiICNgKwCgwACwsQJQsPC0EAIAJBfmo2ArAKDwtBAEEAKAKwCkF+ajYCsAoLRwEDf0EAKAKwCkECaiEAQQAoArQKIQECQANAIAAiAkF+aiABTw0BIAJBAmohACACLwEAQXZqDgQBAAABAAsLQQAgAjYCsAoLmAEBA39BAEEAKAKwCiIBQQJqNgKwCiABQQZqIQFBACgCtAohAgNAAkACQAJAIAFBfGogAk8NACABQX5qLwEAIQMCQAJAIAANACADQSpGDQEgA0F2ag4EAgQEAgQLIANBKkcNAwsgAS8BAEEvRw0CQQAgAUF+ajYCsAoMAQsgAUF+aiEBC0EAIAE2ArAKDwsgAUECaiEBDAALC4gBAQR/QQAoArAKIQFBACgCtAohAgJAAkADQCABIgNBAmohASADIAJPDQEgAS8BACIEIABGDQICQCAEQdwARg0AIARBdmoOBAIBAQIBCyADQQRqIQEgAy8BBEENRw0AIANBBmogASADLwEGQQpGGyEBDAALC0EAIAE2ArAKECUPC0EAIAE2ArAKC2wBAX8CQAJAIABBX2oiAUEFSw0AQQEgAXRBMXENAQsgAEFGakH//wNxQQZJDQAgAEEpRyAAQVhqQf//A3FBB0lxDQACQCAAQaV/ag4EAQAAAQALIABB/QBHIABBhX9qQf//A3FBBElxDwtBAQsuAQF/QQEhAQJAIABBpglBBRAdDQAgAEGWCEEDEB0NACAAQbAJQQIQHSEBCyABC0YBA39BACEDAkAgACACQQF0IgJrIgRBAmoiAEEAKALcCSIFSQ0AIAAgASACEC8NAAJAIAAgBUcNAEEBDwsgBBAmIQMLIAMLgwEBAn9BASEBAkACQAJAAkACQAJAIAAvAQAiAkFFag4EBQQEAQALAkAgAkGbf2oOBAMEBAIACyACQSlGDQQgAkH5AEcNAyAAQX5qQbwJQQYQHQ8LIABBfmovAQBBPUYPCyAAQX5qQbQJQQQQHQ8LIABBfmpByAlBAxAdDwtBACEBCyABC7QDAQJ/QQAhAQJAAkACQAJAAkACQAJAAkACQAJAIAAvAQBBnH9qDhQAAQIJCQkJAwkJBAUJCQYJBwkJCAkLAkACQCAAQX5qLwEAQZd/ag4EAAoKAQoLIABBfGpByghBAhAdDwsgAEF8akHOCEEDEB0PCwJAAkACQCAAQX5qLwEAQY1/ag4DAAECCgsCQCAAQXxqLwEAIgJB4QBGDQAgAkHsAEcNCiAAQXpqQeUAECcPCyAAQXpqQeMAECcPCyAAQXxqQdQIQQQQHQ8LIABBfGpB3AhBBhAdDwsgAEF+ai8BAEHvAEcNBiAAQXxqLwEAQeUARw0GAkAgAEF6ai8BACICQfAARg0AIAJB4wBHDQcgAEF4akHoCEEGEB0PCyAAQXhqQfQIQQIQHQ8LIABBfmpB+AhBBBAdDwtBASEBIABBfmoiAEHpABAnDQQgAEGACUEFEB0PCyAAQX5qQeQAECcPCyAAQX5qQYoJQQcQHQ8LIABBfmpBmAlBBBAdDwsCQCAAQX5qLwEAIgJB7wBGDQAgAkHlAEcNASAAQXxqQe4AECcPCyAAQXxqQaAJQQMQHSEBCyABCzQBAX9BASEBAkAgAEF3akH//wNxQQVJDQAgAEGAAXJBoAFGDQAgAEEuRyAAEChxIQELIAELMAEBfwJAAkAgAEF3aiIBQRdLDQBBASABdEGNgIAEcQ0BCyAAQaABRg0AQQAPC0EBC04BAn9BACEBAkACQCAALwEAIgJB5QBGDQAgAkHrAEcNASAAQX5qQfgIQQQQHQ8LIABBfmovAQBB9QBHDQAgAEF8akHcCEEGEB0hAQsgAQveAQEEf0EAKAKwCiEAQQAoArQKIQECQAJAAkADQCAAIgJBAmohACACIAFPDQECQAJAAkAgAC8BACIDQaR/ag4FAgMDAwEACyADQSRHDQIgAi8BBEH7AEcNAkEAIAJBBGoiADYCsApBAEEALwGYCiICQQFqOwGYCkEAKAKkCiACQQN0aiICQQQ2AgAgAiAANgIEDwtBACAANgKwCkEAQQAvAZgKQX9qIgA7AZgKQQAoAqQKIABB//8DcUEDdGooAgBBA0cNAwwECyACQQRqIQAMAAsLQQAgADYCsAoLECULC3ABAn8CQAJAA0BBAEEAKAKwCiIAQQJqIgE2ArAKIABBACgCtApPDQECQAJAAkAgAS8BACIBQaV/ag4CAQIACwJAIAFBdmoOBAQDAwQACyABQS9HDQIMBAsQLhoMAQtBACAAQQRqNgKwCgwACwsQJQsLNQEBf0EAQQE6APwJQQAoArAKIQBBAEEAKAK0CkECajYCsApBACAAQQAoAtwJa0EBdTYCkAoLQwECf0EBIQECQCAALwEAIgJBd2pB//8DcUEFSQ0AIAJBgAFyQaABRg0AQQAhASACEChFDQAgAkEuRyAAECpyDwsgAQs9AQJ/QQAhAgJAQQAoAtwJIgMgAEsNACAALwEAIAFHDQACQCADIABHDQBBAQ8LIABBfmovAQAQICECCyACC2gBAn9BASEBAkACQCAAQV9qIgJBBUsNAEEBIAJ0QTFxDQELIABB+P8DcUEoRg0AIABBRmpB//8DcUEGSQ0AAkAgAEGlf2oiAkEDSw0AIAJBAUcNAQsgAEGFf2pB//8DcUEESSEBCyABC5wBAQN/QQAoArAKIQECQANAAkACQCABLwEAIgJBL0cNAAJAIAEvAQIiAUEqRg0AIAFBL0cNBBAYDAILIAAQGQwBCwJAAkAgAEUNACACQXdqIgFBF0sNAUEBIAF0QZ+AgARxRQ0BDAILIAIQIUUNAwwBCyACQaABRw0CC0EAQQAoArAKIgNBAmoiATYCsAogA0EAKAK0CkkNAAsLIAILMQEBf0EAIQECQCAALwEAQS5HDQAgAEF+ai8BAEEuRw0AIABBfGovAQBBLkYhAQsgAQumBAEBfwJAIAFBIkYNACABQSdGDQAQJQ8LQQAoArAKIQMgARAaIAAgA0ECakEAKAKwCkEAKALQCRABAkAgAkEBSA0AQQAoAvAJQQRBBiACQQFGGzYCHAtBAEEAKAKwCkECajYCsAoCQAJAAkACQEEAECkiAUHhAEYNACABQfcARg0BQQAoArAKIQEMAgtBACgCsAoiAUECakHACEEKEC8NAUEGIQIMAgtBACgCsAoiAS8BAkHpAEcNACABLwEEQfQARw0AQQQhAiABLwEGQegARg0BC0EAIAFBfmo2ArAKDwtBACABIAJBAXRqNgKwCgJAQQEQKUH7AEYNAEEAIAE2ArAKDwtBACgCsAoiACECA0BBACACQQJqNgKwCgJAAkACQEEBECkiAkEiRg0AIAJBJ0cNAUEnEBpBAEEAKAKwCkECajYCsApBARApIQIMAgtBIhAaQQBBACgCsApBAmo2ArAKQQEQKSECDAELIAIQLCECCwJAIAJBOkYNAEEAIAE2ArAKDwtBAEEAKAKwCkECajYCsAoCQEEBECkiAkEiRg0AIAJBJ0YNAEEAIAE2ArAKDwsgAhAaQQBBACgCsApBAmo2ArAKAkACQEEBECkiAkEsRg0AIAJB/QBGDQFBACABNgKwCg8LQQBBACgCsApBAmo2ArAKQQEQKUH9AEYNAEEAKAKwCiECDAELC0EAKALwCSIBIAA2AhAgAUEAKAKwCkECajYCDAttAQJ/AkACQANAAkAgAEH//wNxIgFBd2oiAkEXSw0AQQEgAnRBn4CABHENAgsgAUGgAUYNASAAIQIgARAoDQJBACECQQBBACgCsAoiAEECajYCsAogAC8BAiIADQAMAgsLIAAhAgsgAkH//wNxC6sBAQR/AkACQEEAKAKwCiICLwEAIgNB4QBGDQAgASEEIAAhBQwBC0EAIAJBBGo2ArAKQQEQKSECQQAoArAKIQUCQAJAIAJBIkYNACACQSdGDQAgAhAsGkEAKAKwCiEEDAELIAIQGkEAQQAoArAKQQJqIgQ2ArAKC0EBECkhA0EAKAKwCiECCwJAIAIgBUYNACAFIARBACAAIAAgAUYiAhtBACABIAIbEAILIAMLcgEEf0EAKAKwCiEAQQAoArQKIQECQAJAA0AgAEECaiECIAAgAU8NAQJAAkAgAi8BACIDQaR/ag4CAQQACyACIQAgA0F2ag4EAgEBAgELIABBBGohAAwACwtBACACNgKwChAlQQAPC0EAIAI2ArAKQd0AC0kBA39BACEDAkAgAkUNAAJAA0AgAC0AACIEIAEtAAAiBUcNASABQQFqIQEgAEEBaiEAIAJBf2oiAg0ADAILCyAEIAVrIQMLIAMLC+wBAgBBgAgLzgEAAHgAcABvAHIAdABtAHAAbwByAHQAZgBvAHIAZQB0AGEAbwB1AHIAYwBlAHIAbwBtAHUAbgBjAHQAaQBvAG4AcwBzAGUAcgB0AHYAbwB5AGkAZQBkAGUAbABlAGMAbwBuAHQAaQBuAGkAbgBzAHQAYQBuAHQAeQBiAHIAZQBhAHIAZQB0AHUAcgBkAGUAYgB1AGcAZwBlAGEAdwBhAGkAdABoAHIAdwBoAGkAbABlAGkAZgBjAGEAdABjAGYAaQBuAGEAbABsAGUAbABzAABB0AkLEAEAAAACAAAAAAQAAEA5AAA=",typeof Buffer<"u"?Buffer.from(A,"base64"):Uint8Array.from(atob(A),(Q)=>Q.charCodeAt(0));var A},jJ=WebAssembly.compile(eH()).then(WebAssembly.instantiate).then(({exports:A})=>{o=A});var A$=/\.m?js$/i;function X0(A){return/^src\//i.test(A)&&A$.test(A)}function f8(A){return X0(A.entry||"")}function Q$(A){let Q=A.lastIndexOf("/");return(Q<0?"":A.slice(0,Q)).split("/").filter(Boolean)}function B$(A,Q){let B=Q$(A);for(let C of Q.split("/"))if(C===""||C===".")continue;else if(C==="..")B.pop();else B.push(C);return B.join("/")}async function u8(A){await jJ;let Q={};for(let[J,K]of A.files)if(X0(J))Q[J]=new TextDecoder().decode(K);let B=(J)=>Object.prototype.hasOwnProperty.call(Q,J),C=(J,K)=>{let L=B$(J,K);if(B(L))return L;if(B(L+".js"))return L+".js";if(B(L+".mjs"))return L+".mjs";if(B(L+"/index.js"))return L+"/index.js";return L},E={};for(let[J,K]of Object.entries(Q))E[J]=C$(K,J,C);return{modules:E,entry:A.manifest.entry}}function C$(A,Q,B){let[C]=OJ(A),E="",J=0;for(let K of C){if(K.n==null)continue;if(K.n[0]!==".")continue;let L="trove:/"+B(Q,K.n),Y=K.d===-1?L:JSON.stringify(L);E+=A.slice(J,K.s)+Y,J=K.e}return E+A.slice(J)}var E$=15000;class wJ{constructor({media:A,dock:Q}={}){this.media=A,this.dock=Q}async spawn(A,Q,B){let C=document.createElement("iframe");C.style.cssText=J$,C.setAttribute("sandbox","allow-scripts allow-forms"),C.setAttribute("referrerpolicy","no-referrer");let E=B?.entry;if(E)A._entrySrcdoc||={},A._entrySrcdoc[E]||=await m8({...A.manifest,entry:E},A.files),C.srcdoc=A._entrySrcdoc[E];else A._srcdoc||=await m8(A.manifest,A.files),C.srcdoc=A._srcdoc;let J={role:Q,iframe:C,channel:null,record:A,place:null,dock:null,mediaActions:null};document.body.appendChild(C);try{await this.#A(A,J,B)}catch(K){try{J.channel?.dispose()}catch{}throw C.remove(),K}return J}#A(A,Q,{onCall:B,onEvent:C,online:E}){return new Promise((J,K)=>{let{iframe:L}=Q,Y=A.manifest,X=!1,H=0,G=()=>{if(window.removeEventListener("message",U),H)clearTimeout(H)},D=(I)=>{if(X)return;X=!0,G(),K(Error(I))},U=(I)=>{if(I.source!==L.contentWindow)return;if(I.data?.__trove==="boot-error")return D(I.data.error||"Plugin failed to load its modules");if(I.data?.__trove!=="ready")return;if(!b8(I.data.protocolVersion))return D(`Plugin speaks protocol ${I.data.protocolVersion}, this host speaks ${PJ}`);window.removeEventListener("message",U);let R=new MessageChannel;Q.channel=new zJ(R.port1,{onCall:(V,_)=>B(A,V,_,Q),onEvent:(V,_)=>C(A,V,_,Q)}),Q.resolveActivated=(V)=>{if(X)return;if(X=!0,H)clearTimeout(H);J(V)},Q.rejectActivated=(V)=>{if(X)return;if(X=!0,H)clearTimeout(H);K(V)},L.contentWindow.postMessage({__trove:"init",manifest:Y,capabilities:A.grants,storage:A.storage,online:E,role:Q.role,protocolVersion:PJ},"*",[R.port2])};H=setTimeout(()=>D("Plugin handshake timed out"),E$),window.addEventListener("message",U),L.addEventListener("error",()=>D("Failed to load plugin iframe"))})}destroy(A){if(!A)return;this.dock?.releaseFrame(A),this.media?.releaseFrame(A);try{A.channel?.emit("deactivate")}catch{}try{A.channel?.dispose()}catch{}A.iframe.remove(),A.record?.frames?.delete(A)}}var J$="position:fixed;left:0;top:0;width:0;height:0;border:0;visibility:hidden;",K$=["default-src 'none'","script-src 'unsafe-inline' 'unsafe-eval' blob:","style-src 'unsafe-inline'","img-src blob: data:","media-src blob: data:","font-src 'none'","connect-src 'none'","base-uri 'none'","form-action 'none'"].join("; "),l8=`<!doctype html><html><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="${K$}"></head><body>`;async function m8(A,Q){if(f8(A))return L$(await u8({manifest:A,files:Q}));let B=new TextDecoder().decode(Q.get(A.entry)??new Uint8Array);return`${l8}
|
|
709
|
-
<script>${NJ}</script>
|
|
710
|
-
<script>${B}</script>
|
|
711
|
-
</body></html>`}function p8(A){return JSON.stringify(A).replace(/</g,"\\u003c").replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}function L$(A){let Q=p8("trove:/"+A.entry);return`${l8}
|
|
712
|
-
<script>${NJ}</script>
|
|
713
|
-
<script id="__trove_src" type="application/json">${p8(A.modules)}</script>
|
|
714
|
-
<script>
|
|
715
|
-
(function () {
|
|
716
|
-
var src = JSON.parse(document.getElementById('__trove_src').textContent);
|
|
717
|
-
var imports = {};
|
|
718
|
-
for (var p in src) imports['trove:/' + p] = URL.createObjectURL(new Blob([src[p] + '\\n//# sourceURL=trove:/' + p], { type: 'text/javascript' }));
|
|
719
|
-
imports['trove'] = URL.createObjectURL(new Blob(['export const activate = globalThis.trove.activate;\\nexport default globalThis.trove;'], { type: 'text/javascript' }));
|
|
720
|
-
var im = document.createElement('script');
|
|
721
|
-
im.type = 'importmap';
|
|
722
|
-
im.textContent = JSON.stringify({ imports: imports });
|
|
723
|
-
document.head.appendChild(im);
|
|
724
|
-
import(${Q}).catch(function (e) {
|
|
725
|
-
try { parent.postMessage({ __trove: 'boot-error', error: String((e && e.message) || e) }, '*'); } catch (_) {}
|
|
726
|
-
});
|
|
727
|
-
})();
|
|
728
|
-
</script>
|
|
729
|
-
</body></html>`}var Y$=/\b(ATTACH|DETACH|VACUUM|PRAGMA)\b/i;function X$(A){let Q="",B=0;while(B<A.length){let C=A[B];if(C==="-"&&A[B+1]==="-"){let E=A.indexOf(`
|
|
730
|
-
`,B);B=E<0?A.length:E;continue}if(C==="/"&&A[B+1]==="*"){let E=A.indexOf("*/",B+2);B=E<0?A.length:E+2,Q+=" ";continue}if(C==="'"||C==='"'||C==="`"){let E=C;B++;while(B<A.length){if(A[B]===E){if(A[B+1]===E){B+=2;continue}B++;break}B++}Q+=" ";continue}if(C==="["){let E=A.indexOf("]",B);B=E<0?A.length:E+1,Q+=" ";continue}Q+=C,B++}return Q}function SJ(A){if(typeof A!=="string"||!A)throw z.invalid("SQL statement is required");if(Y$.test(X$(A)))throw z.invalid("ATTACH, DETACH, VACUUM and PRAGMA are not permitted in plugin storage")}var G$=26214400;async function H$(A,Q){let B=Number(A.headers.get("content-length")||0);if(B&&B>Q)throw Error("Response too large");let C=A.body?.getReader?.();if(!C){let Y=await A.arrayBuffer();if(Y.byteLength>Q)throw Error("Response too large");return Y}let E=[],J=0;for(;;){let{done:Y,value:X}=await C.read();if(Y)break;if(J+=X.byteLength,J>Q)throw await C.cancel().catch(()=>{}),Error("Response too large");E.push(X)}let K=new Uint8Array(J),L=0;for(let Y of E)K.set(Y,L),L+=Y.byteLength;return K.buffer}class _J{constructor({platform:A,clientDb:Q,media:B,dock:C,onChange:E}={}){this.platform=A,this.clientDb=Q,this.media=B,this.dock=C,this.onChange=E||(()=>{})}async hostCall(A,Q,B,C){let E=(K)=>{if(!A.grants.includes(K))throw Error(`Capability "${K}" not granted`)},J=A.id;switch(Q){case"activated":{let K=C||A.frame;if(clearTimeout(K?._timer),B.ok)K?.resolveActivated?.(K);else K?.rejectActivated?.(Error(B.error||"activate() failed"));return{ok:!0}}case"command:execute":{let K=this.#A(A,B.id);if(!dC(A.manifest,K))throw Error(`Command "${B.id}" is not in this plugin's declared commands`);return{ok:!0,result:await this.platform.commands.execute(K,...B.args||[])??null}}case"ui:status":{E("ui");let K=this.#Q(A,B.name,"statusItem");return this.platform.contributions.update(K.uri,{...B.html!==void 0?{html:String(B.html??"")}:{},...B.tooltip!==void 0?{tooltip:String(B.tooltip??"")}:{},...B.visible!==void 0?{visible:!!B.visible}:{visible:!0}}),{ok:!0}}case"context:setRegister":{let K=this.#Q(A,B.name,"register"),L=A.registers?.get(K.uri);if(!L)throw Error(`Register "${B.name}" is not available`);return L(B.value),{ok:!0}}case"resources:list":return[...A.files.keys()].filter(d8);case"resources:read":{if(!d8(B.path))throw Error(`No such resource ${B.path}`);let K=A.files.get(B.path);if(!K)throw Error(`No such resource ${B.path}`);return{bytes:K.slice().buffer}}case"files:read":return E("files"),{text:await this.platform.api.readText(B.id)};case"files:list":return E("files"),this.platform.api.list(B.collection||B.pathOrId,{sort:B.sort,order:B.order,limit:B.limit,cursor:B.cursor});case"files:stat":return E("files"),this.platform.api.stat(B.id);case"files:bytes":{E("files");let K=await this.platform.fileChunks.read(B.id,{start:B.start,end:B.end});return{bytes:K.bytes.buffer,etag:K.etag,total:K.total}}case"files:hasLocal":{E("files");let K=this.platform.fileChunks.status(B.id);return{local:!!K.done,loaded:K.loaded,total:K.total,ratio:K.ratio,filling:K.filling}}case"files:localBlob":{E("files");let K=this.platform.fileChunks.status(B.id);if(!K.done||!K.total)return{blob:null};let L=await this.platform.fileChunks.read(B.id,{start:0,end:K.total}),Y=await this.platform.api.stat(B.id).catch(()=>null);return{blob:new Blob([L.bytes],{type:Y?.node?.contentType||"application/octet-stream"})}}case"items:data:get":return E("files"),this.platform.itemData.get(J,B.id);case"items:data:set":return E("files"),this.platform.itemData.set(J,B.id,B.key,B.value);case"items:data:remove":return E("files"),this.platform.itemData.remove(J,B.id,B.key);case"files:offline:start":return E("files"),this.platform.fileChunks.start(B.id);case"files:offline:status":return E("files"),this.platform.fileChunks.status(B.id);case"files:offline:cancel":return E("files"),this.platform.fileChunks.cancel(B.id),{ok:!0};case"files:offline:remove":return E("files"),this.platform.fileChunks.remove(B.id).then(()=>({ok:!0}));case"files:mediaUrl":{E("files");let{url:K,expiresAt:L}=await this.platform.mediaUrls.url(B.id,{op:B.op||"media"});return{url:K,expiresAt:L}}case"files:index":{E("indexer");let K=kQ(B.indexerId)?B.indexerId:xQ(A.manifest,B.indexerId||"default");return this.platform.api.pushIndex(K,B.nodeId,{semanticTexts:B.semanticTexts,tags:B.tags,metadata:B.metadata,documents:B.documents,facet:B.facet})}case"net:fetch":return E("network"),this.#C(A,B);case"storage:sql":return E("storage"),this.#E(A,B);case"settings:get":return this.platform.settings.get(`${J}.${B.key}`);case"settings:getSecret":return A.secrets?.[B.key]??null;case"settings:set":return this.platform.settings.set(`${J}.${B.key}`,B.value),{ok:!0};case"ui:showPanel":return E("ui"),A.hasUi=!0,this.platform.dispatch(new EC(J)),this.onChange(),{ok:!0};case"media:metadata":{E("media");let K=(B.artwork||[]).filter((L)=>this.#B(A,L?.src));return this.media.apply(C,"metadata",{...B,artwork:K})}case"media:playbackState":return E("media"),this.media.apply(C,"playbackState",B);case"media:position":return E("media"),this.media.apply(C,"position",B);case"media:action":return E("media"),this.media.apply(C,"action",B);case"media:clear":return this.media.apply(C,"clear",B);case"dock:enable":if(E("dock"),C)C.dock={enabled:!0,minSize:B.minSize,maxSize:B.maxSize,dismissed:!1};return{ok:!0};case"dock:disable":if(E("dock"),C?.dock)C.dock.enabled=!1;if(C&&this.dock.docked===C)this.dock.closeDock(C);return{ok:!0};case"dock:close":if(C)this.dock.closeDock(C);return{ok:!0};default:throw Error(`Unknown host method ${Q}`)}}hostEvent(A,Q,B,C){switch(Q){case"manifest":if(C&&C.role!=="primary")break;A.live=B,A.responsive=!0,this.onChange();break;case"ui:toast":this.platform.notifications[B.level||"info"](`${dA(A.manifest)}: ${B.text}`);break;case"ui:badge":A.badge=B.text,this.onChange();break}}#A(A,Q){if(!Q||kQ(Q))return Q;let B=this.platform.contributions.get(xQ(A.manifest,Q));return B?.type==="command"?B.uri:Q}#Q(A,Q,B){let C=Q?this.platform.contributions.get(xQ(A.manifest,Q)):null;if(!C||C.pluginId!==A.id||C.type!==B)throw Error(`"${Q}" is not a ${B} declared by this plugin`);return C}#B(A,Q){if(!Q)return!1;if(/^data:image\//i.test(Q))return!0;if(/^blob:/i.test(Q))return console.warn(`[trove] ${A.id}: media artwork must be a data: URL — a blob: from a sandboxed frame is opaque-origin and cannot be loaded here`),!1;return lC(rQ(A.manifest),Q)}async#C(A,{url:Q,method:B="GET",headers:C,body:E}){let J=rQ(A.manifest);if(c8(Q,this.platform.api?.baseUrl))throw Error("Blocked: a plugin may not call the drive's own API through the network broker");if(!lC(J,Q))throw Error(`Blocked: "${Q}" is not one of this plugin's declared network endpoints`);let K={method:B,credentials:"omit",redirect:"follow",headers:D$(C)};if(E!=null&&B!=="GET"&&B!=="HEAD")K.body=E instanceof ArrayBuffer?new Uint8Array(E):E;let L=await fetch(Q,K);if(L.url&&L.url!==Q){if(c8(L.url,this.platform.api?.baseUrl))throw Error("Blocked: request redirected onto the drive's own API");if(!lC(J,L.url))throw Error(`Blocked: request redirected off this plugin's declared endpoints (${L.url})`)}let Y=await H$(L,G$),X={};return L.headers.forEach((H,G)=>{X[G]=H}),{ok:L.ok,status:L.status,statusText:L.statusText,url:L.url,headers:X,bytes:Y}}async#E(A,{scope:Q="plugin",side:B="server",op:C,sql:E,params:J=[],statements:K}){if(!A.storage?.[Q])throw Error(`Storage scope "${Q}" not granted${Q==="domain"?" (needs a verified domain)":""}`);if(B==="client"){if(C==="batch")for(let G of Array.isArray(K)?K:[])SJ(G?.sql);else SJ(E);let X=Q==="domain"?`dom:${A.manifest.domain}`:`plg:${A.id}`,H=await this.clientDb.obtain(X);return Z$(H,C,E,J,K)}let L={scope:Q,op:C,sql:E,params:J,statements:K,domain:Q==="domain"?A.manifest.domain:void 0};return(await this.platform.api.request("POST",`/api/plugins/${encodeURIComponent(A.id)}/sql`,{body:L})).result}}function c8(A,Q){try{let B=new URL(Q||"",globalThis.location?.href||"http://localhost/");return new URL(A,B).origin===B.origin}catch{return!1}}function d8(A){return A!=="manifest.json"&&!X0(A)}var $$=new Set(["host","cookie","cookie2","set-cookie","origin","referer","content-length","connection"]);function D$(A){let Q={};for(let[B,C]of Object.entries(A||{}))if(!$$.has(String(B).toLowerCase()))Q[B]=C;return Q}function Z$(A,Q,B,C=[],E){switch(Q){case"exec":return A.exec(B);case"run":return A.run(B,...C);case"get":return A.get(B,...C);case"all":return A.all(B,...C);case"batch":return A.batch(E);default:throw Error(`Unknown storage op "${Q}"`)}}var a8=["files","storage","ui","commands","indexer","opener","network","media","dock"];class TJ{constructor(A,{heartbeatMs:Q=20000}={}){this.platform=A,this.plugins=new Map,this.registry=new AE,this.clientDb=new BE({onError:(B,C)=>this.platform.notifications.error(`A plugin's on-device data couldn't be saved (${C}): ${B.message}`)}),this.online=typeof navigator<"u"?navigator.onLine:!0,this.heartbeatMs=Q,this._heartbeat=null,this._probing=!1,this.cell=A.reactive.cell([]),this.media=new GE,this.dock=new HE({destroyFrame:(B)=>this.frames.destroy(B),openFile:(B,C)=>this.platform.dispatch(new GQ(B,C)),onChange:()=>this.#A()}),this.frames=new wJ({media:this.media,dock:this.dock}),this.rpc=new _J({platform:A,clientDb:this.clientDb,media:this.media,dock:this.dock,onChange:()=>this.#A()})}observe(){return this.cell}#A(){this.cell.setValue(this.list())}#Q(A,Q,B){return this.frames.spawn(A,Q,{onCall:(C,E,J,K)=>this.rpc.hostCall(C,E,J,K),onEvent:(C,E,J,K)=>this.rpc.hostEvent(C,E,J,K),online:this.online,entry:B})}#B(A){let Q=A.id,B=this.platform.contributions,C=(J)=>A.disposers.push(J),E=dA(A.manifest);for(let J of IQ(A.manifest)){let K={...J,pluginId:Q};switch(J.type){case"opener":if(A.grants.includes("opener"))C(B.register(J.uri,K));break;case"command":C(this.platform.commands.register({id:J.uri,title:J.title||`${E}: ${J.name}`,category:J.category||E,icon:J.icon,when:J.when,offline:J.offline,palette:J.palette,pluginId:Q,actions:(...L)=>new IJ(Q,J.name,L)}));break;case"statusItem":{let L=J.command?this.#E(A,J.command,E,`status item “${J.name}”`):null;C(B.register(J.uri,{...K,command:L,html:"",visible:!1}));break}case"register":{C(B.register(J.uri,K));let L=this.platform.context.own(J.uri,J.default);A.registers.set(J.uri,L.set),C(()=>{A.registers.delete(J.uri),L.dispose()});break}case"keymap":{let L=A.files.get(J.path);if(!L){this.platform.notifications.warn(`Plugin "${E}": keymap file "${J.path}" is not in the package.`);break}try{let Y=this.#C(A,LL(new TextDecoder().decode(L)),E);C(B.register(J.uri,{...K,bindings:Y}))}catch(Y){this.platform.notifications.warn(`Plugin "${E}": ${Y.message}`)}break}case"indexer":break}}}#C(A,Q,B){let C=[];for(let E of Q){let J=this.#E(A,E.command,B,`shortcut ${E.key}`);if(J)C.push({...E,command:J})}return C}#E(A,Q,B,C){let E=xQ(A.manifest,Q);if(IQ(A.manifest).some((K)=>K.uri===E&&K.type==="command"))return E;if(!dC(A.manifest,Q))return this.platform.notifications.warn(`Plugin "${B}": ${C} runs "${Q}", which it isn't allowed to run — ignored.`),null;return Q}list(){return[...this.plugins.values()].map((A)=>({id:A.id,name:dA(A.manifest),version:A.manifest.version,status:A.status,capabilities:A.grants,error:A.error||null,hasUi:A.hasUi,badge:A.badge||null,trust:A.trust||null,settingsSchema:A.manifest.settings||[],endpoints:cC(rQ(A.manifest)),responsive:!!A.responsive,manifest:A.live||null,features:this.#J(A)}))}#J(A){let Q;try{Q=IQ(A.manifest)}catch{return[]}return Q.map((B)=>({kind:B.type,id:B.uri,name:B.name,title:B.title||B.name,offline:!!B.offline,available:this.#K(A,B)}))}#K(A,Q){if(A.status!=="active"||!A.responsive)return!1;return this.online||!!Q.offline}isAvailable(A){if(!A?.pluginId)return!0;let Q=this.plugins.get(A.pluginId);if(!Q)return!1;return this.#K(Q,A)}canGrant(A,Q){return!KE.has(A)||!!Q}async install(A,{grants:Q,trust:B}={}){let C=EQ(A.manifest),E=LE(A.manifest),J=(Q||E).filter((X)=>a8.includes(X)&&E.includes(X)),K=F$(A.manifest,J)?"account":"device";if(K==="account"){if(!A.raw)throw Error("Package bytes unavailable for a server install");await this.platform.api.installPlugin(A.raw,J)}let L=J.includes("storage")?XE(A.manifest,B):{plugin:!1,domain:!1},Y={id:C,manifest:A.manifest,files:Object.fromEntries([...A.files.entries()]),grants:J,storage:L,trust:B||null,scope:K,settings:{},secrets:{},installedAt:Date.now()};return await this.registry.save(Y),this.#Y(Y),await this.#X(Y),this.plugins.get(C)}async restore(){let A=[];try{A=await this.registry.list()}catch{}for(let Q of A)try{this.#Y(Q),this.#X(Q).catch((B)=>console.error("restore plugin failed",Q.id,B))}catch(B){console.error("skipping corrupt plugin record",Q?.id,B),this.platform.notifications.warn(`Couldn't restore plugin "${Q?.manifest?dA(Q.manifest):Q?.id||"unknown"}" — its saved data looks corrupt.`)}this.#L(A).catch(()=>{})}async#L(A){let Q;try{Q=(await this.platform.api.installedPlugins()).plugins||[]}catch{return}let B=new Set(Q.map((L)=>L.pluginId)),C=new Set(A.map((L)=>L.id)),E=0,J=0,K=0;for(let L of A){if(L.scope!=="account"||B.has(L.id))continue;try{await this.platform.api.installPlugin(SL(U$(L.files)),L.grants||[])}catch(Y){console.error("re-upload plugin failed",L.id,Y),E++}}for(let L of Q){if(C.has(L.pluginId))continue;try{let Y=tQ(await this.platform.api.pluginPackage(L.pluginId)),X=L.grants||[],H={id:L.pluginId,manifest:Y.manifest,files:Object.fromEntries([...Y.files.entries()]),grants:X,storage:X.includes("storage")?{plugin:!0,domain:!!L.sharedStorage}:{plugin:!1,domain:!1},trust:null,scope:"account",settings:{},secrets:{},installedAt:L.createdAt||Date.now()};await this.registry.save(H),this.#Y(H),await this.#X(H),J++}catch(Y){console.error("sync plugin failed",L.pluginId,Y),K++}}if(J)this.platform.notifications.info(`Synced ${J} account plugin${J>1?"s":""} from the server.`);if(E||K){let L=[];if(K)L.push(`${K} couldn't be downloaded`);if(E)L.push(`${E} couldn't be uploaded`);this.platform.notifications.warn(`Some account plugins didn't sync: ${L.join(", ")}.`)}}#Y(A){let Q=(A.manifest.settings||[]).filter((B)=>!B.secret);if(Q.length)A._settingsDispose=this.platform.settings.scopedFor(A.id).register(Q.map((B)=>({...B,category:dA(A.manifest)})))}async#X(A){if(this.plugins.get(A.id)?.status==="active")return;let Q={...A,iframe:null,status:"loading",error:null,disposers:[],channel:null,registers:new Map,hasUi:!1,responsive:!1,frame:null,frames:new Set,storage:A.storage||(A.grants?.includes("storage")?XE(A.manifest,A.trust):{plugin:!1,domain:!1}),files:W$(A.files)};this.plugins.set(A.id,Q);try{this.#B(Q)}catch(B){console.error("registering contributions failed",A.id,B)}this.#A();try{let B=await this.#Q(Q,"primary");if(this.plugins.get(A.id)!==Q)return this.frames.destroy(B),Q;Q.frame=B,Q.iframe=B.iframe,Q.channel=B.channel,Q.status="active",Q.responsive=!0,this.#H(Q).then(()=>this.#A()),this.#G()}catch(B){Q.status="error",Q.error=B?.message||String(B),this.platform.notifications.error(`Plugin "${dA(A.manifest)}" failed to load: ${Q.error}`)}return this.#A(),Q}async setSecret(A,Q,B){let C=await this.registry.get(A);if(!C)return;C.secrets={...C.secrets,[Q]:B},await this.registry.save(C);let E=this.plugins.get(A);if(E)E.secrets=C.secrets;E?.channel?.emit("settings:changed",{key:Q,value:"••••"})}async getSecret(A,Q){return(await this.registry.get(A))?.secrets?.[Q]??""}#G(){if(this._heartbeat||!this.heartbeatMs)return;if(this._heartbeat=setInterval(()=>this.#Z(),this.heartbeatMs),this._heartbeat?.unref)this._heartbeat.unref()}#$(){if(this._heartbeat)clearInterval(this._heartbeat);this._heartbeat=null}async#Z(){if(this._probing)return;this._probing=!0;try{let A=!1;for(let Q of this.plugins.values())if(Q.status==="active")A=await this.#H(Q)||A;if(A)this.#A()}finally{this._probing=!1}}invokeCommand(A,Q,B=[]){return this.plugins.get(A)?.channel?.call("command:execute",{id:Q,args:B})}setHeartbeat(A){if(this.heartbeatMs=A,this.#$(),A&&[...this.plugins.values()].some((Q)=>Q.status==="active"))this.#G()}async#H(A){if(A.status!=="active"||!A.channel)return!1;let Q={responsive:A.responsive,sig:n8(A.live)};try{A.live=await A.channel.call("manifest",{},{timeout:4000}),A.responsive=!0}catch{A.responsive=!1}return Q.responsive!==A.responsive||Q.sig!==n8(A.live)}async setOnline(A){if(this.online===A)return;this.online=A,await Promise.all([...this.plugins.values()].filter((Q)=>Q.status==="active").map(async(Q)=>{try{Q.channel?.emit("connectivity",{online:A})}catch{}for(let B of Q.frames||[])try{B.channel?.emit("connectivity",{online:A})}catch{}await this.#H(Q)})),this.#A()}async refresh(A){let Q=this.plugins.get(A);if(Q)await this.#H(Q),this.#A()}mountPanel(A,Q,{width:B=380,height:C=480}={}){let E=this.plugins.get(A);if(!E?.frame)return null;return Q.style.width=`${B}px`,Q.style.height=`${C}px`,this.dock.place(E.frame,Q,50),E.hasUi=!0,()=>this.dock.hide(E.frame)}mountViewer(A,Q,B,C,E={}){let J=this.plugins.get(A);if(!J)return E.onError?.("Plugin is not available"),null;let K=this.dock.docked;if(K&&K.record===J&&K.node?.id===B.id&&K.openerId===C)return this.dock.undock(K),this.dock.place(K,Q,3),E.onReady?.(),()=>this.#D(K);let L=this.platform.contributions.get(C),Y={cancelled:!1,frame:null};return this.#Q(J,"viewer",L?.entry).then(async(X)=>{if(Y.cancelled){this.frames.destroy(X);return}Y.frame=X,X.node=B,X.openerId=C,J.frames.add(X),this.dock.place(X,Q,3);try{if(await X.channel?.call("opener:open",{openerId:C,file:B,context:{}}),!Y.cancelled)E.onReady?.()}catch(H){if(!Y.cancelled)E.onError?.(H?.message||"Failed to open")}}).catch((X)=>{if(console.error("viewer frame failed to load",X),!Y.cancelled)E.onError?.(X?.message||"This viewer failed to load")}),J.hasUi=!0,()=>{if(Y.cancelled=!0,Y.frame)this.#D(Y.frame)}}#D(A){if(A.dock?.enabled&&!A.dock.dismissed)this.dock.dock(A);else this.frames.destroy(A)}async uninstall(A,{wipeData:Q=!0}={}){let B=this.plugins.get(A),C=B?.manifest?dA(B.manifest):A,E=B?.scope==="account"||(await this.registry.get(A).catch(()=>null))?.scope==="account";if(Q&&E)try{await this.platform.api.uninstallPluginServer(A)}catch(L){this.platform.notifications.error(`Couldn't uninstall "${C}" from the server: ${L.message}. It's still installed.`);return}if(B){try{B.channel?.emit("deactivate")}catch{}for(let L of B.disposers)try{L()}catch{}B._settingsDispose?.();for(let L of[...B.frames||[]])this.frames.destroy(L);if(B.frame)this.dock.stopPlace(B.frame),this.media.releaseActions(B.frame);B.channel?.dispose(),B.iframe?.remove(),this.plugins.delete(A)}let J=[];if(Q){if(!E)await this.platform.api.request("DELETE",`/api/plugins/${encodeURIComponent(A)}/data`).catch(()=>J.push("server-side data"));await this.clientDb.drop(`plg:${A}`).catch(()=>J.push("on-device data"))}let K=!1;try{await this.registry.remove(A)}catch(L){K=!0,console.error("removing the persisted plugin record failed",A,L)}if(![...this.plugins.values()].some((L)=>L.status==="active"))this.#$();if(this.#A(),K)this.platform.notifications.error(`Removed "${C}", but its saved record couldn't be deleted — it may come back when you reload.`);else if(J.length)this.platform.notifications.warn(`Uninstalled "${C}", but couldn't clear its ${J.join(" and ")}.`)}fetchAssetlinks=async(A)=>{return(await this.platform.api.request("GET","/api/plugins/assetlinks",{query:{domain:A}}))?.assetlinks||null};assessTrust(A){return hL(A,this.fetchAssetlinks)}}function W$(A){let Q=new Map;for(let[B,C]of Object.entries(A))Q.set(B,C instanceof Uint8Array?C:new Uint8Array(C));return Q}function U$(A){let Q={};for(let[B,C]of Object.entries(A||{}))Q[B]=C instanceof Uint8Array?C:new Uint8Array(C);return Q}function F$(A,Q){if(Q.includes("storage"))return!0;return T0(A).length>0}function n8(A){if(!A)return"";return`${A.online?1:0}|${[...A.handlers||[]].sort().join(",")}`}var s8=["auto","desktop","phone","tv"],I$=720,R$=1100,M$=/\b(smart-?tv|smarttv|appletv|googletv|android\s*tv|hbbtv|netcast|web0s|webos|tizen|viera|bravia|aquos|crkey|nettv|dtv|philipstv|roku|aft[a-z]{1,3})\b/i;function V$(A="",Q=0){if(!A)return!1;return M$.test(A)&&Q>=R$}class xJ{#A;constructor({window:A=globalThis,settings:Q=null}={}){this.window=A,this.settings=Q,this.urlOverride=N$(A),this.#A=this.#B(),this.cell=c(this.#A),this._onResize=()=>this.refresh()}get(){return this.#A}observe(){return this.cell}install(){if(this.window.addEventListener?.("resize",this._onResize),this.window.addEventListener?.("orientationchange",this._onResize),this.settings)TQ(this.settings.observe(),()=>this.refresh());return this.#Q(this.#A),this}dispose(){this.window.removeEventListener?.("resize",this._onResize),this.window.removeEventListener?.("orientationchange",this._onResize)}refresh(){let A=this.#B();if(A.mode===this.#A.mode&&A.width===this.#A.width&&A.height===this.#A.height&&A.coarse===this.#A.coarse)return;this.#A=A,this.#Q(A),this.cell.setValue(A)}#Q(A){let Q=this.window.document?.documentElement;if(Q)Q.dataset.layout=A.mode}#B(){let A=this.window,Q=A.innerWidth||1280,B=A.innerHeight||800,C=z$(A,"(pointer: coarse)"),E=A.navigator?.userAgent||"",J=this.urlOverride||this.settings?.get?.("workbench.layout")||"auto";return{mode:J!=="auto"&&s8.includes(J)?J:q$({width:Q,coarse:C,ua:E}),width:Q,height:B,coarse:C,forced:J!=="auto"}}}function q$({width:A,coarse:Q,ua:B}){if(V$(B,A))return"tv";if(A<=I$)return"phone";return"desktop"}function z$(A,Q){try{return!!A.matchMedia?.(Q)?.matches}catch{return!1}}function N$(A){try{let Q=new URL(A.location.href).searchParams.get("ui");return Q&&s8.includes(Q)?Q:null}catch{return null}}var r8='a[href], button:not([disabled]), input:not([disabled]), select, textarea, [tabindex]:not([tabindex="-1"])',t8=".launch-item, .grid-tile, .sheet-row, .inbox-item, .plugin-card, .act-task, .act-issue, .chapter",P$=`${r8}, ${t8}`,O$=new Set(["BrowserBack","GoBack","Backspace"]),j$=new Set([10009,461]),w$={ArrowLeft:"left",ArrowRight:"right",ArrowUp:"up",ArrowDown:"down"},S$=new Set(["A","BUTTON","INPUT","SELECT","TEXTAREA"]);class kJ{constructor({workbench:A,viewport:Q,window:B=globalThis}){this.viewport=Q,this.window=B,this.active=!1,this._onKey=(C)=>this.handleKey(C),this._observer=null,this._pending=0,this._bootstrapped=!1}install(){if(this.viewport)TQ(this.viewport.observe(),(A)=>this.setActive(A.mode==="tv"));return this.setActive(this.viewport?.get().mode==="tv"),this}setActive(A){if(A===this.active)return;if(this.active=A,A)this.window.addEventListener?.("keydown",this._onKey),this.#A(),this.prime(),this.window.setTimeout?.(()=>this.prime(),60);else this.window.removeEventListener?.("keydown",this._onKey),this._observer?.disconnect(),this._observer=null,this._bootstrapped=!1}prime(){this.candidates(),this.focusFirst()}#A(){let A=this.window.MutationObserver;if(!A||this._observer)return;this._observer=new A(()=>{if(this._pending)return;this._pending=this.window.requestAnimationFrame?.(()=>{if(this._pending=0,this.active)this.prime()})||0}),this._observer.observe(this.window.document.body,{childList:!0,subtree:!0})}handleKey(A){if(!this.active||A.defaultPrevented||A.altKey||A.ctrlKey||A.metaKey)return;let Q=this.window.document,B=Q.activeElement;if(O$.has(A.key)||j$.has(A.keyCode)){if(A.key==="Backspace"&&o8(B)&&(B.value??"").length>0)return;A.preventDefault(),this.goBack();return}let C=w$[A.key];if(!C){if(A.key==="Enter"&&B&&!S$.has(B.tagName)&&B.matches(t8))A.preventDefault(),B.click();return}if((C==="left"||C==="right")&&o8(B)&&!_$(B,C))return;let E=B&&B!==Q.body?B:null,J=this.find(C,E);if(!J)return;A.preventDefault(),i8(J)}goBack(){if(this.workbench?.closeOverlays())return;this.window.history?.back?.()}candidates(){let A=this.window.document,Q=[];for(let B of A.querySelectorAll(P$)){if(B.getAttribute?.("aria-hidden")==="true"||B.hasAttribute?.("disabled"))continue;let C=B.getBoundingClientRect();if(C.width<2||C.height<2)continue;if(C.bottom<0||C.top>this.window.innerHeight||C.right<0||C.left>this.window.innerWidth)continue;if(!B.matches(r8)&&!B.hasAttribute("tabindex"))B.setAttribute("tabindex","0");Q.push({el:B,rect:C})}return Q}find(A,Q){let B=this.candidates();if(!B.length)return null;let C=Q&&Q.getBoundingClientRect&&Q.getBoundingClientRect().width?Q.getBoundingClientRect():null;if(!C)return B[0].el;let E=null,J=1/0;for(let{el:K,rect:L}of B){if(K===Q)continue;let Y=T$(C,L,A);if(Y==null||Y>=J)continue;J=Y,E=K}return E}focusFirst(){if(this._bootstrapped)return;let A=this.window.document;if(A?.activeElement&&A.activeElement!==A.body)return;let Q=this.candidates();if(!Q.length)return;let B=Q.find((C)=>C.el.classList?.contains("launch-input"))||Q[0];i8(B.el),this._bootstrapped=!0}}function _$(A,Q){let{selectionStart:B,selectionEnd:C}=A;if(B==null||C==null)return!0;if(B!==C)return!1;return Q==="left"?B===0:C>=(A.value??"").length}function o8(A){if(!A)return!1;let Q=A.tagName;if(Q==="TEXTAREA")return!0;if(A.isContentEditable)return!0;if(Q!=="INPUT")return!1;return!["checkbox","radio","button","submit","range","file"].includes(A.type)}function i8(A){A.focus?.({preventScroll:!0}),A.scrollIntoView?.({block:"nearest",inline:"nearest"})}function T$(A,Q,B){let C=B==="up"||B==="down",[E,J]=C?B==="down"?[A.bottom,Q.top]:[A.top,Q.bottom]:B==="right"?[A.right,Q.left]:[A.left,Q.right],L=B==="down"||B==="right"?J-E:E-J;if(L<-2)return null;let[Y,X,H,G]=C?[A.left,A.right,Q.left,Q.right]:[A.top,A.bottom,Q.top,Q.bottom],D=Math.max(0,Math.max(Y,H)-Math.min(X,G)),U=Math.abs((Y+X)/2-(H+G)/2);return Math.max(0,L)+D*3+U*0.2}function DC(){if(typeof window>"u")return null;return window.SpeechRecognition||window.webkitSpeechRecognition||null}function G0(){let A=DC();return!!A&&typeof A.available==="function"}var gJ=(A)=>({langs:[A],processLocally:!0});async function e8(A=navigator.language||"en-US"){if(!G0())return"unavailable";try{return await DC().available(gJ(A))}catch{return"unavailable"}}async function AY(A=navigator.language||"en-US"){if(typeof DC()?.install!=="function")return!1;try{return await DC().install(gJ(A))}catch{return!1}}function QY({lang:A=navigator.language||"en-US",onText:Q,onEnd:B,onError:C}={}){if(!G0())throw Error("On-device speech recognition is not available here");let E=new(DC());E.lang=A,E.interimResults=!0,E.continuous=!1,E.options=gJ(A),E.processLocally=!0;let J=!1;E.onresult=(K)=>{let L="",Y=!1;for(let X=K.resultIndex;X<K.results.length;X++)if(L+=K.results[X][0].transcript,K.results[X].isFinal)Y=!0;Q?.(L.trim(),{final:Y})},E.onerror=(K)=>{if(K.error==="no-speech"||K.error==="aborted")return;C?.(Error(K.error||"Speech recognition failed"))},E.onend=()=>{if(!J)J=!0,B?.()};try{E.start()}catch(K){J=!0,C?.(K),B?.()}return{stop(){if(J)return;J=!0;try{E.stop()}catch{}B?.()}}}class yJ{#A;constructor({notifications:A,settings:Q}={}){this.notifications=A,this.settings=Q,this.session=null,this.#A={supported:G0(),status:"unknown",listening:!1},this.cell=c(this.#A)}get(){return this.#A}observe(){return this.cell}#Q(A){this.#A={...this.#A,...A},this.cell.setValue(this.#A)}async refresh(){if(!this.#A.supported)return"unavailable";let A=await e8(this.#B());return this.#Q({status:A}),A}#B(){return this.settings?.get?.("search.voiceLanguage")||navigator.language||"en-US"}canListen(){return this.#A.supported&&(this.#A.status==="available"||this.#A.status==="downloadable")}async run({onText:A}={}){if(this.openSearchSurface(),await this.focusInput(),!this.#A.supported)return{listening:!1,reason:"unsupported"};let Q=this.#A.status==="unknown"?await this.refresh():this.#A.status;if(Q==="downloadable"){this.notifications?.info("Downloading the on-device voice model — this happens once.");let B=await AY(this.#B());if(this.#Q({status:B?"available":"unavailable"}),!B)return{listening:!1,reason:"install-failed"}}else if(Q!=="available")return{listening:!1,reason:Q};return this.toggle({onText:A})}toggle({onText:A}={}){if(this.session)return this.stop(),{listening:!1};try{return this.session=QY({lang:this.#B(),onText:A,onEnd:()=>{this.session=null,this.#Q({listening:!1})},onError:(Q)=>{if(this.session=null,this.#Q({listening:!1}),!/not-allowed|service-not-allowed|denied/i.test(Q.message))this.notifications?.warn(`Couldn't listen: ${Q.message}`)}}),this.#Q({listening:!0}),{listening:!0}}catch(Q){return this.notifications?.warn(`Couldn't listen: ${Q.message}`),{listening:!1,reason:"error"}}}stop(){this.session?.stop(),this.session=null,this.#Q({listening:!1})}openSearchSurface(){let A=this.workbench;if(!A)return;if(A.state.activity==="home"&&!A.nav?.get?.().activeTabId)A.closeSearchModal?.();else A.openSearchModal()}focusInput({tries:A=12}={}){return new Promise((Q)=>{let B=A,C=()=>{let E=document.querySelector(".search-modal .launch-input")||document.querySelector(".launch-input");if(E){E.focus();try{E.setSelectionRange(E.value.length,E.value.length)}catch{}Q(document.activeElement===E);return}if(--B<=0){Q(!1);return}requestAnimationFrame(C)};C()})}}class hJ{constructor({api:A,settings:Q=null}){this.api=A,this.settings=Q,this.cache=new Map,this._queue=new Map,this._timer=null}get needed(){let A=this.settings?.get("media.signedUrls");if(A==="always")return!0;if(A==="never")return!1;return!!this.api.token?.()}cacheKey(A){return this.api.downloadUrl(A)}async url(A,{op:Q="media"}={}){if(!this.needed)return{url:this.api.downloadUrl(A,{attachment:Q==="download"}),expiresAt:1/0};let B=`${Q}:${A}`,C=this.cache.get(B);if(C&&this.#A(C))return C;return this.#Q(A,Q)}invalidate(A,Q="media"){if(A==null)this.cache.clear();else this.cache.delete(`${Q}:${A}`)}#A(A){if(A.expiresAt===1/0)return!0;let Q=A.expiresAt-A.mintedAt;return Date.now()<A.mintedAt+Q*0.8}#Q(A,Q){if(!this._queue.has(Q))this._queue.set(Q,new Map);let B=this._queue.get(Q),C=B.get(A);if(C)return C.promise;let E,J,K=new Promise((L,Y)=>{E=L,J=Y});if(B.set(A,{resolve:E,reject:J,promise:K}),B.size>=200)this.#B();else if(!this._timer)this._timer=setTimeout(()=>this.#B(),20);return K}async#B(){clearTimeout(this._timer),this._timer=null;let A=this._queue;this._queue=new Map;for(let[Q,B]of A){let C=[...B.keys()];try{let E=await this.api.mintUrls(C,Q),J=Date.now();for(let[K,L]of this.cache)if(L.expiresAt&&L.expiresAt<J)this.cache.delete(K);for(let[K,L]of B){let Y=E.urls?.[K];if(Y){let X={url:Y.url,expiresAt:Y.expiresAt,mintedAt:J};this.cache.set(`${Q}:${K}`,X),L.resolve(X)}else L.reject(Error(E.failed?.[K]==="not_found"?"That file is gone":"You cannot open that file"))}}catch(E){for(let J of B.values())J.reject(E)}}}}class vJ{constructor({api:A,actor:Q=()=>"local"}={}){this.api=A,this.actor=Q,this.local=x$(),this.pending=new Set,this.server=new Map,this.timer=null}async get(A,Q){let B={...this.server.get(bJ(A,Q))||{}};for(let[C,E]of Object.entries(this.local[A]?.[Q]||{}))if(E.present)B[C]=E.value;else delete B[C];return this.#B(A,Q),B}async set(A,Q,B,C){if(!B)return{ok:!1};return this.#A(A,Q,B,{value:C,present:!0}),{ok:!0}}async remove(A,Q,B){if(!B)return{ok:!1};return this.#A(A,Q,B,{value:null,present:!1}),{ok:!0}}#A(A,Q,B,C){this.local[A]||={},this.local[A][Q]||={},this.local[A][Q][B]={...C,at:Date.now(),actor:this.actor()},BY(this.local),this.pending.add(bJ(A,Q)),this.#Q()}#Q(){if(this.timer)return;this.timer=setTimeout(()=>{this.timer=null,this.flush().catch(()=>{})},2000)}async flush(){for(let A of[...this.pending]){let[Q,B]=A.split("\x00"),C=this.local[Q]?.[B];if(!C){this.pending.delete(A);continue}let E=Object.entries(C).map(([J,K])=>({key:J,value:K.value,remove:!K.present}));try{let J=await this.api.request("POST",`/api/items/${encodeURIComponent(B)}/data`,{query:{scope:Q},body:{entries:E}});this.pending.delete(A),this.server.set(A,J?.data||{}),delete this.local[Q][B],BY(this.local)}catch{}}}#B(A,Q){let B=bJ(A,Q);if(this.inflight?.has(B))return;(this.inflight||=new Set).add(B),this.api.request("GET",`/api/items/${encodeURIComponent(Q)}/data`,{query:{scope:A}}).then((C)=>{this.server.set(B,C?.data||{})}).catch(()=>{}).finally(()=>this.inflight.delete(B))}}var bJ=(A,Q)=>`${A}\x00${Q}`;function x$(){try{let A=JSON.parse(localStorage.getItem("trove.itemData"))||{};return A&&typeof A==="object"?A:{}}catch{return{}}}function BY(A){try{let Q=[];for(let[B,C]of Object.entries(A))for(let[E,J]of Object.entries(C))for(let[K,L]of Object.entries(J))Q.push({scope:B,nodeId:E,key:K,cell:L});if(Q.length>5000){Q.sort((B,C)=>(B.cell.at||0)-(C.cell.at||0));for(let{scope:B,nodeId:C,key:E}of Q.slice(0,Q.length-5000))delete A[B][C][E]}localStorage.setItem("trove.itemData",JSON.stringify(A))}catch{}}var CY=(A)=>Math.floor(A/4194304),k$=(A,Q)=>{let B=new Uint8Array(Q),C=0;for(let E of A)B.set(E,C),C+=E.length;return B};class fJ{constructor({api:A,mediaUrls:Q}){this.api=A,this.mediaUrls=Q,this.kept=new Map,this.listeners=new Set}onProgress(A){return this.listeners.add(A),()=>this.listeners.delete(A)}#A(A){let Q=this.status(A);for(let B of[...this.listeners])try{B(A,Q)}catch{}}#Q(A,Q,B){return`${this.mediaUrls.cacheKey(A)}&chunk=${Q||"none"}:4194304:${B}`}async#B(A){if(!("caches"in globalThis))return null;return caches.open(A).catch(()=>null)}async#C(A){let Q=await this.#B("trove-files-v1");if(!Q)return null;return Q.match(this.mediaUrls.cacheKey(A),{ignoreVary:!0}).catch(()=>null)}async read(A,{start:Q=0,end:B,signal:C}={}){let E=await this.#C(A);if(E){let K=await E.blob(),L=B==null?K.size:Math.min(B,K.size);return{bytes:new Uint8Array(await K.slice(Q,L).arrayBuffer()),etag:E.headers.get("etag"),total:K.size}}let J=this.kept.get(A);if(!J)return this.api.readRange(A,{start:Q,end:B,signal:C});return this.#E(A,J,Q,B,C)}async#E(A,Q,B,C,E){let J=await this.#B("trove-chunks-v1");if(!J)return this.api.readRange(A,{start:B,end:C,signal:E});if(Q.total==null){let X=await this.api.readRange(A,{start:0,end:1,signal:E});Q.total=X.total,Q.etag=X.etag}let K=Math.min(C==null?Q.total:C,Q.total);if(K<=B)return{bytes:new Uint8Array(0),etag:Q.etag,total:Q.total};let L=[],Y=0;for(let X=CY(B);X<=CY(K-1);X++){let H=await this.#J(A,Q,X,J,E),G=Math.max(0,B-X*4194304),D=Math.min(H.length,K-X*4194304),U=H.subarray(G,D);L.push(U),Y+=U.length}return{bytes:k$(L,Y),etag:Q.etag,total:Q.total}}async#J(A,Q,B,C,E){let J=this.#Q(A,Q.etag,B),K=await C.match(J).catch(()=>null);if(K)return Q.have.add(B),new Uint8Array(await K.arrayBuffer());let L=B*4194304,Y=Math.min(L+4194304,Q.total),X=await this.api.readRange(A,{start:L,end:Y,signal:E});if(X.etag&&Q.etag&&X.etag!==Q.etag)await this.#L(A),Q.have.clear(),Q.etag=X.etag,Q.total=X.total??Q.total;return await C.put(J,new Response(X.bytes)).catch(()=>{}),Q.have.add(B),this.#A(A),X.bytes}async start(A){if(this.kept.get(A))return this.status(A);let B=await this.api.readRange(A,{start:0,end:1}),C=new AbortController,E={etag:B.etag,total:B.total,filling:!0,done:!1,failed:null,have:new Set,controller:C};return this.kept.set(A,E),this.#A(A),this.#K(A,E,C.signal).catch((J)=>{E.filling=!1,E.failed=J?.message||String(J),this.#A(A)}),this.status(A)}async#K(A,Q,B){let C=await this.#B("trove-chunks-v1");if(!C)throw Error("This browser has no Cache Storage, so nothing can be kept offline");let E=Math.max(1,Math.ceil((Q.total||0)/4194304));for(let J=0;J<E;J++){if(B.aborted)return;await this.#J(A,Q,J,C,B)}Q.filling=!1,Q.done=!0,this.#A(A)}status(A){let Q=this.kept.get(A);if(!Q)return{kept:!1,loaded:0,total:null,ratio:0,filling:!1,done:!1,error:null};let B=Q.total??null,C=B?Math.ceil(B/4194304)-1:-1,E=0;for(let J of Q.have)E+=J===C?B-C*4194304:4194304;return{kept:!0,total:B,loaded:E,ratio:B?Math.min(1,E/B):0,filling:Q.filling,done:Q.done,error:Q.failed}}cancel(A){let Q=this.kept.get(A);if(!Q)return;Q.controller?.abort(),Q.filling=!1,this.#A(A)}async remove(A){let Q=this.kept.get(A);this.cancel(A),this.kept.delete(A),Q?.have?.clear(),await this.#L(A),this.#A(A)}async#L(A){let Q=await this.#B("trove-chunks-v1");if(!Q)return;let B=`${this.mediaUrls.cacheKey(A)}&chunk=`,C=await Q.keys().catch(()=>[]);for(let E of C)if(E.url.startsWith(B))await Q.delete(E).catch(()=>{})}}function g$(){try{return localStorage.getItem("trove.token")||null}catch{return null}}function EY({baseUrl:A=""}={}){let Q=new x0,B=new g0,C=new u0,E=new y0(Q,B,C),J=new f0,K=new UB(Q,E,B,J),L=new m0({baseUrl:A,token:()=>g$()}),Y=new xJ({settings:J}),X=new kJ({viewport:Y}),H=new yJ({notifications:C,settings:J}),G={reactive:tK,contributions:Q,context:B,commands:E,keybindings:K,settings:J,notifications:C,api:L,viewport:Y,spatialNav:X,voice:H};return G.mediaUrls=new hJ({api:G.api,settings:J}),G.fileChunks=new fJ({api:G.api,mediaUrls:G.mediaUrls}),G.itemData=new vJ({api:G.api,actor:()=>G.identity?.get?.()?.principal?.id||"local"}),G.plugins=new TJ(G),E.availability=(D)=>G.plugins.isAvailable(D),y$(G),Y.refresh(),G}function y$(A){A.settings.register([{key:"workbench.theme",type:"enum",enum:["dark","light","midnight"],enumLabels:["Dark","Light","Midnight"],default:"dark",title:"Color theme",category:"Appearance",order:1},{key:"workbench.density",type:"enum",enum:["comfortable","compact"],default:"comfortable",title:"List density",category:"Appearance",order:2},{key:"workbench.layout",type:"enum",enum:["auto","desktop","phone","tv"],enumLabels:["Automatic","Desktop","Phone","TV / remote"],default:"auto",title:"Layout",description:"Automatic follows the screen size. Choose TV for d-pad remote navigation.",category:"Appearance",order:3},{key:"explorer.sort",type:"enum",enum:["name","size","updatedAt"],enumLabels:["Name","Size","Modified"],default:"name",title:"Sort files by",category:"Explorer",order:1},{key:"explorer.sortOrder",type:"enum",enum:["asc","desc"],default:"asc",title:"Sort order",category:"Explorer",order:2},{key:"explorer.confirmDelete",type:"boolean",default:!0,title:"Confirm before deleting",category:"Explorer",order:3},{key:"search.mode",type:"enum",enum:["hybrid","semantic","keyword"],default:"hybrid",title:"Search mode",description:"Hybrid blends semantic meaning with keyword matches.",category:"Search",order:1},{key:"uploads.concurrency",type:"number",minimum:1,maximum:8,default:4,title:"Parallel upload parts",category:"Transfers",order:1},{key:"openers.associations",type:"object",hidden:!0,title:"Default viewers",default:{".md":"core.markdown",".markdown":"core.markdown"}},{key:"explorer.view",type:"string",hidden:!0,title:"Results view"},{key:"media.signedUrls",type:"enum",enum:["auto","always","never"],default:"auto",hidden:!0,title:"Signed media URLs"}]),A.contributions.register("keymap.default",{type:"keymap",bindings:[{key:"mod+shift+p",command:"workbench.showCommandPalette"},{key:"mod+p",command:"workbench.quickOpen"},{key:"mod+shift+f",command:"workbench.view.home"},{key:"mod+shift+e",command:"workbench.view.home"},{key:"mod+,",command:"workbench.openSettings"},{key:"mod+shift+l",command:"explorer.copyLink"},{key:"mod+u",command:"explorer.upload"},{key:"delete",command:"explorer.delete",when:"view.active == 'home' && explorer.hasSelection"},{key:"escape",command:"workbench.closeOverlays"},{key:"f5",command:"explorer.refresh"},{key:"mod+shift+i",command:"workbench.toggleInfoPanel"},{key:"mod+shift+v",command:"search.voice"},{key:"browsersearch",command:"search.voice"}]})}function JY(A,{workbench:Q,overlay:B,navigation:C,explorer:E}){let J=Q.observe(),K=C.observe(),L=B.observe(),Y=E.observe(),X={"view.active":BA([J],(G)=>G.activity),"sidebar.visible":BA([J],(G)=>G.sidebarVisible),"searchModal.open":BA([J],(G)=>!!G.searchModal),"sheet.open":BA([J],(G)=>G.sheet||""),"infoPanel.open":BA([J],(G)=>!!G.infoPanel),"palette.open":BA([L],(G)=>!!G.palette),"editor.open":BA([K],(G)=>!!G.activeFile),"editor.openerId":BA([K],(G)=>G.stack?.at(-1)?.openerId||""),"editor.contentType":BA([K],(G)=>G.activeFile?.contentType||""),"explorer.collectionId":BA([Y],(G)=>G.collectionId??null),"explorer.hasSelection":BA([Y],(G)=>(G.selection?.length||0)>0)},H=Object.entries(X).map(([G,D])=>A.register(G,D));return()=>H.forEach((G)=>G())}function KY(A,Q){let B=Q.observe(),C=[A.register("viewport.mode",BA([B],(E)=>E.mode)),A.register("viewport.phone",BA([B],(E)=>E.mode==="phone")),A.register("viewport.tv",BA([B],(E)=>E.mode==="tv"))];return()=>C.forEach((E)=>E())}var LY="trove.recents",h$=12;class mJ{#A;constructor(){this.#A={stack:[{kind:"search"}],activeTabId:null,activeFile:null,recents:b$()},this.cell=c(this.#A)}get(){return this.#A}observe(){return this.cell}#Q(A){this.#A={...this.#A,...A},this.cell.setValue(this.#A)}#B(){return this.#A.stack[this.#A.stack.length-1]}activeTab(){let A=this.#B();return A?.kind==="file"?A:null}#C(A,{history:Q=!0}={}){let B=A[A.length-1],C=B&&B.kind==="file"?B:null;if(this.#Q({stack:A,activeTabId:C?C.id:null,activeFile:C?C.node:null}),Q)this.#E()}reset(){this.#C([{kind:"search"}])}openFile(A,Q,{reset:B=!1}={}){let C={kind:"file",id:A.id,node:A,openerId:Q},E;if(B)E=[{kind:"search"},C];else{let J=this.#A.stack.findIndex((K)=>K.kind==="file"&&K.id===A.id);if(J>=0)E=this.#A.stack.slice(0,J+1),E[J]=C;else E=[...this.#A.stack,C]}this.#J(A),this.#C(E)}back(){if(this.#A.stack.length<=1)return;try{history.back()}catch{this.pop()}}pop(){if(this.#A.stack.length>1)this.#C(this.#A.stack.slice(0,-1),{history:!1})}forget(A){let Q=this.#A.recents.filter((C)=>C.id!==A);if(Q.length!==this.#A.recents.length)this.#Q({recents:Q}),uJ(Q);let B=this.#A.stack.filter((C)=>!(C.kind==="file"&&C.id===A));this.#C(B.length?B:[{kind:"search"}],{history:!1})}updateTabNode(A){let Q=this.#A.recents.map((C)=>C.id===A.id?{...C,name:A.name,contentType:A.contentType||C.contentType,...RB(A)?{thumbnail:RB(A)}:{}}:C);if(Q.some((C,E)=>C!==this.#A.recents[E]))this.#Q({recents:Q}),uJ(Q);let B=this.#A.stack.map((C)=>C.kind==="file"&&C.id===A.id?{...C,node:A}:C);this.#C(B,{history:!1})}#E(A=!1){let Q=this.#B(),B=Q?.node,C={troveDepth:this.#A.stack.length,node:B?{id:B.id,name:B.name,contentType:B.contentType,collectionId:B.collectionId}:null,openerId:Q?.openerId||null};try{(A?history.replaceState:history.pushState).call(history,C,"")}catch{}}onPopState(A){let Q=A?.state||{},B=Q.troveDepth||1;if(B<=this.#A.stack.length)this.#C(this.#A.stack.slice(0,B),{history:!1});else if(Q.node)this.#C([...this.#A.stack,{kind:"file",id:Q.node.id,node:Q.node,openerId:Q.openerId}],{history:!1})}#J(A){if(!A)return;let Q=RB(A),C=[{id:A.id,name:A.name,contentType:A.contentType||"",collectionId:A.collectionId,...Q?{thumbnail:Q}:{}},...this.#A.recents.filter((E)=>E.id!==A.id)].slice(0,h$);this.#Q({recents:C}),uJ(C)}}function b$(){try{return JSON.parse(localStorage.getItem(LY))||[]}catch{return[]}}function uJ(A){try{localStorage.setItem(LY,JSON.stringify(A))}catch{}}class pJ{#A;constructor(A,Q=null){this.offline=Q,this.platform=A,this.api=A.api,this.#A={me:null,notifications:{items:[],unread:0},inboxOpen:!1,pushSupported:"serviceWorker"in navigator&&"PushManager"in window,pushEnabled:!1,sidecar:null,backlinks:null,posting:!1,replyTo:null},this.cell=c(this.#A),this._pollTimer=null}get(){return this.#A}observe(){return this.cell}#Q(A){this.#A={...this.#A,...A},this.cell.setValue(this.#A)}async init(){try{let A=await this.api.me();this.#Q({me:A.principal,admin:!!A.admin})}catch{}if(await this.refreshNotifications(),this._pollTimer=setInterval(()=>this.refreshNotifications(),45000),this._pollTimer.unref)this._pollTimer.unref();this.#C(),window.addEventListener("focus",()=>this.refreshNotifications()),navigator.serviceWorker?.addEventListener?.("message",(A)=>{if(A.data?.type==="trove-push")this.refreshNotifications()})}async refreshNotifications(){try{let A=await this.api.notifications();this.#Q({notifications:A})}catch{}}toggleInbox(A){let Q=A??!this.#A.inboxOpen;if(this.#Q({inboxOpen:Q}),Q&&this.#A.notifications.unread)this.markAllRead()}async markAllRead(){try{await this.api.markNotificationsRead(),this.#Q({notifications:{...this.#A.notifications,unread:0,items:this.#A.notifications.items.map((A)=>({...A,read:!0}))}})}catch{}}async loadSidecar(A){if(!A)return this.#Q({sidecar:null,backlinks:null});this.#Q({sidecar:{nodeId:A,loading:!0,tags:[],comments:[],subscribers:[]}}),this.loadBacklinks(A);try{let Q=await this.api.sidecar(A);if(this.#A.sidecar?.nodeId!==A)return;this.#Q({sidecar:{...Q,loading:!1}})}catch(Q){if(this.#A.sidecar?.nodeId!==A)return;this.#Q({sidecar:{nodeId:A,loading:!1,error:Q.message,tags:[],comments:[]}})}}async loadBacklinks(A){if(!A)return this.#Q({backlinks:null});this.#Q({backlinks:{nodeId:A,items:[],loading:!0,error:null}});try{let Q=await this.api.backlinks(A);if(this.#A.backlinks?.nodeId!==A)return;this.#Q({backlinks:{nodeId:A,items:Q.items||[],loading:!1,error:null}})}catch(Q){if(this.#A.backlinks?.nodeId!==A)return;this.#Q({backlinks:{nodeId:A,items:[],loading:!1,error:Q.message}})}}async#B(){if(this.#A.sidecar?.nodeId)await this.loadSidecar(this.#A.sidecar.nodeId)}setReplyTo(A){this.#Q({replyTo:A})}async comment(A){let Q=this.#A.sidecar?.nodeId;if(!Q||!A.trim())return;let B=this.#A.replyTo?.id||null;if(this.offline&&!this.offline.get().online){await this.offline.queueOp({method:"POST",path:`/api/items/${encodeURIComponent(Q)}/comments`,body:{body:A,parentId:B}}),this.#Q({replyTo:null}),this.platform.notifications.info("Offline — your comment will post when you reconnect.");return}this.#Q({posting:!0});try{await this.api.addComment(Q,{body:A,parentId:B}),this.#Q({replyTo:null}),await this.#B()}catch(C){this.platform.notifications.error(`Couldn't post comment: ${C.message}`)}finally{this.#Q({posting:!1})}}async deleteComment(A){let Q=this.#A.sidecar?.nodeId;await this.api.deleteComment(Q,A).catch((B)=>this.platform.notifications.error(B.message)),await this.#B()}async react(A,Q){let B=this.#A.sidecar?.nodeId,E=!(YY(this.#A.sidecar?.comments||[],A)?.reactions?.[Q]||[]).includes(this.#A.me?.id);try{await this.api.reactComment(B,A,Q,E)}catch(J){this.platform.notifications.error(`Couldn't react: ${J.message}`)}await this.#B()}async addTag(A,Q){let B=this.#A.sidecar?.nodeId;if(!A.trim())return;if(this.offline&&!this.offline.get().online){await this.offline.queueOp({method:"POST",path:`/api/items/${encodeURIComponent(B)}/tags`,body:{name:A.trim(),value:Q}}),this.platform.notifications.info("Offline — tag will sync when you reconnect.");return}await this.api.setTag(B,A.trim(),Q).catch((C)=>this.platform.notifications.error(C.message)),await this.#B()}async removeTag(A){let Q=this.#A.sidecar?.nodeId;if(this.offline&&!this.offline.get().online){await this.offline.queueOp({method:"DELETE",path:`/api/items/${encodeURIComponent(Q)}/tags/${encodeURIComponent(A)}`}),this.platform.notifications.info("Offline — tag removal will sync when you reconnect.");return}try{await this.api.removeTag(Q,A)}catch(B){this.platform.notifications.error(`Couldn't remove tag: ${B.message}`)}await this.#B()}async#C(){if(!this.#A.pushSupported)return;try{let Q=await(await navigator.serviceWorker.getRegistration())?.pushManager?.getSubscription();this.#Q({pushEnabled:!!Q})}catch{}}async enablePush(){if(!this.#A.pushSupported){this.platform.notifications.warn("Push notifications are not supported in this browser.");return}try{let{publicKey:A}=await this.api.vapidKey();if(!A){this.platform.notifications.warn("This server has no VAPID key configured for web push.");return}let Q=await navigator.serviceWorker.register("/sw.js");if(await navigator.serviceWorker.ready,await Notification.requestPermission()!=="granted")return this.platform.notifications.info("Notifications permission was denied.");let C=await Q.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:v$(A)});await this.api.subscribePush(C.toJSON()),this.#Q({pushEnabled:!0}),this.platform.notifications.success("Notifications enabled — you’ll be pinged when someone @mentions you.")}catch(A){this.platform.notifications.error(`Couldn't enable notifications: ${A.message}`)}}}function YY(A,Q){for(let B of A){if(B.id===Q)return B;let C=YY(B.replies||[],Q);if(C)return C}return null}function v$(A){let Q="=".repeat((4-A.length%4)%4),B=(A+Q).replace(/-/g,"+").replace(/_/g,"/"),C=atob(B),E=new Uint8Array(C.length);for(let J=0;J<C.length;J++)E[J]=C.charCodeAt(J);return E}class lJ{get dimensions(){return 0}async embed(A){throw z.unsupported("embed not implemented")}async embedOne(A){return(await this.embed([A]))[0]}}var f$=new Set("a an the of to in on for and or is are be as at by with from this that it".split(" "));function u$(A){return String(A).toLowerCase().replace(/[^a-z0-9\s]/g," ").split(/\s+/).filter((Q)=>Q.length>1&&!f$.has(Q))}function m$(A){let Q=2166136261;for(let B=0;B<A.length;B++)Q^=A.charCodeAt(B),Q=Math.imul(Q,16777619);return Q>>>0}class cJ extends lJ{constructor({dimensions:A=256}={}){super();this._dim=A}get dimensions(){return this._dim}async embed(A){return A.map((Q)=>this.#A(Q))}#A(A){let Q=new Float64Array(this._dim),B=u$(A),C=[...B];for(let J=0;J<B.length-1;J++)C.push(B[J]+"_"+B[J+1]);for(let J of C){let K=m$(J),L=K%this._dim,Y=K>>31&1?-1:1;Q[L]+=Y}let E=0;for(let J=0;J<Q.length;J++)E+=Q[J]*Q[J];return E=Math.sqrt(E)||1,Array.from(Q,(J)=>J/E)}}class p$ extends lJ{constructor(A){super();if(!A?.url||!A?.dimensions)throw z.invalid("HttpEmbedding requires url and dimensions");this.cfg=A}get dimensions(){return this.cfg.dimensions}async embed(A){let Q=this.cfg.batchSize??64,B=[];for(let C=0;C<A.length;C+=Q){let E=A.slice(C,C+Q);B.push(...await this.#A(E))}return B}async#A(A){return FB(async()=>{let Q;try{Q=await fetch(this.cfg.url,{method:"POST",headers:{"content-type":"application/json",...this.cfg.apiKey?{authorization:`Bearer ${this.cfg.apiKey}`}:{}},body:JSON.stringify({model:this.cfg.model,input:A})})}catch(E){throw uB(E)}if(Q.status===429||Q.status>=500)throw z.transient(`Embedding endpoint ${Q.status}`);if(!Q.ok)throw z.internal(`Embedding endpoint failed: ${Q.status}`);let B=await Q.json();return(B.data??B.embeddings??[]).map((E)=>E.embedding??E)})}}function XY(A,Q,B){let C=[],E=0;while(E<A.length){let J=Math.min(E+Q,A.length);if(J<A.length){let K=A.slice(E,J),L=Math.max(K.lastIndexOf(`
|
|
731
|
-
|
|
732
|
-
`),K.lastIndexOf(". "),K.lastIndexOf(`
|
|
733
|
-
`));if(L>Q*0.75)J=E+L+1}if(C.push(A.slice(E,J).trim()),J>=A.length)break;E=J-B}return C.filter(Boolean)}var l$=new Set("a an the of to in on for and or is are be as at by with from this that it".split(" "));function dJ(A){return String(A).toLowerCase().replace(/[^a-z0-9\s]/g," ").split(/\s+/).filter((Q)=>Q.length>1&&!l$.has(Q))}var c$="trove-offline",GY="trove-files-v1",aJ=new cJ({dimensions:256});class oJ{#A;constructor(A){this.platform=A,this.api=A.api,this.db=null,this.#A={online:navigator.onLine,pins:[],queued:0,syncing:!1},this.cell=c(this.#A)}get(){return this.#A}observe(){return this.cell}#Q(A){this.#A={...this.#A,...A},this.cell.setValue(this.#A)}async init(){if(this.db=await d$(),await this.#E(),await this.#J(),window.addEventListener("online",()=>this.#B()),window.addEventListener("offline",()=>this.#C()),this.#A.online&&!await this.api.reachable())this.#Q({online:!1});if(this.platform.plugins?.setOnline?.(this.#A.online),this.#A.online)this.flushQueue()}async#B(){if(!await this.api.reachable()){this.#Q({online:!1}),await this.platform.plugins?.setOnline?.(!1);return}this.#Q({online:!0}),await this.platform.plugins?.setOnline?.(!0),await this.flushQueue()}async#C(){this.#Q({online:!1}),await this.platform.plugins?.setOnline?.(!1)}async pin(A){if(!A?.id)return;try{if("caches"in window){let E=await caches.open(GY),J=this.platform.mediaUrls,K=J.cacheKey(A.id),{url:L}=await J.url(A.id,{op:"download"}),Y=await fetch(L);if(!Y.ok)throw Error(`Couldn't fetch the file (${Y.status})`);await E.put(new Request(K),Y)}let Q=[],B="";if(C8(A))try{B=await this.api.readText(A.id);let E=XY(B,1000,150),J=await aJ.embed(E.length?E:[A.name]);Q=(E.length?E:[A.name]).map((K,L)=>({text:K,vector:J[L]}))}catch{}let C=(await aJ.embed([A.name]))[0];await n$(this.db,"pins",A.id,{node:A,text:B,chunks:Q,nameVec:C,pinnedAt:Date.now()}),await this.#E(),this.platform.notifications.success(`“${A.name}” is available offline`)}catch(Q){this.platform.notifications.error(`Couldn't make available offline: ${Q.message}`)}}async unpin(A){if(this.#A.pins.find((B)=>B.id===A)&&"caches"in window)await(await caches.open(GY)).delete(this.platform.mediaUrls.cacheKey(A),{ignoreVary:!0}).catch(()=>{});await nJ(this.db,"pins",A),await this.#E()}async#E(){let A=await sJ(this.db,"pins");this.#Q({pins:A.map((Q)=>({id:Q.node.id,name:Q.node.name,contentType:Q.node.contentType,collectionId:Q.node.collectionId,pinnedAt:Q.pinnedAt}))})}async searchOffline(A,{limit:Q=40}={}){let B=await sJ(this.db,"pins");if(!B.length)return[];let C=dJ(A),E=(await aJ.embed([A]))[0],J=[];for(let K of B){let L=dJ(`${K.node.name} ${K.text||""}`),Y=i$(C,new Set(L)),X=HY(E,K.nameVec);for(let G of K.chunks||[])X=Math.max(X,HY(E,G.vector));let H=0.6*X+0.4*Y;if(H>0.02)J.push({nodeId:K.node.id,node:K.node,score:H,snippet:r$(K.text,C),indexerId:"offline"})}return J.sort((K,L)=>L.score-K.score).slice(0,Q)}async queueOp(A){await s$(this.db,"queue",{...A,at:Date.now()}),await this.#J()}async#J(){let A=await sJ(this.db,"queue");this.#Q({queued:A.length})}async flushQueue(){if(!this.#A.online||this.#A.syncing)return;this.#Q({syncing:!0});let A=0,Q=0;try{let B=await o$(this.db,"queue");for(let{key:C,value:E}of B)try{await this.api.request(E.method,E.path,{body:E.body}),await nJ(this.db,"queue",C),A++}catch(J){if(["transient","timeout","unauthorized","quota"].includes(J.code))break;await nJ(this.db,"queue",C),Q++}}finally{if(await this.#J(),this.#Q({syncing:!1}),Q)this.platform.notifications.warn(`${Q} offline change${Q>1?"s":""} couldn't be applied and ${Q>1?"were":"was"} discarded.`);if(A&&this.#A.queued===0)this.platform.notifications.info(`${A} offline change${A>1?"s":""} synced.`)}}}function d$(){return new Promise((A,Q)=>{let B=indexedDB.open(c$,1);B.onupgradeneeded=()=>{let C=B.result;if(!C.objectStoreNames.contains("pins"))C.createObjectStore("pins");if(!C.objectStoreNames.contains("queue"))C.createObjectStore("queue",{autoIncrement:!0})},B.onsuccess=()=>A(B.result),B.onerror=()=>Q(B.error)})}function ZC(A,Q,B,C){return new Promise((E,J)=>{let K=A.transaction(Q,B),L=K.objectStore(Q),Y;Promise.resolve(C(L)).then((X)=>Y=X),K.oncomplete=()=>E(Y),K.onerror=()=>J(K.error)})}var a$=(A)=>new Promise((Q,B)=>{A.onsuccess=()=>Q(A.result),A.onerror=()=>B(A.error)}),n$=(A,Q,B,C)=>ZC(A,Q,"readwrite",(E)=>E.put(C,B)),s$=(A,Q,B)=>ZC(A,Q,"readwrite",(C)=>C.add(B)),nJ=(A,Q,B)=>ZC(A,Q,"readwrite",(C)=>C.delete(B)),sJ=(A,Q)=>ZC(A,Q,"readonly",(B)=>a$(B.getAll()));function o$(A,Q){return ZC(A,Q,"readonly",(B)=>new Promise((C,E)=>{let J=[],K=B.openCursor();K.onsuccess=()=>{let L=K.result;if(!L)return C(J);J.push({key:L.key,value:L.value}),L.continue()},K.onerror=()=>E(K.error)}))}function i$(A,Q){if(!A.length||!Q.size)return 0;let B=0;for(let C of A)if(Q.has(C))B++;return B/A.length}function HY(A,Q){if(!A||!Q)return 0;let B=0;for(let C=0;C<A.length;C++)B+=A[C]*Q[C];return B}function r$(A,Q){if(!A)return null;let B=A.toLowerCase(),C=-1;for(let J of Q){let K=B.indexOf(J);if(K>=0){C=K;break}}if(C<0)return A.slice(0,160).trim();let E=Math.max(0,C-60);return(E>0?"…":"")+A.slice(E,E+200).trim()+"…"}var t$=1000,e$=60000;class iJ{#A;constructor(A){this.platform=A,this.api=A.api,this.#A={tasks:[],issues:[],issuesLoading:!1,tasksError:null,issuesError:null},this.cell=c(this.#A),this._local=new Map,this._server=[],this._timer=null,this._pollMs=null}get(){return this.#A}observe(){return this.cell}#Q(A){this.#A={...this.#A,...A},this.cell.setValue(this.#A)}#B(){this.#Q({tasks:[...this._local.values(),...this._server]})}start(A={}){let Q=A.id||`local_${Math.random().toString(36).slice(2,10)}`,B={id:Q,source:"local",kind:A.kind||"general",title:A.title||"Working",detail:A.detail??null,status:"running",done:0,total:A.total??null,unit:A.unit||null,cancellable:!!A.onCancel,startedAt:Date.now(),endedAt:null,error:null};if(this._local.set(Q,B),this._cancels||=new Map,A.onCancel)this._cancels.set(Q,A.onCancel);this.#B(),this.#E();let C=(E)=>{let J=this._local.get(Q);if(!J||J.status!=="running")return;this._local.set(Q,{...J,...E}),this.#B()};return{id:Q,progress:(E={})=>C({done:E.done??this._local.get(Q)?.done??0,total:E.total===void 0?this._local.get(Q)?.total:E.total,unit:E.unit??this._local.get(Q)?.unit,detail:E.detail??this._local.get(Q)?.detail}),succeed:(E)=>{C({status:"done",endedAt:Date.now(),detail:E??this._local.get(Q)?.detail}),this.#C(Q)},fail:(E)=>{C({status:"failed",endedAt:Date.now(),error:E?.message||String(E||"failed")})},cancel:()=>{C({status:"cancelled",endedAt:Date.now()}),this.#C(Q)}}}#C(A,Q=5000){setTimeout(()=>{this._local.delete(A),this._cancels?.delete(A),this.#B()},Q)}async cancel(A){if(this._local.get(A)){this._cancels?.get(A)?.();return}try{await this.api.cancelTask(A),await this.refreshTasks()}catch(B){this.#Q({tasksError:B.message})}}dismiss(A){if(this._local.delete(A)){this.#B();return}this.api.dismissTask(A).catch(()=>{}),this._server=this._server.filter((Q)=>Q.id!==A),this.#B()}async init(){await this.refresh(),this.#E(),window.addEventListener("focus",()=>this.refresh())}async refresh(){await Promise.all([this.refreshTasks(),this.refreshIssues()])}async refreshTasks(){let A=this.running.length>0;try{let{tasks:Q}=await this.api.tasks();this._server=(Q||[]).map((B)=>({...B,source:"server"})),this.#Q({tasksError:null}),this.#B()}catch(Q){this._server=[],this.#Q({tasksError:Q.message}),this.#B()}if(A&&!this.running.length)this.refreshIssues();this.#E()}async refreshIssues(){this.#Q({issuesLoading:!0});try{let{issues:A}=await this.api.issues();this.#Q({issues:A||[],issuesLoading:!1,issuesError:null})}catch(A){this.#Q({issuesLoading:!1,issuesError:A.message})}}async retryIssue(A){try{await this.api.retryIssue(A),await this.refreshTasks(),this.followUp(),this.platform.notifications.info("Retrying — watch its progress in Activity")}catch(Q){this.platform.notifications.error(`Couldn't retry: ${Q.message}`)}}async dismissIssue(A){let Q=this.#A.issues;this.#Q({issues:Q.filter((B)=>B.id!==A)});try{await this.api.dismissIssue(A)}catch(B){this.#Q({issues:Q}),this.platform.notifications.error(`Couldn't dismiss: ${B.message}`)}}followUp(){for(let A of[400,1500])setTimeout(()=>{this.refreshTasks(),this.refreshIssues()},A)?.unref?.()}get running(){return this.#A.tasks.filter((A)=>A.status==="running")}#E(){let A=this.running.length?t$:e$;if(this._timer&&this._pollMs===A)return;clearTimeout(this._timer),this._pollMs=A,this._timer=setTimeout(()=>{this._timer=null,this.refreshTasks().then(()=>{if(!this.running.length)this.refreshIssues()})},A),this._timer?.unref?.()}dispose(){clearTimeout(this._timer),this._timer=null}}var OB="explorer.hasSelection || editor.open";function $Y(A){let Q=(B,C,E,J={})=>A.platform.commands.register({id:B,title:C,actions:E,...J});Q("workbench.showCommandPalette","Show All Commands",()=>new J0("commands"),{category:"View",icon:"command"}),Q("workbench.quickOpen","Go to File…",()=>new J0("files"),{category:"File",icon:"search"}),Q("workbench.view.home","Go Home (search & browse)",()=>new vQ,{category:"View",icon:"search"}),Q("workbench.view.plugins","Show Plugins",()=>new $C("plugins"),{category:"View"}),Q("workbench.view.admin","Show Administration",()=>new $C("admin"),{category:"View",icon:"gear"}),Q("workbench.openSettings","Open Settings",()=>new $C("settings"),{category:"Preferences",icon:"gear"}),Q("workbench.closeOverlays","Close",()=>new AJ,{palette:!1}),Q("search.voice","Search by Voice",()=>new QJ,{category:"View",icon:"search"}),Q("workbench.showActivity","Show Activity (running work & problems)",()=>new wA(!0),{category:"View",icon:"refresh"}),Q("workbench.rebuildIndex","Rebuild Search Index",()=>new BJ,{category:"View",icon:"refresh"}),Q("workbench.scanCollection","Scan Collection for Outside Changes",()=>new CJ,{category:"Explorer",icon:"refresh"}),Q("workbench.checkStorage","Check Storage Configuration",()=>new EJ,{category:"View",icon:"plug"}),Q("explorer.refresh","Refresh",()=>new tB,{category:"Explorer",icon:"refresh"}),Q("explorer.loadMore","Show More Items",()=>new VE,{palette:!1}),Q("explorer.upload","Upload Files…",()=>new JJ,{category:"Explorer",icon:"upload"}),Q("explorer.copyShareLink","Copy Shareable Link",(B)=>new K0("share",B),{category:"Explorer",icon:"link",when:OB}),Q("explorer.copyLink","Copy Link to Item",(B)=>new K0("trove",B),{category:"Explorer",icon:"link",when:OB}),Q("explorer.rename","Rename",(B)=>new KJ(B),{category:"Explorer",when:OB}),Q("explorer.delete","Delete",()=>new LJ,{category:"Explorer",icon:"trash",when:OB}),Q("explorer.open","Open",(B)=>new XJ(B),{palette:!1}),Q("explorer.download","Download",(B)=>new GJ(B),{category:"Explorer",icon:"download",when:OB}),Q("explorer.showTrash","Show Trash",()=>new YJ,{category:"Explorer",icon:"trash"}),Q("explorer.hideTrash","Hide Trash",()=>new eQ("hide"),{palette:!1}),Q("explorer.restore","Restore from Trash",(B)=>B?new eQ("restore",B):null,{palette:!1}),Q("explorer.purgeOne","Delete Forever",(B)=>B?new eQ("purge",B):null,{palette:!1}),Q("explorer.emptyTrash","Empty Trash",()=>new sA({kind:"confirm",title:"Empty the trash?",body:"Everything in the trash will be destroyed. This cannot be undone.",danger:!0,confirmLabel:"Delete forever",confirmActions:[new eQ("empty")]}),{category:"Explorer",icon:"trash"}),Q("keys.load","Load API Keys",()=>new AC,{palette:!1}),Q("keys.new","New API Key",()=>new HJ,{palette:!1}),Q("keys.cancel","Cancel API Key",()=>new $J,{palette:!1}),Q("keys.dismissMinted","Dismiss API Key",()=>new DJ,{palette:!1}),Q("keys.revoke","Revoke API Key",(B)=>B?new zE(B):null,{palette:!1}),Q("keys.mint","Create API Key",()=>new ZJ,{palette:!1}),Q("offline.pin","Make Available Offline",(B)=>new L0(B,!0),{category:"Offline",icon:"download",when:OB}),Q("offline.unpin","Remove from Offline",(B)=>new L0(B,!1),{palette:!1}),Q("collections.switch","Switch Collection…",(B)=>new WJ(B),{category:"Collections",icon:"files"}),Q("collections.create","New Collection…",()=>new sA({kind:"collection",title:"New collection"}),{category:"Collections",icon:"files"}),Q("workbench.toggleInfoPanel","Toggle Details & Conversation",()=>new UJ,{category:"View",icon:"info"}),Q("notifications.show","Show Notifications",()=>new qQ(!0),{category:"View"}),Q("notifications.enablePush","Enable Push Notifications",()=>new YC,{category:"Notifications"}),Q("plugins.installFromUrl","Install Plugin from URL…",()=>new sA({kind:"prompt",title:"Install plugin from URL",label:"Plugin package (.zip) URL",placeholder:"https://example.com/plugin.zip",confirmLabel:"Fetch",confirmActions:[new rE]}),{category:"Plugins",icon:"plug"}),Q("plugins.installFromFile","Install Plugin from File…",()=>new FJ,{category:"Plugins",icon:"plug"})}function DY(A){let Q=V8(A.settings),B=q8(),C=z8(),E=w8(),J=j8(),K=new iJ(A),L=N8(),Y=O8(),X=P8(),H=new mJ,G=new UE(K),D=new oJ(A),U=new pJ(A,D),I={platform:A,explorer:Q,search:B,transfers:G,social:U,offline:D,activity:K,apiKeys:C,rotation:E,workbench:Y,overlay:X,navigation:H,engine:null},R=new sC({providers:{appState:l.fromSingleton(new Map),explorer:l.fromSingleton(Q),search:l.fromSingleton(B),transfers:l.fromSingleton(G),social:l.fromSingleton(U),offline:l.fromSingleton(D),activity:l.fromSingleton(K),apiKeys:l.fromSingleton(C),rotation:l.fromSingleton(E),acl:l.fromSingleton(J),viewState:l.fromSingleton(L),engine:l.fromLazySingleton(async()=>R,()=>{}),workbench:l.fromSingleton(Y),overlay:l.fromSingleton(X),navigation:l.fromSingleton(H),settings:l.fromSingleton(A.settings),notifications:l.fromSingleton(A.notifications),context:l.fromSingleton(A.context),commands:l.fromSingleton(A.commands),keybindings:l.fromSingleton(A.keybindings),contributions:l.fromSingleton(A.contributions),viewport:l.fromSingleton(A.viewport),voice:l.fromSingleton(A.voice),api:l.fromSingleton(A.api),capabilities:l.fromLazySingleton(async()=>{let V=c(null);return A.api.capabilities().then((_)=>V.setValue(_),()=>{}),V},()=>{}),plugins:l.fromSingleton(A.plugins)}});return I.engine=R,A.commands.dispatch=(V)=>R.dispatch(V),A.dispatch=(V)=>R.dispatch(V),$Y(I),JY(A.context,{workbench:Y,overlay:X,navigation:H,explorer:Q}),KY(A.context,A.viewport),U.init(),D.init(),K.init(),{engine:R,app:I}}var ZY=new WeakMap;function s(A,Q){let B=ZY.get(A);if(!B)B=new WeakMap,ZY.set(A,B);let C=B.get(Q);if(!C)C=_C(A.query(Q),{initial:BQ}),B.set(Q,C);return C}function zA(A,Q,B,C){let E=Object.keys(Q),J=E.map((L)=>s(A,Q[L])),K=BA(J,(...L)=>Object.fromEntries(E.map((Y,X)=>[Y,L[X]])));return T.alias(()=>CQ(K,B,C))}var AD=new FinalizationRegistry(({table:A,key:Q})=>{if(A.get(Q)&&!A.get(Q).deref())A.delete(Q)});function rJ(A,Q){let B=typeof A;if(A===null||B==="string"||B==="number"||B==="boolean")return;if(B!=="object")throw TypeError(`Query argument ${Q} is a ${B}, which cannot be part of a sharing key. Pass an id and let the query look the thing up, or give queryOf a key function.`);if(Array.isArray(A))return A.forEach((E,J)=>rJ(E,`${Q}[${J}]`));let C=Object.getPrototypeOf(A);if(C===Object.prototype||C===null)return Object.entries(A).forEach(([E,J])=>rJ(J,`${Q}.${E}`));throw TypeError(`Query argument ${Q} is a ${A.constructor?.name??"non-plain object"}, which cannot be part of a sharing key. Pass an id and let the query look the thing up, or give queryOf a key function.`)}function tJ(A){if(A===null||typeof A!=="object")return JSON.stringify(A)??"null";if(Array.isArray(A))return`[${A.map(tJ).join(",")}]`;return`{${Object.keys(A).sort().map((Q)=>`${JSON.stringify(Q)}:${tJ(A[Q])}`).join(",")}}`}function QD(...A){return A.forEach((Q,B)=>rJ(Q,`#${B}`)),A.map(tJ).join("|")}function jB(A,Q=QD){let B=new Map;return function(...E){if(this!==void 0&&this!==A)throw TypeError(`${this?.name??"A subclass"}.of() would build a ${A.name}, because \`of\` captures the class it was declared on. Give ${this?.name??"the subclass"} its own \`static of = queryOf(...)\`, or call it on `+A.name+" directly.");let J=Q(...E),K=B.get(J)?.deref();if(K)return K;let L=new A(...E);return B.set(J,new WeakRef(L)),AD.register(L,{table:B,key:J}),L}}function BD(A,Q){if(!Q)return 1;let B=0,C=0;for(let J of Q){let K=A.indexOf(J,C);if(K<0)return 0;B+=K===C?3:1,C=K+1}let E=A.indexOf(Q);if(E>=0)B+=100-Math.min(50,E);return B}function eJ(A,Q,B=60){let C=(Q||"").trim().toLowerCase(),E=A||[];if(!C)return E.slice(0,B);let J=[];for(let K of E){let L=BD(`${K.category||""} ${K.title}`.toLowerCase(),C);if(L>0)J.push([L,K])}return J.sort((K,L)=>L[0]-K[0]||String(K[1].title).localeCompare(String(L[1].title))).slice(0,B).map(([,K])=>K)}function WY({ex:A={},tr:Q={},act:B={},off:C={}}={}){let E=A.items||[],J=B.tasks||[];return{collectionId:A.collectionId??null,collectionLabel:CD(A),totalItems:A.stats?.items??E.length,totalKnown:A.stats?.items!=null,totalBytes:A.stats?.bytes??E.reduce((K,L)=>K+(L.size||0),0),shown:E.length,partial:!!A.nextCursor,usage:A.usage??null,usageLevel:ED(A.usage),uploading:(Q.items||[]).filter((K)=>K.status==="active"),running:J.filter((K)=>K.status==="running"),issues:B.issues||[],off:{online:!0,pins:[],queued:0,syncing:!1,...C}}}function CD(A){if(!A?.collectionId)return"no collection";return(A.collections||[]).find((B)=>B.id===A.collectionId)?.name||A.collectionId}function ED(A){if(!A?.total)return"";let Q=A.available/A.total;return Q<0.05?"critical":Q<0.1?"low":""}function UY(A){let Q=A||{};if(!Q.off?.online)return{kind:"offline",label:"Offline"};if(Q.issues?.length)return{kind:"issues",label:`${Q.issues.length} need${Q.issues.length===1?"s":""} attention`,count:Q.issues.length};if(Q.running?.length||Q.uploading?.length||Q.off?.syncing)return{kind:"working",label:"Working…",count:(Q.running?.length||0)+(Q.uploading?.length||0)};if(Q.usageLevel)return{kind:"lowSpace",label:"Low on space"};return{kind:"idle",label:"Status"}}function AK(A){let Q=A||"";return Q.startsWith("!")?"command":Q.includes("#")?"filter":"search"}function FY(A){return A!=="command"}function JD(A,{pinned:Q=!1,keys:B={}}={}){let C=(E)=>B[E]||void 0;return[{label:"Open",icon:"file-text",actions:[new N("explorer.open",A)]},{label:"Download",icon:"download",actions:[new N("explorer.download",A)]},{label:"Copy shareable link",icon:"link",actions:[new N("explorer.copyShareLink")]},{label:"Copy trove: link",icon:"link",kbd:C("explorer.copyLink"),actions:[new N("explorer.copyLink")]},{sep:!0},{label:"Rename…",actions:[new N("explorer.rename")]},Q?{label:"Remove from offline",icon:"close",actions:[new N("offline.unpin",A)]}:{label:"Make available offline",icon:"download",actions:[new N("offline.pin",A)]},{sep:!0},{label:"Move to trash",icon:"trash",danger:!0,kbd:C("explorer.delete"),actions:[new N("explorer.delete")]}]}function KD(A){return[{label:"Restore",icon:"refresh",actions:[new N("explorer.restore",A.id)]},{sep:!0},{label:"Delete forever",icon:"trash",danger:!0,actions:[new N("explorer.purgeOne",A.id)]}]}function LD(A,{modal:Q,pinnedIds:B,keys:C}){return{icon:MQ(A),title:A.name,detail:A.contentType||"",node:A,actions:[new aA(A,{reset:!!Q}),...Q?[new zB]:[]],menu:()=>JD(A,{pinned:B.has(A.id),keys:C})}}function IY(A,Q=!1){let{ex:B={},se:C={},nav:E={},query:J="",commandMatches:K=[],pinnedIds:L=new Set,keys:Y={}}=A,X=AK(J),H=(O)=>LD(O,{modal:Q,pinnedIds:L,keys:Y}),G=Q?[new zB]:[];if(X==="command")return[{id:"commands",title:"Commands",items:K.map((O)=>({icon:"command",title:O.title,detail:O.category,badge:"command",actions:[new N(O.id),...G]})),empty:"No matching commands."}];let{text:D,filters:U}=sB(J),I=(C.results||[]).map((O)=>O.node),R=C.error,V=(O)=>R?[{icon:"refresh",label:"Retry",title:"Retry",actions:O}]:[];if(U.length){let O=U.map(iC).join(" ")+(D.trim()?` · "${D.trim()}"`:"");return[{id:"filtered",title:C.loading?"Filtering…":R?"Filter failed":"Filtered",verbatim:C.loading||R?null:O,controls:V([new VB(U,D)]),items:I.map(H),empty:C.loading?"Filtering…":R?`Couldn’t filter: ${R}`:"No files match those filters."}]}if(D.trim())return[{id:"results",title:C.loading?"Searching…":R?"Search failed":"Results",controls:V([new VQ(J)]),items:I.map(H),empty:C.loading?"Searching…":R?`Couldn’t search: ${R}`:"No files match."}];let _=[],m=(E.recents||[]).map(H);if(m.length)_.push({id:"recent",title:"Recent",items:m});let b=(B.items||[]).length,q=B.stats?.items??null,p=q??b,k=q!=null?q.toLocaleString():`${b.toLocaleString()}+`,v=(B.items||[]).map(H);if(B.nextCursor)v.push({icon:"refresh",title:B.loadingMore?"Loading…":q!=null?`Show more (${(q-b).toLocaleString()} more)`:"Show more",detail:"or search to jump straight to something",actions:[new N("explorer.loadMore")]});if(B.trash)_.push({id:"trash",title:B.trash.length?`Trash · ${B.trash.length} item${B.trash.length===1?"":"s"}`:"Trash",controls:[...B.trash.length?[{icon:"trash",label:"Empty trash",title:"Destroy everything in the trash",actions:[new N("explorer.emptyTrash")]}]:[],{icon:"close",label:"Close",title:"Hide the trash",actions:[new N("explorer.hideTrash")]}],items:(B.trash||[]).map((O)=>({icon:"trash",title:O.name,detail:`deleted ${new Date(O.deletedAt).toLocaleString()} — restore`,actions:[new N("explorer.restore",O.id)],menu:()=>KD(O)})),empty:"The trash is empty."});return _.push({id:"all",title:B.nextCursor?`All items · showing ${b.toLocaleString()} of ${k}`:"All items",controls:Q?[]:[{icon:"upload",label:"Upload",title:"Upload files to this collection",actions:[new N("explorer.upload")]}],items:v,empty:B.loading?"Loading…":B.error?`Couldn’t load this collection: ${B.error}`:"Nothing here yet — upload a file to get started."}),_}function RY({eligible:A=!1,caps:Q=null}={}){if(!A)return null;let B=Q?.searchPrompt;if(!B?.hint&&!B?.examples?.length)return null;return{hint:B.hint||null,examples:(B.examples||[]).map((C)=>{let{text:E,filters:J}=sB(C.query);return{query:C.query,label:C.label||null,actions:[new AB(C.query),J.length?new VB(J,E):new VQ(E)]}})}}var MY="explorer.view";function VY({views:A=[],saved:Q=null}={},B=[],C=null){if(!A.length)return null;let E=Q&&A.find((L)=>L.id===Q);if(E)return E;let J=C&&A.find((L)=>L.id===C);if(J)return J;let K=B.map((L)=>L.node).filter(Boolean);if(K.length>=3){let L=(X)=>X.match&&Object.keys(X.match).length&&K.filter((H)=>YD(X,H)).length/K.length>0.6,Y=A.find(L);if(Y)return Y}return A[0]}function YD(A,Q){let B=Q.contentType||"",C=(Q.name||"").toLowerCase(),E=C.includes(".")?C.slice(C.lastIndexOf(".")):"";if((A.match.ext||[]).includes(E))return!0;return(A.match.mime||[]).some((J)=>J.endsWith("/*")?B.startsWith(J.slice(0,-1)):B===J)}class KA extends YQ{static deps=[];constructor(A,Q,B,{bootAction:C=null}={}){super();if(this.dep=A,this.cellOf=Q,this.project=B,C)this.bootAction=C}get deps(){return[this.dep,"appState"]}boot(A,{notify:Q}){let B=this.cellOf(A[this.dep]);if(!B){Q(null);return}let C=A[this.dep],E=()=>this.project?this.project(B.getValue(),C):B.getValue();Q(E()),H0(A,this,B.onDirty(()=>Q(E())))}kill(A){$0(A,this)}}function H0(A,Q,B){A.appState.set(Q,B)}function $0(A,Q){let B=A.appState?.get(Q);if(Array.isArray(B))B.forEach((C)=>C());else B?.();A.appState?.delete(Q)}var WC=new KA("explorer",(A)=>A.observe(),(A)=>({...A,selectedNodes:rB(A),collectionMenu:eC(A,(Q)=>new N("collections.switch",Q),()=>new N("collections.create")),collectionAdmin:U8(A,{open:(Q)=>new N("collections.switch",Q),scan:()=>new N("workbench.scanCollection"),rotate:()=>new N("workbench.openSettings"),create:()=>new N("collections.create"),access:(Q)=>new SE(Q)})})),QK=new KA("search",(A)=>A.observe()),BK=new KA("transfers",(A)=>A.observe()),D0=new KA("activity",(A)=>A.observe()),UC=new KA("social",(A)=>A.observe()),Z0=new KA("offline",(A)=>A.observe(),(A)=>({...A,pinnedIds:new Set((A?.pins||[]).map((Q)=>Q.id))})),qY=(A)=>CK.of(A);class CK extends YQ{static deps=["rotation","appState","engine"];static of=jB(CK);constructor(A){super();this.collectionId=A,this.bootAction=new PB(A)}boot(A,{notify:Q}){let B=A.rotation.observe();Q(B.getValue());let C=B.onDirty(()=>Q(B.getValue())),E=setInterval(()=>{if(A.rotation.get().rotation?.status==="running")A.engine.dispatch(new PB(this.collectionId))},2500);H0(A,this,[C,()=>clearInterval(E)])}kill(A){$0(A,this)}}var zY=(A)=>EK.of(A);class EK extends YQ{static deps=["acl","appState"];static of=jB(EK);constructor(A){super();this.collectionId=A,this.bootAction=new Y0(A)}boot(A,{notify:Q}){let B=A.acl.observe();Q(B.getValue()),H0(A,this,B.onDirty(()=>Q(B.getValue())))}kill(A){$0(A,this)}}var NY=new KA("apiKeys",(A)=>A.observe(),(A)=>({...A,draftScopes:tC(A)}),{bootAction:new AC}),FC=new KA("workbench",(A)=>A.observe()),JK=new KA("navigation",(A)=>A.observe()),IC=new KA("overlay",(A)=>A.observe()),PY=new KA("notifications",(A)=>A.observe()),W0=new KA("settings",(A)=>A.observe()),OY=new KA("settings",(A)=>A.observe(),(A,Q)=>Q.grouped()),jY=new KA("context",(A)=>A.observe()),wY=new KA("viewport",(A)=>A.observe()),SY=new KA("voice",(A)=>A.observe(),(A,Q)=>({...A,canListen:!!Q.canListen?.()})),RC=new KA("plugins",(A)=>A?.observe?.()),KK=new KA("viewState",(A)=>A.observe());class DQ extends YQ{static deps=[];constructor(A,Q,B){super();this.deps=[...A,"appState"],this.sources=Q,this.project=B}boot(A,{notify:Q}){let B=()=>Q(this.project(A));B(),H0(A,this,this.sources(A).filter(Boolean).map((C)=>C.onDirty(B)))}kill(A){$0(A,this)}}var fQ=["contributions","context","plugins","settings","commands","keybindings"],uQ=(A)=>[A.contributions.observe(),A.context.observe(),A.plugins?.observe?.(),A.settings.observe()];function _Y(A){return A.commands.paletteCommands().map((Q)=>({id:Q.id,title:Q.title??Q.id,category:Q.category??null,icon:Q.icon??null,keybinding:A.keybindings.labelFor(Q.id),available:A.commands.isAvailable(Q)}))}var XD=[...fQ,"overlay","workbench"],GD=(A)=>[...uQ(A),A.workbench.observe(),A.overlay.observe()],TY=new DQ(XD,GD,(A)=>eJ(_Y(A),A.overlay.get().palette?.query||"")),xY=new DQ(fQ,uQ,(A)=>{return A.contributions.ofType("statusItem").filter((Q)=>Q.visible!==!1&&Q.html).filter((Q)=>!Q.when||A.context.evaluate(Q.when)).filter((Q)=>A.plugins?.isAvailable?.(Q)??!0).sort((Q,B)=>(Q.order??0)-(B.order??0)||String(Q.name).localeCompare(String(B.name))).map((Q)=>({id:Q.id,slot:Q.slot==="left"?"left":"right",html:Q.html,tooltip:Q.tooltip??null,command:Q.command??null}))}),kY=new DQ(fQ,uQ,(A)=>{let Q=A.keybindings.resolved(),B=A.keybindings.overrides(),C=new Map;for(let E of Q)C.set(E.key,(C.get(E.key)||0)+1);return Q.map((E)=>({bindingId:E.bindingId,command:E.command,title:A.contributions.get(E.command)?.title??E.command,key:E.key,label:v0(E.key),custom:!!B[E.bindingId],clash:C.get(E.key)>1}))}),LK=(A=!1)=>YK.of(!!A),HD=[...fQ,"explorer","search","workbench","navigation","offline","capabilities"];class YK extends DQ{static of=jB(YK);constructor(A){super(HD,(Q)=>[...uQ(Q),Q.explorer.observe(),Q.search.observe(),Q.workbench.observe(),Q.navigation.observe(),Q.offline.observe(),Q.capabilities],(Q)=>{let B=Q.workbench.get(),C=Q.offline.observe().getValue()||{},E={ex:Q.explorer.observe().getValue()||{},se:Q.search.observe().getValue()||{},nav:Q.navigation.observe().getValue()||{},query:B.launch.query||"",commandMatches:eJ(_Y(Q),(B.launch.query||"").slice(1)),pinnedIds:new Set((C.pins||[]).map((L)=>L.id)),keys:mY(Q)},J=IY(E,this.modal),K=AK(E.query);return{groups:J,mode:K,view:VY(bY(Q),J.flatMap((L)=>L.items),K==="search"?E.se.resolved?.view??null:null),help:RY({eligible:K!=="command"&&!!E.se.ran&&!E.se.loading&&!E.se.error&&!(E.se.results||[]).length,caps:Q.capabilities.getValue()})}});this.modal=A}}var gY=new DQ(["explorer","transfers","activity","offline"],(A)=>[A.explorer.observe(),A.transfers.observe(),A.activity.observe(),A.offline.observe()],(A)=>{let Q=WY({ex:A.explorer.observe().getValue(),tr:A.transfers.observe().getValue(),act:A.activity.observe().getValue(),off:A.offline.observe().getValue()});return{...Q,condition:UY(Q)}}),yY=new DQ(fQ,uQ,(A)=>A.contributions.ofType("opener").filter((Q)=>!Q.when||A.context.evaluate(Q.when)).filter((Q)=>A.plugins?.isAvailable?.(Q)??!0).sort((Q,B)=>(B.priority??0)-(Q.priority??0)).map((Q)=>WE(Q,A.plugins))),hY=new DQ(fQ,uQ,bY);function bY(A){return{views:A.contributions.ofType("view").filter((Q)=>!Q.when||A.context.evaluate(Q.when)).sort((Q,B)=>(B.priority??0)-(Q.priority??0)).map((Q)=>({id:Q.id,title:Q.title??Q.name??Q.id,icon:Q.icon??null,match:Q.match??null,render:Q.render,move:Q.move})),saved:A.settings.get("explorer.view")||null}}var vY=new DQ(fQ,uQ,(A)=>{let Q=A.settings.get(MB)||{};return Object.entries(Q).map(([B,C])=>{let E=A.contributions.get(C);return{typeKey:B,openerId:C,openerTitle:E?.title||C,missing:!E}})}),fY=(A)=>XK.of(A);class XK extends KA{static of=jB(XK);constructor(A){super("social",(Q)=>Q.observe(),(Q)=>Q?.sidecar??null);this.nodeId=A,this.bootAction=new XC(A),this.killAction=new RJ(A)}}class wB extends YQ{static deps=["api"];static of=jB(wB);constructor(A,Q,B){super();this.nodeId=A,this.maxBytes=Q,this.size=B}async boot({api:A},{notify:Q}){Q(await A.readTextCapped(this.nodeId,{maxBytes:this.maxBytes,size:this.size}))}kill(){}}var uY=new DQ(fQ,uQ,mY);function mY(A){return Object.fromEntries(A.keybindings.resolved().map((Q)=>[Q.command,A.keybindings.labelFor(Q.command)]).filter(([,Q])=>Q))}var MC=new KA("capabilities",(A)=>A);var{svg:DD,h:ZD}=T,GK={link:[{d:"M10 13a5 5 0 0 0 7.07 0l3-3A5 5 0 0 0 13 3l-1.5 1.5"},{d:"M14 11a5 5 0 0 0-7.07 0l-3 3A5 5 0 0 0 11 21l1.5-1.5"}],file:[{d:"M6 3h8l5 5v13a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"},{d:"M14 3v5h5"}],"file-text":[{d:"M6 3h8l5 5v13a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"},{d:"M14 3v5h5M9 13h6M9 17h6M9 9h2"}],"file-image":[{d:"M6 3h8l5 5v13a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"},{d:"M14 3v5h5"},{d:"M8.5 15l2-2 3 3 2-1.5"},{d:"M10 12a1 1 0 1 0 0-.01"}],"file-audio":[{d:"M6 3h8l5 5v13a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"},{d:"M14 3v5h5M10 12v5M13 10v9"}],"file-video":[{d:"M6 3h8l5 5v13a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"},{d:"M14 3v5h5M10 12l4 2.5-4 2.5z"}],book:[{d:"M4 5a2 2 0 0 1 2-2h13v16H6a2 2 0 0 0-2 2z"},{d:"M4 19a2 2 0 0 1 2-2h13"}],search:[{d:"M11 4a7 7 0 1 0 0 14 7 7 0 0 0 0-14zM20 20l-3.5-3.5"}],mic:[{d:"M12 3a3 3 0 0 0-3 3v6a3 3 0 0 0 6 0V6a3 3 0 0 0-3-3z"},{d:"M5 11a7 7 0 0 0 14 0M12 18v3M9 21h6"}],command:[{d:"M8 6a2 2 0 1 0-2 2h12a2 2 0 1 0-2-2v12a2 2 0 1 0 2-2H6a2 2 0 1 0 2 2z"}],gear:[{d:"M12 9a3 3 0 1 0 0 6 3 3 0 0 0 0-6z"},{d:"M19 12a7 7 0 0 0-.1-1.2l2-1.6-2-3.4-2.4 1a7 7 0 0 0-2-1.2L14 2h-4l-.5 2.6a7 7 0 0 0-2 1.2l-2.4-1-2 3.4 2 1.6A7 7 0 0 0 5 12a7 7 0 0 0 .1 1.2l-2 1.6 2 3.4 2.4-1a7 7 0 0 0 2 1.2L10 22h4l.5-2.6a7 7 0 0 0 2-1.2l2.4 1 2-3.4-2-1.6A7 7 0 0 0 19 12z"}],upload:[{d:"M12 16V4M7 9l5-5 5 5M4 20h16"}],download:[{d:"M12 4v12M7 11l5 5 5-5M4 20h16"}],trash:[{d:"M4 7h16M9 7V4h6v3M6 7l1 13h10l1-13M10 11v6M14 11v6"}],refresh:[{d:"M20 11a8 8 0 1 0-.5 4M20 5v6h-6"}],"chevron-right":[{d:"M9 6l6 6-6 6"}],"chevron-left":[{d:"M15 6l-6 6 6 6"}],"chevron-down":[{d:"M6 9l6 6 6-6"}],close:[{d:"M6 6l12 12M18 6L6 18"}],tag:[{d:"M4 4h6.5a1 1 0 0 1 .7.3l8.5 8.5a1 1 0 0 1 0 1.4l-5.5 5.5a1 1 0 0 1-1.4 0L4.3 11.2a1 1 0 0 1-.3-.7V4z"},{d:"M8 8a0.6 0.6 0 1 0 0-.01"}],play:[{d:"M8 5v14l11-7z",fill:"currentColor",stroke:"none"}],pause:[{d:"M8 5h3v14H8zM13 5h3v14h-3z",fill:"currentColor",stroke:"none"}],"skip-back":[{d:"M11 6v12L3 12zM13 6l8 6-8 6zM21 6v12",fill:"none"}],"skip-forward":[{d:"M13 6v12l8-6zM3 6l8 6-8 6zM3 6v12"}],"back-30":[{d:"M11 8a7 7 0 1 0 7 7"},{d:"M11 4l-3 4 4 1"}],"fwd-30":[{d:"M13 8a7 7 0 1 1-7 7"},{d:"M13 4l3 4-4 1"}],plug:[{d:"M9 3v6M15 3v6M6 9h12v3a6 6 0 0 1-12 0zM12 18v3"}],bell:[{d:"M18 8a6 6 0 1 0-12 0c0 7-3 9-3 9h18s-3-2-3-9z"},{d:"M13.73 21a2 2 0 0 1-3.46 0"}],files:[{d:"M4 4h9l3 3v3M8 8h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2v-9a2 2 0 0 1 2-2z"}],dots:[{d:"M5 12h.01M12 12h.01M19 12h.01"}],check:[{d:"M5 12l5 5L20 6"}],plus:[{d:"M12 5v14M5 12h14"}],"arrow-up":[{d:"M12 19V5M6 11l6-6 6 6"}],star:[{d:"M12 3l2.7 5.6 6.1.9-4.4 4.3 1 6.1L12 17l-5.4 2.9 1-6.1L3.2 9.5l6.1-.9z"}],info:[{d:"M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18zM12 11v5M12 8h.01"}],warn:[{d:"M12 3l9 16H3zM12 10v4M12 17h.01"}],x:[{d:"M6 6l12 12M18 6L6 18"}],list:[{d:"M8 6h12M8 12h12M8 18h12M4 6h.01M4 12h.01M4 18h.01"}],grid:[{d:"M4 4h7v7H4zM13 4h7v7h-7zM4 13h7v7H4zM13 13h7v7h-7z"}]};function F(A,{size:Q=18,strokeWidth:B=1.6,className:C}={}){let E=Object.hasOwn(GK,A)?GK[A]:GK.file;return DD({$attrs:{viewBox:"0 0 24 24",width:Q,height:Q,fill:"none",stroke:"currentColor","stroke-width":B,"stroke-linecap":"round","stroke-linejoin":"round",...C?{class:C}:{}}},...E.map((J)=>ZD("path",{$attrs:WD(J)})))}function WD(A){let Q={d:A.d};if(A.fill)Q.fill=A.fill;if(A.stroke)Q.stroke=A.stroke;return Q}function EA(A){if(A==null||Number.isNaN(A))return"—";let Q=["B","KB","MB","GB","TB"],B=0,C=A;while(C>=1024&&B<Q.length-1)C/=1024,B++;return`${C>=100||B===0?Math.round(C):C.toFixed(1)} ${Q[B]}`}function HK(A){if(!A)return"";let Q=Date.now()-A,B=86400000;if(Q<60000)return"just now";if(Q<3600000)return`${Math.floor(Q/60000)}m ago`;if(Q<B)return`${Math.floor(Q/3600000)}h ago`;if(Q<7*B)return`${Math.floor(Q/B)}d ago`;return new Date(A).toLocaleDateString(void 0,{month:"short",day:"numeric",year:Q>330*B?"numeric":void 0})}var UD=/@\[([^\]]+)\]\(([^)]+)\)|(?:^|\s)@([a-zA-Z0-9._@-]{2,})/g;function pY(A){let Q=A||"",B=[],C=new RegExp(UD.source,"g"),E=0,J;while(J=C.exec(Q)){let K=!!J[3],L=J.index+(K&&J[0].startsWith(" ")?1:0);if(L>E)B.push({type:"text",value:Q.slice(E,L)});B.push({type:"mention",name:J[1]||J[3],id:J[2]||null}),E=C.lastIndex}if(E<Q.length)B.push({type:"text",value:Q.slice(E)});return B}var{div:h,span:HA,button:xA,textarea:FD,input:ID,p:l9}=T,RD=["\uD83D\uDC4D","❤️","\uD83C\uDF89","\uD83D\uDC40","\uD83D\uDE80"];function lY(A){let Q=A.so.me;if(!Q||Q.anonymous)return null;let B=(Q.name||Q.id||"?")[0].toUpperCase();return h({className:"principal",title:Q.email||Q.name||Q.id},Q.picture?T.img({src:Q.picture,alt:"",className:"avatar-img"}):HA({className:"avatar-txt"},B))}function cY(A,Q){let B=A.so.notifications;return h({className:"bell-wrap"},xA({className:"iconbtn bell",title:"Notifications"},F("bell",{size:19}),B.unread?HA({className:"bell-badge"},String(B.unread>9?"9+":B.unread)):null).on({click:()=>Q.engine.dispatch(new qQ)}),A.so.inboxOpen?MD(A,Q):null)}function MD(A,Q){let B=A.so.notifications.items;return h({},h({className:"scrim",$styling:{background:"transparent","z-index":"54"}}).on({click:()=>Q.engine.dispatch(new qQ(!1))}),h({className:"inbox"},h({className:"inbox-head"},HA("Notifications"),A.so.pushSupported&&!A.so.pushEnabled?xA({className:"link"},"Enable push").on({click:()=>Q.engine.dispatch(new YC)}):A.so.pushEnabled?HA({className:"muted"},F("check",{size:13})):null),B.length?h({className:"inbox-items"},...B.slice(0,30).map((C)=>VD(C,Q))):h({className:"inbox-empty"},F("info",{size:24}),HA("You’re all caught up."))))}function VD(A,Q){let B=A.items?.[0];return h({className:`inbox-item ${A.read?"":"unread"}`},h({className:"ii-title"},A.title),B?.excerpt?h({className:"ii-excerpt"},"“"+B.excerpt+"”"):null,h({className:"ii-time"},HK(A.createdAt))).on({click:()=>{if(B?.nodeId)Q.engine.dispatch(new oE(B.nodeId));Q.engine.dispatch(new qQ(!1))}})}function dY(A,Q){let B=A.nav,C=B.activeFile?{id:B.activeTabId,node:B.activeFile}:null;return h({className:"infopanel"},h({className:"ip-head"},F("info",{size:15}),HA("Details"),xA({className:"iconbtn",title:"Close"},F("close",{size:14})).on({click:()=>Q.engine.dispatch(new CC(!1))})),!C?h({className:"ip-empty"},HA("Open a file to see its tags and conversation.")):Q.watch(s(Q.engine,fY(C.node.id)),(E)=>h({className:"ip-body"},qD(C.node,A,Q),zD(C.node,A,Q),PD(E,Q),OD(A,E,Q))))}function qD(A,Q,B){let C=Q.off?.pinnedIds?.has(A.id)??!1;return h({className:"ip-file"},h({className:"ip-name"},A.name),h({className:"ip-path"},A.contentType||""),xA({className:`btn small ${C?"on":""}`,$styling:{"margin-top":"10px"}},F(C?"check":"download",{size:14}),C?"Available offline":"Make available offline").on({click:()=>C?B.engine.dispatch(new N("offline.unpin",A)):B.engine.dispatch(new N("offline.pin",A))}))}function zD(A,Q,B){let C=Q.so.backlinks,E=A.collectionId?iB(A):null,J=C&&C.nodeId===A.id?C:null;return h({className:"ip-section"},h({className:"ip-label"},"Links"),E?xA({className:"ip-uri",title:"Copy this item’s link"},F("link",{size:12}),HA(E)).on({click:()=>ND(B,E)}):null,h({className:"ip-label",$styling:{"margin-top":"10px"}},"Linked from"),J?.loading?h({className:"ip-muted"},"Loading…"):J?.error?h({className:"ip-muted error"},`Couldn’t load links: ${J.error}`):J?.items?.length?h({className:"ip-backlinks"},...J.items.map((K)=>xA({className:"ip-backlink",title:K.name},F("file-text",{size:12}),HA(K.name)).on({click:()=>B.engine.dispatch(new aA(K))}))):h({className:"ip-muted"},"Nothing links here yet."))}function ND(A,Q){A.engine.dispatch(new tA(Q,`Copied ${Q}`))}function PD(A,Q){let B=A?.tags||[];return h({className:"ip-section"},h({className:"ip-label"},"Tags"),h({className:"tags"},...B.map((C)=>HA({className:"tag"},C.value?`${C.name}: ${C.value}`:C.name,xA({className:"tag-x"},F("close",{size:11})).on({click:()=>Q.engine.dispatch(new pE(C.name))}))),ID({className:"tag-input",placeholder:"+ tag",value:""}).on({keydown:(C)=>{if(C.key==="Enter"&&C.target.value.trim()){let E=C.target.value.trim(),[J,...K]=E.split(":");Q.engine.dispatch(new mE(J.trim(),K.join(":").trim()||void 0)),C.target.value=""}}})))}function OD(A,Q,B){if(Q?.loading)return h({className:"ip-section"},h({className:"spinner"}));let C=Q?.comments||[],E=Q?.error?h({className:"conv-empty"},HA(`Couldn't load the conversation: ${Q.error}`),xA({className:"btn",$styling:{"margin-top":"8px"}},"Retry").on({click:()=>B.engine.dispatch(new XC(Q.nodeId))})):C.length?h({className:"thread"},...C.map((J)=>aY(J,A,B,0))):h({className:"conv-empty"},"No comments yet. Start the discussion — use @ to mention someone.");return h({className:"ip-section conv"},h({className:"ip-label"},`Conversation${Q?.commentCount?` · ${Q.commentCount}`:""}`),E,Q?.error?null:jD(A,B))}function aY(A,Q,B,C){let E=Q.so.me,J=E&&A.author?.id===E.id;return h({className:"comment",$styling:C?{marginLeft:"18px"}:{}},h({className:"c-head"},HA({className:"c-avatar"},(A.author?.name||"?")[0].toUpperCase()),HA({className:"c-author"},A.author?.name||A.author?.id||"Someone"),HA({className:"c-time"},HK(A.createdAt),A.edited?" · edited":"")),A.deleted?h({className:"c-body deleted"},"comment deleted"):h({className:"c-body"},wD(A.body)),!A.deleted?h({className:"c-actions"},...RD.map((K)=>{let L=A.reactions?.[K]||[];return xA({className:`react ${L.includes(E?.id)?"on":""}`},K,L.length?HA({className:"rc"},String(L.length)):null).on({click:()=>B.engine.dispatch(new uE(A.id,K))})}),xA({className:"c-link"},"Reply").on({click:()=>B.engine.dispatch(new C0({id:A.id,author:A.author}))}),J?xA({className:"c-link danger"},"Delete").on({click:()=>B.engine.dispatch(new fE(A.id))}):null):null,(A.replies||[]).length?h({className:"replies"},...A.replies.map((K)=>aY(K,Q,B,C+1))):null).key(A.id)}function jD(A,Q){let B=A.so.me,C=A.so.replyTo;if(!B){if(!A.off?.online)return h({className:"conv-signin"},"You’re offline. Conversations come back when you reconnect.");return h({className:"conv-signin"},HA("You’re signed out, so you can read this conversation but not add to it."),xA({className:"c-link"},"Reload to sign in").on({click:()=>window.location.reload()}))}return h({className:"composer"},C?h({className:"replying"},`Replying to ${C.author?.name||"comment"}`,xA({className:"c-link"},"cancel").on({click:()=>Q.engine.dispatch(new C0(null))})):null,FD({className:"composer-input",placeholder:"Write a comment… @mention someone",rows:2,value:""}).on({keydown:(E)=>{if(E.key==="Enter"&&(E.metaKey||E.ctrlKey))Q.engine.dispatch(new B0(E.target.value)),E.target.value=""}}),h({className:"composer-actions"},HA({className:"muted"},"⌘/Ctrl + Enter"),xA({className:"btn primary",disabled:A.so.posting},"Comment").on({click:(E)=>{let J=E.target.closest(".composer").querySelector(".composer-input");Q.engine.dispatch(new B0(J.value)),J.value=""}})))}function wD(A){return pY(A).map((Q)=>Q.type==="mention"?HA({className:"mention"},`@${Q.name}`):Q.value)}var{div:nY,button:$K,span:SD,img:_D}=T,TD=[{id:"home",icon:"search",title:"Search & files",command:"workbench.view.home"},{id:"plugins",icon:"plug",title:"Plugins",command:"workbench.view.plugins"},{id:"admin",icon:"book",title:"Administration",command:"workbench.view.admin"}];function DK(A,Q){let B=A.wb.activity,C=A.plugins?.filter((E)=>E.status==="active").length||0;return nY({className:"activitybar"},$K({className:"brand-mark",title:"Trove — home"},_D({src:"/icon.svg",alt:"Trove"})).on({click:()=>Q.engine.dispatch(new N("workbench.view.home"))}),...TD.map((E)=>$K({className:`item ${B===E.id?"active":""}`,title:E.title},F(E.icon,{size:22}),E.id==="plugins"&&C?SD({className:"badge"},String(C)):null).on({click:()=>Q.engine.dispatch(new N(E.command))})),nY({className:"spacer"}),cY(A,Q),$K({className:`item ${B==="settings"?"active":""}`,title:"Settings"},F("gear",{size:21})).on({click:()=>Q.engine.dispatch(new N("workbench.openSettings"))}),lY(A))}var xD=new Set(["SPAN","B","STRONG","I","EM","CODE","SMALL","BR","S","U"]),kD=new Set(["class","title"]);function sY(A){let Q=document.createDocumentFragment();if(typeof A!=="string"||!A)return Q;let B=document.createElement("template");B.innerHTML=A.slice(0,4096);let C={nodes:200};for(let E of B.content.childNodes){let J=tY(E,C);if(J)Q.appendChild(J)}return Q}function oY(A){return(sY(A).textContent||"").trim()}function iY(A,Q){return[...sY(A).childNodes].map((B)=>rY(B,Q)).filter((B)=>B!=null)}function rY(A,Q){if(A.nodeType===Node.TEXT_NODE)return A.nodeValue;let B=Q[A.tagName.toLowerCase()];if(!B)return A.textContent;let C={};if(A.className)C.className=A.className;if(A.title)C.title=A.title;return B(C,...[...A.childNodes].map((E)=>rY(E,Q)).filter((E)=>E!=null))}function tY(A,Q){if(Q.nodes--<=0)return null;if(A.nodeType===Node.TEXT_NODE)return document.createTextNode(A.nodeValue);if(A.nodeType!==Node.ELEMENT_NODE)return null;if(!xD.has(A.tagName))return null;let B=document.createElement(A.tagName.toLowerCase());for(let C of A.attributes){let E=C.name.toLowerCase();if(!kD.has(E))continue;B.setAttribute(E,C.value.slice(0,200))}for(let C of A.childNodes){let E=tY(C,Q);if(E)B.appendChild(E)}return B}var{div:BB,button:CB,span:$A}=T;function eY(A,Q){let B=iY(A.html,T);if(!B.length)return null;let C=A.tooltip?oY(A.tooltip):"";return A.command?CB({className:"seg",title:C},...B).on({click:()=>Q.engine.dispatch(new N(A.command))}):$A({className:"seg",title:C},...B)}function gD(A,Q){let B=A.act||{tasks:[],issues:[]},C=B.tasks.filter((K)=>K.status==="running"),E=()=>Q.engine.dispatch(new wA(!0)),J=[];if(C.length){let K=C[0],Y=K.total!=null&&K.total>0?Math.round((K.done||0)/K.total*100):null;J.push(CB({className:"seg sb-activity",title:C.map((X)=>X.title).join(`
|
|
734
|
-
`)},BB({className:"spinner",$styling:{width:"11px",height:"11px"}}),$A(C.length>1?`${C.length} running`:`${K.title}${Y==null?"":` ${Y}%`}`)).on({click:E}))}if(B.issues.length)J.push(CB({className:"seg sb-attention",title:B.issues.map((K)=>K.title).join(`
|
|
735
|
-
`)},F("info",{size:12}),$A(`${B.issues.length} need${B.issues.length===1?"s":""} attention`)).on({click:E}));return J}function ZK({usage:A,usageLevel:Q=""}){if(!A?.total)return null;let B=Math.min(100,Math.round(A.used/A.total*100));return $A({className:`seg sb-usage ${Q}`,title:`${EA(A.used)} used of ${EA(A.total)} — ${EA(A.available)} free on this volume`},BB({className:"usage-bar"},BB({className:"usage-fill",$styling:{width:`${B}%`}})),$A(`${EA(A.available)} free`))}function WK(A,Q){let B=A.ex,C=B.items||[],E=A.facts,{totalItems:J,totalBytes:K}=E,L=A.caps,Y=E.uploading,X=A.statusItems||[],H=X.filter((U)=>U.slot==="left").map((U)=>eY(U,Q)),G=X.filter((U)=>U.slot!=="left").map((U)=>eY(U,Q)),D=E.off;return BB({className:"statusbar"},!D.online?$A({className:"seg offline-badge",title:"You are offline — pinned files and cached data are available"},F("info",{size:12}),$A("Offline")):D.syncing?$A({className:"seg",title:"Syncing offline changes"},BB({className:"spinner",$styling:{width:"11px",height:"11px"}}),$A("Syncing…")):null,D.queued?$A({className:"seg",title:"Changes waiting to sync"},`${D.queued} queued`):null,D.pins.length?CB({className:"seg",title:`${D.pins.length} file(s) available offline`},F("download",{size:12}),$A(`${D.pins.length} offline`),F("chevron-down",{size:11})).on({click:(U)=>{let I=D.pins.slice(0,12).flatMap((R)=>[{label:R.name,icon:"file-text",actions:[new N("explorer.open",R)]},{label:`Remove “${R.name}” from offline`,icon:"close",actions:[new N("offline.unpin",R)]},{sep:!0}]);if(D.pins.length>12)I.push({label:`…and ${D.pins.length-12} more`,actions:[]});Q.engine.dispatch(new $Q(I,{rect:U.currentTarget.getBoundingClientRect(),prefer:"up"}))}}):null,CB({className:"seg",title:"Switch collection"},F("files",{size:13}),$A(E.collectionLabel),(B.collections||[]).length>1||B.canCreateCollection?F("chevron-down",{size:11}):null).on({click:(U)=>{let I=B.collectionMenu||[];if(I.length>1||B.canCreateCollection)Q.engine.dispatch(new $Q(I,{rect:U.currentTarget.getBoundingClientRect(),prefer:"up"}));else Q.engine.dispatch(new N("workbench.view.home"))}}),Y.length?CB({className:"seg",title:"Active uploads — click to cancel"},BB({className:"spinner",$styling:{width:"11px",height:"11px"}}),$A(`${Y.length} uploading`)).on({click:(U)=>Q.engine.dispatch(new $Q(Y.map((I)=>({label:`Cancel ${I.name} (${Math.round((I.ratio||0)*100)}%)`,icon:"close",danger:!0,actions:[new LC(I.id)]})),{x:U.clientX,y:U.clientY}))}):$A({className:"seg",title:B.nextCursor?`Showing ${C.length} of ${E.totalKnown?J:"more"}`:""},`${J.toLocaleString()}${E.totalKnown||!E.partial?"":"+"} item${J===1?"":"s"}`),...H,BB({className:"spacer"}),...gD(A,Q),...G,$A({className:"seg",title:E.totalKnown||!E.partial?"Total size of this collection":`Size of the ${E.shown.toLocaleString()} items loaded so far — this server doesn’t report a collection total`},`${EA(K)}${E.totalKnown||!E.partial?"":"+"}`),ZK(E),L?$A({className:"seg",title:"Storage backend capabilities"},F(L.storage?.presignDownload?"download":"files",{size:12}),$A(L.storage?.presignDownload?"S3 direct":"proxied")):null,L?.features?.semanticSearch?CB({className:"seg",title:"Semantic search enabled"},F("star",{size:12}),$A("semantic")).on({click:()=>Q.engine.dispatch(new N("workbench.view.home"))}):null)}async function NA(A,Q){for(let B of Q?.actions||[])if((await lA(A.engine,B))?.type!=="complete")break}var{div:UK,span:AX,button:QX}=T;function U0(A,Q){let B=A.controls||[];return UK({className:"launch-h"},UK({className:"lh-title"},AX(A.title),A.verbatim?AX({className:"lh-verbatim"},A.verbatim):null),B.length?UK({className:"lh-actions"},...B.map((C)=>QX({className:"launch-up",title:C.title||C.label},C.icon?F(C.icon,{size:13}):null,C.label).on({click:()=>NA(Q,C)}))):null)}function F0(A,Q,B){if(!A.menu)return null;return QX({className:"launch-more",title:`Actions for ${A.title}`,$attrs:{"aria-label":`Actions for ${A.title}`}},F("dots",{size:14})).on({click:(C)=>{C.stopPropagation(),EB(C.currentTarget,A,Q,null,B)}})}function EB(A,Q,B,C,E){let J=A?.getBoundingClientRect?.(),K=C?.clientX??(J?J.right-8:0),L=C?.clientY??(J?J.bottom:0),Y=Q.menu();E?.(),B.engine.dispatch(new $Q(Y,{x:K,y:L}))}var{div:VC,span:FK}=T;function I0({groups:A,index:Q,handlers:B,ui:C}){let E=-1;return VC({className:"launch-view view-list"},...A.map((J)=>VC({className:"launch-group"},U0(J,C),J.items.length?VC({className:"launch-list"},...J.items.map((K)=>{let L=++E;return yD(K,L===Q,{hover:()=>B.hover(L),select:()=>B.select(L)},C)})):VC({className:"launch-empty"},J.empty||"Nothing here."))))}function yD(A,Q,{hover:B,select:C},E){return VC({className:`launch-item ${Q?"active":""}`},F(A.icon,{size:15}),FK({className:"name"},A.title),A.detail?FK({className:"launch-detail"},A.detail):null,A.badge?FK({className:"launch-kind"},A.badge):null,F0(A,E,C)).on({click:()=>NA(E,A),mouseenter:B,...A.menu?{contextmenu:(J)=>{J.preventDefault(),EB(J.currentTarget,A,E,J,C)}}:{}})}function SB(A,Q,B,{op:C="media",onError:E}={}){let J=B.platform.mediaUrls,K=null,L=!1,Y=!1,X=()=>{clearTimeout(K),K=null},H=(I)=>{if(X(),!Number.isFinite(I))return;let R=Math.max(1000,(I-Date.now())*0.8);K=setTimeout(()=>G({resume:!0}),Math.min(R,2147483647))};async function G({resume:I}){if(L)return;let R=hD(A),V=R&&I?A.currentTime:0,_=R&&I?!A.paused&&!A.ended:!1,m;try{m=await J.url(Q.id,{op:C})}catch(b){if(!L)E?.(b.message);return}if(L)return;if(A.src=m.url,R){if(A.load(),V>0||_){let b=()=>{if(A.removeEventListener("loadedmetadata",b),V>0&&Number.isFinite(A.duration)&&A.duration>V)A.currentTime=V;if(_)A.play().catch(()=>{})};A.addEventListener("loadedmetadata",b)}}H(m.expiresAt)}let D=()=>{Y=!1};A.addEventListener("load",D),A.addEventListener("loadeddata",D);let U=()=>{if(L)return;if(Y){E?.(null);return}Y=!0,J.invalidate(Q.id,C),G({resume:!0})};return A.addEventListener("error",U),G({resume:!1}),()=>{L=!0,X(),A.removeEventListener("error",U),A.removeEventListener("load",D),A.removeEventListener("loadeddata",D)}}function hD(A){return typeof A?.play==="function"&&typeof A?.load==="function"}function BX(A,Q,B,C){if(B?.src)return A.src=B.src,()=>{};let E=null,J=!0;return C.platform.fileChunks.read(Q.id,B.range).then(({bytes:K})=>{if(!J||!K?.length)return;E=URL.createObjectURL(new Blob([K],{type:B.contentType||"image/jpeg"})),A.src=E}).catch(()=>{A.style.display="none"}),()=>{if(J=!1,E)URL.revokeObjectURL(E);E=null}}var{div:JB,span:bD,img:CX}=T;function EX({groups:A,index:Q,handlers:B,ui:C}){let E=-1;return JB({className:"launch-view view-grid"},...A.map((J)=>JB({className:"launch-group"},U0(J,C),J.items.length?JB({className:"grid-list"},...J.items.map((K)=>{let L=++E;return fD(K,L===Q,{hover:()=>B.hover(L),select:()=>B.select(L)},C)})):JB({className:"launch-empty"},J.empty||"Nothing here."))))}function JX({key:A,textual:Q}){if(A==="ArrowLeft")return Q?null:-1;if(A==="ArrowRight")return Q?null:1;let B=vD();if(A==="ArrowUp")return-B;if(A==="ArrowDown")return B;return null}function vD(){let A=document.querySelectorAll(".grid-list .grid-tile");if(A.length<2)return 1;let Q=A[0].offsetTop,B=0;for(let C of A){if(C.offsetTop!==Q)break;B++}return B||1}function fD(A,Q,{hover:B,select:C},E){let J=A.node,K=RB(J),L=!K&&(J?.contentType||"").startsWith("image/");return JB({className:`grid-tile ${Q?"active":""}`,title:A.detail?`${A.title} — ${A.detail}`:A.title},JB({className:"gt-media"},F(A.icon,{size:26}),K?CX({className:"gt-img",alt:"",loading:"lazy",decoding:"async"}).on({$attach:(Y)=>{Y._detachThumb=BX(Y,J,K,E)},$detach:(Y)=>{Y._detachThumb?.(),Y._detachThumb=null}}).opaque():null,L?CX({className:"gt-img",alt:"",loading:"lazy",decoding:"async"}).on({$attach:(Y)=>{Y._detachMedia=SB(Y,J,E,{onError:()=>{Y.style.display="none"}})},$detach:(Y)=>{Y._detachMedia?.(),Y._detachMedia=null}}).opaque():null,A.badge?bD({className:"gt-badge"},A.badge):null,F0(A,E,C)),JB({className:"gt-name"},A.title)).on({click:()=>NA(E,A),mouseenter:B,...A.menu?{contextmenu:(Y)=>{Y.preventDefault(),EB(Y.currentTarget,A,E,Y,C)}}:{}})}var{div:IK,button:uD,span:mD}=T,pD={"core.view.list":{title:"List",icon:"list",priority:50,render:I0},"core.view.grid":{title:"Grid",icon:"grid",priority:40,match:{mime:["image/*","video/*"]},render:EX,move:JX}};function KX(A){for(let[Q,B]of Object.entries(pD))A.contributions.register(Q,{type:"view",...B})}function LX(A,Q,B,{mode:C}={}){if(C!==void 0&&!FY(C))return null;let E=A?.views||[];if(E.length<2)return null;return IK({className:"view-switch"},...E.map((J)=>uD({className:`vs-btn ${J.id===Q?.id?"on":""}`,title:`${J.title} view`,"aria-pressed":J.id===Q?.id?"true":"false"},F(J.icon||"list",{size:14})).on({click:()=>B.engine.dispatch(new bQ(MY,J.id))})))}function YX(A,Q,B){try{let C=A?.move?.({key:Q,...B});return Number.isFinite(C)&&C!==0?C:null}catch{return null}}function XX(A,Q){try{if(typeof A?.render==="function")return A.render(Q)}catch(B){return console.error(`view "${A?.id}" failed`,B),IK({},IK({className:"view-error"},F("warn",{size:13}),mD(`The “${A?.title||A?.id}” view could not be drawn — showing the list instead.`)),I0(Q))}return I0(Q)}var{div:mQ,span:_B,input:lD,button:RK}=T,cD=new Set(["ArrowUp","ArrowDown","ArrowLeft","ArrowRight"]);function dD(A,{compact:Q=!1,modal:B=!1}={}){let C=A?.searchPrompt,E=(Q?C?.short||C?.placeholder:C?.placeholder)||(Q?"Search files":"Search files · # filter by tag");return Q||B?E:`${E} · ! run a command`}var MK=new Map,HX=(A,Q,B)=>{clearTimeout(MK.get(A)),MK.set(A,setTimeout(Q,B))};function aD(A,Q,B){HX(Q,()=>A.engine.dispatch(new VQ(B)),240)}function GX(A,Q){clearTimeout(MK.get(Q)),A.engine.dispatch(new AB("")),A.engine.dispatch(new VQ(""))}function nD(A,Q,B,C){HX(Q,()=>A.engine.dispatch(new VB(B,C)),200)}function R0(A,Q,B={}){let C=!!B.modal,E=A.wb.launch.query,J=C?A.modalContent:A.content,{groups:K,mode:L,view:Y}=J,X=K.flatMap((q)=>q.items),H=X.length?Math.min(A.wb.launch.index,X.length-1):0,G=C?"modal":"home",D=(q)=>{let p=q.target.value;if(Q.engine.dispatch(new AB(p)),p.startsWith("!"))return;let{text:k,filters:v}=sB(p);if(v.length)nD(Q,G,v,k);else aD(Q,G,k)},U=(q)=>Q.engine.dispatch(new _E(q)),I=(q)=>Q.engine.dispatch(new dE(q,X[q]?.node)),R=(q)=>Q.engine.dispatch(new cE(q,X.map((p)=>p.node))),V=(q)=>{let p=cD.has(q.key)?YX(Y,q.key,{index:H,count:X.length,textual:E.length>0}):null;if(p!==null)q.preventDefault(),R(p);else if(q.key==="ArrowDown")q.preventDefault(),R(1);else if(q.key==="ArrowUp")q.preventDefault(),R(-1);else if(q.key==="Enter")q.preventDefault(),NA(Q,X[H]);else if(q.key==="Escape"&&E)q.preventDefault(),GX(Q,G);else if(q.key==="ContextMenu"||q.shiftKey&&q.key==="F10"){let k=X[H];if(k?.menu)q.preventDefault(),EB(document.querySelector(".launch-item.active, .grid-tile.active"),k,Q)}},_=L==="search"?A.se.resolved:null,m=_&&(_.source==="llm"||_.tagFilters&&_.tagFilters.length||(_.semanticText||"").trim()!==E.trim()),b=mQ({className:"launcher"},mQ({className:"launch-box"},F(L==="command"?"command":L==="filter"?"tag":"search",{size:18}),lD({className:"launch-input",value:E,autofocus:!0,spellcheck:!1,placeholder:dD(A.caps,{compact:A.vp?.mode==="phone",modal:C})}).on({input:D,keydown:V}),E?RK({className:"launch-clear",title:"Clear"},F("close",{size:14})).on({click:()=>GX(Q,G)}):null,A.voice?.canListen?RK({className:`launch-mic ${A.voice?.listening?"on":""}`,title:A.voice?.listening?"Stop listening":"Search by voice","aria-pressed":A.voice?.listening?"true":"false"},F("mic",{size:15})).on({click:()=>Q.engine.dispatch(new N("search.voice"))}):null,C?null:LX(A.views,Y,Q,{mode:L})),m?sD(_):null,mQ({className:"launch-body"},XX(Y,{groups:K,index:H,handlers:{hover:U,select:I},state:A,ui:Q}),oD(J.help,Q)));return C?b:mQ({className:"editor"},b)}function sD(A){return mQ({className:"launch-resolved"},_B({className:"rq-label"},A.source==="llm"?"Interpreted as":"Searching"),(A.semanticText||"").trim()?_B({className:"rq-text"},`“${A.semanticText.trim()}”`):null,...(A.tagFilters||[]).map((Q)=>_B({className:"rq-chip"},F("tag",{size:11}),iC(Q))))}function oD(A,Q){if(!A)return null;return mQ({className:"launch-help"},A.hint?mQ({className:"lh-hint"},F("info",{size:13}),_B(A.hint)):null,A.examples.length?mQ({className:"lh-examples"},...A.examples.map((B)=>RK({className:"lh-example",title:B.label||"Try this search"},_B({className:"lh-q"},B.query),B.label?_B({className:"lh-label"},B.label):null).on({click:()=>NA(Q,B)}))):null)}var{div:M,h2:iD,h3:pQ,p:ZQ,span:JA,select:rD,option:tD,input:TB,label:DX,button:kA,ul:d7,li:a7,code:eD}=T;function VK(A,Q,B){let C=A.settingsGroups||new Map;return M({className:"editor"},M({className:"stage"},M({className:"settings"},iD("Settings"),ZQ({className:"sub"},"Preferences are stored in this browser. Plugins contribute their own settings here too."),...C.map((E)=>AZ(E,Q)),CZ(Q,A.caps),HZ(A,Q),JZ(A,Q),WZ(A.assoc,Q),B.keybindings())))}function AZ(A,Q){return M({className:"group"},pQ(A.category),...A.items.map((B)=>QZ(B,Q)))}function QZ(A,Q){return M({className:"setting"},M({className:"info"},M({className:"t"},A.title||A.key),A.description?M({className:"d"},A.description):null),M({className:"control"},BZ(A,Q)))}function BZ(A,Q){let B=(C)=>Q.engine.dispatch(new bQ(A.key,C));if(A.type==="boolean")return DX({className:"switch"},TB({type:"checkbox",checked:!!A.value}).on({change:(C)=>B(C.target.checked)}),JA({className:"track"}));if(A.type==="enum")return rD({className:"input"},...A.enum.map((C,E)=>tD({value:C,selected:A.value===C},A.enumLabels&&A.enumLabels[E]||C))).on({change:(C)=>B(C.target.value)});if(A.type==="number"){let C=(E)=>{let J=Number(E.target.value);if(E.target.value===""||Number.isNaN(J)){E.target.value=A.value;return}if(A.minimum!=null)J=Math.max(A.minimum,J);if(A.maximum!=null)J=Math.min(A.maximum,J);E.target.value=J,B(J)};return TB({className:"input",type:"number",value:A.value,$attrs:{min:A.minimum??"",max:A.maximum??""}}).on({change:C})}return TB({className:"input",value:A.value??""}).on({change:(C)=>B(C.target.value)})}function CZ(A,Q){if(!Q)return null;let B=Q.mcp,C=Q.auth||{authorizationServers:[],source:"none"};if(!B?.enabled)return M({className:"group"},pQ("AI agents (MCP)"),ZQ({className:"sub"},"MCP is switched off on this server. Set TROVE_MCP=on to enable it."));let E=(L)=>()=>A.engine.dispatch(new tA(L)),J=C.authorizationServers||[],K=C.source==="jwt-issuer"?"from TROVE_JWT_ISSUER":C.source==="configured"?"from TROVE_AUTH_SERVER":null;return M({className:"group"},pQ("AI agents (MCP)"),ZQ({className:"sub"},"Point an AI assistant at this drive. It signs in as you and sees exactly the collections you can see."),M({className:"setting"},M({className:"info"},M({className:"t"},"Server URL"),M({className:"d"},"Paste this into your assistant’s MCP settings.")),M({className:"control mcp-url"},JA({className:"mono"},B.endpoint),kA({className:"btn small",title:"Copy"},F("link",{size:13})).on({click:E(B.endpoint)}))),M({className:"setting"},M({className:"info"},M({className:"t"},"Sign-in required"),M({className:"d"},B.requiresAuth?"Agents must present a token, the same one this browser uses.":"This drive is open, so agents connect without a token — exactly like the web app does.")),M({className:"control"},JA({className:"mono"},B.requiresAuth?"Yes":"No"))),B.needsAuthorizationServer?M({className:"mcp-warn"},F("warn",{size:15}),JA("This drive requires a token but no authorization server is set, so an agent has nowhere to sign in. Set TROVE_AUTH_SERVER (or TROVE_JWT_ISSUER) to the issuer URL of your identity provider and restart.")):null,M({className:"setting"},M({className:"info"},M({className:"t"},"Authorization server"),M({className:"d"},"Where clients are sent to sign in — for the whole drive, not just for agents. "+"Set with TROVE_AUTH_SERVER; defaults to TROVE_JWT_ISSUER when that is set.")),M({className:"control"},J.length?JA({className:"mono"},J.join(", ")+(K?` (${K})`:"")):JA({className:"mono muted"},"not set"))),M({className:"setting"},M({className:"info"},M({className:"t"},"Discovery document"),M({className:"d"},"What a client reads to find out how to authenticate (RFC 9728).")),M({className:"control mcp-url"},JA({className:"mono small"},C.metadataUrl))))}var EZ=[{id:"read",label:"Read",hint:"list and download"},{id:"write",label:"Write",hint:"upload and rename"},{id:"delete",label:"Delete",hint:"trash and purge"},{id:"admin",label:"Admin",hint:"includes all of the above"}],ZX="*";function JZ(A,Q){let B=A.keys||{};if(B.forbidden)return null;if(B.error)return M({className:"group"},pQ("API keys"),ZQ({className:"sub"},`Couldn’t load the key list: ${B.error}`),M({className:"keys-actions"},kA({className:"btn"},"Try again").on({click:()=>Q.engine.dispatch(new N("keys.load"))})));if(!B.loaded)return null;let C=A.ex?.collections||[];return M({className:"group"},pQ("API keys"),ZQ({className:"sub"},"Give a script or a service access without giving it an account. A key carries capabilities and no identity, so anything it does is attributed to the key rather "+"than to a person — and it can only reach the collections you scope it to."),B.minted?KZ(B.minted,Q):null,B.draft?LZ(B,C,Q):null,!B.draft&&!B.minted?M({className:"keys-actions"},kA({className:"btn"},F("plus",{size:14}),"New key").on({click:()=>Q.engine.dispatch(new N("keys.new"))})):null,B.keys?.length?M({className:"keys-list"},...B.keys.map((E)=>YZ(E,B,C,Q))):M({className:"keys-empty"},"No keys yet."))}function KZ(A,Q){let B=()=>Q.engine.dispatch(new tA(A.secret,"Key copied"));return M({className:"key-minted"},M({className:"key-minted-head"},F("warn",{size:15}),JA(`“${A.key.name}” is ready — copy it now.`)),ZQ({className:"key-minted-note"},"This is the only time it can be shown. It is stored as a hash, so it cannot be "+"recovered — if it is lost, revoke the key and make another."),M({className:"key-secret"},eD({className:"mono"},A.secret),kA({className:"btn small",title:"Copy"},F("link",{size:13})).on({click:B})),M({className:"keys-actions"},kA({className:"btn"},"Done").on({click:()=>Q.engine.dispatch(new N("keys.dismissMinted"))})))}function LZ(A,Q,B){let{draft:C,draftScopes:E}=A,J=!!C.name.trim()&&!!E;return M({className:"key-form"},M({className:"setting"},M({className:"info"},M({className:"t"},"Name"),M({className:"d"},"What it is for. This is what the list shows, so make it recognisable.")),M({className:"control"},TB({className:"input",value:C.name,$attrs:{placeholder:"CI uploader"}}).on({input:(K)=>B.engine.dispatch(new E0({name:K.target.value}))}))),M({className:"setting"},M({className:"info"},M({className:"t"},"Expires after"),M({className:"d"},"Days from now. Leave blank and it never expires.")),M({className:"control"},TB({className:"input",type:"number",value:C.expiresInDays,$attrs:{min:"1",max:"3650",placeholder:"never"}}).on({input:(K)=>B.engine.dispatch(new E0({expiresInDays:K.target.value}))}))),M({className:"key-scopes"},M({className:"key-scopes-head"},M({className:"t"},"What it may do"),M({className:"d"},"Per collection. A key with nothing ticked grants nothing and cannot be created.")),$X({id:ZX,name:"All collections",wildcard:!0},C,B),...Q.map((K)=>$X(K,C,B))),M({className:"keys-actions"},kA({className:"btn primary",$attrs:J?{}:{disabled:"true"}},A.busy==="mint"?"Creating…":"Create key").on({click:()=>J&&B.engine.dispatch(new N("keys.mint"))}),kA({className:"btn"},"Cancel").on({click:()=>B.engine.dispatch(new N("keys.cancel"))})))}function $X(A,Q,B){let C=new Set(Q.caps[A.id]||[]);return M({className:`key-scope ${A.wildcard?"wildcard":""}`},M({className:"key-scope-name"},F(A.wildcard?"grid":"files",{size:14}),JA(A.name||A.id)),M({className:"key-scope-caps"},...EZ.map((E)=>DX({className:`cap ${C.has(E.id)?"on":""}`,title:E.hint},TB({type:"checkbox",checked:C.has(E.id)}).on({change:()=>B.engine.dispatch(new lE(A.id,E.id))}),JA(E.label)))))}function YZ(A,Q,B,C){let E=!!A.revokedAt,J=A.expiresAt!=null&&A.expiresAt<=Date.now(),K=E||J;return M({className:`key-row ${K?"dead":""}`},M({className:"key-row-main"},M({className:"key-row-name"},JA({className:"t"},A.name),E?JA({className:"key-tag"},"revoked"):J?JA({className:"key-tag"},"expired"):null),M({className:"key-row-scopes"},...XZ(A,B)),M({className:"key-row-meta"},GZ(A))),!K?kA({className:"btn small danger",$attrs:Q.busy===A.id?{disabled:"true"}:{}},Q.busy===A.id?"…":"Revoke").on({click:()=>C.engine.dispatch(new N("keys.revoke",A.id))}):null)}function XZ(A,Q){let B=(C)=>Q.find((E)=>E.id===C)?.name||C;return(A.scopes||[]).map((C)=>JA({className:"key-chip"},JA({className:"where"},C.collectionId===ZX?"all collections":B(C.collectionId)),JA({className:"what"},C.capabilities.join(" · "))))}function GZ(A){let Q=(C)=>new Date(C).toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"}),B=[`created ${Q(A.createdAt)}`];if(A.createdBy)B.push(`by ${A.createdBy}`);if(B.push(A.lastUsedAt?`last used ${Q(A.lastUsedAt)}`:"never used"),A.expiresAt)B.push(`expires ${Q(A.expiresAt)}`);return B.join(" · ")}function HZ(A,Q){let B=A.ex?.collectionId,C=A.ex?.collections?.find((E)=>E.id===B)?.encryption;if(!C?.enabled)return null;return Q.watch(s(Q.engine,qY(B)),(E)=>$Z(C,E||{},Q))}function $Z(A,Q,B){let C=Q.rotation?.status==="running",E=Q.estimate;return M({className:"group"},pQ("Encryption"),ZQ({className:"sub"},"Files in this collection are sealed before they leave your browser. The drive holds the key."),M({className:"setting"},M({className:"info"},M({className:"t"},"Key fingerprint"),M({className:"d"},"Identifies the key this collection is on.")),M({className:"control"},kA({className:"btn small",title:"Copy"},T.h("code",A.fingerprint)).on({click:()=>B.engine.dispatch(new tA(A.fingerprint,"Fingerprint copied"))}))),M({className:"setting"},M({className:"info"},M({className:"t"},C?"Rotating the key":"Rotate the key"),M({className:"d"},C?`${Q.rotation.moved} moved${Q.rotation.failed?`, ${Q.rotation.failed} failed`:""} — this continues in the background.`:DZ(E))),M({className:"control"},C?kA({className:"btn small",disabled:!!Q.busy},"Stop").on({click:()=>B.engine.dispatch(new qJ)}):kA({className:"btn small",disabled:!!Q.busy},"Rotate").on({click:()=>B.engine.dispatch(new VJ)}))),C?null:M({},ZZ(E),ZQ({className:"sub"},"Every file is re-sealed under a new key and the old one is retired once nothing is left on it. Files stay readable throughout.")))}function DZ(A){if(!A)return"Re-seals every file under a fresh key.";return A.summary||"Re-seals every file under a fresh key."}function ZZ(A){if(!A?.applicable||!(A.lines||[]).length)return null;return M({className:"rot-bill"},...A.lines.map((Q)=>M({className:"rb-line"},JA(Q.label||Q.name||""),JA({className:"mono"},Q.amount||Q.value||""))),A.total?M({className:"rb-line total"},JA("Estimated total"),JA({className:"mono"},A.total)):null,A.asOf?M({className:"rb-asof"},`Prices as of ${A.asOf}.`):null)}function WZ(A,Q){return M({className:"group"},pQ("Default Openers"),A.length?M({},...A.map((B)=>M({className:"setting"},M({className:"info"},M({className:"t"},B.typeKey),M({className:"d"},B.missing?`${B.openerTitle} (no longer installed)`:`Opens with ${B.openerTitle}`)),M({className:"control"},kA({className:"iconbtn",title:"Forget this default"},F("close",{size:14})).on({click:()=>Q.engine.dispatch(new GC(B.typeKey,null))}))))):ZQ({className:"sub",$styling:{margin:0}},"No default openers set yet. When a file type has more than one viewer, you can pick one and check “Always use this”."))}var qK="keybindingCapture";function WX(A,Q,B){let C=(K)=>Q.engine.dispatch(new QB(qK,K)),E=()=>C(null),J=(K,L)=>Q.engine.dispatch(new NE(K,L));return M({className:"group"},pQ("Keyboard Shortcuts"),ZQ({className:"sub"},"Click a shortcut to record a new one. Esc cancels; Backspace clears it."),...A.map((K)=>{let L=B===K.bindingId;return M({className:"setting"},M({className:"info"},M({className:"t"},K.title),M({className:"d"},K.command)),M({className:"control"},K.clash&&!L?JA({className:"kbd-clash",title:"Another command answers to this shortcut too — the one registered last wins"},F("warn",{size:12})):null,kA({className:`kbd-edit ${L?"listening":""} ${K.clash?"clash":""}`,title:L?"Press the new shortcut":"Click to rebind"},L?JA("Press keys…"):T.h("kbd",K.label)).on({click:()=>C(L?null:K.bindingId),blur:()=>{if(L)E()},keydown:(Y)=>{if(!L)return;if(Y.preventDefault(),Y.stopPropagation(),Y.key==="Escape")return E();if(Y.key==="Backspace")return J(K.bindingId,null),E();if(["Control","Meta","Alt","Shift"].includes(Y.key))return;J(K.bindingId,b0(Y)),E()},$attach:(Y)=>{if(L)queueMicrotask(()=>Y.focus())}}),K.custom?kA({className:"c-link",title:"Back to the default"},"reset").on({click:()=>{J(K.bindingId,null),C(null)}}):null))}))}var{div:eA,h2:UX,p:FX,button:NK,span:zK}=T;function PK(A,Q){let B=A.ex||{};return eA({className:"editor"},eA({className:"stage"},eA({className:"gate"},B.gate==="create"?UZ(Q):FZ(B,Q))))}function UZ(A){return eA({className:"gate-card"},eA({className:"gate-icon"},F("files",{size:26})),UX("Make your first collection"),FX({className:"gate-sub"},"A collection is a backing store you own — a bucket, a directory, a mount. Files "+"live in one, and permissions are granted on one. Nothing can be uploaded until there is somewhere to put it."),eA({className:"gate-actions"},NK({className:"btn primary"},F("plus",{size:14}),"New collection").on({click:()=>A.engine.dispatch(new N("collections.create"))})))}function FZ(A,Q){let B=A.collections||[];return eA({className:"gate-card"},eA({className:"gate-icon"},F("grid",{size:26})),UX(B.length===1?"Open your collection":"Choose a collection"),FX({className:"gate-sub"},B.length===1?"This is the one you have access to. Opening it will be remembered for next time.":"Files, search and uploads all belong to one collection. Your choice is remembered for next time, and you can switch from the status bar whenever you like."),eA({className:"gate-list"},...B.map((C)=>NK({className:"gate-choice"},eA({className:"gate-choice-main"},zK({className:"n"},C.name||C.id),zK({className:"d"},C.driver?`${C.driver}${C.description?` · ${C.description}`:""}`:C.description||"")),zK({className:"gate-caps"},(C.capabilities||[]).join(" · "))).on({click:()=>Q.engine.dispatch(new N("collections.switch",C.id))}))),A.canCreateCollection?eA({className:"gate-actions"},NK({className:"btn"},F("plus",{size:14}),"New collection").on({click:()=>Q.engine.dispatch(new N("collections.create"))})):null)}var{div:i,span:vA,p:IZ,button:qC,h2:RZ,input:OK,label:MZ}=T;function jK(A,Q){let B=A.plugins||[];return i({className:"editor"},i({className:"stage"},i({className:"plugins"},RZ("Plugins"),IZ({className:"sub",$styling:{color:"var(--text-dim)",margin:"0 0 8px"}},"Plugins are sandboxed packages you install from a file or URL. They run in an isolated iframe and reach Trove only through a message channel, using the capabilities you granted."),i({className:"plugin-install"},qC({className:"btn primary"},F("upload",{size:15}),"Install from file…").on({click:()=>Q.engine.dispatch(new N("plugins.installFromFile"))}),qC({className:"btn"},F("plug",{size:15}),"Install from URL…").on({click:()=>Q.engine.dispatch(new N("plugins.installFromUrl"))})),B.length?i({$styling:{display:"flex","flex-direction":"column",gap:"12px","margin-top":"14px"}},...B.map((C)=>VZ(C,A,Q))):i({className:"empty",$styling:{padding:"48px"}},F("plug",{size:30}),vA("No plugins installed yet.")))))}function VZ(A,Q,B){let C=!A.responsive?"not responding":A.manifest?.online===!1?"offline":"connected",E=A.features||[];return i({className:"plugin-card"},i({className:"top"},i({className:"avatar"},(A.name||"?")[0].toUpperCase()),i({$styling:{flex:"1"}},i({className:"name"},A.name,A.version?vA({$styling:{color:"var(--text-faint)","font-weight":"400","margin-left":"6px"}},"v"+A.version):null),i({$styling:{"font-size":"11px",color:"var(--text-faint)"}},A.id)),NZ(A.trust),vA({className:`status ${A.status}`},A.status)),A.error?i({className:"desc",$styling:{color:"var(--danger)"}},A.error):null,i({className:"caps"},...(A.capabilities||[]).map((J)=>vA({className:"cap"},J))),(A.endpoints||[]).length?i({className:"plugin-endpoints",$styling:{"font-size":"11px",color:"var(--text-faint)","margin-top":"2px"}},F("plug",{size:11})," Network: ",(A.endpoints||[]).map((J)=>J.host).join(", ")):null,A.status==="active"?i({className:"plugin-features"},i({className:"pf-head"},vA(`Features · ${C}`),vA({className:"muted"},`${E.filter((J)=>J.available).length}/${E.length} available`)),E.length?i({className:"pf-list"},...E.map(OZ)):i({className:"muted",$styling:{"font-size":"12px"}},A.responsive?"No contributions announced.":"No manifest received — the plugin may not be running.")):null,(A.settingsSchema||[]).length?qZ(A,B,Q):null,i({className:"actions"},A.hasUi?qC({className:"btn"},F("command",{size:14}),"Open panel").on({click:()=>B.engine.dispatch(new EC(A.id))}):null,qC({className:"btn"},F("refresh",{size:14}),"Refresh").on({click:()=>B.engine.dispatch(new nE(A.id))}),qC({className:"btn danger"},"Uninstall").on({click:()=>B.engine.dispatch(new sA({kind:"confirm",title:`Uninstall ${A.name}?`,danger:!0,confirmLabel:"Uninstall",body:"The plugin and all data it stored will be removed.",confirmActions:[new ME(A.id)]}))})))}function qZ(A,Q,B){return i({className:"plugin-features"},i({className:"pf-head"},vA("Settings")),i({$styling:{display:"flex","flex-direction":"column",gap:"8px"}},...A.settingsSchema.map((C)=>zZ(A,C,Q,B))))}function zZ(A,Q,B,C){let E=`${A.id}.${Q.key}`,J=Q.secret?"":C.settings?.[E]??Q.default??"";return i({className:"setting",$styling:{padding:"6px 0"}},i({className:"info"},i({className:"t"},Q.title||Q.key),Q.description?i({className:"d"},Q.description):null),i({className:"control"},Q.secret?OK({className:"input",type:"password",placeholder:"Set secret…"}).on({change:(K)=>{if(K.target.value)B.engine.dispatch(new sE(A.id,Q.key,K.target.value)),K.target.value="",K.target.placeholder="Saved ✓"}}):Q.type==="boolean"?MZ({className:"switch"},OK({type:"checkbox",checked:!!J}).on({change:(K)=>B.engine.dispatch(new bQ(E,K.target.checked))}),vA({className:"track"})):OK({className:"input",value:J}).on({change:(K)=>B.engine.dispatch(new bQ(E,K.target.value))})))}function NZ(A){if(!A)return null;let Q=nB(A),B=Q.status==="verified"?Q.domain:Q.status==="invalid"?"invalid signature":Q.status;return vA({className:`trust ${Q.tone}`,title:Q.explanation},F(Q.icon,{size:12}),B)}var PZ={command:"command",opener:"file",indexer:"search",statusItem:"info"};function OZ(A){return i({className:`pf-row ${A.available?"":"off"}`},F(PZ[A.kind]||"command",{size:13}),vA({className:"pf-title"},A.title),vA({className:"pf-kind"},A.kind),A.offline?vA({className:"pf-badge offline-ok",title:"Works offline"},"offline ✓"):null,vA({className:`pf-dot ${A.available?"on":"no"}`,title:A.available?"Available now":"Unavailable now"}))}var{div:y,h2:jZ,h3:zC,p:xB,span:AQ,button:fA,select:wZ,option:wK,input:SZ}=T;function SK(A,Q){let B=A.caps;return y({className:"editor"},y({className:"stage"},y({className:"settings admin"},jZ("Administration"),xB({className:"sub"},"How this drive is configured, and what it can do. Most of it is decided by the deployment rather than here."),_Z(B,A,Q),TZ(A,Q),gZ(B,A,Q),yZ(B,A),hZ(A,Q))))}function PA(A,Q,B){return y({className:"setting"},y({className:"info"},y({className:"t"},A),Q?y({className:"d"},Q):null),y({className:"control"},typeof B==="string"?AQ({className:"mono"},B):B))}function _Z(A,Q,B){let C=A?.auth||{},E=A?.principal||Q.so?.me||{},J=C.authorizationServers||[];return y({className:"group"},zC("Access"),xB({className:"sub"},"Who can reach this drive. Set by the deployment, not here."),PA("Signed in as",E.anonymous?"This drive does not require a sign-in.":E.email||E.id,E.anonymous?"anonymous":E.name||E.id||"—"),PA("Sign-in required","Whether a caller must present a token.",A?.mcp?.requiresAuth?"Yes":"No"),PA("Authorization server","Where clients are sent to sign in.",J.length?J.join(", "):"not set"),PA("API keys","Credentials for scripts and services, scoped per collection.",fA({className:"btn small"},"In Settings").on({click:()=>B.engine.dispatch(new N("workbench.openSettings"))})))}function TZ(A,Q){let B=A.ex?.collectionAdmin,C=B?.rows||[],E=(J)=>()=>NA(Q,{actions:J});return y({className:"group"},zC("Collections"),xB({className:"sub"},"What exists on this drive, where its bytes live, and which key seals it."),...C.length?C.map((J)=>y({className:"setting stacked"},y({className:"info"},y({className:"t"},J.name,J.current?AQ({className:"mono muted"}," · open"):null),y({className:"d"},J.encrypted?`${J.driver} · sealed, key ${String(J.fingerprint).slice(0,12)}…`:`${J.driver} · not encrypted`),y({className:"d"},`You may: ${J.capabilities.join(", ")||"nothing"}`)),y({className:"control admin-actions"},J.current?null:fA({className:"btn small"},"Open").on({click:E(J.actions.open)}),fA({className:"btn small"},"Scan").on({click:E(J.actions.scan)}),J.actions.rotate?fA({className:"btn small"},"Rotate key…").on({click:E(J.actions.rotate)}):null,J.actions.access?fA({className:`btn small ${A.wb?.aclFor===J.id?"on":""}`},"Access…").on({click:E(J.actions.access)}):null),A.wb?.aclFor===J.id?Q.watch(s(Q.engine,zY(J.id)),(K)=>kZ(K,Q,J.id)):null)):[PA("Collections","Nothing has been created yet.","none")],B?.canCreate?y({className:"setting"},y({className:"info"},y({className:"t"},"New collection"),y({className:"d"},"A backing store you own — a bucket, a directory, a mount. Encryption is chosen here, at creation.")),y({className:"control"},fA({className:"btn small"},"Create…").on({click:E(B.create)}))):PA("New collection","You do not have permission to create one on this drive.","not allowed"))}var xZ=["read","write","delete","admin"];function kZ(A,Q,B){if(!A)return y({className:"acl"},AQ({className:"mono muted"},"Loading access…"));if(A.error)return y({className:"acl"},AQ({className:"mono muted"},A.error));let C=A.grants||[],E=(L)=>Q.engine.dispatch(new MJ(B,L)),J=(L)=>{let Y=new Set(L.capabilities||[]),X=L.type==="anyone"?"Everyone":`${L.type}: ${L.subject}`;return y({className:"acl-row"},AQ({className:"acl-who"},X),...xZ.map((H)=>fA({className:`btn small ${Y.has(H)?"on":""}`,title:H==="admin"?"admin implies every other capability":`toggle ${H}`},H).on({click:()=>E({type:L.type,subject:L.subject,capabilities:Y.has(H)?(L.capabilities||[]).filter((G)=>G!==H):[...L.capabilities||[],H]})})),fA({className:"btn small",title:"remove this grant entirely"},"×").on({click:()=>E({type:L.type,subject:L.subject,capabilities:[]})}))},K=(A.admins||[]).map((L)=>y({className:"acl-row acl-fixed"},AQ({className:"acl-who"},L),AQ({className:"mono muted"},"admin · set by this deployment")));return y({className:"acl"},...K,...C.length?C.map(J):K.length?[]:[AQ({className:"mono muted"},"Nobody yet.")],y({className:"acl-row acl-add"},wZ({className:"acl-type"},wK({value:"user"},"user"),wK({value:"role"},"role"),wK({value:"anyone"},"anyone")),SZ({className:"acl-subject",placeholder:"email, or a role name"}),fA({className:"btn small"},"Grant read").on({click:(L)=>{let Y=L.target.closest(".acl-add"),X=Y.querySelector(".acl-type").value,H=Y.querySelector(".acl-subject").value.trim();if(X!=="anyone"&&!H)return;E({type:X,subject:X==="anyone"?"":H,capabilities:["read"]})}})))}function gZ(A,Q,B){let C=A?.storage||{},E=A?.storageDrivers||[],J=Q.ex?.usage,K=(L)=>AQ({className:`mono ${L?"":"muted"}`},L?"yes":"no");return y({className:"group"},zC("Storage"),xB({className:"sub"},"The backing stores this deployment offers, and what they support."),PA("Drivers offered","What a new collection may be created on.",E.length?E.map((L)=>L.label||L.key).join(", "):"none registered"),PA("Direct downloads","A presigned URL sends bytes from the store, not through the drive.",K(C.presignDownload)),PA("Direct uploads","A presigned PUT sends bytes to the store, not through the drive.",K(C.presignUpload)),PA("Multipart","Large files go up in parts, resumably.",K(C.multipart)),PA("Range requests","Seeking inside a file without fetching the whole thing.",K(C.range)),J?.total?PA("Space","Reported by the backing store.",`${EA(J.available)} free of ${EA(J.total)}`):PA("Space","This store does not report a total, which object stores generally cannot.","not reported"),y({className:"setting"},y({className:"info"},y({className:"t"},"Check the backing stores"),y({className:"d"},"Asks whether each store can actually be reached from here — the failure that makes every file open to a spinner.")),y({className:"control"},fA({className:"btn small"},"Run check").on({click:()=>B.engine.dispatch(new N("workbench.checkStorage"))}))))}function yZ(A,Q){let B=A?.indexers||[],C=Q.plugins||[];return y({className:"group"},zC("Extensions"),xB({className:"sub"},"What reads and adds to this drive."),y({className:"setting"},y({className:"info"},y({className:"t"},"Indexers"),y({className:"d"},"They read file contents to make them searchable — including in an encrypted collection, since indexing happens on the drive’s side of the encryption.")),y({className:"control"},AQ({className:"mono"},B.length?B.map((E)=>E.displayName||E.id).join(", "):"none"))),C.length?y({},...C.map((E)=>y({className:"setting"},y({className:"info"},y({className:"t"},E.manifest?.displayName||E.id),y({className:"d"},(E.grants||[]).length?`May: ${(E.grants||[]).join(", ")}`:"Granted nothing — it runs in its sandbox and can only draw.")),y({className:"control"},AQ({className:`mono ${E.status==="active"?"":"muted"}`},E.status||"idle"))))):PA("Plugins","Installed by an administrator, from a signed package.","none installed"))}function hZ(A,Q){let B=A.act||{tasks:[],issues:[]},C=(B.tasks||[]).filter((E)=>E.status==="running");return y({className:"group"},zC("Work"),xB({className:"sub"},"Background jobs and anything that needs attention."),PA("Running now","Scans, reindexes and rotations happening on the server.",C.length?`${C.length}`:"nothing running"),PA("Needs attention","Standing problems — they persist until fixed, unlike a toast.",B.issues?.length?`${B.issues.length}`:"none"),y({className:"setting stacked"},y({className:"info"},y({className:"t"},"Maintenance"),y({className:"d"},"A scan picks up files changed in the bucket by something other than Trove. A reindex rebuilds search from scratch.")),y({className:"control admin-actions"},fA({className:"btn small"},"Activity panel").on({click:()=>Q.engine.dispatch(new N("workbench.showActivity"))}),fA({className:"btn small"},"Scan").on({click:()=>Q.engine.dispatch(new N("workbench.scanCollection"))}),fA({className:"btn small"},"Reindex").on({click:()=>Q.engine.dispatch(new N("workbench.rebuildIndex"))}))))}class _K extends P{static deps=["api","engine","notifications"];constructor(A,Q=null){super();this.uri=A,this.from=Q}async execute({api:A,engine:Q,notifications:B}){let C=rC(this.uri);if(!C){B.warn(`"${this.uri}" isn’t a valid Trove link.`);return}try{let E=await A.stat(this.uri);if(!E?.node)throw Error("not found");await lA(Q,new aA(E.node))}catch(E){B.warn(bZ(C,E,this.from))}}}function bZ(A,Q,B){let C=B?.name?` (linked from "${B.name}")`:"";if(Q?.status===403||Q?.code==="forbidden")return`You don’t have access to that item in "${A.collection}"${C}.`;if(A.by==="name")return`Nothing named "${A.value}" in "${A.collection}"${C} — it may have been renamed or deleted.`;return`That item no longer exists in "${A.collection}"${C}.`}var{div:KB,span:xK,h1:vZ,h2:fZ,h3:uZ,p:zX,ul:mZ,ol:pZ,li:lZ,pre:cZ,code:NX,a:IX,em:dZ,strong:aZ,blockquote:nZ,hr:sZ,br:oZ}=T;function PX(A,Q){let B=SC(s(Q.engine,wB.of(A.id,TK,A.size)),(C)=>C.text);return T.alias(()=>Q.watch(B,(C)=>{try{return KB({className:"viewer markdown"},KB({className:"md"},...OX(C,A,Q)))}catch(E){return console.error("markdown render failed",E),RX(`This document couldn’t be displayed: ${E.message}`)}},{placeholder:()=>KB({className:"viewer"},KB({className:"loading"},KB({className:"spinner"}),xK("Loading…"))),error:(C)=>RX(C.message)}))()}function RX(A){return KB({className:"viewer"},KB({className:"fallback"},F("warn",{size:40}),xK(A)))}var TK=524288,iZ=5000,rZ=2000;function OX(A,Q,B){let C=String(A??""),E=C.length>TK,J=(E?C.slice(0,TK):C).split(/\r?\n/),K=[],L=0;while(L<J.length){if(K.length>=iZ)return[...K,MX()];let Y=J[L],X=/^\s*(```+|~~~+)(.*)$/.exec(Y);if(X){let R=X[1][0].repeat(3),V=[];L++;while(L<J.length&&!J[L].trimStart().startsWith(R))V.push(J[L++]);L++,K.push(cZ({className:"md-code"},NX(V.join(`
|
|
736
|
-
`))));continue}if(!Y.trim()){L++;continue}let H=/^(#{1,6})\s+(.*)$/.exec(Y);if(H){let R=H[1].length,V=R===1?vZ:R===2?fZ:uZ;K.push(V({className:`md-h md-h${R}`},...NC(H[2],Q,B))),L++;continue}if(/^\s*(-{3,}|\*{3,}|_{3,})\s*$/.test(Y)){K.push(sZ({className:"md-hr"})),L++;continue}if(/^\s*>/.test(Y)){let R=[];while(L<J.length&&/^\s*>/.test(J[L]))R.push(J[L++].replace(/^\s*>\s?/,""));K.push(nZ({className:"md-quote"},...OX(R.join(`
|
|
737
|
-
`),Q,B)));continue}let G=/^\s*([-*+]|\d+[.)])\s+/.exec(Y);if(G){let R=/\d/.test(G[1]),V=[];while(L<J.length){let _=/^\s*([-*+]|\d+[.)])\s+(.*)$/.exec(J[L]);if(!_||/\d/.test(_[1])!==R)break;V.push(lZ({className:"md-li"},...NC(_[2],Q,B))),L++}K.push((R?pZ:mZ)({className:"md-list"},...V));continue}let D=[];while(L<J.length&&J[L].trim()&&!tZ(J[L]))D.push(J[L++]);let U=D.join(`
|
|
738
|
-
`),I=[];U.split(`
|
|
739
|
-
`).forEach((R,V)=>{if(V)I.push(oZ());I.push(...NC(R,Q,B))}),K.push(zX({className:"md-p"},...I))}return E?[...K,MX()]:K}function MX(){return zX({className:"md-truncated"},"This document is too large to display in full. Download it to read the rest.")}function tZ(A){return/^(#{1,6}\s|\s*>|\s*([-*+]|\d+[.)])\s|\s*(```|~~~))/.test(A)||/^\s*(-{3,}|\*{3,}|_{3,})\s*$/.test(A)}var eZ=[{re:/`([^`]+)`/,node:(A)=>NX({className:"md-inline-code"},A[1])},{re:/\[([^\]]*)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/,node:(A,Q,B)=>qX(A[2],A[1]||A[2],Q,B)},{re:/(\*\*|__)(.+?)\1/,node:(A,Q,B,C)=>aZ(...NC(A[2],Q,B,C+1))},{re:/(\*|_)(.+?)\1/,node:(A,Q,B,C)=>dZ(...NC(A[2],Q,B,C+1))},{re:/(trove:[^\s<>"'`)\]}]+|https?:\/\/[^\s<>"'`)\]}]+)/,node:(A,Q,B)=>qX(VX(A[1]),VX(A[1]),Q,B)}];function NC(A,Q,B,C=0){if(!A)return[];if(C>12)return[A];let E=[],J=A;while(J){if(E.length>=rZ){E.push(J);break}let K=null;for(let X of eZ){let H=X.re.exec(J);if(H&&(K===null||H.index<K.m.index))K={m:H,rule:X}}if(!K){E.push(J);break}let{m:L,rule:Y}=K;if(L.index)E.push(J.slice(0,L.index));E.push(Y.node(L,Q,B,C)),J=J.slice(L.index+L[0].length)}return E}function VX(A){return A.replace(/[.,;:!?]+$/,"")}function qX(A,Q,B,C){if(rC(A))return IX({className:"md-link md-trove",href:"#",title:A},Q).on({click:(J)=>{J.preventDefault(),C.engine.dispatch(new _K(A,B))}});if(/^https?:\/\//i.test(A))return IX({className:"md-link",href:A,target:"_blank",rel:"noopener noreferrer",title:A},Q);return xK({className:"md-deadlink",title:`Unsupported link: ${A}`},Q)}var{div:DA,pre:A4,img:Q4,span:zQ,button:B4,video:C4,audio:E4}=T,J4={"core.audio":{title:"Audio Player",priority:20,match:{mime:["audio/*"],ext:[".mp3",".flac",".wav",".opus",".ogg",".m4a",".m4b"]},component:G4},"core.video":{title:"Video Player",priority:20,match:{mime:["video/*"],ext:[".mp4",".webm",".mkv",".mov"]},component:H4},"core.image":{title:"Image Viewer",priority:20,match:{mime:["image/*"],ext:[".png",".jpg",".jpeg",".gif",".webp",".svg",".avif"]},component:X4},"core.markdown":{title:"Markdown",priority:30,match:{ext:[".md",".markdown"],mime:["text/markdown"]},component:PX},"core.text":{title:"Text Viewer",priority:10,match:{mime:["text/*","application/json"],ext:[".txt",".md",".json",".js",".mjs",".ts",".jsx",".tsx",".css",".html",".xml",".yaml",".yml",".toml",".ini",".log",".csv",".py",".rb",".go",".rs",".sh",".c",".h",".cpp",".java"]},component:L4}};function jX(A){for(let[Q,B]of Object.entries(J4))A.contributions.register(Q,{type:"opener",...B})}function wX(A,Q,B){let C=B.platform.contributions.get(Q);if(C?.component)try{return C.component(A,B)}catch(E){return _X(E.message)}if(C?.pluginId)return $4(C,A,B);return SX(A,B)}var K4=524288;function L4(A,Q){let B=s(Q.engine,wB.of(A.id,K4,A.size));return T.alias(()=>Q.watch(B,({text:C,truncated:E,total:J})=>DA({className:"viewer text"},A4(C),E?DA({className:"md-truncated"},`Showing the first ${Math.round(C.length/1024)} KB${J?` of ${(J/1048576).toFixed(1)} MB`:""}. `,zQ("Download the file to read all of it.")):null),{placeholder:()=>DA({className:"viewer"},DA({className:"loading"},DA({className:"spinner"}),zQ("Loading…"))),error:(C)=>_X(C.message)}))()}var Y4="This file couldn't be loaded — it may be missing or in an unsupported format.";function kK(A,Q,B){let C=c({error:null}),J=B((K)=>C.setValue({error:K||Y4}));return T.alias(()=>CQ(C,(K)=>K.error?SX(A,Q,K.error):J))()}var gK=(A,Q,B,C)=>A.on({$attach:(E)=>{E._detachMedia=SB(E,Q,B,{onError:C})},$detach:(E)=>{E._detachMedia?.(),E._detachMedia=null}}).opaque();function X4(A,Q){return kK(A,Q,(B)=>DA({className:"viewer image"},gK(Q4({alt:A.name}),A,Q,B)))}function G4(A,Q){return kK(A,Q,(B)=>DA({className:"viewer",$styling:{display:"grid","place-items":"center",gap:"16px",padding:"40px"}},F("file-audio",{size:48}),zQ({$styling:{color:"var(--text-dim)"}},A.name),gK(E4({controls:!0,$styling:{width:"min(520px, 90%)"}}),A,Q,B)))}function H4(A,Q){return kK(A,Q,(B)=>DA({className:"viewer",$styling:{display:"grid","place-items":"center",background:"#000"}},gK(C4({controls:!0,$styling:{"max-width":"100%","max-height":"100%"}}),A,Q,B)))}function SX(A,Q,B){return DA({className:"viewer"},DA({className:"fallback"},F(B?"warn":"file",{size:44}),zQ({$styling:{"font-weight":600}},A.name),zQ(`${A.contentType||"Unknown type"} · ${EA(A.size)}`),zQ({$styling:{color:"var(--text-faint)","max-width":"340px"}},B||"No preview available for this file type. Install a plugin that handles it, or download the file."),B4({className:"btn primary"},F("download",{size:15}),"Download").on({click:()=>Q.engine.dispatch(new N("explorer.download",A))})))}function $4(A,Q,B){let C=c({ready:!1,error:null});return DA({className:"viewer plugin-viewer"},CQ(C,(E)=>{if(E.ready)return null;return DA({className:"pv-status"},E.error?DA({className:"fallback"},F("warn",{size:40}),zQ(E.error)):DA({className:"loading"},DA({className:"spinner"}),zQ("Opening…")))}),DA({className:"pv-host"}).on({$attach:(E)=>{E._detach=B.platform.plugins.mountViewer(A.pluginId,E,Q,A.id,{onReady:()=>C.setValue({ready:!0,error:null}),onError:(J)=>C.setValue({ready:!1,error:J||"This viewer failed to load"})})},$detach:(E)=>{E._detach?.(),E._detach=null}}).opaque())}function _X(A){return DA({className:"viewer"},DA({className:"fallback"},F("warn",{size:40}),zQ(A||"Failed to open")))}var{div:gB,span:TX,button:kB}=T,M0=new Map;function V0(A,Q){let B=A.wb,C=A.nav.stack.filter((J)=>J.kind==="file");U4(C);let E=C[C.length-1];if(!E)return gB({className:"editor"});return gB({className:"editor"},D4(C,E,A,Q),gB({className:"stage"},W4(E,Q)))}function D4(A,Q,B,C){return gB({className:"viewer-nav"},kB({className:"vn-back",title:"Back (Esc)"},F("chevron-left",{size:16})).on({click:()=>C.engine.dispatch(new aE)}),gB({className:"vn-trail"},kB({className:"vn-crumb"},F("search",{size:13}),TX("Search")).on({click:()=>C.engine.dispatch(new vQ)}),...A.map((E)=>kB({className:`vn-crumb ${E.id===Q.id?"active":""}`,title:E.node.name},F(MQ(E.node),{size:13}),TX({className:"label"},E.node.name)).on({click:()=>C.engine.dispatch(new GQ(E.node,E.openerId))}))),gB({className:"vn-actions"},Z4(Q,B,C),kB({className:"iconbtn",title:"Details & comments"},F("info",{size:15})).on({click:()=>C.engine.dispatch(new CC)}),kB({className:"iconbtn",title:"Close (Esc)"},F("close",{size:15})).on({click:()=>C.engine.dispatch(new vQ)})))}function Z4(A,Q,B){let C=E8(Q.openers,A.node);if(C.length<=1)return null;return kB({className:"iconbtn",title:"Open with…"},F("dots",{size:15})).on({click:()=>B.engine.dispatch(new sA({kind:"opener-chooser",node:A.node,openers:C,current:A.openerId}))})}function W4(A,Q){let B=`${A.id}:${A.openerId}`,C=M0.get(B);if(!C)C=()=>wX(A.node,A.openerId,Q),M0.set(B,C);return T.alias(C)().key(A.id)}function U4(A){let Q=new Set(A.map((B)=>`${B.id}:${B.openerId}`));for(let B of M0.keys())if(!Q.has(B))M0.delete(B)}var{div:oA,input:F4,span:lQ}=T;function yK(A,Q){let B=A.overlay.palette;if(!B)return null;let C=B.mode==="files"?B.query.trim()?A.se.paletteFiles||[]:[]:A.matches||[],E=Math.min(B.index,Math.max(0,C.length-1)),J=(K)=>{if(!K)return;if(Q.engine.dispatch(new BC),B.mode==="files")Q.engine.dispatch(new aA(K.node));else Q.engine.dispatch(new N(K.id))};return oA({},oA({className:"scrim"}).on({click:()=>Q.engine.dispatch(new BC)}),oA({className:"palette"},oA({className:"search"},F(B.mode==="files"?"search":"command",{size:18}),F4({type:"text",value:B.query,autofocus:!0,placeholder:B.mode==="files"?"Search files by name…":"Type a command…"}).on({input:(K)=>q4(Q,K.target.value),keydown:(K)=>V4(K,Q,C,E,J),$attach:(K)=>{if(queueMicrotask(()=>K.focus()),K.value!==B.query)K.value=B.query}})),oA({className:"results"},C.length?C.map((K,L)=>{let Y=()=>Q.engine.dispatch(new jE(L));return B.mode==="files"?M4(K,L===E,J,Y):R4(K,L===E,Q,J,Y)}):I4(B,A))))}function I4(A,Q){if(A.mode!=="files")return oA({className:"none"},"No matching commands");if(Q.se.paletteError)return oA({className:"none error"},F("warn",{size:14}),` ${Q.se.paletteError}`);if(Q.se.paletteLoading)return oA({className:"none"},oA({className:"spinner"})," Searching…");return oA({className:"none"},A.query.trim()?"No files found":"Type to search files by name")}function R4(A,Q,B,C,E){return oA({className:`opt ${Q?"active":""} ${A.available?"":"unavailable"}`},lQ({className:"ico"},F(A.icon||"command",{size:16})),A.category?lQ({className:"cat"},A.category+" ›"):null,lQ({className:"title"},A.title),!A.available?lQ({className:"offline-tag"},"offline"):null,A.keybinding?lQ({className:"kbd"},T.h("kbd",A.keybinding)):null).on({click:()=>C(A),mouseenter:E})}function M4(A,Q,B,C){return oA({className:`opt ${Q?"active":""}`},lQ({className:"ico"},F(MQ(A.node),{size:16})),lQ({className:"title"},A.node.name),lQ({className:"sub"},A.node.contentType||"")).on({click:()=>B(A),mouseenter:C})}function V4(A,Q,B,C,E){if(A.key==="ArrowDown")A.preventDefault(),Q.engine.dispatch(new A0(1,B.length));else if(A.key==="ArrowUp")A.preventDefault(),Q.engine.dispatch(new A0(-1,B.length));else if(A.key==="Enter")A.preventDefault(),E(B[C]);else if(A.key==="Escape")A.preventDefault(),Q.engine.dispatch(new BC)}var xX=null;function q4(A,Q){A.engine.dispatch(new OE(Q)),clearTimeout(xX),xX=setTimeout(()=>A.engine.dispatch(new qE(Q)),200)}var{div:a,span:LA,button:kX,h3:sF,p:z4,label:yX,input:hX}=T;function bX(A,Q,B){let C=A.summary,E=oC(B,aB,A,{grants:C.capabilities.filter((X)=>!X.adminOnly||A.isAdmin).map((X)=>X.id),acknowledged:!1}),J=A.policy||{requiresAcknowledgement:!1},K=J.requiresAcknowledgement&&!E.acknowledged,L=(X)=>Q.engine.dispatch(new QB(aB,{...E,...X})),Y=(X)=>L({grants:E.grants.includes(X)?E.grants.filter((H)=>H!==X):[...E.grants,X]});return a({},a({className:"scrim"}).on({click:()=>Q.engine.dispatch(new TA)}),a({className:"dialog review",$styling:{width:"min(560px, 96vw)"}},P4(C),a({className:"review-body"},C.description?z4({className:"review-desc"},C.description):null,yB("Capabilities it requests",C.capabilities.length?a({className:"cap-list"},...C.capabilities.map((X)=>j4(X,A.isAdmin,E.grants.includes(X.id),()=>Y(X.id)))):k4("None — this plugin only runs in its sandbox.")),(C.network||[]).length?yB("Network access",a({className:"contrib-list"},...C.network.map(_4))):null,(C.commands||[]).length?yB("Commands it can run",a({className:"contrib-list"},...C.commands.map((X)=>S4(X,Q)))):null,C.storage?yB("Storage",T4(C.storage)):null,C.contributions.length?yB("What it adds",a({className:"contrib-list"},...C.contributions.map(w4))):null,C.settings.length?yB("Settings",a({className:"contrib-list"},...C.settings.map(x4))):null,a({className:"review-meta"},`${C.fileCount} files · ${EA(C.sizeBytes)} · id ${C.id}`)),J.headline?N4(J,E,L):null,a({className:"row-actions"},kX({className:"btn"},"Cancel").on({click:()=>Q.engine.dispatch(new TA)}),kX({className:`btn primary ${K?"disabled":""}`,disabled:K},F("plug",{size:15}),"Install").on({click:()=>!K&&NA(Q,{actions:A.installActions})}))))}function N4(A,Q,B){return a({className:`review-warning ${A.status}`},a({className:"rw-head"},F("warn",{size:15}),LA(A.headline)),a({className:"rw-detail"},A.detail),A.requiresAcknowledgement?yX({className:"rw-ack"},hX({type:"checkbox",checked:!!Q.acknowledged}).on({change:(C)=>B({acknowledged:!!C.target.checked})}),LA("I know this package is unsigned and I trust where it came from")):null)}function P4(A){let Q=A.trust||{status:"unverified"};return a({className:"review-head"},a({className:"avatar"},(A.name||"?")[0].toUpperCase()),a({className:"rh-main"},a({className:"rh-name"},A.name,LA({className:"rh-ver"},"v"+A.version)),a({className:"rh-author"},"by "+A.author)),O4(Q))}function O4(A){let Q=nB(A),B=Q.status==="verified"&&Q.domain?`Verified · ${Q.domain}`:Q.status==="invalid"?"Invalid signature":Q.status==="signed"?"Signed":"Unverified";return LA({className:`trust ${Q.tone}`,title:Q.explanation},F(Q.icon,{size:13}),B)}function j4(A,Q,B,C){let E=A.adminOnly&&!Q;return yX({className:`cap-row ${E?"blocked":""}`},hX({type:"checkbox",checked:B&&!E,disabled:E}).on({change:()=>!E&&C()}),a({className:"cap-info"},a({className:"cap-name"},A.id,A.adminOnly?LA({className:"pf-badge",$styling:{color:"var(--warn)","margin-left":"6px"}},"admin only"):null),a({className:"cap-desc"},A.description+(E?" — requires an administrator":""))))}function w4(A){let Q={command:"command",opener:"file",indexer:"search",statusItem:"info",register:"info",keymap:"command"}[A.kind]||"command";return a({className:"contrib-row"},F(Q,{size:13}),LA({className:"cr-title"},A.title),A.detail?LA({className:"cr-detail"},A.detail):null,A.offline?LA({className:"pf-badge offline-ok"},"offline"):null,LA({className:"pf-kind"},A.kind))}function S4(A,Q){let B=Q?.platform?.contributions?.get?.(A),C=B?.pluginId?"plugin":B?"built-in":"not installed";return a({className:`contrib-row ${B?"":"blocked"}`},F("command",{size:13}),LA({className:"cr-title"},B?.title||A),LA({className:"cr-detail"},A),LA({className:"pf-kind"},C))}function _4(A){return a({className:"contrib-row"},F("plug",{size:13}),LA({className:"cr-title"},A.host),A.path?LA({className:"cr-detail"},A.path):null,LA({className:"pf-kind"},A.scheme))}function T4(A){let Q=[];if(A.plugin)Q.push(gX("Private database","A SQLite store just for this plugin (server + this device).",!1));if(A.domain)Q.push(gX("Shared database","Shared with other plugins from its domain (SQLite).",A.domainBlocked));return a({className:"contrib-list"},...Q)}function gX(A,Q,B){return a({className:`contrib-row ${B?"blocked":""}`},F("plug",{size:13}),LA({className:"cr-title"},A),LA({className:"cr-detail"},B?Q+" — needs a verified domain":Q),B?LA({className:"pf-badge",$styling:{color:"var(--warn)"}},"unavailable"):null)}function x4(A){return a({className:"contrib-row"},F("gear",{size:13}),LA({className:"cr-title"},A.title),A.secret?LA({className:"pf-badge",$styling:{color:"var(--warn)"}},"secret"):LA({className:"pf-kind"},A.type))}function yB(A,Q){return a({className:"review-section"},a({className:"rs-title"},A),Q)}function k4(A){return a({className:"muted",$styling:{"font-size":"12.5px"}},A)}var{div:w,span:uA,button:mA,input:cQ,h3:hK,p:EI,select:uX,option:q0,label:dQ,textarea:JI}=T;function mX(A,Q){let B=A.overlay.dialog;if(!B)return null;if(B.kind==="collection")return y4(B,Q,A.caps,A.view);if(B.kind==="plugin-review")return bX(B,Q,A.view);if(B.kind==="opener-chooser")return g4(B,Q);let C=sL(A.view,B),E=()=>{if(B.kind==="confirm")Q.engine.dispatch(new TA);NA(Q,{actions:B.confirmActions})};return w({},w({className:"scrim"}).on({click:()=>Q.engine.dispatch(new TA)}),w({className:"dialog"},hK(B.title),B.body?w({className:"body"},B.body):null,B.kind==="prompt"?w({className:"field"},B.label?uA({$styling:{"font-size":"12px",color:"var(--text-dim)"}},B.label):null,cQ({className:"input",value:C,placeholder:B.placeholder||"",autofocus:!0}).on({input:(J)=>Q.engine.dispatch(new QB(dB,{ref:B,value:J.target.value})),keydown:(J)=>{if(J.key==="Enter")E();if(J.key==="Escape")Q.engine.dispatch(new TA)},$attach:(J)=>queueMicrotask(()=>{J.focus(),J.select()})})):null,w({className:"row-actions"},mA({className:"btn"},"Cancel").on({click:()=>Q.engine.dispatch(new TA)}),mA({className:`btn ${B.danger?"danger":"primary"}`},B.confirmLabel||"OK").on({click:E}))))}function g4(A,Q){let B=A.openerId||A.current||A.openers[0]?.id,C=!!A.remember,E=()=>{if(C&&B)Q.engine.dispatch(new GC(J8(A.node),B));Q.engine.dispatch(new TA),Q.engine.dispatch(new GQ(A.node,B,{reset:!!A.reset}))};return w({},w({className:"scrim"}).on({click:()=>Q.engine.dispatch(new TA)}),w({className:"dialog opener-chooser"},hK(`Open “${A.node.name}” with…`),w({className:"opener-list"},...A.openers.map((J)=>dQ({className:`opener-opt ${J.id===B?"sel":""}`},cQ({type:"radio",name:"opener-choice",checked:J.id===B}).on({change:()=>Q.engine.dispatch(new QC({openerId:J.id}))}),F(J.icon||MQ(A.node),{size:18}),w({className:"oo-main"},uA({className:"oo-title"},J.title||J.id),uA({className:"oo-src"},J.source))).on({click:()=>Q.engine.dispatch(new QC({openerId:J.id}))}))),dQ({className:"opener-remember"},cQ({type:"checkbox",checked:C}).on({change:(J)=>Q.engine.dispatch(new QC({remember:J.target.checked}))}),uA(`Always use this for ${K8(A.node)}`)),w({className:"row-actions"},mA({className:"btn"},"Cancel").on({click:()=>Q.engine.dispatch(new TA)}),mA({className:"btn primary"},"Open").on({click:E}))))}var vX="collectionDialog";function y4(A,Q,B,C){let E=B?.storageDrivers||[],J={name:"",description:"",driver:E[0]?.key||"",encrypt:!1,encryptWhat:"all",encryptList:""},K=oC(C,vX,A,{form:J}),L=K.form,Y=E.find((I)=>I.key===L.driver)||E[0],X=(I)=>(R)=>{let V=R.target.type==="checkbox"?R.target.checked:R.target.value;Q.engine.dispatch(new eE(vX,K.ref,{[I]:V},J))},H=()=>{let I={driver:L.driver};for(let R of Y?.fields||[]){let V=L[R.name];if(V!==void 0&&V!=="")I[R.name]=R.type==="number"?Number(V):V}Q.engine.dispatch(new tE({name:L.name,description:L.description,store:I,encryption:h4(L)}))},G=(I,R,V="")=>w({className:"field",$styling:{"margin-bottom":"10px"}},dQ(I),cQ({className:"input",placeholder:V}).on({input:X(R)})),D=L.encrypt&&L.encryptWhat!=="all"&&!pX(L.encryptList).length?L.encryptWhat==="extensions"?"Name at least one extension, or choose every file.":"Name at least one media type, or choose every file.":null,U=!!L.name.trim()&&!!L.driver&&!D&&(Y?.fields||[]).every((I)=>!I.required||String(L[I.name]??"").trim());return w({},w({className:"scrim"}).on({click:()=>Q.engine.dispatch(new TA)}),w({className:"dialog",$styling:{width:"min(480px, 94vw)"}},hK("New collection"),w({className:"body"},"A collection is a backing store you own. Configure where its files live."),G("Name","name","Team Vault"),E.length?w({className:"field",$styling:{"margin-bottom":"10px"}},dQ("Backing store"),uX({className:"input"},...E.map((I)=>q0({value:I.key,selected:L.driver===I.key},I.label))).on({change:X("driver")})):w({className:"body"},"This server has no storage drivers registered, so a collection cannot be created."),Y?v4(Y,L,X):null,b4(L,X,B,D),w({className:"row-actions"},mA({className:"btn"},"Cancel").on({click:()=>Q.engine.dispatch(new TA)}),mA({className:"btn primary",$attrs:U?{}:{disabled:"true"}},"Create collection").on({click:()=>U&&H()}))))}function h4(A){if(!A.encrypt)return null;let Q=pX(A.encryptList);return{enabled:!0,rules:A.encryptWhat==="all"?{all:!0}:A.encryptWhat==="extensions"?{extensions:Q}:{mimeTypes:Q}}}function pX(A){return String(A||"").split(/[\s,]+/).map((Q)=>Q.trim()).filter(Boolean)}function b4(A,Q,B,C){let E=(B?.indexers||[]).filter((J)=>J.readsContent!==!1);return w({className:"field enc-section",$styling:{"margin-bottom":"10px"}},dQ({className:"enc-toggle"},cQ({type:"checkbox",checked:!!A.encrypt}).on({change:Q("encrypt")}),uA("Encrypt files in this collection")),!A.encrypt?w({className:"enc-hint"},"Files are stored exactly as uploaded."):w({className:"enc-body"},w({className:"field"},dQ("What to encrypt"),uX({className:"input"},q0({value:"all",selected:A.encryptWhat==="all"},"Every file"),q0({value:"extensions",selected:A.encryptWhat==="extensions"},"Only these extensions"),q0({value:"mimeTypes",selected:A.encryptWhat==="mimeTypes"},"Only these media types")).on({change:Q("encryptWhat")})),A.encryptWhat!=="all"?w({className:"field"},cQ({className:"input",value:A.encryptList,placeholder:A.encryptWhat==="extensions"?".pdf, .docx, .key":"image, application/pdf"}).on({input:Q("encryptList")}),w({className:"enc-hint"},A.encryptWhat==="extensions"?"Separated by commas. The leading dot is optional.":"Separated by commas. “image” covers every image type.")):null,C?w({className:"enc-problem"},F("warn",{size:13}),uA(C)):null,w({className:"enc-scope"},w({className:"es-title"},"What this does"),w({className:"es-line"},"Files are sealed in your browser before they are uploaded, so the storage provider only ever holds ciphertext."),w({className:"es-title"},"What it does not do"),w({className:"es-line"},"It is not end-to-end. The drive holds the key and decrypts for anything that reads through it — previews, downloads, and search indexing."),E.length?w({className:"es-line"},`These read file contents in the clear: ${E.map((J)=>J.title||J.id).join(", ")}.`):null,w({className:"es-line note"},"This applies to files uploaded from now on. Turning it off later does not decrypt anything already sealed."))))}function v4(A,Q,B){if(!A.fields.length)return w({className:"body",$styling:{"font-size":"12px"}},A.description||"This store needs no configuration.");return w({},A.description?w({className:"body",$styling:{"font-size":"12px","margin-bottom":"10px"}},A.description):null,...A.fields.map((C)=>C.type==="boolean"?w({className:"field",$styling:{"margin-bottom":"10px"}},dQ({},cQ({type:"checkbox"}).on({change:B(C.name)}),` ${C.label}`),C.help?w({className:"body",$styling:{"font-size":"11.5px"}},C.help):null):w({className:"field",$styling:{"margin-bottom":"10px"}},dQ(C.label+(C.required?"":" (optional)")),cQ({className:"input",placeholder:C.placeholder,autocomplete:"off",type:C.type==="password"||C.secret?"password":C.type==="number"?"number":"text"}).on({input:B(C.name)}),C.help?w({className:"body",$styling:{"font-size":"11.5px"}},C.help):null)))}var fX=220,f4=34,u4=20;function m4(A,Q){let{innerWidth:B,innerHeight:C}=window;if(!A)return{x:Math.round(B/2-fX/2),y:Math.round(C/3)};let E=A.rect?A.rect.left:A.x,J=A.rect?A.prefer==="up"?A.rect.top-8-Q:A.rect.bottom+8:A.y;return{x:Math.max(8,Math.min(E,B-fX)),y:Math.max(8,Math.min(J,C-Q))}}function lX(A,Q){let B=A.overlay.contextMenu;if(!B||!B.items?.length)return null;let C=Math.min(B.items.length*f4+u4,window.innerHeight-24),{x:E,y:J}=m4(B.at,C);return w({},w({className:"scrim",$styling:{background:"transparent"}}).on({click:()=>Q.engine.dispatch(new qB),contextmenu:(K)=>{K.preventDefault(),Q.engine.dispatch(new qB)}}),w({className:"menu",$styling:{left:E+"px",top:J+"px"}},...B.items.map((K,L)=>K.sep?w({className:"sep"}):mA({className:`mi ${K.danger?"danger":""}`,autofocus:L===0},K.icon?F(K.icon,{size:15}):null,uA(K.label),K.kbd?uA({className:"kbd"},K.kbd):null).on({click:()=>{Q.engine.dispatch(new qB),NA(Q,K)},keydown:(Y)=>{if(Y.key==="Escape")Y.preventDefault(),Q.engine.dispatch(new qB)},$attach:(Y)=>{if(L===0)queueMicrotask(()=>Y.focus())}}))))}function cX(A,Q){let B=A.notif||[];if(!B.length)return null;return w({className:"toasts"},...B.slice(-5).map((C)=>w({className:`toast ${C.level}`},w({className:"bar"}),w({className:"msg"},C.message),mA({className:"x"},F("close",{size:14})).on({click:()=>Q.engine.dispatch(new PE(C.id))})).key(C.id)))}function dX(A,Q){let B=A.tr.items;if(!B.length)return null;return w({className:"tray"},w({className:"head"},F("upload",{size:14}),uA({$styling:{"margin-left":"6px"}},"Transfers"),w({className:"actions"},mA({className:"iconbtn",title:"Clear finished"},F("check",{size:14})).on({click:()=>Q.engine.dispatch(new vE)}))),w({className:"items"},...B.map((C)=>w({className:`xfer ${C.status}`},w({className:"top"},F(C.status==="error"?"warn":C.status==="done"?"check":"upload",{size:14}),uA({className:"name"},C.name),C.status==="active"?mA({className:"iconbtn",title:"Cancel"},F("close",{size:13})).on({click:()=>Q.engine.dispatch(new LC(C.id))}):uA({className:"pct"},C.status==="done"?EA(C.total):C.status)),C.status==="active"?w({className:"progress"},w({$styling:{width:`${Math.round(C.ratio*100)}%`}})):C.error?w({$styling:{"font-size":"11px",color:"var(--danger)","margin-top":"4px"}},C.error):null,C.status==="active"?w({className:"pct",$styling:{"margin-top":"4px"}},`${EA(C.loaded)} / ${EA(C.total)}`):null,(C.status==="error"||C.status==="cancelled")&&C.retryable?w({className:"xfer-actions"},mA({className:"btn small"},F("refresh",{size:12}),uA("Retry")).on({click:()=>Q.engine.dispatch(new hE(C.id))}),mA({className:"btn small ghost"},"Dismiss").on({click:()=>Q.engine.dispatch(new bE(C.id))})):null).key(C.id))))}function aX(A,Q){let B=A.overlay.pluginPanel;if(!B)return null;let C=(A.plugins||[]).find((E)=>E.id===B);return w({className:"plugin-panel",$styling:{width:"380px"}},w({className:"head"},F("plug",{size:14}),uA(C?.name||B),mA({className:"iconbtn x"},F("close",{size:14})).on({click:()=>Q.engine.dispatch(new TE)})),w({className:"host"}).on({$attach:(E)=>{E._detach=Q.platform.plugins.mountPanel(B,E,{width:380,height:460})},$detach:(E)=>E._detach?.()}))}var{div:d,button:NQ,span:PC,h3:p4,p:nX,pre:l4}=T,c4={running:"refresh",done:"check",failed:"close",cancelled:"close"};function d4(A,Q){Q.engine.dispatch(new tA(A))}function sX(A){if(A.total==null)return null;return A.unit==="bytes"?`${EA(A.done||0)} of ${EA(A.total)}`:`${A.done||0} of ${A.total}${A.unit?` ${A.unit}`:""}`}function oX(A,Q){let B=A.status==="running",C=B&&A.total!=null&&A.total>0,E=C?Math.min(100,Math.round((A.done||0)/A.total*100)):0;return d({className:`act-task act-${A.status}`,"data-task-id":A.id},d({className:"act-row"},B?d({className:"spinner",$styling:{width:"12px",height:"12px"}}):F(c4[A.status]||"info",{size:13}),d({className:"act-body"},d({className:"act-title"},A.title),A.detail?d({className:"act-detail"},A.detail):null,A.error?d({className:"act-error"},A.error):null),B&&A.cancellable?NQ({className:"act-action",title:"Cancel"},F("close",{size:12})).on({click:()=>Q.engine.dispatch(new xE(A.id))}):!B?NQ({className:"act-action",title:"Dismiss"},F("close",{size:12})).on({click:()=>Q.engine.dispatch(new kE(A.id))}):null),B?d({className:`act-bar ${C?"":"indeterminate"}`},d({className:"act-fill",$styling:C?{width:`${E}%`}:{}})):null,B&&sX(A)?d({className:"act-amount"},sX(A)):null)}function a4(A,Q){let B=new Date(A.firstAt||A.lastAt).toLocaleString();return d({className:`act-issue act-sev-${A.severity||"error"}`,"data-issue-id":A.id},d({className:"act-row"},F(A.severity==="warning"?"info":"close",{size:13}),d({className:"act-body"},d({className:"act-title"},A.title),A.detail?d({className:"act-detail"},A.detail):null,A.remedy?l4({className:"act-remedy"},A.remedy):null,d({className:"act-meta"},A.count>1?`${A.count} times, since ${B}`:`since ${B}`))),d({className:"act-actions"},A.remedy?NQ({className:"btn small ghost"},"Copy fix").on({click:()=>d4(A.remedy,Q)}):null,A.retryable?NQ({className:"btn small act-retry"},F("refresh",{size:12}),PC("Retry")).on({click:()=>Q.engine.dispatch(new gE(A.id))}):null,NQ({className:"btn small ghost act-dismiss"},"Dismiss").on({click:()=>Q.engine.dispatch(new yE(A.id))})))}function bK(A,Q){let B=A.act||{tasks:[],issues:[]};if(!A.overlay.activityPanel)return null;let C=B.tasks.filter((J)=>J.status==="running"),E=B.tasks.filter((J)=>J.status!=="running");return d({className:"activity-panel"},d({className:"act-head"},p4("Activity"),NQ({className:"act-action",title:"Close"},F("close",{size:13})).on({click:()=>Q.engine.dispatch(new wA(!1))})),B.tasksError||B.issuesError?d({className:"act-offline"},F("info",{size:12}),PC(`Couldn't reach the server — this list may be out of date (${B.issuesError||B.tasksError})`)):null,d({className:"act-section"},d({className:"act-section-title"},"Running"),C.length?d(...C.map((J)=>oX(J,Q))):nX({className:"act-empty"},"Nothing running.")),B.issues.length?d({className:"act-section"},d({className:"act-section-title"},`Needs attention (${B.issues.length})`),d(...B.issues.map((J)=>a4(J,Q)))):d({className:"act-section"},d({className:"act-section-title"},"Needs attention"),nX({className:"act-empty"},B.issuesError?"Could not load the list of problems.":B.issuesLoading?"Checking…":"No standing problems.")),E.length?d({className:"act-section"},d({className:"act-section-title"},"Recently finished"),d(...E.map((J)=>oX(J,Q)))):null,d({className:"act-foot act-actions"},NQ({className:"btn small ghost act-rebuild"},F("refresh",{size:12}),PC("Rebuild search index")).on({click:()=>Q.engine.dispatch(new N("workbench.rebuildIndex"))}),NQ({className:"btn small ghost act-scan"},F("refresh",{size:12}),PC("Scan for outside changes")).on({click:()=>Q.engine.dispatch(new N("workbench.scanCollection"))}),NQ({className:"btn small ghost act-storage"},F("plug",{size:12}),PC("Check storage")).on({click:()=>Q.engine.dispatch(new N("workbench.checkStorage"))})))}var{div:ZA,button:LB,span:WQ,img:tX}=T,iX=[{id:"home",icon:"search",label:"Files",command:"workbench.view.home"},{id:"upload",icon:"upload",label:"Upload",command:"explorer.upload"},{id:"plugins",icon:"plug",label:"Plugins",command:"workbench.view.plugins"}],rX={offline:{icon:"info",tone:"warn"},issues:{icon:"warn",tone:"danger"},working:{spinner:!0,tone:""},lowSpace:{icon:"info",tone:"warn"},idle:{icon:"info",tone:""}};function eX(A,Q){let B=A.facts,C=B.condition,E={...rX[C.kind]||rX.idle,label:C.label,badge:C.kind==="issues"?C.count:0},J=A.wb.activity==="settings"?"Settings":A.wb.activity==="plugins"?"Plugins":B.collectionLabel;return ZA({className:"phonebar top"},LB({className:"pb-brand",title:"Trove — home"},tX({src:"/icon.svg",alt:"Trove"})).on({click:()=>Q.engine.dispatch(new N("workbench.view.home"))}),ZA({className:"pb-title"},J),LB({className:`pb-status ${E.tone}`,title:E.label,$attrs:{"aria-label":E.label}},E.spinner?ZA({className:"spinner",$styling:{width:"15px",height:"15px"}}):F(E.icon,{size:18}),E.badge?WQ({className:"pb-badge"},String(E.badge>9?"9+":E.badge)):null).on({click:()=>Q.engine.dispatch(new Q0("status"))}))}function A1(A,Q){let B=A.wb.activity,C=A.wb.sheet,E=A.so.notifications.unread;return ZA({className:"phonebar bottom"},...iX.map((J)=>LB({className:`pb-tab ${!C&&B===J.id?"active":""}`,$attrs:{"aria-label":J.label}},F(J.icon,{size:21}),WQ({className:"pb-label"},J.label)).on({click:()=>{Q.engine.dispatch(new nA),Q.engine.dispatch(new N(J.command))}})),LB({className:`pb-tab ${C==="more"||!C&&!iX.some((J)=>J.id===B)?"active":""}`,$attrs:{"aria-label":"More"}},F("dots",{size:21}),E?WQ({className:"pb-badge"},String(E>9?"9+":E)):null,WQ({className:"pb-label"},"More")).on({click:()=>Q.engine.dispatch(new Q0("more"))}))}function SA({icon:A,label:Q,value:B,danger:C,onClick:E}){let J=[F(A,{size:18}),WQ({className:"sr-label"},Q),B!=null?WQ({className:"sr-value"},B):null,E?F("chevron-right",{size:16,className:"sr-go"}):null];return E?LB({className:`sheet-row ${C?"danger":""}`},...J).on({click:E}):ZA({className:"sheet-row static"},...J)}function Q1(A,Q){let B=A.wb.sheet;if(!B)return null;return ZA({className:"sheet-wrap"},ZA({className:"scrim"}).on({click:()=>Q.engine.dispatch(new nA)}),ZA({className:"sheet"},ZA({className:"sheet-grip"}).on({click:()=>Q.engine.dispatch(new nA)}),B==="status"?n4(A,Q):s4(A,Q)))}function n4(A,Q){let B=A.facts,C=(E)=>()=>{Q.engine.dispatch(new nA),Q.engine.dispatch(new N(E))};return ZA({className:"sheet-body"},ZA({className:"sheet-title"},B.collectionLabel),B.issues.length?SA({icon:"warn",danger:!0,label:`${B.issues.length} need${B.issues.length===1?"s":""} attention`,onClick:()=>{Q.engine.dispatch(new nA),Q.engine.dispatch(new wA(!0))}}):null,B.running.length||B.uploading.length?SA({icon:"refresh",label:`${B.running.length+B.uploading.length} running`,onClick:()=>{Q.engine.dispatch(new nA),Q.engine.dispatch(new wA(!0))}}):null,!B.off.online?SA({icon:"info",label:"Offline",value:`${B.off.pins.length} pinned`}):null,B.off.queued?SA({icon:"upload",label:"Waiting to sync",value:String(B.off.queued)}):null,SA({icon:"files",label:"Items",value:B.partial?`${B.shown.toLocaleString()} of ${B.totalKnown?B.totalItems.toLocaleString():"more"}`:B.totalItems.toLocaleString()}),SA({icon:"file",label:"Size",value:`${EA(B.totalBytes)}${B.totalKnown||!B.partial?"":"+"}`}),B.usage?.total?ZA({className:"sheet-row static usage"},F("download",{size:18}),WQ({className:"sr-label"},"Free space"),ZK(B)):null,A.caps?SA({icon:A.caps.storage?.presignDownload?"download":"files",label:"Transfers",value:A.caps.storage?.presignDownload?"Direct to storage":"Through the server"}):null,A.caps?.features?.semanticSearch?SA({icon:"star",label:"Search",value:"Semantic + keyword"}):null,ZA({className:"sheet-actions"},LB({className:"btn small ghost"},F("refresh",{size:13}),WQ("Scan for changes")).on({click:C("workbench.scanCollection")}),LB({className:"btn small ghost"},F("refresh",{size:13}),WQ("Activity")).on({click:()=>{Q.engine.dispatch(new nA),Q.engine.dispatch(new wA(!0))}})))}function s4(A,Q){let B=(J)=>()=>{Q.engine.dispatch(new nA),Q.engine.dispatch(new N(J))},C=A.so.me,E=A.so.notifications.unread;return ZA({className:"sheet-body"},C&&!C.anonymous?ZA({className:"sheet-me"},C.picture?tX({src:C.picture,alt:"",className:"avatar-img"}):WQ({className:"avatar-txt"},(C.name||C.id||"?")[0].toUpperCase()),ZA({},ZA({className:"sm-name"},C.name||C.id),C.email?ZA({className:"sm-sub"},C.email):null)):null,SA({icon:"bell",label:E?`Notifications (${E})`:"Notifications",onClick:()=>{Q.engine.dispatch(new nA),Q.engine.dispatch(new qQ(!0))}}),SA({icon:"refresh",label:"Activity & problems",onClick:()=>{Q.engine.dispatch(new nA),Q.engine.dispatch(new wA(!0))}}),SA({icon:"info",label:"Details & conversation",onClick:B("workbench.toggleInfoPanel")}),SA({icon:"trash",label:"Trash",onClick:B("explorer.showTrash")}),SA({icon:"refresh",label:"Refresh",onClick:B("explorer.refresh")}),SA({icon:"command",label:"All commands",onClick:B("workbench.showCommandPalette")}),SA({icon:"gear",label:"Settings",onClick:B("workbench.openSettings")}))}var{alias:o4,div:UQ}=T;function vK({engine:A,platform:Q}){let B={engine:A,platform:Q,watch:CQ},C=BA([s(A,FC),s(A,IC),s(A,JK),s(A,WC),s(A,QK),s(A,jY),s(A,W0),s(A,Z0),s(A,wY),s(A,SY),s(A,KK),s(A,MC),s(A,uY),s(A,LK(!1)),s(A,LK(!0)),s(A,hY),s(A,yY)],(K,L,Y,X,H,G,D,U,I,R,V,_,m,b,q,p,k)=>({wb:K,overlay:L,nav:Y,ex:X,se:H,ctx:G,settings:D,off:U,vp:I,voice:R,view:V,caps:_,commandKeys:m,content:b,modalContent:q,views:p,openers:k})),E={ex:WC,tr:BK,act:D0,off:Z0,so:UC,wb:FC,statusItems:xY,caps:MC,facts:gY},J={statusBar:zA(A,E,(K)=>WK(K,B),{placeholder:()=>UQ({className:"statusbar"})}),phoneTopBar:zA(A,E,(K)=>eX(K,B),{placeholder:()=>UQ({className:"phonebar top"})}),phoneBottomBar:zA(A,E,(K)=>A1(K,B),{placeholder:()=>UQ({className:"phonebar bottom"})}),phoneSheet:zA(A,E,(K)=>Q1(K,B)),transferTray:zA(A,{tr:BK},(K)=>dX(K,B)),toasts:zA(A,{notif:PY},(K)=>cX(K,B)),activityPanel:zA(A,{act:D0,overlay:IC},(K)=>bK(K,B)),pluginPanel:zA(A,{overlay:IC,plugins:RC},(K)=>aX(K,B)),settingsView:zA(A,{settings:W0,settingsGroups:OY,keys:NY,caps:MC,ex:WC,assoc:vY},(K)=>VK(K,B,J)),keybindings:zA(A,{bindings:kY,view:KK},(K)=>WX(K.bindings||[],B,K.view?.[qK]??null)),pluginsView:zA(A,{plugins:RC,settings:W0},(K)=>jK(K,B)),adminView:zA(A,{caps:MC,ex:WC,plugins:RC,act:D0,so:UC,wb:FC},(K)=>SK(K,B)),infoPanel:zA(A,{so:UC,off:Z0,nav:JK},(K)=>dY(K,B)),activityBar:zA(A,{wb:FC,plugins:RC,so:UC},(K)=>DK(K,B)),commandPalette:zA(A,{overlay:IC,se:QK,matches:TY},(K)=>yK(K,B))};return o4(()=>CQ(C,(K)=>i4(K,B,J)))}function i4(A,Q,B){let C=A.vp?.mode||"desktop",E=C==="phone";return UQ({className:`shell ${C} ${A.settings["workbench.density"]==="compact"?"compact":""}`},E?B.phoneTopBar():null,UQ({className:"body"},E?null:B.activityBar(),r4(A,Q,B)),E?B.phoneBottomBar():B.statusBar(),E?B.phoneSheet():null,t4(A,Q),B.commandPalette(),mX(A,Q),lX(A,Q),B.pluginPanel(),B.toasts(),B.transferTray(),B.activityPanel())}function r4(A,Q,B){if(A.ex?.gate&&A.wb.activity!=="settings")return PK(A,Q);switch(A.wb.activity){case"settings":return B.settingsView();case"plugins":return B.pluginsView();case"admin":return B.adminView();default:{if(!A.nav.activeTabId)return R0(A,Q);if(!A.wb.infoPanel)return V0(A,Q);return A.vp?.mode==="phone"?B.infoPanel():UQ({className:"editor-split"},V0(A,Q),B.infoPanel())}}}function t4(A,Q){if(!A.wb.searchModal)return UQ();return UQ({className:"search-modal"},UQ({className:"scrim"}).on({click:()=>Q.engine.dispatch(new zB)}),UQ({className:"search-modal-panel"},R0(A,Q,{modal:!0})))}function C1({root:A=document.querySelector(".workbench"),baseUrl:Q="",openers:B=[],views:C=[],settings:E=[],serviceWorker:J=!0,debug:K=globalThis.__troveDebug===!0}={}){let L=EY({baseUrl:Q}),{engine:Y,app:X}=DY(L);if(jX(L),KX(L),B1(L,"opener",B),B1(L,"view",C),E.length)L.settings.register(E);L.plugins.restore();let H=vK({engine:Y,platform:L});T.reconcile(A,[H()]);let G=()=>{document.documentElement.dataset.theme=L.settings.get("workbench.theme")||"dark"};if(G(),TQ(L.settings.observe(),()=>G()),L.viewport.install(),L.voice.refresh().catch(()=>{}),L.spatialNav.install(),L.keybindings.install(window),window.addEventListener("popstate",(D)=>X.navigation.onPopState(D)),AW(Y),J&&"serviceWorker"in navigator)window.addEventListener("load",()=>navigator.serviceWorker.register("/sw.js").catch(()=>{}));if(QW(Y),Y.dispatch(new RE),K)e4({platform:L,engine:Y,app:X});return{platform:L,engine:Y,app:X}}function e4({platform:A,engine:Q,app:B}){window.__trove={platform:A,engine:Q,app:B,test:{parsePackage:tQ,assessTrust:(C)=>A.plugins.assessTrust(C),install:(C,E)=>A.plugins.install(C,E),NavigateAction:hA,open:(C,E)=>A.dispatch(new GQ(C,E)),contextMenu:(C,E)=>A.dispatch(new $Q(C,E)),attachMedia:SB}}}function B1(A,Q,B){for(let C of B){if(!C?.id)throw Error(`A ${Q} passed to createWorkbench needs an "id"`);let{id:E,...J}=C;A.contributions.register(E,{type:Q,...J})}}function AW(A){let Q=0;window.addEventListener("keydown",(B)=>{if(B.key==="Shift"&&!B.repeat){let C=Date.now();if(C-Q<400)A.dispatch(new wE),Q=0;else Q=C}else if(B.key!=="Shift")Q=0})}function QW(A){let Q=0;window.addEventListener("dragenter",(B)=>{if(!B.dataTransfer?.types.includes("Files"))return;Q++,document.body.classList.add("dragging-file")}),window.addEventListener("dragover",(B)=>{if(B.dataTransfer?.types.includes("Files"))B.preventDefault()}),window.addEventListener("dragleave",()=>{if(--Q<=0)Q=0,document.body.classList.remove("dragging-file")}),window.addEventListener("drop",(B)=>{if(!B.dataTransfer?.files?.length)return;B.preventDefault(),Q=0,document.body.classList.remove("dragging-file"),A.dispatch(new eB(B.dataTransfer.files))})}C1();
|
|
740
|
-
|
|
741
|
-
//# debugId=09842CF07C72A8E664756E2164756E21
|
|
742
|
-
//# sourceMappingURL=main-axerf2vw.js.map
|