diff --git a/main.js b/main.js index a6576ba..55f145c 100644 --- a/main.js +++ b/main.js @@ -1,139 +1,140 @@ -"use strict";var Vs=Object.defineProperty;var sr=Object.getOwnPropertyDescriptor;var nr=Object.getOwnPropertyNames;var or=Object.prototype.hasOwnProperty;var Gt=(c,a)=>()=>(c&&(a=c(c=0)),a);var Xe=(c,a)=>{for(var t in a)Vs(c,t,{get:a[t],enumerable:!0})},ar=(c,a,t,e)=>{if(a&&typeof a=="object"||typeof a=="function")for(let i of nr(a))!or.call(c,i)&&i!==t&&Vs(c,i,{get:()=>a[i],enumerable:!(e=sr(a,i))||e.enumerable});return c};var rr=c=>ar(Vs({},"__esModule",{value:!0}),c);function Ws(c){return Array.isArray(c)?c.filter(a=>typeof a=="string"):typeof c=="string"?c.split(/[,\s]+/).filter(Boolean):[]}function be(c,a){let t=a.replace(/^#/,"");return Ws(c?.tags).some(e=>e.replace(/^#/,"")===t)}function Xs(c,a){let t=a.replace(/^#/,""),e=Ws(c.tags);e.some(i=>i.replace(/^#/,"")===t)||e.push(t),c.tags=e}function Zs(c,a){let t=a.replace(/^#/,""),e=Ws(c.tags).filter(i=>i.replace(/^#/,"")!==t);e.length?c.tags=e:delete c.tags}function Ne(c){return c.split("/").some(a=>Ze.has(a))}function lo(c){return c.split("/").some(a=>a==="_archive"||a===".archive")}function Rt(c){let a=(c??"").trim();return!a||/^\[\[.*\]\]$/.test(a)?a:`[[${a}]]`}function Be(c){let a=(c??"").trim(),t=a.match(/^\[\[(.*)\]\]$/);return t&&(a=t[1]),a.split("|")[0].split("#")[0].split("^")[0].trim()}function co(c){let a=c.match(/\.([^./]+)$/);return!!a&&Ar.has(a[1].toLowerCase())}function ho(c,a){if(!Array.isArray(a))return!1;for(let t of a){let e=(t??"").trim();if(e){if(e.length>2&&e.startsWith("/")&&e.endsWith("/"))try{if(new RegExp(e.slice(1,-1)).test(c))return!0}catch{}else if(c===e||c.startsWith(e.endsWith("/")?e:e+"/"))return!0}}return!1}function Hi(c,a){let t=c.toLowerCase().split(/\s+/).filter(Boolean);if(t.length===0)return!0;let e=a.toLowerCase();return t.every(i=>e.includes(i))}function ne(c){if(typeof c!="string")return null;let a=c.replace(/^\[\[/,"").replace(/\]\]$/,""),[t,e]=a.split("|"),i=t.match(/_authors\/(.+?)-([a-z0-9]{4,12})(?:\.md)?$/i);if(!i)return null;let s=i[2],n=(e??"").trim()||i[1].replace(/-/g," ").trim();return{id:s,name:n}}function me(c){let a=c?.assignedTo,t=Array.isArray(a)?a:a!=null?[a]:[],e=[];for(let i of t){let s=ne(i);s&&e.push(s)}return e}var J,ie,fe,Ce,De,F,se,Ze,Ar,rt=Gt(()=>{"use strict";J="stashpad-view",ie="stashpad-panels",fe="stashpad-folder-panel",Ce="stashpad-detail",De="stashpad-trash",F="__root__";se=["id","parent","created","modified","attachments","position","author","contributors","parentLink","children","due","assignedTo","assignedBy","pinned","pinnedAt","imported","okfParent","okfChildren"],Ze=new Set(["_attachments","_authors","_exports","_imports","_processed","_archive",".archive"]);Ar=new Set(["edtz"])});function _e(c,a){let t=c.replace(/\r\n/g,` +"use strict";var sn=Object.defineProperty;var fr=Object.getOwnPropertyDescriptor;var Cr=Object.getOwnPropertyNames;var Br=Object.prototype.hasOwnProperty;var Lt=(c,a)=>()=>(c&&(a=c(c=0)),a);var ii=(c,a)=>{for(var t in a)sn(c,t,{get:a[t],enumerable:!0})},mr=(c,a,t,e)=>{if(a&&typeof a=="object"||typeof a=="function")for(let i of Cr(a))!Br.call(c,i)&&i!==t&&sn(c,i,{get:()=>a[i],enumerable:!(e=fr(a,i))||e.enumerable});return c};var Qr=c=>mr(sn({},"__esModule",{value:!0}),c);function nn(c){return Array.isArray(c)?c.filter(a=>typeof a=="string"):typeof c=="string"?c.split(/[,\s]+/).filter(Boolean):[]}function Te(c,a){let t=a.replace(/^#/,"");return nn(c?.tags).some(e=>e.replace(/^#/,"")===t)}function on(c,a){let t=a.replace(/^#/,""),e=nn(c.tags);e.some(i=>i.replace(/^#/,"")===t)||e.push(t),c.tags=e}function an(c,a){let t=a.replace(/^#/,""),e=nn(c.tags).filter(i=>i.replace(/^#/,"")!==t);e.length?c.tags=e:delete c.tags}function He(c){return c.split("/").some(a=>si.has(a))}function Bo(c){return c.split("/").some(a=>a==="_archive"||a===".archive")}function qt(c){let a=(c??"").trim();return!a||/^\[\[.*\]\]$/.test(a)?a:`[[${a}]]`}function Ee(c){let a=(c??"").trim(),t=a.match(/^\[\[(.*)\]\]$/);return t&&(a=t[1]),a.split("|")[0].split("#")[0].split("^")[0].trim()}function mo(c){let a=c.match(/\.([^./]+)$/);return!!a&&yr.has(a[1].toLowerCase())}function Qo(c,a){if(!Array.isArray(a))return!1;for(let t of a){let e=(t??"").trim();if(e){if(e.length>2&&e.startsWith("/")&&e.endsWith("/"))try{if(new RegExp(e.slice(1,-1)).test(c))return!0}catch{}else if(c===e||c.startsWith(e.endsWith("/")?e:e+"/"))return!0}}return!1}function Ji(c,a){let t=c.toLowerCase().split(/\s+/).filter(Boolean);if(t.length===0)return!0;let e=a.toLowerCase();return t.every(i=>e.includes(i))}function re(c){if(typeof c!="string")return null;let a=c.replace(/^\[\[/,"").replace(/\]\]$/,""),[t,e]=a.split("|"),i=t.match(/_authors\/(.+?)-([a-z0-9]{4,12})(?:\.md)?$/i);if(!i)return null;let s=i[2],n=(e??"").trim()||i[1].replace(/-/g," ").trim();return{id:s,name:n}}function we(c){let a=c?.assignedTo,t=Array.isArray(a)?a:a!=null?[a]:[],e=[];for(let i of t){let s=re(i);s&&e.push(s)}return e}var J,oe,Qe,ye,Me,F,ae,si,yr,rt=Lt(()=>{"use strict";J="stashpad-view",oe="stashpad-panels",Qe="stashpad-folder-panel",ye="stashpad-detail",Me="stashpad-trash",F="__root__";ae=["id","parent","created","modified","attachments","position","author","contributors","parentLink","children","due","assignedTo","assignedBy","pinned","pinnedAt","listPinned","listPinnedAt","imported","okfParent","okfChildren"],si=new Set(["_attachments","_authors","_exports","_imports","_processed","_archive",".archive"]);yr=new Set(["edtz"])});function oi(c,a){let t=c.replace(/\r\n/g,` `);if(a==="lines")return t.split(` `).map(n=>n.trim()).filter(Boolean);if(a==="paragraphs")return t.split(/\n[ \t]*\n+/).map(n=>n.trim()).filter(Boolean);let e=[],i=[],s=n=>/^#{1,6}\s/.test(n);for(let n of t.split(` `))s(n)&&i.some(o=>o.trim())&&(e.push(i.join(` `).trim()),i=[]),i.push(n);return i.some(n=>n.trim())&&e.push(i.join(` -`).trim()),e.filter(Boolean)}function oe(c,a,t){c.empty();try{(0,uo.setIcon)(c,a)}catch{}let e=c.querySelector("svg");e&&e.querySelector("path, line, circle, rect, polyline, polygon, ellipse")||(c.empty(),c.createSpan({cls:"stashpad-icon-fallback",text:t}))}function fo(c){if(c instanceof Element&&c.closest(".modal, .modal-container, .suggestion-container, .menu, .prompt"))return!0;let a=new Set([document]);c instanceof Element&&c.ownerDocument&&a.add(c.ownerDocument);for(let t of a)if(t.body?.querySelector(".modal-bg")||t.body?.querySelector(".modal-container .modal")||t.body?.querySelector(".suggestion-container")||t.body?.querySelector(".menu.mod-active"))return!0;return!1}function Co(c){let a=[],t=/^([ \t]*)(`{3,})[ \t]*([^\n`]*)\n([\s\S]*?)\n\1\2[ \t]*$/gm,e;for(;(e=t.exec(c))!=null;)a.push({lang:e[3].trim(),code:e[4]});return a}function ti(c){return c.split("/").map(a=>a.split(" ").map(t=>t&&/^[a-z]/.test(t)?t[0].toUpperCase()+t.slice(1):t).join(" ")).join("/")}function Bo(c,a,t){let e=new Set(a),i=c.filter(n=>!e.has(n)),s=c.findIndex(n=>e.has(n));if(s<0)return c.slice();switch(t){case"top":return[...a,...i];case"bottom":return[...i,...a];case"up":{let n=Math.max(0,s-1),o=i.slice();return o.splice(n,0,...a),o}case"down":{let n=(()=>{let l=-1;return c.forEach((d,g)=>{e.has(d)&&(l=g)}),l})(),o=0;for(let l=0;l{"use strict";uo=require("obsidian"),je={lines:"Each line",paragraphs:"Paragraphs (blank line)",headings:"Headings"}});function lr(c,a){return c>12?c>=24?0:c:a==="am"?c===12?0:c:c===12?12:c+12}function Ui(c,a){c.addClass("stashpad-when-pop-time");let t=a.seedPeriod,e=c.createDiv({cls:"stashpad-when-time-display"}),i=e.createEl("input",{cls:"stashpad-when-time-field",attr:{type:"text",inputmode:"numeric",maxlength:"2"}});i.value=String(a.seedH),e.createSpan({cls:"stashpad-when-time-colon",text:":"});let s=e.createEl("input",{cls:"stashpad-when-time-field",attr:{type:"text",inputmode:"numeric",maxlength:"2"}});s.value=String(a.seedM).padStart(2,"0");let n=e.createDiv({cls:"stashpad-when-time-period"}),o=n.createEl("button",{cls:"stashpad-when-time-ampm",text:"AM"});o.type="button";let r=n.createEl("button",{cls:"stashpad-when-time-ampm",text:"PM"});r.type="button";let A=()=>{o.toggleClass("is-active",t==="am"),r.toggleClass("is-active",t==="pm")};A(),o.addEventListener("mousedown",m=>m.preventDefault()),r.addEventListener("mousedown",m=>m.preventDefault()),o.addEventListener("click",m=>{m.preventDefault(),t="am",A()}),r.addEventListener("click",m=>{m.preventDefault(),t="pm",A()});let l=i;i.addEventListener("focus",()=>{l=i,i.select()}),s.addEventListener("focus",()=>{l=s,s.select()});let d=()=>{let w=(parseInt(i.value||"0",10)||0)>12;o.toggleClass("is-disabled",w),r.toggleClass("is-disabled",w),o.disabled=w,r.disabled=w},g=m=>{let w=m.value.replace(/\D/g,"").slice(0,2);if(w===""){m.value="",m===i&&d();return}let Q=parseInt(w,10);m===i?Q>24&&(Q=24):Q>59&&(Q=59),m.value=String(Q),m===i&&d()};for(let m of[i,s])m.addEventListener("input",()=>g(m));d();let p=()=>{let m=parseInt(i.value||"12",10)||12,w=parseInt(s.value||"0",10)||0,Q=m>12;a.onFinalize({hours24:lr(m,t),minutes:w,raw:{hh:m,mm:w,period:t,is24:Q}}),a.close()};a.setOnEnter?.(p);let h=[i,s,o,r],I=(m,w)=>{let Q=h.indexOf(m);if(Q===-1)return;let E=(Q+w+h.length)%h.length;h[E].focus()},u=m=>{m.addEventListener("keydown",w=>{w.key==="Enter"?(w.preventDefault(),w.stopPropagation(),p()):w.key==="Escape"?(w.preventDefault(),w.stopPropagation(),a.close()):w.key==="Tab"&&(w.preventDefault(),w.stopPropagation(),I(m,w.shiftKey?-1:1))})},f=c.createDiv({cls:"stashpad-when-time-pad"}),C=["1","2","3","4","5","6","7","8","9","backspace","0","insert"],B=null;for(let m of C){let w=f.createEl("button",{cls:"stashpad-when-time-padbtn"});w.type="button",m==="backspace"?(0,mo.setIcon)(w,"delete"):m==="insert"?(w.setText("OK"),B=w):w.setText(m),m==="insert"&&w.addClass("is-go"),w.addEventListener("mousedown",Q=>Q.preventDefault()),w.addEventListener("click",Q=>{if(Q.preventDefault(),m==="insert"){p();return}if(m==="backspace"){l.value=l.value.slice(0,-1),g(l),l.focus();return}let E=l.selectionStart===0&&l.selectionEnd===l.value.length&&l.value.length>0,v=2,y=E||l.value.length>=v?m:l.value+m;l.value=y,g(l),l.focus(),l.setSelectionRange(l.value.length,l.value.length),l===i&&l.value.length>=v&&(s.focus(),s.select())})}B&&h.push(B);for(let m of h)u(m);i.focus(),i.select()}function Qo(c){let{hh:a,mm:t,period:e,is24:i}=c.raw;return i?`${a}:${String(t).padStart(2,"0")}`:`${a}:${String(t).padStart(2,"0")}${e}`}var mo,_s=Gt(()=>{"use strict";mo=require("obsidian")});function Eo(c){let a=Math.floor(4294967296/c)*c,t=new Uint32Array(1),e;do crypto.getRandomValues(t),e=t[0];while(e>=a);return e%c}function tn(c=5){let a=[];for(let t=0;t=1&&s.every(r=>/^[a-zA-Z]+$/.test(r))&&(i=Math.min(i,s.length*11)),cr.has(c.toLowerCase())&&(i=Math.min(i,12));let n=i<36?0:i<56?1:i<76?2:3,o=["Weak \u2014 easily guessed","Fair","Good","Strong"][n];return{bits:i,level:n,label:o}}function dr(c){let a=2166136261;for(let t=0;t>>0).toString(16).padStart(8,"0")}function ii(c){let a="stashpad-",t=dr(c),e=64-a.length-1-t.length,i=c.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,Math.max(0,e)).replace(/-+$/g,"");return`${a}${i}-${t}`}var yo,cr,Gi=Gt(()=>{"use strict";yo="able acid acorn actor adept agile alarm album alert algae amber amble anchor angle ankle apple april arbor arc arctic arena armor arrow ascot aspen atlas atom attic auburn audio autumn award axis bacon badge bagel baker balmy bamboo banjo barge basil basin batch beach beam bean bear beaver begin belt bench berry birch bison black blade blaze bliss bloom blue board boat bold bolt bonus boost booth borax bother bottle boulder bounce bovine bowl brave bread breeze brick bridge brisk broad bronze brook broom brown brush bubble bucket bug bulb bundle burst cabin cable cacao cactus camel cameo candle canoe canvas canyon cargo carol carrot castle catch cedar cello chalk charm chart cheese cherry chess chime chirp cider cinder circle citrus clamp clay clever cliff cloak clock cloud clover coast cobra cocoa comet coral cosmos cotton couch cougar crane crater cream crest cricket crisp crown crumb crystal cube cumin curio dagger daisy dapper dawn deck deer delta denim depot desert dial diamond dingo ditch dock dodge dolphin domino donut draft dragon drift drum dune dusk eagle early earth easel ebony echo eclipse edge eel eagle elbow elder ember emboss emerald ember emu engine ermine ether ever fable falcon fancy farm fawn feather felt fennel fern ferry fiber fiddle field fig finch flame flask flax fleet flint float flock flora flute focus foam forest fossil fox frame frost fudge garden gecko ginger glacier glade glass glide globe glory glove gnat goat golden gopher gourd grape grass gravel grove guava gull hammer hamlet harbor hatch hazel heron hickory hippo honey hornet hostel ivory ivy jade jaguar jasmine jelly jetty jewel jolly jungle juniper kayak kelp kettle kiwi koala ladle lagoon lamp lantern larch lark lasso lava ledge lemon lentil leopard lever lilac lime linen lizard llama lobby locket lodge lotus lunar lupine lynx maple marble marsh meadow medal melon mellow mentor mesa metro mimic mint mirror mocha morsel moss mottle mural muslin nacho nectar nest noble nomad noodle nougat nutmeg oasis oat ocean ochre olive onyx opal orbit orca otter oval owl oxide oyster pace paddle palm panda pantry papaya parka parsley pasta pearl pebble pelican pepper pewter phantom piano picnic pigeon pilot pine pixel plank plaza plum pocket pollen pond poplar poppy portal potato pottery prairie prism puffin pumice quail quartz quill quilt quince rabbit radish raft rapid raven reed reef relish ribbon ridge rind ripple river robin rocket rope rover ruby rudder rust saffron sage salmon sandal sash satin sauce scout sedge sequin shadow shale shark shell shore shrub silk silo silver siren sketch slate sleet slope sloth smoke snail sonar sorrel spark sparrow spice spire sprig spruce squid stable stamp starling steam stem stilt stone stork storm stove straw stream stucco summit sundae sunset swan sweater syrup tabby talon tango tapir tassel tawny teal tempo thicket thimble thistle thorn thunder tidal tiger timber toffee token topaz torch totem trail tulip tundra turtle tusk twig umber unicorn valley vanilla velvet vermil violet viper vista vivid vortex waffle walnut warbler wasp water weasel wharf wheat whisk willow window winter wisp wombat wonder woven yam yarn yeast yew yodel yonder zebra zenith zephyr zigzag zinc zircon".split(/\s+/).filter(Boolean).filter((c,a,t)=>t.indexOf(c)===a);cr=new Set(["password","passw0rd","password1","123456","12345678","123456789","qwerty","abc123","letmein","welcome","admin","iloveyou","monkey","dragon","sunshine","princess","football","baseball","trustno1","000000","111111","secret"])});var Ri={};Xe(Ri,{newId:()=>tt});function tt(c=6){let a="",t=new Uint8Array(c);crypto.getRandomValues(t);for(let e=0;e{"use strict";wo="abcdefghijkmnpqrstuvwxyz23456789"});var gi={};Xe(gi,{AssignModal:()=>Ai,ColorPickerModal:()=>Ee,ConfirmDeleteModal:()=>Me,ConfirmModal:()=>gt,CustomColorModal:()=>Li,DueDatePickerModal:()=>li,EncryptionPasswordModal:()=>yt,ExportStashModal:()=>oi,ImportDupChoiceModal:()=>di,ImportLogModal:()=>sn,LogModal:()=>xe,NotificationHistoryModal:()=>ci,OkfExportModal:()=>hi,SplitNoteModal:()=>ni,StashPasswordModal:()=>ai,TypeToConfirmModal:()=>ri,buildAssigneePicker:()=>nn});function nn(c,a){let t=[...a.initial],e=a.knownAuthors,i=c.createDiv({cls:"stashpad-assign"});i.createDiv({cls:"stashpad-assign-label",text:"Assign to"});let s=i.createDiv({cls:"stashpad-assign-chips"}),n=i.createDiv({cls:"stashpad-assign-input-wrap"}),o=n.createEl("input",{type:"text",cls:"stashpad-assign-input",attr:{placeholder:"Add a person \u2014 type a name\u2026"}}),r=n.createDiv({cls:"stashpad-assign-suggest"});r.setCssStyles({display:"none"});let A=()=>a.onChange([...t]),l=()=>{s.empty(),t.length===0&&s.createSpan({cls:"stashpad-assign-empty",text:"No one yet"});for(let p of t){let h=s.createSpan({cls:"stashpad-assign-chip"});h.createSpan({cls:"stashpad-assign-chip-name",text:p.name});let I=h.createSpan({cls:"stashpad-assign-chip-x",text:"\xD7"});I.title=`Remove ${p.name}`,I.onclick=()=>{t=t.filter(u=>u.id!==p.id),A(),l()}}},d=p=>{p.name.trim()&&(t.some(h=>h.id===p.id)||t.push(p),o.value="",r.setCssStyles({display:"none"}),A(),l(),o.focus())},g=()=>{let p=o.value.trim();r.empty();let h=new Set(t.map(f=>f.id)),u=e.filter(f=>!h.has(f.id)&&Hi(p,f.name)).slice(0,6).map(f=>({label:f.name,onPick:()=>d(f)}));if(p&&!e.some(f=>f.name.toLowerCase()===p.toLowerCase())&&u.push({label:`Create \u201C${p}\u201D`,onPick:()=>d({id:tt(6),name:p})}),u.length===0){r.setCssStyles({display:"none"});return}r.setCssStyles({display:""});for(let f of u){let C=r.createDiv({cls:"stashpad-assign-suggest-item",text:f.label});C.onmousedown=B=>{B.preventDefault(),f.onPick()}}};o.addEventListener("input",g),o.addEventListener("focus",g),o.addEventListener("keydown",p=>{if(p.key==="Enter"){p.preventDefault();let h=r.querySelector(".stashpad-assign-suggest-item");h&&h.dispatchEvent(new MouseEvent("mousedown"))}else p.key==="Escape"&&r.style.display!=="none"&&(p.stopPropagation(),r.setCssStyles({display:"none"}))}),o.addEventListener("blur",()=>{window.setTimeout(()=>{r.setCssStyles({display:"none"})},120)}),l()}var q,hr,Qe,xe,Me,ni,oi,ai,yt,ri,Li,si,Ee,gt,Ai,li,ye,ci,sn,di,hi,vt=Gt(()=>{"use strict";q=require("obsidian");ei();_s();rt();Gi();xt();hr=q.moment,Qe=class Qe extends q.Modal{constructor(t,e,i){super(t);this.text=e;this.jsonlPath=i;this.events=[];this.visible=[];this.shownCount=0;this.typeFilter=null;this.listEl=null;this.footerEl=null;this.countEl=null;this.filterSelEl=null}onOpen(){this.contentEl.empty(),this.titleEl.setText("Stashpad log"),this.modalEl.addClass("stashpad-log-modal"),this.events=[];for(let A of this.text.trim().split(/\r?\n/))if(A)try{this.events.push(JSON.parse(A))}catch{}this.events.reverse();let t=this.contentEl.createDiv({cls:"stashpad-log-toolbar"});this.countEl=t.createSpan({cls:"stashpad-log-count"}),this.updateCount(),this.filterSelEl=t.createEl("select",{cls:"stashpad-log-type-filter"}),this.filterSelEl.onchange=()=>this.setTypeFilter(this.filterSelEl.value||null),this.refreshTypeFilter();let e=t.createEl("button",{text:"Reveal JSONL"});e.onclick=()=>this.shellAct("reveal");let i=t.createEl("button",{text:"Open in default app"});i.onclick=()=>this.shellAct("open");let s=t.createEl("button",{text:"Copy raw JSONL"}),n=null;s.onclick=async()=>{await navigator.clipboard.writeText(this.text),s.setText("Copied"),n!=null&&window.clearTimeout(n),n=window.setTimeout(()=>{s.setText("Copy raw JSONL"),n=null},1500)};let o=t.createEl("button",{text:"Export copy"});o.onclick=()=>this.exportCopy();let r=t.createEl("button",{cls:"mod-warning",text:"Clear log"});r.onclick=()=>this.clearLog(),this.listEl=this.contentEl.createDiv({cls:"stashpad-log-list"}),this.refreshList(),this.footerEl=this.contentEl.createDiv({cls:"stashpad-log-footer"}),this.renderFooter()}refreshList(){if(this.listEl){if(this.visible=this.typeFilter?this.events.filter(t=>t.type===this.typeFilter):this.events.slice(),this.shownCount=0,this.listEl.empty(),!this.visible.length){this.listEl.createDiv({cls:"stashpad-log-empty",text:this.typeFilter?`No "${this.typeFilter}" events.`:"No events yet."}),this.updateCount();return}this.appendMore(Qe.PAGE)}}setTypeFilter(t){(this.typeFilter??null)!==(t??null)&&(this.typeFilter=t,this.refreshList(),this.renderFooter())}refreshTypeFilter(){if(!this.filterSelEl)return;let t=this.filterSelEl;t.empty();let e=new Map;for(let n of this.events)e.set(n.type,(e.get(n.type)??0)+1);let i=[...e.entries()].sort((n,o)=>o[1]-n[1]||n[0].localeCompare(o[0])),s=t.createEl("option",{text:`All types (${this.events.length})`});s.value="";for(let[n,o]of i){let r=t.createEl("option",{text:`${n} (${o})`});r.value=n}this.typeFilter&&!e.has(this.typeFilter)&&(this.typeFilter=null),t.value=this.typeFilter??""}updateCount(){if(!this.countEl)return;let t=this.visible.length,e=this.typeFilter?`${t} ${this.typeFilter} event${t===1?"":"s"}`:`${t} event${t===1?"":"s"}`;this.shownCount===0||this.shownCount>=t?this.countEl.setText(e):this.countEl.setText(`Showing ${this.shownCount} of ${e}`)}appendMore(t){if(!this.listEl)return;let e=Math.min(this.visible.length,this.shownCount+t);for(let i=this.shownCount;i{this.appendMore(Qe.PAGE),this.renderFooter()},t>Qe.PAGE){let i=this.footerEl.createEl("button",{text:`Load all (${t})`});i.onclick=()=>{this.appendMore(t),this.renderFooter()}}}shellAct(t){try{let e=this.app.vault.adapter.getFullPath?.(this.jsonlPath);if(!e)throw new Error("no full path");let{shell:i}=window.require("electron");t==="reveal"?i.showItemInFolder(e):i.openPath(e)}catch(e){new q.Notice(`Couldn't ${t}: ${e.message}`)}}async exportCopy(){try{let t=(0,q.moment)().format("YYYY-MM-DD_HHmmss"),e=this.jsonlPath.replace(/\/[^/]+$/,"")||"",i=e?`${e}/${t}-log.jsonl`:`${t}-log.jsonl`;return await this.app.vault.adapter.write(i,this.text),new q.Notice(`Exported log \u2192 ${i}`),i}catch(t){return new q.Notice(`Export failed: ${t.message}`),null}}clearLog(){new gt(this.app,"Clear log?","A timestamped copy will be saved alongside the active log before it's truncated.","Export & clear",async t=>{if(!(!t||!await this.exportCopy())){try{await this.app.vault.adapter.write(this.jsonlPath,"")}catch(i){new q.Notice(`Clear failed: ${i.message}`);return}this.text="",this.events=[],this.typeFilter=null,this.shownCount=0,this.refreshTypeFilter(),this.refreshList(),this.footerEl&&this.footerEl.empty(),new q.Notice("Log cleared.")}}).open()}renderEvent(t){let e=document.createElement("div");e.className=`stashpad-log-row stashpad-log-${t.type}`;let i=(0,q.moment)(t.ts).isValid()?(0,q.moment)(t.ts).format("YYYY-MM-DD HH:mm:ss"):t.ts,s=document.createElement("span");s.className="stashpad-log-ts",s.textContent=i,e.appendChild(s);let n=document.createElement("span");n.className="stashpad-log-type",n.textContent=t.type,e.appendChild(n);let o=document.createElement("span");o.className="stashpad-log-author",o.textContent=t.author?t.author:"\u2014",t.author||o.classList.add("is-empty"),e.appendChild(o);let r=document.createElement("span");return r.className="stashpad-log-msg",r.textContent=this.describe(t),e.appendChild(r),e}describe(t){let e=t.payload??{};switch(t.type){case"create":return`Created "${e.path??t.id}" under ${e.parent??"?"}`;case"delete":{let i=Array.isArray(e.attachmentsRemoved)?e.attachmentsRemoved.length:0,s=e.mergedInto?` (merged into ${e.mergedInto})`:"";return`Deleted ${t.id}${s}${i?` \u2014 also removed ${i} attachment${i===1?"":"s"}`:""}`}case"missing":return`Missing: ${e.lastPath??t.id}`;case"parent_change":{let i=e.reason?` (${e.reason})`:"";return`Moved ${t.id} from ${e.from??"null"} \u2192 ${e.to??"null"}${i}`}case"rename":return`Renamed ${e.from??"?"} \u2192 ${e.to??"?"}`;case"reorder":{let i=e.count??1,s=e.dir??"?",n=e.parent??t.id??"?";return`Reordered ${i} note${i===1?"":"s"} (${s}) under ${n}`}case"complete":{let i=e.count??1,s=e.undo?" (undo)":e.redo?" (redo)":"";return`Marked ${i} note${i===1?"":"s"} complete${s}`}case"uncomplete":{let i=e.count??1,s=e.undo?" (undo)":e.redo?" (redo)":"";return`Unmarked ${i} note${i===1?"":"s"}${s}`}case"stash_export":{let i=e.noteCount??"?";return`Exported ${i} note${i===1?"":"s"} \u2192 ${e.path??"?"}`}case"stash_import":{let i=e.noteCount??"?",s=[];e.attachmentsWritten&&s.push(`${e.attachmentsWritten} attachment${e.attachmentsWritten===1?"":"s"}`),e.collisionsRenamed&&s.push(`${e.collisionsRenamed} renamed`);let n=s.length?` (${s.join(", ")})`:"";return`Imported ${i} note${i===1?"":"s"} from ${e.from??"?"} \u2192 ${e.into??"?"}${n}`}case"attachment_add":return`Added attachment ${e.path??t.id}`;case"attachment_remove":return`Removed attachment ${e.path??t.id}`;case"palette_color_add":return`Added palette color ${e.color??t.id}`;case"palette_color_remove":return`Removed palette color ${e.color??t.id}`;default:return JSON.stringify(e)}}onClose(){this.contentEl.empty()}};Qe.PAGE=100;xe=Qe,Me=class extends q.Modal{constructor(t,e,i,s,n,o){super(t);this.noteTitle=e;this.descendantCount=i;this.attachmentCount=s;this.offerAttachmentDelete=n;this.onChoose=o}onOpen(){this.modalEl?.addClass("stashpad-compact-modal"),this.contentEl.empty(),this.titleEl.setText(`Delete "${this.noteTitle}"?`);let t=[];this.descendantCount>0&&t.push(`${this.descendantCount} descendant note${this.descendantCount===1?"":"s"} will also be deleted.`),this.attachmentCount>0&&t.push(`${this.attachmentCount} attachment${this.attachmentCount===1?"":"s"} found across these notes.`),this.contentEl.createEl("p",{text:t.join(" ")});let e=this.offerAttachmentDelete&&this.attachmentCount>0;if(this.offerAttachmentDelete&&this.attachmentCount>0){let o=this.contentEl.createEl("label",{cls:"stashpad-modal-check"}),r=o.createEl("input",{type:"checkbox"});r.checked=e,r.onchange=()=>{e=r.checked},o.createSpan({text:" Also delete attachments"})}let i=this.contentEl.createDiv({cls:"stashpad-modal-btns"}),s=i.createEl("button",{text:"Cancel"});s.onclick=()=>this.close();let n=i.createEl("button",{cls:"mod-warning",text:"Delete"});n.onclick=()=>{this.close(),this.onChoose(e)}}onClose(){this.contentEl.empty()}},ni=class extends q.Modal{constructor(t,e,i,s,n){super(t);this.body=e;this.onSplitAtLine=i;this.onSplitAtChar=s;this.onSplitMany=n;this.mode="line";this.cursorTextarea=null;this.lines=e.replace(/\r\n/g,` +`).trim()),e.filter(Boolean)}function Mt(c,a,t){c.empty();try{(0,vo.setIcon)(c,a)}catch{}let e=c.querySelector("svg");e&&e.querySelector("path, line, circle, rect, polyline, polygon, ellipse")||(c.empty(),c.createSpan({cls:"stashpad-icon-fallback",text:t}))}function Fo(c){if(c instanceof Element&&c.closest(".modal, .modal-container, .suggestion-container, .menu, .prompt"))return!0;let a=new Set([document]);c instanceof Element&&c.ownerDocument&&a.add(c.ownerDocument);for(let t of a)if(t.body?.querySelector(".modal-bg")||t.body?.querySelector(".modal-container .modal")||t.body?.querySelector(".suggestion-container")||t.body?.querySelector(".menu.mod-active"))return!0;return!1}function ko(c){let a=[],t=/^([ \t]*)(`{3,})[ \t]*([^\n`]*)\n([\s\S]*?)\n\1\2[ \t]*$/gm,e;for(;(e=t.exec(c))!=null;)a.push({lang:e[3].trim(),code:e[4]});return a}function ai(c){return c.split("/").map(a=>a.split(" ").map(t=>t&&/^[a-z]/.test(t)?t[0].toUpperCase()+t.slice(1):t).join(" ")).join("/")}function So(c,a,t){let e=new Set(a),i=c.filter(n=>!e.has(n)),s=c.findIndex(n=>e.has(n));if(s<0)return c.slice();switch(t){case"top":return[...a,...i];case"bottom":return[...i,...a];case"up":{let n=Math.max(0,s-1),o=i.slice();return o.splice(n,0,...a),o}case"down":{let n=(()=>{let l=-1;return c.forEach((d,p)=>{e.has(d)&&(l=p)}),l})(),o=0;for(let l=0;l0){let n=e[i-1];return(!/[a-z0-9]/.test(n)?600:500)-Math.min(i,99)}let s=0;for(let n=0;n({t:e,s:Er(t,e.raw)})).filter(e=>e.s>=0).sort((e,i)=>i.s-e.s||i.t.count-e.t.count||e.t.label.localeCompare(i.t.label)).map(e=>e.t):a}var vo,ni,ve,Fe,ri=Lt(()=>{"use strict";vo=require("obsidian"),ni={lines:"Each line",paragraphs:"Paragraphs (blank line)",headings:"Headings"};ve="__stashpad:tagged__",Fe="__stashpad:untagged__"});function wr(c,a){return c>12?c>=24?0:c:a==="am"?c===12?0:c:c===12?12:c+12}function Oi(c,a){c.addClass("stashpad-when-pop-time");let t=a.seedPeriod,e=c.createDiv({cls:"stashpad-when-time-display"}),i=e.createEl("input",{cls:"stashpad-when-time-field",attr:{type:"text",inputmode:"numeric",maxlength:"2"}});i.value=String(a.seedH),e.createSpan({cls:"stashpad-when-time-colon",text:":"});let s=e.createEl("input",{cls:"stashpad-when-time-field",attr:{type:"text",inputmode:"numeric",maxlength:"2"}});s.value=String(a.seedM).padStart(2,"0");let n=e.createDiv({cls:"stashpad-when-time-period"}),o=n.createEl("button",{cls:"stashpad-when-time-ampm",text:"AM"});o.type="button";let r=n.createEl("button",{cls:"stashpad-when-time-ampm",text:"PM"});r.type="button";let A=()=>{o.toggleClass("is-active",t==="am"),r.toggleClass("is-active",t==="pm")};A(),o.addEventListener("mousedown",m=>m.preventDefault()),r.addEventListener("mousedown",m=>m.preventDefault()),o.addEventListener("click",m=>{m.preventDefault(),t="am",A()}),r.addEventListener("click",m=>{m.preventDefault(),t="pm",A()});let l=i;i.addEventListener("focus",()=>{l=i,i.select()}),s.addEventListener("focus",()=>{l=s,s.select()});let d=()=>{let y=(parseInt(i.value||"0",10)||0)>12;o.toggleClass("is-disabled",y),r.toggleClass("is-disabled",y),o.disabled=y,r.disabled=y},p=m=>{let y=m.value.replace(/\D/g,"").slice(0,2);if(y===""){m.value="",m===i&&d();return}let Q=parseInt(y,10);m===i?Q>24&&(Q=24):Q>59&&(Q=59),m.value=String(Q),m===i&&d()};for(let m of[i,s])m.addEventListener("input",()=>p(m));d();let g=()=>{let m=parseInt(i.value||"12",10)||12,y=parseInt(s.value||"0",10)||0,Q=m>12;a.onFinalize({hours24:wr(m,t),minutes:y,raw:{hh:m,mm:y,period:t,is24:Q}}),a.close()};a.setOnEnter?.(g);let h=[i,s,o,r],I=(m,y)=>{let Q=h.indexOf(m);if(Q===-1)return;let E=(Q+y+h.length)%h.length;h[E].focus()},u=m=>{m.addEventListener("keydown",y=>{y.key==="Enter"?(y.preventDefault(),y.stopPropagation(),g()):y.key==="Escape"?(y.preventDefault(),y.stopPropagation(),a.close()):y.key==="Tab"&&(y.preventDefault(),y.stopPropagation(),I(m,y.shiftKey?-1:1))})},f=c.createDiv({cls:"stashpad-when-time-pad"}),C=["1","2","3","4","5","6","7","8","9","backspace","0","insert"],B=null;for(let m of C){let y=f.createEl("button",{cls:"stashpad-when-time-padbtn"});y.type="button",m==="backspace"?(0,bo.setIcon)(y,"delete"):m==="insert"?(y.setText("OK"),B=y):y.setText(m),m==="insert"&&y.addClass("is-go"),y.addEventListener("mousedown",Q=>Q.preventDefault()),y.addEventListener("click",Q=>{if(Q.preventDefault(),m==="insert"){g();return}if(m==="backspace"){l.value=l.value.slice(0,-1),p(l),l.focus();return}let E=l.selectionStart===0&&l.selectionEnd===l.value.length&&l.value.length>0,v=2,w=E||l.value.length>=v?m:l.value+m;l.value=w,p(l),l.focus(),l.setSelectionRange(l.value.length,l.value.length),l===i&&l.value.length>=v&&(s.focus(),s.select())})}B&&h.push(B);for(let m of h)u(m);i.focus(),i.select()}function No(c){let{hh:a,mm:t,period:e,is24:i}=c.raw;return i?`${a}:${String(t).padStart(2,"0")}`:`${a}:${String(t).padStart(2,"0")}${e}`}var bo,An=Lt(()=>{"use strict";bo=require("obsidian")});function Mo(c){let a=Math.floor(4294967296/c)*c,t=new Uint32Array(1),e;do crypto.getRandomValues(t),e=t[0];while(e>=a);return e%c}function ln(c=5){let a=[];for(let t=0;t=1&&s.every(r=>/^[a-zA-Z]+$/.test(r))&&(i=Math.min(i,s.length*11)),vr.has(c.toLowerCase())&&(i=Math.min(i,12));let n=i<36?0:i<56?1:i<76?2:3,o=["Weak \u2014 easily guessed","Fair","Good","Strong"][n];return{bits:i,level:n,label:o}}function Fr(c){let a=2166136261;for(let t=0;t>>0).toString(16).padStart(8,"0")}function Ai(c){let a="stashpad-",t=Fr(c),e=64-a.length-1-t.length,i=c.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,Math.max(0,e)).replace(/-+$/g,"");return`${a}${i}-${t}`}var xo,vr,Yi=Lt(()=>{"use strict";xo="able acid acorn actor adept agile alarm album alert algae amber amble anchor angle ankle apple april arbor arc arctic arena armor arrow ascot aspen atlas atom attic auburn audio autumn award axis bacon badge bagel baker balmy bamboo banjo barge basil basin batch beach beam bean bear beaver begin belt bench berry birch bison black blade blaze bliss bloom blue board boat bold bolt bonus boost booth borax bother bottle boulder bounce bovine bowl brave bread breeze brick bridge brisk broad bronze brook broom brown brush bubble bucket bug bulb bundle burst cabin cable cacao cactus camel cameo candle canoe canvas canyon cargo carol carrot castle catch cedar cello chalk charm chart cheese cherry chess chime chirp cider cinder circle citrus clamp clay clever cliff cloak clock cloud clover coast cobra cocoa comet coral cosmos cotton couch cougar crane crater cream crest cricket crisp crown crumb crystal cube cumin curio dagger daisy dapper dawn deck deer delta denim depot desert dial diamond dingo ditch dock dodge dolphin domino donut draft dragon drift drum dune dusk eagle early earth easel ebony echo eclipse edge eel eagle elbow elder ember emboss emerald ember emu engine ermine ether ever fable falcon fancy farm fawn feather felt fennel fern ferry fiber fiddle field fig finch flame flask flax fleet flint float flock flora flute focus foam forest fossil fox frame frost fudge garden gecko ginger glacier glade glass glide globe glory glove gnat goat golden gopher gourd grape grass gravel grove guava gull hammer hamlet harbor hatch hazel heron hickory hippo honey hornet hostel ivory ivy jade jaguar jasmine jelly jetty jewel jolly jungle juniper kayak kelp kettle kiwi koala ladle lagoon lamp lantern larch lark lasso lava ledge lemon lentil leopard lever lilac lime linen lizard llama lobby locket lodge lotus lunar lupine lynx maple marble marsh meadow medal melon mellow mentor mesa metro mimic mint mirror mocha morsel moss mottle mural muslin nacho nectar nest noble nomad noodle nougat nutmeg oasis oat ocean ochre olive onyx opal orbit orca otter oval owl oxide oyster pace paddle palm panda pantry papaya parka parsley pasta pearl pebble pelican pepper pewter phantom piano picnic pigeon pilot pine pixel plank plaza plum pocket pollen pond poplar poppy portal potato pottery prairie prism puffin pumice quail quartz quill quilt quince rabbit radish raft rapid raven reed reef relish ribbon ridge rind ripple river robin rocket rope rover ruby rudder rust saffron sage salmon sandal sash satin sauce scout sedge sequin shadow shale shark shell shore shrub silk silo silver siren sketch slate sleet slope sloth smoke snail sonar sorrel spark sparrow spice spire sprig spruce squid stable stamp starling steam stem stilt stone stork storm stove straw stream stucco summit sundae sunset swan sweater syrup tabby talon tango tapir tassel tawny teal tempo thicket thimble thistle thorn thunder tidal tiger timber toffee token topaz torch totem trail tulip tundra turtle tusk twig umber unicorn valley vanilla velvet vermil violet viper vista vivid vortex waffle walnut warbler wasp water weasel wharf wheat whisk willow window winter wisp wombat wonder woven yam yarn yeast yew yodel yonder zebra zenith zephyr zigzag zinc zircon".split(/\s+/).filter(Boolean).filter((c,a,t)=>t.indexOf(c)===a);vr=new Set(["password","passw0rd","password1","123456","12345678","123456789","qwerty","abc123","letmein","welcome","admin","iloveyou","monkey","dragon","sunshine","princess","football","baseball","trustno1","000000","111111","secret"])});var zi={};ii(zi,{newId:()=>tt});function tt(c=6){let a="",t=new Uint8Array(c);crypto.getRandomValues(t);for(let e=0;e{"use strict";To="abcdefghijkmnpqrstuvwxyz23456789"});var fi={};ii(fi,{ColorPickerModal:()=>De,ConfirmDeleteModal:()=>Ue,ConfirmModal:()=>pt,CustomColorModal:()=>Vi,DueDatePickerModal:()=>Ge,EncryptionPasswordModal:()=>vt,ExportStashModal:()=>di,ImportDupChoiceModal:()=>Ii,ImportLogModal:()=>dn,LogModal:()=>Pe,NotificationHistoryModal:()=>gi,OkfExportModal:()=>ui,SplitNoteModal:()=>ci,StashPasswordModal:()=>hi,TypeToConfirmModal:()=>pi,buildAssigneePicker:()=>Ho});function Ho(c,a){let t=[...a.initial],e=a.knownAuthors,i=c.createDiv({cls:"stashpad-assign"});i.createDiv({cls:"stashpad-assign-label",text:"Assign to"});let s=i.createDiv({cls:"stashpad-assign-chips"}),n=i.createDiv({cls:"stashpad-assign-input-wrap"}),o=n.createEl("input",{type:"text",cls:"stashpad-assign-input",attr:{placeholder:"Add a person \u2014 type a name\u2026"}}),r=n.createDiv({cls:"stashpad-assign-suggest"});r.setCssStyles({display:"none"});let A=()=>a.onChange([...t]),l=()=>{s.empty(),t.length===0&&s.createSpan({cls:"stashpad-assign-empty",text:"No one yet"});for(let g of t){let h=s.createSpan({cls:"stashpad-assign-chip"});h.createSpan({cls:"stashpad-assign-chip-name",text:g.name});let I=h.createSpan({cls:"stashpad-assign-chip-x",text:"\xD7"});I.title=`Remove ${g.name}`,I.onclick=()=>{t=t.filter(u=>u.id!==g.id),A(),l()}}},d=g=>{g.name.trim()&&(t.some(h=>h.id===g.id)||t.push(g),o.value="",r.setCssStyles({display:"none"}),A(),l(),o.focus())},p=()=>{let g=o.value.trim();r.empty();let h=new Set(t.map(f=>f.id)),u=e.filter(f=>!h.has(f.id)&&Ji(g,f.name)).slice(0,6).map(f=>({label:f.name,onPick:()=>d(f)}));if(g&&!e.some(f=>f.name.toLowerCase()===g.toLowerCase())&&u.push({label:`Create \u201C${g}\u201D`,onPick:()=>d({id:tt(6),name:g})}),u.length===0){r.setCssStyles({display:"none"});return}r.setCssStyles({display:""});for(let f of u){let C=r.createDiv({cls:"stashpad-assign-suggest-item",text:f.label});C.onmousedown=B=>{B.preventDefault(),f.onPick()}}};o.addEventListener("input",p),o.addEventListener("focus",p),o.addEventListener("keydown",g=>{if(g.key==="Enter"){g.preventDefault();let h=r.querySelector(".stashpad-assign-suggest-item");h&&h.dispatchEvent(new MouseEvent("mousedown"))}else g.key==="Escape"&&r.style.display!=="none"&&(g.stopPropagation(),r.setCssStyles({display:"none"}))}),o.addEventListener("blur",()=>{window.setTimeout(()=>{r.setCssStyles({display:"none"})},120)}),l()}var q,kr,ke,Pe,Ue,ci,di,hi,vt,pi,Vi,li,De,pt,Ge,Se,gi,dn,Ii,ui,Ft=Lt(()=>{"use strict";q=require("obsidian");ri();An();rt();Yi();Tt();kr=q.moment,ke=class ke extends q.Modal{constructor(t,e,i){super(t);this.text=e;this.jsonlPath=i;this.events=[];this.visible=[];this.shownCount=0;this.typeFilter=null;this.listEl=null;this.footerEl=null;this.countEl=null;this.filterSelEl=null}onOpen(){this.contentEl.empty(),this.titleEl.setText("Stashpad log"),this.modalEl.addClass("stashpad-log-modal"),this.events=[];for(let A of this.text.trim().split(/\r?\n/))if(A)try{this.events.push(JSON.parse(A))}catch{}this.events.reverse();let t=this.contentEl.createDiv({cls:"stashpad-log-toolbar"});this.countEl=t.createSpan({cls:"stashpad-log-count"}),this.updateCount(),this.filterSelEl=t.createEl("select",{cls:"stashpad-log-type-filter"}),this.filterSelEl.onchange=()=>this.setTypeFilter(this.filterSelEl.value||null),this.refreshTypeFilter();let e=t.createEl("button",{text:"Reveal JSONL"});e.onclick=()=>this.shellAct("reveal");let i=t.createEl("button",{text:"Open in default app"});i.onclick=()=>this.shellAct("open");let s=t.createEl("button",{text:"Copy raw JSONL"}),n=null;s.onclick=async()=>{await navigator.clipboard.writeText(this.text),s.setText("Copied"),n!=null&&window.clearTimeout(n),n=window.setTimeout(()=>{s.setText("Copy raw JSONL"),n=null},1500)};let o=t.createEl("button",{text:"Export copy"});o.onclick=()=>this.exportCopy();let r=t.createEl("button",{cls:"mod-warning",text:"Clear log"});r.onclick=()=>this.clearLog(),this.listEl=this.contentEl.createDiv({cls:"stashpad-log-list"}),this.refreshList(),this.footerEl=this.contentEl.createDiv({cls:"stashpad-log-footer"}),this.renderFooter()}refreshList(){if(this.listEl){if(this.visible=this.typeFilter?this.events.filter(t=>t.type===this.typeFilter):this.events.slice(),this.shownCount=0,this.listEl.empty(),!this.visible.length){this.listEl.createDiv({cls:"stashpad-log-empty",text:this.typeFilter?`No "${this.typeFilter}" events.`:"No events yet."}),this.updateCount();return}this.appendMore(ke.PAGE)}}setTypeFilter(t){(this.typeFilter??null)!==(t??null)&&(this.typeFilter=t,this.refreshList(),this.renderFooter())}refreshTypeFilter(){if(!this.filterSelEl)return;let t=this.filterSelEl;t.empty();let e=new Map;for(let n of this.events)e.set(n.type,(e.get(n.type)??0)+1);let i=[...e.entries()].sort((n,o)=>o[1]-n[1]||n[0].localeCompare(o[0])),s=t.createEl("option",{text:`All types (${this.events.length})`});s.value="";for(let[n,o]of i){let r=t.createEl("option",{text:`${n} (${o})`});r.value=n}this.typeFilter&&!e.has(this.typeFilter)&&(this.typeFilter=null),t.value=this.typeFilter??""}updateCount(){if(!this.countEl)return;let t=this.visible.length,e=this.typeFilter?`${t} ${this.typeFilter} event${t===1?"":"s"}`:`${t} event${t===1?"":"s"}`;this.shownCount===0||this.shownCount>=t?this.countEl.setText(e):this.countEl.setText(`Showing ${this.shownCount} of ${e}`)}appendMore(t){if(!this.listEl)return;let e=Math.min(this.visible.length,this.shownCount+t);for(let i=this.shownCount;i{this.appendMore(ke.PAGE),this.renderFooter()},t>ke.PAGE){let i=this.footerEl.createEl("button",{text:`Load all (${t})`});i.onclick=()=>{this.appendMore(t),this.renderFooter()}}}shellAct(t){try{let e=this.app.vault.adapter.getFullPath?.(this.jsonlPath);if(!e)throw new Error("no full path");let{shell:i}=window.require("electron");t==="reveal"?i.showItemInFolder(e):i.openPath(e)}catch(e){new q.Notice(`Couldn't ${t}: ${e.message}`)}}async exportCopy(){try{let t=(0,q.moment)().format("YYYY-MM-DD_HHmmss"),e=this.jsonlPath.replace(/\/[^/]+$/,"")||"",i=e?`${e}/${t}-log.jsonl`:`${t}-log.jsonl`;return await this.app.vault.adapter.write(i,this.text),new q.Notice(`Exported log \u2192 ${i}`),i}catch(t){return new q.Notice(`Export failed: ${t.message}`),null}}clearLog(){new pt(this.app,"Clear log?","A timestamped copy will be saved alongside the active log before it's truncated.","Export & clear",async t=>{if(!(!t||!await this.exportCopy())){try{await this.app.vault.adapter.write(this.jsonlPath,"")}catch(i){new q.Notice(`Clear failed: ${i.message}`);return}this.text="",this.events=[],this.typeFilter=null,this.shownCount=0,this.refreshTypeFilter(),this.refreshList(),this.footerEl&&this.footerEl.empty(),new q.Notice("Log cleared.")}}).open()}renderEvent(t){let e=document.createElement("div");e.className=`stashpad-log-row stashpad-log-${t.type}`;let i=(0,q.moment)(t.ts).isValid()?(0,q.moment)(t.ts).format("YYYY-MM-DD HH:mm:ss"):t.ts,s=document.createElement("span");s.className="stashpad-log-ts",s.textContent=i,e.appendChild(s);let n=document.createElement("span");n.className="stashpad-log-type",n.textContent=t.type,e.appendChild(n);let o=document.createElement("span");o.className="stashpad-log-author",o.textContent=t.author?t.author:"\u2014",t.author||o.classList.add("is-empty"),e.appendChild(o);let r=document.createElement("span");return r.className="stashpad-log-msg",r.textContent=this.describe(t),e.appendChild(r),e}describe(t){let e=t.payload??{};switch(t.type){case"create":return`Created "${e.path??t.id}" under ${e.parent??"?"}`;case"delete":{let i=Array.isArray(e.attachmentsRemoved)?e.attachmentsRemoved.length:0,s=e.mergedInto?` (merged into ${e.mergedInto})`:"";return`Deleted ${t.id}${s}${i?` \u2014 also removed ${i} attachment${i===1?"":"s"}`:""}`}case"missing":return`Missing: ${e.lastPath??t.id}`;case"parent_change":{let i=e.reason?` (${e.reason})`:"";return`Moved ${t.id} from ${e.from??"null"} \u2192 ${e.to??"null"}${i}`}case"rename":return`Renamed ${e.from??"?"} \u2192 ${e.to??"?"}`;case"reorder":{let i=e.count??1,s=e.dir??"?",n=e.parent??t.id??"?";return`Reordered ${i} note${i===1?"":"s"} (${s}) under ${n}`}case"complete":{let i=e.count??1,s=e.undo?" (undo)":e.redo?" (redo)":"";return`Marked ${i} note${i===1?"":"s"} complete${s}`}case"uncomplete":{let i=e.count??1,s=e.undo?" (undo)":e.redo?" (redo)":"";return`Unmarked ${i} note${i===1?"":"s"}${s}`}case"stash_export":{let i=e.noteCount??"?";return`Exported ${i} note${i===1?"":"s"} \u2192 ${e.path??"?"}`}case"stash_import":{let i=e.noteCount??"?",s=[];e.attachmentsWritten&&s.push(`${e.attachmentsWritten} attachment${e.attachmentsWritten===1?"":"s"}`),e.collisionsRenamed&&s.push(`${e.collisionsRenamed} renamed`);let n=s.length?` (${s.join(", ")})`:"";return`Imported ${i} note${i===1?"":"s"} from ${e.from??"?"} \u2192 ${e.into??"?"}${n}`}case"attachment_add":return`Added attachment ${e.path??t.id}`;case"attachment_remove":return`Removed attachment ${e.path??t.id}`;case"palette_color_add":return`Added palette color ${e.color??t.id}`;case"palette_color_remove":return`Removed palette color ${e.color??t.id}`;default:return JSON.stringify(e)}}onClose(){this.contentEl.empty()}};ke.PAGE=100;Pe=ke,Ue=class extends q.Modal{constructor(t,e,i,s,n,o){super(t);this.noteTitle=e;this.descendantCount=i;this.attachmentCount=s;this.offerAttachmentDelete=n;this.onChoose=o}onOpen(){this.modalEl?.addClass("stashpad-compact-modal"),this.contentEl.empty(),this.titleEl.setText(`Delete "${this.noteTitle}"?`);let t=[];this.descendantCount>0&&t.push(`${this.descendantCount} descendant note${this.descendantCount===1?"":"s"} will also be deleted.`),this.attachmentCount>0&&t.push(`${this.attachmentCount} attachment${this.attachmentCount===1?"":"s"} found across these notes.`),this.contentEl.createEl("p",{text:t.join(" ")});let e=this.offerAttachmentDelete&&this.attachmentCount>0;if(this.offerAttachmentDelete&&this.attachmentCount>0){let o=this.contentEl.createEl("label",{cls:"stashpad-modal-check"}),r=o.createEl("input",{type:"checkbox"});r.checked=e,r.onchange=()=>{e=r.checked},o.createSpan({text:" Also delete attachments"})}let i=this.contentEl.createDiv({cls:"stashpad-modal-btns"}),s=i.createEl("button",{text:"Cancel"});s.onclick=()=>this.close();let n=i.createEl("button",{cls:"mod-warning",text:"Delete"});n.onclick=()=>{this.close(),this.onChoose(e)}}onClose(){this.contentEl.empty()}},ci=class extends q.Modal{constructor(t,e,i,s,n){super(t);this.body=e;this.onSplitAtLine=i;this.onSplitAtChar=s;this.onSplitMany=n;this.mode="line";this.cursorTextarea=null;this.lines=e.replace(/\r\n/g,` `).split(` -`),this.lineCursorIdx=Math.max(1,Math.min(this.lines.length-1,Math.floor(this.lines.length/2))),this.lines.length<2&&(this.mode="cursor")}onOpen(){this.titleEl.setText("Split note"),this.modalEl.addClass("stashpad-split-modal"),this.render(),this.scope.register([],"Tab",t=>{this.lines.length<2||(t.preventDefault(),this.mode=this.mode==="line"?"cursor":"line",this.render())}),this.scope.register([],"Enter",t=>{this.mode==="line"&&(t.preventDefault(),this.commitLine())}),this.scope.register(["Mod"],"Enter",t=>{this.mode==="cursor"&&(t.preventDefault(),this.commitCursor())}),this.scope.register([],"ArrowUp",t=>{this.mode==="line"&&(t.preventDefault(),this.lineCursorIdx=Math.max(1,this.lineCursorIdx-1),this.render())}),this.scope.register([],"ArrowDown",t=>{this.mode==="line"&&(t.preventDefault(),this.lineCursorIdx=Math.min(this.lines.length-1,this.lineCursorIdx+1),this.render())})}commitLine(){let t=this.lineCursorIdx;this.close(),this.onSplitAtLine(t)}commitCursor(){let t=this.cursorTextarea;if(!t)return;let e=t.selectionStart;if(e<=0||e>=t.value.length){new q.Notice("Move the cursor inside the text \u2014 neither end can be empty.");return}this.close(),this.onSplitAtChar(e)}render(){this.contentEl.empty();let t=this.contentEl.createDiv({cls:"stashpad-split-quick"});t.createSpan({cls:"stashpad-split-quick-label",text:"Split by:"}),["lines","paragraphs","headings"].forEach(o=>{let r=_e(this.body,o),A=t.createEl("button",{cls:"stashpad-split-quick-btn",text:`${je[o]} (${r.length})`});A.disabled=r.length<2,A.onmousedown=l=>l.preventDefault(),A.onclick=()=>{let l=_e(this.body,o);if(l.length<2){new q.Notice("That delimiter wouldn't split this note.");return}this.close(),this.onSplitMany(l)}});let e=this.contentEl.createDiv({cls:"stashpad-split-toggle-bar"});if(this.lines.length>=2){let o=e.createEl("button",{text:"Line split",cls:"stashpad-split-mode-btn"});this.mode==="line"&&o.addClass("is-active"),o.onclick=()=>{this.mode="line",this.render()}}let i=e.createEl("button",{text:"Cursor split",cls:"stashpad-split-mode-btn"});this.mode==="cursor"&&i.addClass("is-active"),i.onclick=()=>{this.mode="cursor",this.render()};let s=e.createEl("button",{text:"Split",cls:"stashpad-split-confirm-btn mod-cta"});s.onmousedown=o=>o.preventDefault(),s.onclick=()=>{this.mode==="line"?this.commitLine():this.commitCursor()},this.mode==="line"?this.renderLineMode():this.renderCursorMode();let n=this.contentEl.createDiv({cls:"stashpad-split-help"});q.Platform.isMobile?n.setText(this.mode==="line"?"Tap a line to position the divider, then Split.":"Tap inside the text to position the cursor, then Split."):n.setText(this.mode==="line"?"\u2191/\u2193 pick split line \xB7 Enter or Split confirm \xB7 Tab \u2192 cursor mode \xB7 Esc cancel \xB7 Children stay with the first part":"Click or arrow to position cursor \xB7 Mod+Enter or Split confirm \xB7 Tab \u2192 line mode \xB7 Esc cancel \xB7 Children stay with the first part")}renderLineMode(){let t=this.contentEl.createDiv({cls:"stashpad-split-list"}),e=null;for(let i=0;i{let n=Math.max(1,Math.min(this.lines.length-1,i+1));n!==this.lineCursorIdx&&(this.lineCursorIdx=n,this.render())}}e&&window.requestAnimationFrame(()=>e.scrollIntoView({block:"center"}))}renderCursorMode(){let e=this.contentEl.createDiv({cls:"stashpad-split-cursor-wrap"}).createEl("textarea",{cls:"stashpad-split-cursor-ta"});e.value=this.body,e.readOnly=!1,this.cursorTextarea=e;let i=parseFloat(getComputedStyle(e).lineHeight)||22,s=q.Platform.isMobile?3:12,n=2,o=()=>{e.setCssStyles({height:"auto"});let r=Math.min(e.scrollHeight,i*s+16);e.setCssStyles({height:`${Math.max(r,i*n+16)}px`})};requestAnimationFrame(()=>{o();let r=Math.floor(e.value.length/2);e.focus(),e.setSelectionRange(r,r)}),e.addEventListener("input",o)}onClose(){this.cursorTextarea=null,this.contentEl.empty()}},oi=class extends q.Modal{constructor(t,e,i,s,n){super(t);this.defaultBaseName=e;this.noteCount=i;this.onConfirm=s;this.kdfProbe=n;this.delivered=!1}onOpen(){this.contentEl.empty(),this.titleEl.setText("Export to .stash"),this.modalEl.addClass("stashpad-export-modal"),this.contentEl.createEl("p",{cls:"stashpad-export-desc",text:`${this.noteCount} note${this.noteCount===1?"":"s"} will be bundled into a single .stash file.`});let t=this.contentEl.createDiv({cls:"stashpad-export-field"});t.createEl("label",{cls:"stashpad-export-label",text:"File name"});let e=t.createEl("input",{type:"text"});e.addClass("stashpad-export-name"),e.value=this.defaultBaseName;let i=this.contentEl.createEl("div",{cls:"stashpad-export-preview"}),s=this.contentEl.createDiv({cls:"stashpad-export-encrypt"}),n=s.createDiv({cls:"stashpad-export-toggle"}),o=n.createEl("input",{type:"checkbox"});o.id="stashpad-export-encrypt-cb";let r=n.createEl("label",{text:"Encrypt with a password"});r.htmlFor=o.id;let A=s.createDiv({cls:"stashpad-export-pw-area"});A.setCssStyles({display:"none"});let l=[],d=G=>{let V=A.createDiv({cls:"stashpad-export-pw-row"}),K=V.createEl("input",{type:"password"});K.addClass("stashpad-export-name"),K.placeholder=G;let O=V.createEl("button",{cls:"stashpad-export-copy"}),it=()=>{let at=K.value.length===0;O.setText(at?"Paste":"Copy"),O.toggleClass("is-paste",at),O.setAttr("aria-label",`${at?"Paste into":"Copy"} ${G.toLowerCase()}`)};return O.onclick=async at=>{if(at.preventDefault(),K.value.length===0)try{let _=(await navigator.clipboard?.readText())?.trim();if(!_){new q.Notice("Clipboard is empty.");return}K.value=_,K.dispatchEvent(new Event("input")),new q.Notice("Pasted from clipboard.")}catch{new q.Notice("Couldn't read the clipboard.")}else navigator.clipboard?.writeText(K.value).then(()=>new q.Notice("Passphrase copied to clipboard."),()=>new q.Notice("Couldn't access the clipboard."))},it(),l.push(it),K},g=d("Password"),p=d("Confirm password"),h=A.createDiv({cls:"stashpad-export-strength"}),I=h.createDiv({cls:"stashpad-strength-bar"}),u=[0,1,2,3].map(()=>I.createDiv({cls:"stashpad-strength-seg"})),f=h.createEl("span",{cls:"stashpad-strength-label"}),C=A.createDiv({cls:"stashpad-export-genrow"}),B=C.createEl("button",{cls:"stashpad-export-gen",text:"Generate strong passphrase"}),m=C.createEl("button",{cls:"stashpad-export-show",text:"Show"}),w=A.createEl("div",{cls:"stashpad-export-pw-hint"}),Q=A.createEl("div",{cls:"stashpad-export-pw-suite"});Q.setText("Encryption: AES-256-GCM. Checking key-derivation suite for this device\u2026"),this.kdfProbe?this.kdfProbe().then(G=>{Q.toggleClass("is-weak",!G),Q.setText(G?"Encryption: Argon2id + AES-256-GCM \u2014 the strongest suite (used on this device).":"\u26A0\uFE0F Argon2id can't run on this device, so this export will use the weaker PBKDF2 (600k) + AES-256-GCM fallback.")}).catch(()=>{Q.setText("Encryption: AES-256-GCM with a password-derived key.")}):Q.setText("Encryption: Argon2id + AES-256-GCM (falls back to PBKDF2 if Argon2 can't run here).");let E=this.app.secretStorage,v=A.createDiv({cls:"stashpad-export-remember"}),y=v.createEl("input",{type:"checkbox"});y.id="stashpad-export-remember-cb";let b=v.createEl("label",{text:"Remember in this vault (this device) \u2014 skips the prompt when you re-import here."});b.htmlFor=y.id;let N=A.createDiv({cls:"stashpad-export-remember-note"});N.setText("Saved only in this device's keychain \u2014 it doesn't sync to your other devices and isn't shared with anyone you send this file to. Keep the passphrase somewhere safe if you'll open this export elsewhere."),N.setCssStyles({display:"none"}),y.onchange=()=>{N.setCssStyles({display:y.checked?"":"none"})},E||v.setCssStyles({display:"none"});let P=()=>{let G=e.value.trim()||this.defaultBaseName;return o.checked?`${G}-encrypted`:G},H=()=>i.setText(`Saves as: ${P()}-.stash`);e.oninput=H;let D=this.contentEl.createDiv({cls:"stashpad-export-footer"}),S=D.createEl("button",{text:"Cancel"});S.onclick=()=>this.close();let M=D.createEl("button",{cls:"mod-cta",text:"Export"}),U=()=>{let G=en(g.value);h.style.visibility=g.value?"visible":"hidden",u.forEach((V,K)=>V.toggleClass("is-on",g.value!==""&&K<=G.level)),I.dataset.level=String(G.level),f.setText(G.label)},R=()=>{let G=o.checked;A.setCssStyles({display:G?"":"none"});let V=!0;G&&(g.value?g.value!==p.value?(w.setText("Passwords don't match."),w.addClass("is-error"),V=!1):(w.setText("\u26A0\uFE0F If you lose this password, the export can't be recovered."),w.removeClass("is-error")):(w.setText("Enter a password to encrypt this export."),w.removeClass("is-error"),V=!1)),U(),l.forEach(K=>K()),M.disabled=!V,M.toggleClass("is-disabled",!V),H()},W=!1,Y=G=>{W=G,g.type=p.type=G?"text":"password",m.setText(G?"Hide":"Show")};m.onclick=G=>{G.preventDefault(),Y(!W)},B.onclick=G=>{G.preventDefault(),g.value=p.value=tn(),Y(!1),new q.Notice("Passphrase generated (hidden) \u2014 Show to view, or Copy to save it."),R()},o.onchange=R,g.oninput=R,p.oninput=R,R();let z=()=>this.commit(P(),o.checked?g.value:null,o.checked&&y.checked);M.onclick=z,this.scope.register([],"Enter",G=>{G.preventDefault(),M.disabled||z()}),requestAnimationFrame(()=>{e.focus(),e.select()})}commit(t,e,i){let s=t.trim()||this.defaultBaseName,n=e&&e.length?e:null;this.delivered=!0,this.close(),this.onConfirm(s,n,!!n&&i)}onClose(){this.contentEl.empty()}},ai=class extends q.Modal{constructor(t,e,i,s){super(t);this.errorMsg=e;this.allowLater=i;this.onResult=s;this.delivered=!1}onOpen(){this.contentEl.empty(),this.titleEl.setText("Encrypted .stash"),this.modalEl.addClass("stashpad-export-modal"),this.contentEl.createEl("p",{cls:"stashpad-export-desc",text:"This export is password-protected. Enter its password to import it."}),this.errorMsg&&this.contentEl.createEl("div",{cls:"stashpad-export-error",text:this.errorMsg});let t=this.contentEl.createEl("input",{type:"password"});t.addClass("stashpad-export-name"),t.placeholder="Password";let e=this.contentEl.createDiv({cls:"stashpad-export-footer"});if(e.createEl("button",{text:"Cancel"}).onclick=()=>this.close(),this.allowLater){let s=e.createEl("button",{text:"Remind me later"});s.title="Don't import now \u2014 surface the reminder again later.",s.onclick=()=>this.finish({kind:"later"})}let i=e.createEl("button",{cls:"mod-cta",text:"Decrypt & import"});i.onclick=()=>this.submit(t.value),this.scope.register([],"Enter",s=>{s.preventDefault(),this.submit(t.value)}),requestAnimationFrame(()=>t.focus())}submit(t){t&&this.finish({kind:"password",value:t})}finish(t){this.delivered=!0,this.close(),this.onResult(t)}onClose(){this.delivered||(this.delivered=!0,this.onResult({kind:"cancel"})),this.contentEl.empty()}},yt=class extends q.Modal{constructor(t,e){super(t);this.opts=e;this.succeeded=!1}onOpen(){let{mode:t}=this.opts;this.contentEl.empty(),this.modalEl.addClass("stashpad-export-modal","stashpad-encryption-modal"),this.titleEl.setText(this.opts.title??(t==="setup"?"Set up encryption password":t==="change"?"Change encryption password":"Unlock encryption")),this.contentEl.createDiv({cls:"stashpad-beta-row"}).createEl("span",{cls:"stashpad-beta-badge",text:"BETA"}),this.opts.intro?this.contentEl.createEl("p",{cls:"stashpad-export-desc",text:this.opts.intro}):t==="setup"&&this.contentEl.createEl("p",{cls:"stashpad-export-desc",text:"This single password protects everything you encrypt in this vault. It is stored only on this device. There is NO recovery \u2014 if you lose it, anything you've encrypted is gone for good."});let e=[],i=u=>{let f=this.contentEl.createDiv({cls:"stashpad-export-pw-row stashpad-encryption-row"}),C=f.createEl("input",{type:"password"});C.addClass("stashpad-export-name","stashpad-encryption-field"),C.placeholder=u;let B=f.createEl("button",{cls:"stashpad-export-copy"}),m=()=>{let w=C.value.length===0;B.setText(w?"Paste":"Copy"),B.toggleClass("is-paste",w),B.setAttr("aria-label",`${w?"Paste into":"Copy"} ${u.toLowerCase()}`)};return B.onclick=async w=>{if(w.preventDefault(),C.value.length===0)try{let Q=(await navigator.clipboard?.readText())?.trim();if(!Q){new q.Notice("Clipboard is empty.");return}C.value=Q,C.dispatchEvent(new Event("input")),new q.Notice("Pasted from clipboard.")}catch{new q.Notice("Couldn't read the clipboard.")}else navigator.clipboard?.writeText(C.value).then(()=>new q.Notice("Copied to clipboard."),()=>new q.Notice("Couldn't access the clipboard."))},C.addEventListener("input",m),m(),e.push(m),C},s=null,n=null,o=null;if((t==="unlock"||t==="change")&&(s=i("Current password")),(t==="setup"||t==="change")&&(n=i(t==="change"?"New password":"Password"),o=i("Confirm password")),n){let u=this.contentEl.createDiv({cls:"stashpad-export-strength"}),f=u.createDiv({cls:"stashpad-strength-bar"}),C=[0,1,2,3].map(()=>f.createDiv({cls:"stashpad-strength-seg"})),B=u.createEl("span",{cls:"stashpad-strength-label"}),m=this.contentEl.createDiv({cls:"stashpad-encryption-counter"}),w=()=>{let y=n.value,b=en(y);C.forEach((N,P)=>N.toggleClass("is-on",P0&&y.length<6?" \u2014 use at least 6":""}`),m.toggleClass("is-weak",y.length>0&&y.length<6)};n.addEventListener("input",w),w();let Q=this.contentEl.createDiv({cls:"stashpad-export-genrow"});Q.createEl("button",{cls:"stashpad-export-gen",text:"Generate strong passphrase"}).onclick=y=>{y.preventDefault();let b=tn(5);n.value=b,o&&(o.value=b),w(),e.forEach(N=>N()),new q.Notice("Generated \u2014 copy it somewhere safe; there's no recovery."),navigator.clipboard?.writeText(b).catch(()=>{})};let E=Q.createEl("button",{cls:"stashpad-export-show",text:"Show"});E.onclick=y=>{y.preventDefault();let b=n.type==="password";n.type=b?"text":"password",o&&(o.type=b?"text":"password"),E.setText(b?"Hide":"Show")};let v=this.contentEl.createEl("div",{cls:"stashpad-export-pw-suite"});v.setText("Encryption: AES-256-GCM. Checking key-derivation suite\u2026"),this.opts.kdfProbe?this.opts.kdfProbe().then(y=>{v.toggleClass("is-weak",!y),v.setText(y?"Encryption: Argon2id + AES-256-GCM \u2014 the strongest suite (used on this device).":"\u26A0\uFE0F Argon2id can't run here, so this will use the weaker PBKDF2 (600k) + AES-256-GCM fallback.")}).catch(()=>v.setText("Encryption: AES-256-GCM with a password-derived key.")):v.setText("Encryption: Argon2id + AES-256-GCM (PBKDF2 fallback if Argon2 can't run here).")}let r=null,A=this.app.secretStorage;if(this.opts.offerKeychain&&A){let u=this.contentEl.createDiv({cls:"stashpad-export-remember"});r=u.createEl("input",{type:"checkbox"}),r.id="stashpad-enc-remember";let f=u.createEl("label",{text:"Remember on this device (keychain) \u2014 auto-unlock here without re-typing."});f.htmlFor=r.id;let C=this.contentEl.createDiv({cls:"stashpad-export-remember-note"});C.setText("Stored only in this device's keychain \u2014 doesn't sync to your other devices. Anyone with access to this unlocked device + keychain could decrypt."),C.setCssStyles({display:"none"}),r.onchange=()=>{C.setCssStyles({display:r.checked?"":"none"})}}let l=this.contentEl.createEl("div",{cls:"stashpad-export-error"});l.setCssStyles({display:"none"});let d=u=>{l.setText(u),l.setCssStyles({display:""})},g=this.contentEl.createDiv({cls:"stashpad-export-footer"});g.createEl("button",{text:"Cancel"}).onclick=()=>this.close();let p=g.createEl("button",{cls:"mod-cta",text:t==="setup"?"Set up":t==="change"?"Change":"Unlock"}),h=!1,I=async()=>{if(h)return;let u=s?.value??void 0,f=n?.value??void 0;if((t==="unlock"||t==="change")&&!u){d("Enter your current password.");return}if(t==="setup"||t==="change"){if(!f){d("Enter a password.");return}if(f.length<6){d("Use at least 6 characters.");return}if(f!==o?.value){d("Passwords don't match.");return}}h=!0,p.disabled=!0,l.setCssStyles({display:"none"});let C=p.textContent;p.setText("Working\u2026");try{let B=await this.opts.onSubmit({current:u,next:f,remember:!!r?.checked});if(B){d(B),h=!1,p.disabled=!1,p.setText(C??"OK");return}this.succeeded=!0,this.close()}catch(B){d(`Failed: ${B.message}`),h=!1,p.disabled=!1,p.setText(C??"OK")}};p.onclick=()=>void I(),this.scope.register([],"Enter",u=>{u.preventDefault(),I()}),requestAnimationFrame(()=>(s??n)?.focus())}onClose(){this.contentEl.empty(),this.succeeded||this.opts.onCancel?.()}},ri=class extends q.Modal{constructor(t,e){super(t);this.opts=e}onOpen(){this.contentEl.empty(),this.modalEl.addClass("stashpad-export-modal","stashpad-encryption-modal"),this.titleEl.setText(this.opts.title),this.contentEl.createEl("p",{cls:"stashpad-export-desc",text:this.opts.body});let t=null;this.opts.requirePassword&&(this.contentEl.createEl("p",{cls:"stashpad-export-desc"}).setText("Enter your encryption password:"),t=this.contentEl.createEl("input",{type:"password"}),t.addClass("stashpad-export-name","stashpad-encryption-field"),t.placeholder="Password"),this.contentEl.createEl("p",{cls:"stashpad-export-desc"}).setText(`Type "${this.opts.phrase}" to confirm.`);let e=this.contentEl.createEl("input",{type:"text"});e.addClass("stashpad-export-name","stashpad-encryption-field"),e.placeholder=this.opts.phrase;let i=this.contentEl.createEl("div",{cls:"stashpad-export-error"});i.setCssStyles({display:"none"});let s=this.contentEl.createDiv({cls:"stashpad-export-footer"});s.createEl("button",{text:"Cancel"}).onclick=()=>this.close();let n=s.createEl("button",{cls:"mod-cta mod-warning",text:this.opts.confirmText}),o=()=>e.value.trim().toLowerCase()===this.opts.phrase.trim().toLowerCase(),r=()=>{n.disabled=!o()||!!this.opts.requirePassword&&!t?.value};e.addEventListener("input",r),t?.addEventListener("input",r),r();let A=!1,l=async()=>{if(!(A||!o())){if(this.opts.requirePassword&&(A=!0,n.disabled=!0,i.setCssStyles({display:"none"}),!await this.opts.requirePassword(t.value))){i.setText("Wrong password."),i.setCssStyles({display:""}),A=!1,r();return}this.close(),await this.opts.onConfirm()}};n.onclick=()=>void l(),this.scope.register([],"Enter",d=>{d.preventDefault(),l()}),requestAnimationFrame(()=>(t??e).focus())}onClose(){this.contentEl.empty()}},Li=class extends q.Modal{constructor(t,e,i){super(t);this.onResult=i;this.delivered=!1;this.value=e&&/^#[0-9a-f]{6}$/i.test(e)?e:"#888888"}onOpen(){this.contentEl.empty(),this.titleEl.setText("Custom color"),this.modalEl.addClass("stashpad-custom-color-modal");let t=this.contentEl.createDiv({cls:"stashpad-custom-color-row"}),e=t.createDiv({cls:"stashpad-custom-color-preview"});e.style.background=this.value;let i=t.createEl("input",{type:"color"});i.value=this.value,i.addClass("stashpad-custom-color-wheel"),e.onclick=()=>i.click();let s=t.createEl("input",{type:"text"});s.addClass("stashpad-custom-color-hex"),s.placeholder="#RRGGBB",s.value=this.value,s.maxLength=7;let n=d=>{let g=d.startsWith("#")?d:"#"+d;/^#[0-9a-f]{6}$/i.test(g)&&(this.value=g,e.style.background=g,i.value=g,s.value!==g&&(s.value=g))};i.oninput=()=>n(i.value),s.oninput=()=>n(s.value);let o=this.contentEl.createDiv({cls:"stashpad-color-footer"}),r=o.createEl("button",{text:"Cancel"});r.onclick=()=>{this.delivered=!0,this.close()};let A=o.createEl("button",{cls:"mod-cta",text:"Save"});A.title="Apply this color to the selection (without adding to your palette).",A.onclick=()=>this.commit({addToPalette:!1});let l=o.createEl("button",{cls:"mod-cta",text:"Add to palette"});l.title="Apply and save this color so it appears as a tile next time.",l.onclick=()=>this.commit({addToPalette:!0}),this.scope.register([],"Enter",d=>{d.preventDefault(),this.commit({addToPalette:!1})}),this.scope.register(["Mod"],"Enter",d=>{d.preventDefault(),this.commit({addToPalette:!0})}),requestAnimationFrame(()=>s.focus())}commit(t){this.delivered=!0,this.close(),this.onResult(this.value,t)}onClose(){this.delivered||(this.delivered=!0,this.onResult(this.value,{addToPalette:!1})),this.contentEl.empty()}},si=class si extends q.Modal{constructor(t,e,i,s,n){super(t);this.currentColor=e;this.customPalette=i;this.onPick=s;this.onDeleteCustom=n;this.focusIdx=-1;this.items=[]}onOpen(){this.contentEl.empty(),this.titleEl.setText("Pick a color"),this.modalEl.addClass("stashpad-color-modal");let t=this.contentEl.createDiv({cls:"stashpad-color-grid"});this.items=[];let e=t.createDiv({cls:"stashpad-color-tile stashpad-color-none"});e.title="No color",e.onclick=()=>this.activate(0),this.items.push({kind:"none",color:null,el:e});let i=[...si.DEFAULT_PALETTE,...this.customPalette];for(let r of i){let A=t.createDiv({cls:"stashpad-color-tile"});A.style.background=r,A.title=r;let l=!si.DEFAULT_PALETTE.some(g=>g.toLowerCase()===r.toLowerCase()),d=this.items.length;if(A.onclick=()=>this.activate(d),l&&this.onDeleteCustom){let g=A.createSpan({cls:"stashpad-color-tile-del",text:"\xD7"});g.title="Remove from palette",g.onclick=p=>{p.stopPropagation(),this.handleDelete(r)}}this.items.push({kind:l?"custom":"preset",color:r,el:A})}let s=t.createDiv({cls:"stashpad-color-tile stashpad-color-add"});s.title="Custom color\u2026";let n=this.items.length;s.onclick=()=>this.activate(n),this.items.push({kind:"add",color:null,el:s});let o=this.items.findIndex(r=>this.currentColor===null?r.kind==="none":this.currentColor?r.color!==null&&r.color.toLowerCase()===this.currentColor.toLowerCase():!1);this.focusIdx=o>=0?o:0,this.refreshActive(),this.scope.register([],"ArrowRight",r=>{r.preventDefault(),this.moveFocus(1)}),this.scope.register([],"ArrowLeft",r=>{r.preventDefault(),this.moveFocus(-1)}),this.scope.register([],"ArrowDown",r=>{r.preventDefault(),this.moveFocus(this.columns())}),this.scope.register([],"ArrowUp",r=>{r.preventDefault(),this.moveFocus(-this.columns())}),this.scope.register([],"Enter",r=>{r.preventDefault(),this.activate(this.focusIdx)}),requestAnimationFrame(()=>this.modalEl.focus())}activate(t){if(t<0||t>=this.items.length)return;this.focusIdx=t,this.refreshActive();let e=this.items[t];if(e.kind==="add"){this.close(),new Li(this.app,this.currentColor,(i,s)=>{this.onPick(i,s)}).open();return}this.close(),this.onPick(e.color,{addToPalette:!1})}columns(){if(!this.items.length)return 1;let t=this.items[0].el.parentElement;if(!t)return 1;let e=t.getBoundingClientRect(),i=this.items[0].el.getBoundingClientRect();if(i.width<=0)return 1;let s=i.top,n=0;for(let o of this.items){let r=o.el.getBoundingClientRect();if(Math.abs(r.top-s)<1)n++;else break}return Math.max(1,n)}async handleDelete(t){if(this.onDeleteCustom)try{let e=await this.onDeleteCustom(t);this.customPalette=Array.isArray(e)?e:this.customPalette.filter(i=>i.toLowerCase()!==t.toLowerCase()),this.onOpen()}catch(e){console.warn("Stashpad: palette delete failed",e)}}moveFocus(t){if(!this.items.length)return;let e=Math.max(0,Math.min(this.items.length-1,this.focusIdx+t));this.focusIdx=e,this.refreshActive()}refreshActive(){for(let t=0;t{this.didChoose=!0,this.close(),this.onChoose(!1)};let s=e.createEl("button",{cls:"mod-cta",text:this.confirmText});s.onclick=()=>{this.didChoose=!0,this.close(),this.onChoose(!0)},requestAnimationFrame(()=>s.focus())}onClose(){this.contentEl.empty(),this.didChoose||(this.didChoose=!0,this.onChoose(!1))}};Ai=class extends q.Modal{constructor(t,e,i){super(t);this.opts=e;this.onPick=i;this.didChoose=!1;this.assignees=[];this.assignees=[...e.currentAssignees]}onOpen(){this.modalEl?.addClass("stashpad-compact-modal"),this.contentEl.empty(),this.titleEl.setText("Assign task");let t=this.contentEl.createDiv({cls:"stashpad-due-picker"});nn(t,{knownAuthors:this.opts.knownAuthors,initial:this.assignees,onChange:n=>{this.assignees=n}});let e=this.contentEl.createDiv({cls:"stashpad-modal-btns"}),i=e.createEl("button",{text:"Cancel"});i.onclick=()=>{this.didChoose=!0,this.close()};let s=e.createEl("button",{cls:"mod-cta",text:"Save"});s.onclick=()=>{this.didChoose=!0,this.close(),this.onPick(this.assignees)}}onClose(){this.contentEl.empty(),this.didChoose}},li=class extends q.Modal{constructor(t,e,i,s={}){super(t);this.current=e;this.onPick=i;this.opts=s;this.didChoose=!1;this.assignees=[];this.tinyClosePopover=null;this.assignees=[...s.currentAssignees??[]]}onOpen(){this.modalEl?.addClass("stashpad-compact-modal"),this.contentEl.empty(),this.titleEl.setText("Set due date");let t=null;if(this.current){let f=Date.parse(this.current);Number.isNaN(f)||(t=new Date(f))}let e=this.contentEl.createDiv({cls:"stashpad-due-picker"}),i=e.createDiv({cls:"stashpad-due-fields"}),s=i.createDiv({cls:"stashpad-due-field"}),n=s.createSpan({cls:"stashpad-due-field-icon"});(0,q.setIcon)(n,"calendar");let o=s.createEl("input",{type:"date",cls:"stashpad-due-date"}),r=i.createDiv({cls:"stashpad-due-field"}),A=r.createSpan({cls:"stashpad-due-field-icon"});(0,q.setIcon)(A,"clock");let l=r.createEl("input",{type:"time",cls:"stashpad-due-time"});n.onclick=()=>{try{o.showPicker?.()}catch{}},A.onclick=()=>this.openTimeNumpad(A,l),t&&(o.value=this.toDateValue(t),l.value=this.toTimeValue(t)),this.renderAssignSection(e);let d=e.createDiv({cls:"stashpad-due-grid"}),g=(f,C)=>{let B=d.createEl("button",{cls:"stashpad-due-btn stashpad-due-preset",text:f});B.onclick=()=>{let m=C();o.value=this.toDateValue(m),l.value||(l.value=this.toTimeValue(m))}},p=f=>(f.setHours(9,0,0,0),f);g("Today",()=>p(this.startOfTodayLocal())),g("Tomorrow",()=>{let f=this.startOfTodayLocal();return f.setDate(f.getDate()+1),p(f)}),g("Next week",()=>{let f=this.startOfTodayLocal();return f.setDate(f.getDate()+7),p(f)});let h=d.createEl("button",{cls:"stashpad-due-btn",text:"Clear"});h.onclick=()=>{o.value="",l.value="",o.focus()};let I=d.createEl("button",{cls:"stashpad-due-btn",text:"Cancel"});I.onclick=()=>{this.didChoose=!0,this.close()};let u=d.createEl("button",{cls:"stashpad-due-btn mod-cta",text:"Set"});u.onclick=()=>{if(!o.value){this.didChoose=!0,this.close(),this.onPick({iso:null,assignees:this.assignees});return}let[f,C,B]=o.value.split("-").map(E=>parseInt(E,10)),m=9,w=0;if(l.value){let[E,v]=l.value.split(":").map(y=>parseInt(y,10));m=E,w=v}let Q=new Date(f,C-1,B,m,w,0,0);this.didChoose=!0,this.close(),this.onPick({iso:Q.toISOString(),assignees:this.assignees})},requestAnimationFrame(()=>o.focus())}onClose(){this.tinyClosePopover?.(),this.contentEl.empty(),this.didChoose}renderAssignSection(t){nn(t,{knownAuthors:this.opts.knownAuthors??[],initial:this.assignees,onChange:e=>{this.assignees=e}})}openTimeNumpad(t,e){this.tinyClosePopover?.();let i=9,s=0;if(e.value){let[h,I]=e.value.split(":").map(u=>parseInt(u,10));Number.isFinite(h)&&(i=h),Number.isFinite(I)&&(s=I)}else{let h=new Date;i=h.getHours(),s=h.getMinutes()}let n=i>=12?"pm":"am",o=i===0?12:i>12?i-12:i,r=document.body.createDiv({cls:"stashpad-when-popover stashpad-due-time-pop"});r.setCssStyles({position:"fixed",zIndex:"9999"});let A=null,l=()=>{r.remove(),document.removeEventListener("mousedown",d,!0),document.removeEventListener("keydown",g,!0),this.tinyClosePopover===l&&(this.tinyClosePopover=null)},d=h=>{!r.contains(h.target)&&h.target!==t&&!t.contains(h.target)&&l()},g=h=>{h.key==="Escape"?(h.preventDefault(),h.stopPropagation(),l()):h.key==="Enter"&&A&&(h.preventDefault(),h.stopPropagation(),A())};this.tinyClosePopover=l,Ui(r,{seedH:o,seedM:s,seedPeriod:n,close:l,setOnEnter:h=>{A=h},onFinalize:h=>{e.value=`${String(h.hours24).padStart(2,"0")}:${String(h.minutes).padStart(2,"0")}`}});let p=t.getBoundingClientRect();r.setCssStyles({left:`${Math.max(8,Math.min(p.left,window.innerWidth-220))}px`,top:`${p.bottom+4}px`}),setTimeout(()=>{document.addEventListener("mousedown",d,!0),document.addEventListener("keydown",g,!0)},0)}startOfTodayLocal(){let t=new Date;return t.setHours(0,0,0,0),t}toDateValue(t){let e=t.getFullYear(),i=String(t.getMonth()+1).padStart(2,"0"),s=String(t.getDate()).padStart(2,"0");return`${e}-${i}-${s}`}toTimeValue(t){let e=String(t.getHours()).padStart(2,"0"),i=String(t.getMinutes()).padStart(2,"0");return`${e}:${i}`}},ye=class ye extends q.Modal{constructor(t,e,i,s=null,n){super(t);this.service=e;this.openLog=i;this.currentAuthorId=s;this.getNoteAuthorIds=n;this.records=[];this.visible=[];this.shownCount=0;this.categoryFilter=null;this.listEl=null;this.footerEl=null;this.countEl=null;this.filterSelEl=null;this.unsubscribe=null;this.authorFilter="all";this.authorSelEl=null}onOpen(){this.contentEl.empty(),this.titleEl.setText("Stashpad notification history"),this.modalEl.addClass("stashpad-log-modal"),this.modalEl.addClass("stashpad-notif-history-modal"),this.records=this.service.recent();let t=this.contentEl.createDiv({cls:"stashpad-log-toolbar"});if(this.countEl=t.createSpan({cls:"stashpad-log-count"}),this.updateCount(),this.filterSelEl=t.createEl("select",{cls:"stashpad-log-type-filter"}),this.filterSelEl.onchange=()=>this.setCategoryFilter(this.filterSelEl.value||null),this.refreshCategoryFilter(),this.authorSelEl=t.createEl("select",{cls:"stashpad-log-type-filter stashpad-notif-author-filter"}),this.authorSelEl.onchange=()=>this.setAuthorFilter(this.authorSelEl.value||"all"),this.refreshAuthorFilter(),this.openLog){let i=t.createEl("button",{text:"Open log"});i.title="Open the per-folder Stashpad log for the most recent notification's folder.",i.onclick=()=>{let s=this.records.find(n=>!!n.folder);this.openLog?.(s?.folder)}}let e=t.createEl("button",{cls:"mod-warning",text:"Clear history"});e.onclick=()=>{new gt(this.app,"Clear notification history?",`This will permanently remove all ${this.records.length} stored notifications from the history. The current toasts on screen are unaffected. This can't be undone.`,"Clear history",i=>{i&&this.service.clearHistory()}).open()},this.listEl=this.contentEl.createDiv({cls:"stashpad-log-list"}),this.refreshList(),this.footerEl=this.contentEl.createDiv({cls:"stashpad-log-footer"}),this.renderFooter(),this.unsubscribe=this.service.onChange(()=>{this.records=this.service.recent(),this.refreshCategoryFilter(),this.refreshAuthorFilter(),this.refreshList(),this.renderFooter()})}setAuthorFilter(t){this.authorFilter!==t&&(this.authorFilter=t,this.refreshList(),this.renderFooter())}refreshAuthorFilter(){if(!this.authorSelEl)return;let t=this.authorSelEl;t.empty(),t.createEl("option",{text:"All authors"}).value="all",this.currentAuthorId&&(t.createEl("option",{text:"Me"}).value="me"),t.createEl("option",{text:"Cross-author"}).value="cross";let e=new Set;for(let s of this.records)s.authorId&&s.authorId!==this.currentAuthorId&&e.add(s.authorId);if(e.size>0){let s=t.createEl("option",{text:"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"});s.disabled=!0;for(let n of[...e].sort())t.createEl("option",{text:n}).value=n}new Set(["all","cross",...this.currentAuthorId?["me"]:[],...e]).has(this.authorFilter)||(this.authorFilter="all"),t.value=this.authorFilter}isCrossAuthor(t){let e=t.authorId??null;if(!e)return!1;for(let i of t.affectedAuthorIds??[])if(i&&i!==e)return!0;if(!this.getNoteAuthorIds)return!1;for(let i of t.affectedIds){let s=this.getNoteAuthorIds(i);for(let n of s)if(n&&n!==e)return!0}return!1}onClose(){this.unsubscribe?.(),this.unsubscribe=null,this.contentEl.empty()}setCategoryFilter(t){(this.categoryFilter??null)!==(t??null)&&(this.categoryFilter=t,this.refreshList(),this.renderFooter())}refreshCategoryFilter(){if(!this.filterSelEl)return;let t=this.filterSelEl;t.empty();let e=new Map;for(let n of this.records)e.set(n.category,(e.get(n.category)??0)+1);let i=[...e.entries()].sort((n,o)=>o[1]-n[1]||n[0].localeCompare(o[0])),s=t.createEl("option",{text:`All categories (${this.records.length})`});s.value="";for(let[n,o]of i){let r=t.createEl("option",{text:`${n} (${o})`});r.value=n}this.categoryFilter&&!e.has(this.categoryFilter)&&(this.categoryFilter=null),t.value=this.categoryFilter??""}refreshList(){if(this.listEl){if(this.visible=this.records.filter(t=>{if(this.categoryFilter&&t.category!==this.categoryFilter)return!1;switch(this.authorFilter){case"all":return!0;case"me":return!!this.currentAuthorId&&t.authorId===this.currentAuthorId;case"cross":return this.isCrossAuthor(t);default:return t.authorId===this.authorFilter}}),this.shownCount=0,this.listEl.empty(),!this.visible.length){this.listEl.createDiv({cls:"stashpad-log-empty",text:this.categoryFilter?`No "${this.categoryFilter}" notifications.`:"No notifications yet."}),this.updateCount();return}this.appendMore(ye.PAGE)}}appendMore(t){if(!this.listEl)return;let e=Math.min(this.visible.length,this.shownCount+t);for(let i=this.shownCount;i0){let l=i.createDiv({cls:"stashpad-notif-actions-snapshot"});for(let d of e.actionLabels){let g=l.createSpan({cls:"stashpad-notif-action-chip"});g.setText(d),g.title="Action button was shown on the original toast (handler not retained)."}}}updateCount(){if(!this.countEl)return;let t=this.visible.length,e=this.categoryFilter?`${t} ${this.categoryFilter} notification${t===1?"":"s"}`:`${t} notification${t===1?"":"s"}`;this.shownCount===0||this.shownCount>=t?this.countEl.setText(e):this.countEl.setText(`Showing ${this.shownCount} of ${e}`)}renderFooter(){if(!this.footerEl)return;this.footerEl.empty();let t=this.visible.length-this.shownCount;if(t<=0)return;let e=this.footerEl.createEl("button",{text:`Load ${Math.min(ye.PAGE,t)} more`});if(e.onclick=()=>{this.appendMore(ye.PAGE),this.renderFooter()},t>ye.PAGE){let i=this.footerEl.createEl("button",{text:`Load all (${t})`});i.onclick=()=>{this.appendMore(t),this.renderFooter()}}}};ye.PAGE=100;ci=ye,sn=class extends q.Modal{constructor(t,e){super(t);this.entries=e}onOpen(){if(this.contentEl.empty(),this.titleEl.setText("Stashpad import log"),this.entries.length===0){this.contentEl.createDiv({cls:"stashpad-log-empty",text:"Nothing imported yet."});return}let t=this.contentEl.createDiv({cls:"stashpad-import-log-list"});for(let e of this.entries){let i=t.createDiv({cls:"stashpad-import-log-row"}),s=(0,q.moment)(e.ts).format("YYYY-MM-DD HH:mm");i.createSpan({cls:"stashpad-import-log-when",text:s});let n=e.kind==="folder"?"folder":e.kind==="md"?"note":"file";i.createSpan({cls:`stashpad-import-log-kind is-${e.kind}`,text:n}),i.createSpan({cls:"stashpad-import-log-name",text:e.originalName});let o=[e.folder.split("/").pop()||e.folder];e.notePaths.length>1&&o.push(`${e.notePaths.length} notes`),i.createSpan({cls:"stashpad-import-log-meta",text:o.join(" \xB7 ")})}}onClose(){this.contentEl.empty()}},di=class extends q.Modal{constructor(t,e,i){super(t);this.message=e;this.onChoose=i;this.chose=!1}onOpen(){this.modalEl?.addClass("stashpad-compact-modal"),this.contentEl.empty(),this.titleEl.setText("Possible duplicate import");let t=this.contentEl.createDiv({cls:"stashpad-confirm-body"});for(let o of this.message.split(` -`))t.createDiv({cls:"stashpad-confirm-line",text:o});let e=this.contentEl.createDiv({cls:"stashpad-modal-btns"}),i=e.createEl("button",{text:"Skip duplicates"});i.onclick=()=>{this.chose=!0,this.close(),this.onChoose("skip")};let s=e.createEl("button",{text:"Replace existing"});s.onclick=()=>{this.chose=!0,this.close(),this.onChoose("replace")};let n=e.createEl("button",{cls:"mod-cta",text:"Import anyway"});n.onclick=()=>{this.chose=!0,this.close(),this.onChoose("anyway")}}onClose(){this.chose||this.onChoose("skip"),this.contentEl.empty()}},hi=class extends q.Modal{constructor(t,e,i,s){super(t);this.noteCount=i;this.onConfirm=s;this.base=e}onOpen(){this.contentEl.empty(),this.modalEl.addClass("stashpad-export-modal"),this.titleEl.setText("Export as OKF"),this.contentEl.createEl("p",{cls:"stashpad-export-desc",text:`Export ${this.noteCount} note${this.noteCount===1?"":"s"} as an Open Knowledge Format bundle. Pick one or more formats.`});let t=this.contentEl.createEl("input",{type:"text"});t.addClass("stashpad-export-name"),t.value=this.base,t.placeholder="Export name";let e=(A,l)=>{let d=this.contentEl.createDiv({cls:"stashpad-okf-fmt"}),g=d.createEl("input",{type:"checkbox"});return g.checked=l,d.createEl("label",{text:A}),g},i=e(".zip \u2014 OKF bundle (portable)",!0),s=e(".tar.gz \u2014 OKF bundle (tarball)",!1),n=e(".stash \u2014 Stashpad format (re-importable)",!1),o=this.contentEl.createDiv({cls:"stashpad-export-footer"});o.createEl("button",{text:"Cancel"}).onclick=()=>this.close();let r=o.createEl("button",{cls:"mod-cta",text:"Export"});r.onclick=()=>{if(!i.checked&&!s.checked&&!n.checked){new q.Notice("Pick at least one format.");return}this.close(),this.onConfirm(t.value.trim()||this.base,{zip:i.checked,targz:s.checked,stash:n.checked})},requestAnimationFrame(()=>t.focus())}onClose(){this.contentEl.empty()}}});function Et(c,a=Lt){let t=a instanceof Set?a:new Set(a.map(o=>o.toLowerCase())),e=(c.split(/\r?\n/).find(o=>o.trim().length>0)??"").trim();if(!e)return"Untitled";let s=e.replace(/['‘-‛ʼ]/g,"").replace(/[^A-Za-z0-9\s]+/g," ").split(/\s+/).filter(o=>o&&!t.has(o.toLowerCase())).map(o=>o.length>=2&&/^[A-Z0-9]+$/.test(o)?o:o.charAt(0).toUpperCase()+o.slice(1).toLowerCase()),n="";for(let o of s){let r=n?`${n}-${o}`:o;if(r.length>50)break;n=r}return n||"Untitled"}function wt(c,a){return`${c}-${a}.md`}function ve(c){let a=c.match(/-([a-z0-9]{4,12})$/);return a?a[1]:null}var Lt,Te=Gt(()=>{"use strict";Lt=["a","an","the","and","or","but","if","then","else","of","in","on","at","to","for","with","by","from","as","is","are","was","were","be","been","being","i","you","he","she","it","we","they","this","that","these","those","my","your","our","their","do","does","did","so","just","very","really","im"]});var Yi={};Xe(Yi,{JdBuildConfirmModal:()=>Ii,buildJdIndexNotes:()=>an,buildJdIndexPreview:()=>Ki,buildJdPreviewNotice:()=>Oi,scanForJdNotes:()=>He});function on(c,a){if(/^\d+-\d+$/.test(c))return null;if(c.includes(".")){let e=c.split(".").slice(0,-1).join(".");return a.has(e)?e:on(e,a)}if(/^\d+$/.test(c)){let t=parseInt(c,10);for(let e of a){let i=e.match(/^(\d+)-(\d+)$/);if(!i)continue;let s=parseInt(i[1],10),n=parseInt(i[2],10);if(t>=s&&t<=n)return e}return null}return null}function He(c,a,t){let e=c.vault.getMarkdownFiles(),i=pr(e,t),s=t.jdIndexIncludeStashpadFolders===!0,n=s?new Set:new Set(a.discoverStashpadFolders()),o=h=>s?!1:Array.from(n).some(I=>h===I||h.startsWith(I+"/")),r=[],A=[],l=[];for(let h of i){let I=h.parent?.path?.replace(/\/+$/,"")??"";if(o(I)){l.push(h);continue}let u=h.basename.match(vo);u?r.push({prefix:u[1],segments:u[1].split("."),title:u[2],file:h,folder:null}):A.push(h)}let d=(t.jdIndexScope??"vault")==="folder"?(t.jdIndexScopeFolder??"").trim().replace(/^\/+|\/+$/g,""):"",g=h=>{let I=h.path.replace(/\/+$/,"");if(!(d&&I&&I!==d&&!I.startsWith(d+"/"))){if(I&&!o(I)){let u=h.name.match(vo);u&&r.push({prefix:u[1],segments:u[1].split("."),title:u[2],file:null,folder:h})}}for(let u of h.children)u instanceof pt.TFolder&&g(u)};g(c.vault.getRoot());let p=t.jdIndexSort??"natural";return r.sort((h,I)=>Ir(h,I,p)),{indexed:r,nonIndex:A,skippedStashpadNotes:l}}async function Ki(c,a,t){let e=rn(t.jdIndexStashpadFolder??"");if(!e)return{...He(c,a,t),previewPath:null,error:"no-dest"};let i=He(c,a,t),s=gr(c,e);if(!s)return{...i,previewPath:null,error:"no-home"};let n=ur(i.indexed,i.nonIndex,i.skippedStashpadNotes),r=(await c.vault.read(s)).match(/^---\r?\n[\s\S]*?\r?\n---\r?\n/),A=r?`${r[0]}${n}`:n;return await c.vault.modify(s,A),{...i,previewPath:s.path}}function gr(c,a){let t=c.vault.getAbstractFileByPath(a);if(!(t instanceof pt.TFolder))return null;for(let e of t.children){if(!(e instanceof pt.TFile)||e.extension!=="md")continue;if((c.metadataCache.getFileCache(e)?.frontmatter??{}).id===F)return e}return null}async function an(c,a,t){let e=rn(t.jdIndexStashpadFolder??"");if(!e)return{created:0,updated:0,skipped:0,destFolder:"",error:"no-dest"};if(!new Set(a.discoverStashpadFolders()).has(e))return{created:0,updated:0,skipped:0,destFolder:e,error:"dest-not-stashpad"};let s=He(c,a,t),n=new Map;for(let f of s.indexed)n.set(f.prefix,f);for(let f of s.indexed)if(f.prefix.includes("."))for(let C=1;C{A.push(f);for(let C of r.get(f)??[])l(C)};for(let f of o)l(f);let d=new Map,g=c.vault.getAbstractFileByPath(e);if(g instanceof pt.TFolder)for(let f of g.children){if(!(f instanceof pt.TFile)||f.extension!=="md")continue;let C=c.metadataCache.getFileCache(f)?.frontmatter??{};typeof C.jdPrefix=="string"&&d.set(C.jdPrefix,f)}let p=new Map,h=0,I=0,u=0;for(let f of A){let C=n.get(f)??null,B=on(f,new Set(n.keys())),m=B?p.get(B)??F:F,w=C?`${f} ${C.title}`:f,Q=C?.file?`[[${C.file.basename}]]`:"",E=Q?`${Q} -`:`${w} -`,v=d.get(f);if(v){try{let y=null;await c.fileManager.processFrontMatter(v,H=>{H.jdPrefix=f,m&&(H.parent=m),(!H.id||typeof H.id!="string")&&(H.id=tt()),H.created||(H.created=new Date().toISOString()),H.attachments||(H.attachments=[]),y=H.id});let N=(await c.vault.read(v)).match(/^---\r?\n[\s\S]*?\r?\n---\r?\n/),P=N?`${N[0]}${E}`:E;await c.vault.modify(v,P),y&&p.set(f,y),I++}catch(y){console.error("[stashpad] buildJdIndexNotes: update failed",y),u++}continue}try{let y=tt();p.set(f,y);let b=Et(w,t.slugStopWords),N=wt(b,y),P=`${e}/${N}`,H=["---",`id: ${y}`,`parent: ${m}`,`created: "${new Date().toISOString()}"`,"attachments: []",`jdPrefix: "${f}"`,"---",""].join(` -`);await c.vault.create(P,H+E),h++}catch(y){console.error("[stashpad] buildJdIndexNotes: create failed for",f,y),u++}}return{created:h,updated:I,skipped:u,destFolder:e}}function rn(c){return(c||"").trim().replace(/^\/+|\/+$/g,"")}function pr(c,a){if((a.jdIndexScope??"vault")==="vault")return c;let t=rn(a.jdIndexScopeFolder??"");return t?c.filter(e=>{let i=e.parent?.path?.replace(/\/+$/,"")??"";return i===t||i.startsWith(t+"/")}):c}function Ir(c,a,t){if(t==="created"){let e=c.file?.stat?.ctime??0,i=a.file?.stat?.ctime??0;if(e!==i)return e-i}return ko(c.segments,a.segments)}function Fo(c,a){let t=c.match(/^(\d+)-(\d+)$/),e=a.match(/^(\d+)-(\d+)$/),i=t?[t[1]]:c.split("."),s=e?[e[1]]:a.split(".");return ko(i,s)}function ko(c,a){let t=Math.min(c.length,a.length);for(let e=0;e{s.set(o,r);for(let A of e.get(o)??[])n(A,r+1)};for(let o of i)n(o,0);return{roots:i,childrenOf:e,depthOf:s}}function ur(c,a,t){let e=[],i=s=>"#".repeat(Math.min(s+1,6));if(e.push("# Indexed"),e.push(""),c.length===0){let s=t.length>0?`_No notes matched. ${t.length} note${t.length===1?" was":"s were"} excluded because they live inside a Stashpad folder \u2014 toggle "Include Stashpad folders in scan" in Settings \u2192 JD Index Builder if you want them included._`:"_No notes matched the JD-prefix convention. Check Scope and Designated folder in Settings \u2192 JD Index Builder._";e.push(s)}else{let s=new Map;for(let l of c)s.set(l.prefix,l);for(let l of c)if(l.prefix.includes("."))for(let d=1;d{let d=s.get(l),g=r.get(l)??0,p=" ".repeat(g),h=i(g),I=d?.folder?` ${d.title} _(folder)_`:(d?.file,"");d?.file?e.push(`${p}- ${h} [[${d.file.basename}|${d.prefix} ${d.title}]]`):d?.folder?e.push(`${p}- ${h} ${d.prefix}${I}`):e.push(`${p}- ${h} ${l}`);for(let u of o.get(l)??[])A(u)};for(let l of n)A(l)}if(a.length>0){e.push(""),e.push(`# Non-indexed (${a.length})`),e.push(""),e.push("_These notes don't match the JD-prefix convention. Rename them to ` ` and re-run to include them._"),e.push("");for(let s of a)e.push(`- # [[${s.basename}]] \xB7 \`${s.path}\``)}if(t.length>0){let s=new Map;for(let o of t){let r=o.parent?.path?.replace(/\/+$/,"")??"";s.set(r,(s.get(r)??0)+1)}let n=Array.from(s.entries()).sort((o,r)=>o[0].localeCompare(r[0]));e.push(""),e.push(`# Excluded folders (${n.length})`),e.push(""),e.push(`_Stashpad folders are excluded by default so the index doesn't reference itself. Toggle "Include Stashpad folders in scan" in Settings \u2192 JD Index Builder to include them._`),e.push("");for(let[o,r]of n)e.push(`- # All ${r} file${r===1?"":"s"} in \`${o||"(vault root)"}\``)}return e.join(` +`),this.lineCursorIdx=Math.max(1,Math.min(this.lines.length-1,Math.floor(this.lines.length/2))),this.lines.length<2&&(this.mode="cursor")}onOpen(){this.titleEl.setText("Split note"),this.modalEl.addClass("stashpad-split-modal"),this.render(),this.scope.register([],"Tab",t=>{this.lines.length<2||(t.preventDefault(),this.mode=this.mode==="line"?"cursor":"line",this.render())}),this.scope.register([],"Enter",t=>{this.mode==="line"&&(t.preventDefault(),this.commitLine())}),this.scope.register(["Mod"],"Enter",t=>{this.mode==="cursor"&&(t.preventDefault(),this.commitCursor())}),this.scope.register([],"ArrowUp",t=>{this.mode==="line"&&(t.preventDefault(),this.lineCursorIdx=Math.max(1,this.lineCursorIdx-1),this.render())}),this.scope.register([],"ArrowDown",t=>{this.mode==="line"&&(t.preventDefault(),this.lineCursorIdx=Math.min(this.lines.length-1,this.lineCursorIdx+1),this.render())})}commitLine(){let t=this.lineCursorIdx;this.close(),this.onSplitAtLine(t)}commitCursor(){let t=this.cursorTextarea;if(!t)return;let e=t.selectionStart;if(e<=0||e>=t.value.length){new q.Notice("Move the cursor inside the text \u2014 neither end can be empty.");return}this.close(),this.onSplitAtChar(e)}render(){this.contentEl.empty();let t=this.contentEl.createDiv({cls:"stashpad-split-quick"});t.createSpan({cls:"stashpad-split-quick-label",text:"Split by:"}),["lines","paragraphs","headings"].forEach(o=>{let r=oi(this.body,o),A=t.createEl("button",{cls:"stashpad-split-quick-btn",text:`${ni[o]} (${r.length})`});A.disabled=r.length<2,A.onmousedown=l=>l.preventDefault(),A.onclick=()=>{let l=oi(this.body,o);if(l.length<2){new q.Notice("That delimiter wouldn't split this note.");return}this.close(),this.onSplitMany(l)}});let e=this.contentEl.createDiv({cls:"stashpad-split-toggle-bar"});if(this.lines.length>=2){let o=e.createEl("button",{text:"Line split",cls:"stashpad-split-mode-btn"});this.mode==="line"&&o.addClass("is-active"),o.onclick=()=>{this.mode="line",this.render()}}let i=e.createEl("button",{text:"Cursor split",cls:"stashpad-split-mode-btn"});this.mode==="cursor"&&i.addClass("is-active"),i.onclick=()=>{this.mode="cursor",this.render()};let s=e.createEl("button",{text:"Split",cls:"stashpad-split-confirm-btn mod-cta"});s.onmousedown=o=>o.preventDefault(),s.onclick=()=>{this.mode==="line"?this.commitLine():this.commitCursor()},this.mode==="line"?this.renderLineMode():this.renderCursorMode();let n=this.contentEl.createDiv({cls:"stashpad-split-help"});q.Platform.isMobile?n.setText(this.mode==="line"?"Tap a line to position the divider, then Split.":"Tap inside the text to position the cursor, then Split."):n.setText(this.mode==="line"?"\u2191/\u2193 pick split line \xB7 Enter or Split confirm \xB7 Tab \u2192 cursor mode \xB7 Esc cancel \xB7 Children stay with the first part":"Click or arrow to position cursor \xB7 Mod+Enter or Split confirm \xB7 Tab \u2192 line mode \xB7 Esc cancel \xB7 Children stay with the first part")}renderLineMode(){let t=this.contentEl.createDiv({cls:"stashpad-split-list"}),e=null;for(let i=0;i<this.lines.length;i++){i===this.lineCursorIdx&&(e=t.createDiv({cls:"stashpad-split-divider",text:"\u2500\u2500 split here \u2500\u2500"}));let s=t.createDiv({cls:"stashpad-split-line"});s.createSpan({cls:"stashpad-split-lineno",text:String(i+1)}),s.createSpan({cls:"stashpad-split-text",text:this.lines[i]||" "}),s.onclick=()=>{let n=Math.max(1,Math.min(this.lines.length-1,i+1));n!==this.lineCursorIdx&&(this.lineCursorIdx=n,this.render())}}e&&window.requestAnimationFrame(()=>e.scrollIntoView({block:"center"}))}renderCursorMode(){let e=this.contentEl.createDiv({cls:"stashpad-split-cursor-wrap"}).createEl("textarea",{cls:"stashpad-split-cursor-ta"});e.value=this.body,e.readOnly=!1,this.cursorTextarea=e;let i=parseFloat(getComputedStyle(e).lineHeight)||22,s=q.Platform.isMobile?3:12,n=2,o=()=>{e.setCssStyles({height:"auto"});let r=Math.min(e.scrollHeight,i*s+16);e.setCssStyles({height:`${Math.max(r,i*n+16)}px`})};requestAnimationFrame(()=>{o();let r=Math.floor(e.value.length/2);e.focus(),e.setSelectionRange(r,r)}),e.addEventListener("input",o)}onClose(){this.cursorTextarea=null,this.contentEl.empty()}},di=class extends q.Modal{constructor(t,e,i,s,n){super(t);this.defaultBaseName=e;this.noteCount=i;this.onConfirm=s;this.kdfProbe=n;this.delivered=!1}onOpen(){this.contentEl.empty(),this.titleEl.setText("Export to .stash"),this.modalEl.addClass("stashpad-export-modal"),this.contentEl.createEl("p",{cls:"stashpad-export-desc",text:`${this.noteCount} note${this.noteCount===1?"":"s"} will be bundled into a single .stash file.`});let t=this.contentEl.createDiv({cls:"stashpad-export-field"});t.createEl("label",{cls:"stashpad-export-label",text:"File name"});let e=t.createEl("input",{type:"text"});e.addClass("stashpad-export-name"),e.value=this.defaultBaseName;let i=this.contentEl.createEl("div",{cls:"stashpad-export-preview"}),s=this.contentEl.createDiv({cls:"stashpad-export-encrypt"}),n=s.createDiv({cls:"stashpad-export-toggle"}),o=n.createEl("input",{type:"checkbox"});o.id="stashpad-export-encrypt-cb";let r=n.createEl("label",{text:"Encrypt with a password"});r.htmlFor=o.id;let A=s.createDiv({cls:"stashpad-export-pw-area"});A.setCssStyles({display:"none"});let l=[],d=R=>{let $=A.createDiv({cls:"stashpad-export-pw-row"}),K=$.createEl("input",{type:"password"});K.addClass("stashpad-export-name"),K.placeholder=R;let O=$.createEl("button",{cls:"stashpad-export-copy"}),it=()=>{let at=K.value.length===0;O.setText(at?"Paste":"Copy"),O.toggleClass("is-paste",at),O.setAttr("aria-label",`${at?"Paste into":"Copy"} ${R.toLowerCase()}`)};return O.onclick=async at=>{if(at.preventDefault(),K.value.length===0)try{let _=(await navigator.clipboard?.readText())?.trim();if(!_){new q.Notice("Clipboard is empty.");return}K.value=_,K.dispatchEvent(new Event("input")),new q.Notice("Pasted from clipboard.")}catch{new q.Notice("Couldn't read the clipboard.")}else navigator.clipboard?.writeText(K.value).then(()=>new q.Notice("Passphrase copied to clipboard."),()=>new q.Notice("Couldn't access the clipboard."))},it(),l.push(it),K},p=d("Password"),g=d("Confirm password"),h=A.createDiv({cls:"stashpad-export-strength"}),I=h.createDiv({cls:"stashpad-strength-bar"}),u=[0,1,2,3].map(()=>I.createDiv({cls:"stashpad-strength-seg"})),f=h.createEl("span",{cls:"stashpad-strength-label"}),C=A.createDiv({cls:"stashpad-export-genrow"}),B=C.createEl("button",{cls:"stashpad-export-gen",text:"Generate strong passphrase"}),m=C.createEl("button",{cls:"stashpad-export-show",text:"Show"}),y=A.createEl("div",{cls:"stashpad-export-pw-hint"}),Q=A.createEl("div",{cls:"stashpad-export-pw-suite"});Q.setText("Encryption: AES-256-GCM. Checking key-derivation suite for this device\u2026"),this.kdfProbe?this.kdfProbe().then(R=>{Q.toggleClass("is-weak",!R),Q.setText(R?"Encryption: Argon2id + AES-256-GCM \u2014 the strongest suite (used on this device).":"\u26A0\uFE0F Argon2id can't run on this device, so this export will use the weaker PBKDF2 (600k) + AES-256-GCM fallback.")}).catch(()=>{Q.setText("Encryption: AES-256-GCM with a password-derived key.")}):Q.setText("Encryption: Argon2id + AES-256-GCM (falls back to PBKDF2 if Argon2 can't run here).");let E=this.app.secretStorage,v=A.createDiv({cls:"stashpad-export-remember"}),w=v.createEl("input",{type:"checkbox"});w.id="stashpad-export-remember-cb";let D=v.createEl("label",{text:"Remember in this vault (this device) \u2014 skips the prompt when you re-import here."});D.htmlFor=w.id;let N=A.createDiv({cls:"stashpad-export-remember-note"});N.setText("Saved only in this device's keychain \u2014 it doesn't sync to your other devices and isn't shared with anyone you send this file to. Keep the passphrase somewhere safe if you'll open this export elsewhere."),N.setCssStyles({display:"none"}),w.onchange=()=>{N.setCssStyles({display:w.checked?"":"none"})},E||v.setCssStyles({display:"none"});let P=()=>{let R=e.value.trim()||this.defaultBaseName;return o.checked?`${R}-encrypted`:R},H=()=>i.setText(`Saves as: ${P()}-<timestamp>.stash`);e.oninput=H;let b=this.contentEl.createDiv({cls:"stashpad-export-footer"}),S=b.createEl("button",{text:"Cancel"});S.onclick=()=>this.close();let M=b.createEl("button",{cls:"mod-cta",text:"Export"}),U=()=>{let R=cn(p.value);h.style.visibility=p.value?"visible":"hidden",u.forEach(($,K)=>$.toggleClass("is-on",p.value!==""&&K<=R.level)),I.dataset.level=String(R.level),f.setText(R.label)},L=()=>{let R=o.checked;A.setCssStyles({display:R?"":"none"});let $=!0;R&&(p.value?p.value!==g.value?(y.setText("Passwords don't match."),y.addClass("is-error"),$=!1):(y.setText("\u26A0\uFE0F If you lose this password, the export can't be recovered."),y.removeClass("is-error")):(y.setText("Enter a password to encrypt this export."),y.removeClass("is-error"),$=!1)),U(),l.forEach(K=>K()),M.disabled=!$,M.toggleClass("is-disabled",!$),H()},W=!1,z=R=>{W=R,p.type=g.type=R?"text":"password",m.setText(R?"Hide":"Show")};m.onclick=R=>{R.preventDefault(),z(!W)},B.onclick=R=>{R.preventDefault(),p.value=g.value=ln(),z(!1),new q.Notice("Passphrase generated (hidden) \u2014 Show to view, or Copy to save it."),L()},o.onchange=L,p.oninput=L,g.oninput=L,L();let V=()=>this.commit(P(),o.checked?p.value:null,o.checked&&w.checked);M.onclick=V,this.scope.register([],"Enter",R=>{R.preventDefault(),M.disabled||V()}),requestAnimationFrame(()=>{e.focus(),e.select()})}commit(t,e,i){let s=t.trim()||this.defaultBaseName,n=e&&e.length?e:null;this.delivered=!0,this.close(),this.onConfirm(s,n,!!n&&i)}onClose(){this.contentEl.empty()}},hi=class extends q.Modal{constructor(t,e,i,s){super(t);this.errorMsg=e;this.allowLater=i;this.onResult=s;this.delivered=!1}onOpen(){this.contentEl.empty(),this.titleEl.setText("Encrypted .stash"),this.modalEl.addClass("stashpad-export-modal"),this.contentEl.createEl("p",{cls:"stashpad-export-desc",text:"This export is password-protected. Enter its password to import it."}),this.errorMsg&&this.contentEl.createEl("div",{cls:"stashpad-export-error",text:this.errorMsg});let t=this.contentEl.createEl("input",{type:"password"});t.addClass("stashpad-export-name"),t.placeholder="Password";let e=this.contentEl.createDiv({cls:"stashpad-export-footer"});if(e.createEl("button",{text:"Cancel"}).onclick=()=>this.close(),this.allowLater){let s=e.createEl("button",{text:"Remind me later"});s.title="Don't import now \u2014 surface the reminder again later.",s.onclick=()=>this.finish({kind:"later"})}let i=e.createEl("button",{cls:"mod-cta",text:"Decrypt & import"});i.onclick=()=>this.submit(t.value),this.scope.register([],"Enter",s=>{s.preventDefault(),this.submit(t.value)}),requestAnimationFrame(()=>t.focus())}submit(t){t&&this.finish({kind:"password",value:t})}finish(t){this.delivered=!0,this.close(),this.onResult(t)}onClose(){this.delivered||(this.delivered=!0,this.onResult({kind:"cancel"})),this.contentEl.empty()}},vt=class extends q.Modal{constructor(t,e){super(t);this.opts=e;this.succeeded=!1}onOpen(){let{mode:t}=this.opts;this.contentEl.empty(),this.modalEl.addClass("stashpad-export-modal","stashpad-encryption-modal"),this.titleEl.setText(this.opts.title??(t==="setup"?"Set up encryption password":t==="change"?"Change encryption password":"Unlock encryption")),this.contentEl.createDiv({cls:"stashpad-beta-row"}).createEl("span",{cls:"stashpad-beta-badge",text:"BETA"}),this.opts.intro?this.contentEl.createEl("p",{cls:"stashpad-export-desc",text:this.opts.intro}):t==="setup"&&this.contentEl.createEl("p",{cls:"stashpad-export-desc",text:"This single password protects everything you encrypt in this vault. It is stored only on this device. There is NO recovery \u2014 if you lose it, anything you've encrypted is gone for good."});let e=[],i=u=>{let f=this.contentEl.createDiv({cls:"stashpad-export-pw-row stashpad-encryption-row"}),C=f.createEl("input",{type:"password"});C.addClass("stashpad-export-name","stashpad-encryption-field"),C.placeholder=u;let B=f.createEl("button",{cls:"stashpad-export-copy"}),m=()=>{let y=C.value.length===0;B.setText(y?"Paste":"Copy"),B.toggleClass("is-paste",y),B.setAttr("aria-label",`${y?"Paste into":"Copy"} ${u.toLowerCase()}`)};return B.onclick=async y=>{if(y.preventDefault(),C.value.length===0)try{let Q=(await navigator.clipboard?.readText())?.trim();if(!Q){new q.Notice("Clipboard is empty.");return}C.value=Q,C.dispatchEvent(new Event("input")),new q.Notice("Pasted from clipboard.")}catch{new q.Notice("Couldn't read the clipboard.")}else navigator.clipboard?.writeText(C.value).then(()=>new q.Notice("Copied to clipboard."),()=>new q.Notice("Couldn't access the clipboard."))},C.addEventListener("input",m),m(),e.push(m),C},s=null,n=null,o=null;if((t==="unlock"||t==="change")&&(s=i("Current password")),(t==="setup"||t==="change")&&(n=i(t==="change"?"New password":"Password"),o=i("Confirm password")),n){let u=this.contentEl.createDiv({cls:"stashpad-export-strength"}),f=u.createDiv({cls:"stashpad-strength-bar"}),C=[0,1,2,3].map(()=>f.createDiv({cls:"stashpad-strength-seg"})),B=u.createEl("span",{cls:"stashpad-strength-label"}),m=this.contentEl.createDiv({cls:"stashpad-encryption-counter"}),y=()=>{let w=n.value,D=cn(w);C.forEach((N,P)=>N.toggleClass("is-on",P<D.level)),B.setText(w?D.label:""),m.setText(`${w.length} character${w.length===1?"":"s"}${w.length>0&&w.length<6?" \u2014 use at least 6":""}`),m.toggleClass("is-weak",w.length>0&&w.length<6)};n.addEventListener("input",y),y();let Q=this.contentEl.createDiv({cls:"stashpad-export-genrow"});Q.createEl("button",{cls:"stashpad-export-gen",text:"Generate strong passphrase"}).onclick=w=>{w.preventDefault();let D=ln(5);n.value=D,o&&(o.value=D),y(),e.forEach(N=>N()),new q.Notice("Generated \u2014 copy it somewhere safe; there's no recovery."),navigator.clipboard?.writeText(D).catch(()=>{})};let E=Q.createEl("button",{cls:"stashpad-export-show",text:"Show"});E.onclick=w=>{w.preventDefault();let D=n.type==="password";n.type=D?"text":"password",o&&(o.type=D?"text":"password"),E.setText(D?"Hide":"Show")};let v=this.contentEl.createEl("div",{cls:"stashpad-export-pw-suite"});v.setText("Encryption: AES-256-GCM. Checking key-derivation suite\u2026"),this.opts.kdfProbe?this.opts.kdfProbe().then(w=>{v.toggleClass("is-weak",!w),v.setText(w?"Encryption: Argon2id + AES-256-GCM \u2014 the strongest suite (used on this device).":"\u26A0\uFE0F Argon2id can't run here, so this will use the weaker PBKDF2 (600k) + AES-256-GCM fallback.")}).catch(()=>v.setText("Encryption: AES-256-GCM with a password-derived key.")):v.setText("Encryption: Argon2id + AES-256-GCM (PBKDF2 fallback if Argon2 can't run here).")}let r=null,A=this.app.secretStorage;if(this.opts.offerKeychain&&A){let u=this.contentEl.createDiv({cls:"stashpad-export-remember"});r=u.createEl("input",{type:"checkbox"}),r.id="stashpad-enc-remember";let f=u.createEl("label",{text:"Remember on this device (keychain) \u2014 auto-unlock here without re-typing."});f.htmlFor=r.id;let C=this.contentEl.createDiv({cls:"stashpad-export-remember-note"});C.setText("Stored only in this device's keychain \u2014 doesn't sync to your other devices. Anyone with access to this unlocked device + keychain could decrypt."),C.setCssStyles({display:"none"}),r.onchange=()=>{C.setCssStyles({display:r.checked?"":"none"})}}let l=this.contentEl.createEl("div",{cls:"stashpad-export-error"});l.setCssStyles({display:"none"});let d=u=>{l.setText(u),l.setCssStyles({display:""})},p=this.contentEl.createDiv({cls:"stashpad-export-footer"});p.createEl("button",{text:"Cancel"}).onclick=()=>this.close();let g=p.createEl("button",{cls:"mod-cta",text:t==="setup"?"Set up":t==="change"?"Change":"Unlock"}),h=!1,I=async()=>{if(h)return;let u=s?.value??void 0,f=n?.value??void 0;if((t==="unlock"||t==="change")&&!u){d("Enter your current password.");return}if(t==="setup"||t==="change"){if(!f){d("Enter a password.");return}if(f.length<6){d("Use at least 6 characters.");return}if(f!==o?.value){d("Passwords don't match.");return}}h=!0,g.disabled=!0,l.setCssStyles({display:"none"});let C=g.textContent;g.setText("Working\u2026");try{let B=await this.opts.onSubmit({current:u,next:f,remember:!!r?.checked});if(B){d(B),h=!1,g.disabled=!1,g.setText(C??"OK");return}this.succeeded=!0,this.close()}catch(B){d(`Failed: ${B.message}`),h=!1,g.disabled=!1,g.setText(C??"OK")}};g.onclick=()=>void I(),this.scope.register([],"Enter",u=>{u.preventDefault(),I()}),requestAnimationFrame(()=>(s??n)?.focus())}onClose(){this.contentEl.empty(),this.succeeded||this.opts.onCancel?.()}},pi=class extends q.Modal{constructor(t,e){super(t);this.opts=e}onOpen(){this.contentEl.empty(),this.modalEl.addClass("stashpad-export-modal","stashpad-encryption-modal"),this.titleEl.setText(this.opts.title),this.contentEl.createEl("p",{cls:"stashpad-export-desc",text:this.opts.body});let t=null;this.opts.requirePassword&&(this.contentEl.createEl("p",{cls:"stashpad-export-desc"}).setText("Enter your encryption password:"),t=this.contentEl.createEl("input",{type:"password"}),t.addClass("stashpad-export-name","stashpad-encryption-field"),t.placeholder="Password"),this.contentEl.createEl("p",{cls:"stashpad-export-desc"}).setText(`Type "${this.opts.phrase}" to confirm.`);let e=this.contentEl.createEl("input",{type:"text"});e.addClass("stashpad-export-name","stashpad-encryption-field"),e.placeholder=this.opts.phrase;let i=this.contentEl.createEl("div",{cls:"stashpad-export-error"});i.setCssStyles({display:"none"});let s=this.contentEl.createDiv({cls:"stashpad-export-footer"});s.createEl("button",{text:"Cancel"}).onclick=()=>this.close();let n=s.createEl("button",{cls:"mod-cta mod-warning",text:this.opts.confirmText}),o=()=>e.value.trim().toLowerCase()===this.opts.phrase.trim().toLowerCase(),r=()=>{n.disabled=!o()||!!this.opts.requirePassword&&!t?.value};e.addEventListener("input",r),t?.addEventListener("input",r),r();let A=!1,l=async()=>{if(!(A||!o())){if(this.opts.requirePassword&&(A=!0,n.disabled=!0,i.setCssStyles({display:"none"}),!await this.opts.requirePassword(t.value))){i.setText("Wrong password."),i.setCssStyles({display:""}),A=!1,r();return}this.close(),await this.opts.onConfirm()}};n.onclick=()=>void l(),this.scope.register([],"Enter",d=>{d.preventDefault(),l()}),requestAnimationFrame(()=>(t??e).focus())}onClose(){this.contentEl.empty()}},Vi=class extends q.Modal{constructor(t,e,i){super(t);this.onResult=i;this.delivered=!1;this.value=e&&/^#[0-9a-f]{6}$/i.test(e)?e:"#888888"}onOpen(){this.contentEl.empty(),this.titleEl.setText("Custom color"),this.modalEl.addClass("stashpad-custom-color-modal");let t=this.contentEl.createDiv({cls:"stashpad-custom-color-row"}),e=t.createDiv({cls:"stashpad-custom-color-preview"});e.style.background=this.value;let i=t.createEl("input",{type:"color"});i.value=this.value,i.addClass("stashpad-custom-color-wheel"),e.onclick=()=>i.click();let s=t.createEl("input",{type:"text"});s.addClass("stashpad-custom-color-hex"),s.placeholder="#RRGGBB",s.value=this.value,s.maxLength=7;let n=d=>{let p=d.startsWith("#")?d:"#"+d;/^#[0-9a-f]{6}$/i.test(p)&&(this.value=p,e.style.background=p,i.value=p,s.value!==p&&(s.value=p))};i.oninput=()=>n(i.value),s.oninput=()=>n(s.value);let o=this.contentEl.createDiv({cls:"stashpad-color-footer"}),r=o.createEl("button",{text:"Cancel"});r.onclick=()=>{this.delivered=!0,this.close()};let A=o.createEl("button",{cls:"mod-cta",text:"Save"});A.title="Apply this color to the selection (without adding to your palette).",A.onclick=()=>this.commit({addToPalette:!1});let l=o.createEl("button",{cls:"mod-cta",text:"Add to palette"});l.title="Apply and save this color so it appears as a tile next time.",l.onclick=()=>this.commit({addToPalette:!0}),this.scope.register([],"Enter",d=>{d.preventDefault(),this.commit({addToPalette:!1})}),this.scope.register(["Mod"],"Enter",d=>{d.preventDefault(),this.commit({addToPalette:!0})}),requestAnimationFrame(()=>s.focus())}commit(t){this.delivered=!0,this.close(),this.onResult(this.value,t)}onClose(){this.delivered||(this.delivered=!0,this.onResult(this.value,{addToPalette:!1})),this.contentEl.empty()}},li=class li extends q.Modal{constructor(t,e,i,s,n){super(t);this.currentColor=e;this.customPalette=i;this.onPick=s;this.onDeleteCustom=n;this.focusIdx=-1;this.items=[]}onOpen(){this.contentEl.empty(),this.titleEl.setText("Pick a color"),this.modalEl.addClass("stashpad-color-modal");let t=this.contentEl.createDiv({cls:"stashpad-color-grid"});this.items=[];let e=t.createDiv({cls:"stashpad-color-tile stashpad-color-none"});e.title="No color",e.onclick=()=>this.activate(0),this.items.push({kind:"none",color:null,el:e});let i=[...li.DEFAULT_PALETTE,...this.customPalette];for(let r of i){let A=t.createDiv({cls:"stashpad-color-tile"});A.style.background=r,A.title=r;let l=!li.DEFAULT_PALETTE.some(p=>p.toLowerCase()===r.toLowerCase()),d=this.items.length;if(A.onclick=()=>this.activate(d),l&&this.onDeleteCustom){let p=A.createSpan({cls:"stashpad-color-tile-del",text:"\xD7"});p.title="Remove from palette",p.onclick=g=>{g.stopPropagation(),this.handleDelete(r)}}this.items.push({kind:l?"custom":"preset",color:r,el:A})}let s=t.createDiv({cls:"stashpad-color-tile stashpad-color-add"});s.title="Custom color\u2026";let n=this.items.length;s.onclick=()=>this.activate(n),this.items.push({kind:"add",color:null,el:s});let o=this.items.findIndex(r=>this.currentColor===null?r.kind==="none":this.currentColor?r.color!==null&&r.color.toLowerCase()===this.currentColor.toLowerCase():!1);this.focusIdx=o>=0?o:0,this.refreshActive(),this.scope.register([],"ArrowRight",r=>{r.preventDefault(),this.moveFocus(1)}),this.scope.register([],"ArrowLeft",r=>{r.preventDefault(),this.moveFocus(-1)}),this.scope.register([],"ArrowDown",r=>{r.preventDefault(),this.moveFocus(this.columns())}),this.scope.register([],"ArrowUp",r=>{r.preventDefault(),this.moveFocus(-this.columns())}),this.scope.register([],"Enter",r=>{r.preventDefault(),this.activate(this.focusIdx)}),requestAnimationFrame(()=>this.modalEl.focus())}activate(t){if(t<0||t>=this.items.length)return;this.focusIdx=t,this.refreshActive();let e=this.items[t];if(e.kind==="add"){this.close(),new Vi(this.app,this.currentColor,(i,s)=>{this.onPick(i,s)}).open();return}this.close(),this.onPick(e.color,{addToPalette:!1})}columns(){if(!this.items.length)return 1;let t=this.items[0].el.parentElement;if(!t)return 1;let e=t.getBoundingClientRect(),i=this.items[0].el.getBoundingClientRect();if(i.width<=0)return 1;let s=i.top,n=0;for(let o of this.items){let r=o.el.getBoundingClientRect();if(Math.abs(r.top-s)<1)n++;else break}return Math.max(1,n)}async handleDelete(t){if(this.onDeleteCustom)try{let e=await this.onDeleteCustom(t);this.customPalette=Array.isArray(e)?e:this.customPalette.filter(i=>i.toLowerCase()!==t.toLowerCase()),this.onOpen()}catch(e){console.warn("Stashpad: palette delete failed",e)}}moveFocus(t){if(!this.items.length)return;let e=Math.max(0,Math.min(this.items.length-1,this.focusIdx+t));this.focusIdx=e,this.refreshActive()}refreshActive(){for(let t=0;t<this.items.length;t++)this.items[t].el.toggleClass("is-active",t===this.focusIdx)}onClose(){this.contentEl.empty()}};li.DEFAULT_PALETTE=["#E07A78","#E08A47","#E0A744","#B0CC6E","#6BC07A","#5BA9CE","#9B82C9","#C57AB5","#D75AA8"];De=li,pt=class extends q.Modal{constructor(t,e,i,s,n){super(t);this.titleText=e;this.message=i;this.confirmText=s;this.onChoose=n;this.didChoose=!1}onOpen(){this.modalEl?.addClass("stashpad-compact-modal"),this.contentEl.empty(),this.titleEl.setText(this.titleText);let t=this.contentEl.createDiv({cls:"stashpad-confirm-body"});for(let n of this.message.split(` +`))t.createDiv({cls:"stashpad-confirm-line",text:n});let e=this.contentEl.createDiv({cls:"stashpad-modal-btns"}),i=e.createEl("button",{text:"Cancel"});i.onclick=()=>{this.didChoose=!0,this.close(),this.onChoose(!1)};let s=e.createEl("button",{cls:"mod-cta",text:this.confirmText});s.onclick=()=>{this.didChoose=!0,this.close(),this.onChoose(!0)},requestAnimationFrame(()=>s.focus())}onClose(){this.contentEl.empty(),this.didChoose||(this.didChoose=!0,this.onChoose(!1))}};Ge=class extends q.Modal{constructor(t,e,i,s={}){super(t);this.current=e;this.onPick=i;this.opts=s;this.didChoose=!1;this.assignees=[];this.tinyClosePopover=null;this.assignees=[...s.currentAssignees??[]]}onOpen(){this.modalEl?.addClass("stashpad-compact-modal"),this.contentEl.empty(),this.titleEl.setText(this.opts.title??"Set due date");let t=null;if(this.current){let B=Date.parse(this.current);Number.isNaN(B)||(t=new Date(B))}let e=this.contentEl.createDiv({cls:"stashpad-due-picker"}),i=e.createDiv({cls:"stashpad-due-fields"}),s=i.createDiv({cls:"stashpad-due-field"}),n=s.createSpan({cls:"stashpad-due-field-icon"});(0,q.setIcon)(n,"calendar");let o=s.createEl("input",{type:"date",cls:"stashpad-due-date"}),r=s.createSpan({cls:"stashpad-due-clear",attr:{"aria-label":"Clear date"}});(0,q.setIcon)(r,"x"),r.onclick=()=>{o.value="",o.focus()};let A=i.createDiv({cls:"stashpad-due-field"}),l=A.createSpan({cls:"stashpad-due-field-icon"});(0,q.setIcon)(l,"clock");let d=A.createEl("input",{type:"time",cls:"stashpad-due-time"}),p=A.createSpan({cls:"stashpad-due-clear",attr:{"aria-label":"Clear time"}});(0,q.setIcon)(p,"x"),p.onclick=()=>{d.value="",d.focus()},n.onclick=()=>{try{o.showPicker?.()}catch{}},l.onclick=()=>this.openTimeNumpad(l,d),t&&(o.value=this.toDateValue(t),d.value=this.toTimeValue(t)),this.renderAssignSection(e);let g=e.createDiv({cls:"stashpad-due-grid"}),h=(B,m)=>{let y=g.createEl("button",{cls:"stashpad-due-btn stashpad-due-preset",text:B});y.onclick=()=>{let Q=m();o.value=this.toDateValue(Q),d.value||(d.value=this.toTimeValue(Q))}},I=B=>(B.setHours(9,0,0,0),B);h("Today",()=>I(this.startOfTodayLocal())),h("Tomorrow",()=>{let B=this.startOfTodayLocal();return B.setDate(B.getDate()+1),I(B)}),h("Next week",()=>{let B=this.startOfTodayLocal();return B.setDate(B.getDate()+7),I(B)});let u=g.createEl("button",{cls:"stashpad-due-btn",text:"Clear"});u.onclick=()=>{o.value="",d.value="",o.focus()};let f=g.createEl("button",{cls:"stashpad-due-btn",text:"Cancel"});f.onclick=()=>{this.didChoose=!0,this.close()};let C=g.createEl("button",{cls:"stashpad-due-btn mod-cta",text:"Set"});C.onclick=()=>{if(!o.value){this.didChoose=!0,this.close(),this.onPick({iso:null,assignees:this.assignees});return}let[B,m,y]=o.value.split("-").map(w=>parseInt(w,10)),Q=9,E=0;if(d.value){let[w,D]=d.value.split(":").map(N=>parseInt(N,10));Q=w,E=D}let v=new Date(B,m-1,y,Q,E,0,0);this.didChoose=!0,this.close(),this.onPick({iso:v.toISOString(),assignees:this.assignees})},requestAnimationFrame(()=>o.focus())}onClose(){this.tinyClosePopover?.(),this.contentEl.empty(),this.didChoose}renderAssignSection(t){Ho(t,{knownAuthors:this.opts.knownAuthors??[],initial:this.assignees,onChange:e=>{this.assignees=e}})}openTimeNumpad(t,e){this.tinyClosePopover?.();let i=9,s=0;if(e.value){let[h,I]=e.value.split(":").map(u=>parseInt(u,10));Number.isFinite(h)&&(i=h),Number.isFinite(I)&&(s=I)}else{let h=new Date;i=h.getHours(),s=h.getMinutes()}let n=i>=12?"pm":"am",o=i===0?12:i>12?i-12:i,r=document.body.createDiv({cls:"stashpad-when-popover stashpad-due-time-pop"});r.setCssStyles({position:"fixed",zIndex:"9999"});let A=null,l=()=>{r.remove(),document.removeEventListener("mousedown",d,!0),document.removeEventListener("keydown",p,!0),this.tinyClosePopover===l&&(this.tinyClosePopover=null)},d=h=>{!r.contains(h.target)&&h.target!==t&&!t.contains(h.target)&&l()},p=h=>{h.key==="Escape"?(h.preventDefault(),h.stopPropagation(),l()):h.key==="Enter"&&A&&(h.preventDefault(),h.stopPropagation(),A())};this.tinyClosePopover=l,Oi(r,{seedH:o,seedM:s,seedPeriod:n,close:l,setOnEnter:h=>{A=h},onFinalize:h=>{e.value=`${String(h.hours24).padStart(2,"0")}:${String(h.minutes).padStart(2,"0")}`}});let g=t.getBoundingClientRect();r.setCssStyles({left:`${Math.max(8,Math.min(g.left,window.innerWidth-220))}px`,top:`${g.bottom+4}px`}),setTimeout(()=>{document.addEventListener("mousedown",d,!0),document.addEventListener("keydown",p,!0)},0)}startOfTodayLocal(){let t=new Date;return t.setHours(0,0,0,0),t}toDateValue(t){let e=t.getFullYear(),i=String(t.getMonth()+1).padStart(2,"0"),s=String(t.getDate()).padStart(2,"0");return`${e}-${i}-${s}`}toTimeValue(t){let e=String(t.getHours()).padStart(2,"0"),i=String(t.getMinutes()).padStart(2,"0");return`${e}:${i}`}},Se=class Se extends q.Modal{constructor(t,e,i,s=null,n){super(t);this.service=e;this.openLog=i;this.currentAuthorId=s;this.getNoteAuthorIds=n;this.records=[];this.visible=[];this.shownCount=0;this.categoryFilter=null;this.listEl=null;this.footerEl=null;this.countEl=null;this.filterSelEl=null;this.unsubscribe=null;this.authorFilter="all";this.authorSelEl=null}onOpen(){this.contentEl.empty(),this.titleEl.setText("Stashpad notification history"),this.modalEl.addClass("stashpad-log-modal"),this.modalEl.addClass("stashpad-notif-history-modal"),this.records=this.service.recent();let t=this.contentEl.createDiv({cls:"stashpad-log-toolbar"});if(this.countEl=t.createSpan({cls:"stashpad-log-count"}),this.updateCount(),this.filterSelEl=t.createEl("select",{cls:"stashpad-log-type-filter"}),this.filterSelEl.onchange=()=>this.setCategoryFilter(this.filterSelEl.value||null),this.refreshCategoryFilter(),this.authorSelEl=t.createEl("select",{cls:"stashpad-log-type-filter stashpad-notif-author-filter"}),this.authorSelEl.onchange=()=>this.setAuthorFilter(this.authorSelEl.value||"all"),this.refreshAuthorFilter(),this.openLog){let i=t.createEl("button",{text:"Open log"});i.title="Open the per-folder Stashpad log for the most recent notification's folder.",i.onclick=()=>{let s=this.records.find(n=>!!n.folder);this.openLog?.(s?.folder)}}let e=t.createEl("button",{cls:"mod-warning",text:"Clear history"});e.onclick=()=>{new pt(this.app,"Clear notification history?",`This will permanently remove all ${this.records.length} stored notifications from the history. The current toasts on screen are unaffected. This can't be undone.`,"Clear history",i=>{i&&this.service.clearHistory()}).open()},this.listEl=this.contentEl.createDiv({cls:"stashpad-log-list"}),this.refreshList(),this.footerEl=this.contentEl.createDiv({cls:"stashpad-log-footer"}),this.renderFooter(),this.unsubscribe=this.service.onChange(()=>{this.records=this.service.recent(),this.refreshCategoryFilter(),this.refreshAuthorFilter(),this.refreshList(),this.renderFooter()})}setAuthorFilter(t){this.authorFilter!==t&&(this.authorFilter=t,this.refreshList(),this.renderFooter())}refreshAuthorFilter(){if(!this.authorSelEl)return;let t=this.authorSelEl;t.empty(),t.createEl("option",{text:"All authors"}).value="all",this.currentAuthorId&&(t.createEl("option",{text:"Me"}).value="me"),t.createEl("option",{text:"Cross-author"}).value="cross";let e=new Set;for(let s of this.records)s.authorId&&s.authorId!==this.currentAuthorId&&e.add(s.authorId);if(e.size>0){let s=t.createEl("option",{text:"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"});s.disabled=!0;for(let n of[...e].sort())t.createEl("option",{text:n}).value=n}new Set(["all","cross",...this.currentAuthorId?["me"]:[],...e]).has(this.authorFilter)||(this.authorFilter="all"),t.value=this.authorFilter}isCrossAuthor(t){let e=t.authorId??null;if(!e)return!1;for(let i of t.affectedAuthorIds??[])if(i&&i!==e)return!0;if(!this.getNoteAuthorIds)return!1;for(let i of t.affectedIds){let s=this.getNoteAuthorIds(i);for(let n of s)if(n&&n!==e)return!0}return!1}onClose(){this.unsubscribe?.(),this.unsubscribe=null,this.contentEl.empty()}setCategoryFilter(t){(this.categoryFilter??null)!==(t??null)&&(this.categoryFilter=t,this.refreshList(),this.renderFooter())}refreshCategoryFilter(){if(!this.filterSelEl)return;let t=this.filterSelEl;t.empty();let e=new Map;for(let n of this.records)e.set(n.category,(e.get(n.category)??0)+1);let i=[...e.entries()].sort((n,o)=>o[1]-n[1]||n[0].localeCompare(o[0])),s=t.createEl("option",{text:`All categories (${this.records.length})`});s.value="";for(let[n,o]of i){let r=t.createEl("option",{text:`${n} (${o})`});r.value=n}this.categoryFilter&&!e.has(this.categoryFilter)&&(this.categoryFilter=null),t.value=this.categoryFilter??""}refreshList(){if(this.listEl){if(this.visible=this.records.filter(t=>{if(this.categoryFilter&&t.category!==this.categoryFilter)return!1;switch(this.authorFilter){case"all":return!0;case"me":return!!this.currentAuthorId&&t.authorId===this.currentAuthorId;case"cross":return this.isCrossAuthor(t);default:return t.authorId===this.authorFilter}}),this.shownCount=0,this.listEl.empty(),!this.visible.length){this.listEl.createDiv({cls:"stashpad-log-empty",text:this.categoryFilter?`No "${this.categoryFilter}" notifications.`:"No notifications yet."}),this.updateCount();return}this.appendMore(Se.PAGE)}}appendMore(t){if(!this.listEl)return;let e=Math.min(this.visible.length,this.shownCount+t);for(let i=this.shownCount;i<e;i++)this.renderRow(this.listEl,this.visible[i]);this.shownCount=e,this.updateCount()}renderRow(t,e){let i=t.createDiv({cls:`stashpad-notif-row stashpad-notif-row-${e.kind}`}),s=i.createDiv({cls:"stashpad-notif-meta"}),n=s.createSpan({cls:"stashpad-notif-time"}),o=kr(e.ts);if(n.setText(o.fromNow()),n.title=o.format("YYYY-MM-DD HH:mm:ss"),s.createSpan({cls:`stashpad-notif-cat stashpad-notif-cat-${e.category}`}).setText(e.category),i.createDiv({cls:"stashpad-notif-msg"}).setText(e.message),e.actionLabels.length>0){let l=i.createDiv({cls:"stashpad-notif-actions-snapshot"});for(let d of e.actionLabels){let p=l.createSpan({cls:"stashpad-notif-action-chip"});p.setText(d),p.title="Action button was shown on the original toast (handler not retained)."}}}updateCount(){if(!this.countEl)return;let t=this.visible.length,e=this.categoryFilter?`${t} ${this.categoryFilter} notification${t===1?"":"s"}`:`${t} notification${t===1?"":"s"}`;this.shownCount===0||this.shownCount>=t?this.countEl.setText(e):this.countEl.setText(`Showing ${this.shownCount} of ${e}`)}renderFooter(){if(!this.footerEl)return;this.footerEl.empty();let t=this.visible.length-this.shownCount;if(t<=0)return;let e=this.footerEl.createEl("button",{text:`Load ${Math.min(Se.PAGE,t)} more`});if(e.onclick=()=>{this.appendMore(Se.PAGE),this.renderFooter()},t>Se.PAGE){let i=this.footerEl.createEl("button",{text:`Load all (${t})`});i.onclick=()=>{this.appendMore(t),this.renderFooter()}}}};Se.PAGE=100;gi=Se,dn=class extends q.Modal{constructor(t,e){super(t);this.entries=e}onOpen(){if(this.contentEl.empty(),this.titleEl.setText("Stashpad import log"),this.entries.length===0){this.contentEl.createDiv({cls:"stashpad-log-empty",text:"Nothing imported yet."});return}let t=this.contentEl.createDiv({cls:"stashpad-import-log-list"});for(let e of this.entries){let i=t.createDiv({cls:"stashpad-import-log-row"}),s=(0,q.moment)(e.ts).format("YYYY-MM-DD HH:mm");i.createSpan({cls:"stashpad-import-log-when",text:s});let n=e.kind==="folder"?"folder":e.kind==="md"?"note":"file";i.createSpan({cls:`stashpad-import-log-kind is-${e.kind}`,text:n}),i.createSpan({cls:"stashpad-import-log-name",text:e.originalName});let o=[e.folder.split("/").pop()||e.folder];e.notePaths.length>1&&o.push(`${e.notePaths.length} notes`),i.createSpan({cls:"stashpad-import-log-meta",text:o.join(" \xB7 ")})}}onClose(){this.contentEl.empty()}},Ii=class extends q.Modal{constructor(t,e,i){super(t);this.message=e;this.onChoose=i;this.chose=!1}onOpen(){this.modalEl?.addClass("stashpad-compact-modal"),this.contentEl.empty(),this.titleEl.setText("Possible duplicate import");let t=this.contentEl.createDiv({cls:"stashpad-confirm-body"});for(let o of this.message.split(` +`))t.createDiv({cls:"stashpad-confirm-line",text:o});let e=this.contentEl.createDiv({cls:"stashpad-modal-btns"}),i=e.createEl("button",{text:"Skip duplicates"});i.onclick=()=>{this.chose=!0,this.close(),this.onChoose("skip")};let s=e.createEl("button",{text:"Replace existing"});s.onclick=()=>{this.chose=!0,this.close(),this.onChoose("replace")};let n=e.createEl("button",{cls:"mod-cta",text:"Import anyway"});n.onclick=()=>{this.chose=!0,this.close(),this.onChoose("anyway")}}onClose(){this.chose||this.onChoose("skip"),this.contentEl.empty()}},ui=class extends q.Modal{constructor(t,e,i,s){super(t);this.noteCount=i;this.onConfirm=s;this.base=e}onOpen(){this.contentEl.empty(),this.modalEl.addClass("stashpad-export-modal"),this.titleEl.setText("Export as OKF"),this.contentEl.createEl("p",{cls:"stashpad-export-desc",text:`Export ${this.noteCount} note${this.noteCount===1?"":"s"} as an Open Knowledge Format bundle. Pick one or more formats.`});let t=this.contentEl.createEl("input",{type:"text"});t.addClass("stashpad-export-name"),t.value=this.base,t.placeholder="Export name";let e=(A,l)=>{let d=this.contentEl.createDiv({cls:"stashpad-okf-fmt"}),p=d.createEl("input",{type:"checkbox"});return p.checked=l,d.createEl("label",{text:A}),p},i=e(".zip \u2014 OKF bundle (portable)",!0),s=e(".tar.gz \u2014 OKF bundle (tarball)",!1),n=e(".stash \u2014 Stashpad format (re-importable)",!1),o=this.contentEl.createDiv({cls:"stashpad-export-footer"});o.createEl("button",{text:"Cancel"}).onclick=()=>this.close();let r=o.createEl("button",{cls:"mod-cta",text:"Export"});r.onclick=()=>{if(!i.checked&&!s.checked&&!n.checked){new q.Notice("Pick at least one format.");return}this.close(),this.onConfirm(t.value.trim()||this.base,{zip:i.checked,targz:s.checked,stash:n.checked})},requestAnimationFrame(()=>t.focus())}onClose(){this.contentEl.empty()}}});function Qt(c,a=Jt){let t=a instanceof Set?a:new Set(a.map(o=>o.toLowerCase())),e=(c.split(/\r?\n/).find(o=>o.trim().length>0)??"").trim();if(!e)return"Untitled";let s=e.replace(/['‘-‛ʼ]/g,"").replace(/[^A-Za-z0-9\s]+/g," ").split(/\s+/).filter(o=>o&&!t.has(o.toLowerCase())).map(o=>o.length>=2&&/^[A-Z0-9]+$/.test(o)?o:o.charAt(0).toUpperCase()+o.slice(1).toLowerCase()),n="";for(let o of s){let r=n?`${n}-${o}`:o;if(r.length>50)break;n=r}return n||"Untitled"}function yt(c,a){return`${c}-${a}.md`}function le(c){let a=c.match(/-([a-z0-9]{4,12})$/);return a?a[1]:null}var Jt,Re=Lt(()=>{"use strict";Jt=["a","an","the","and","or","but","if","then","else","of","in","on","at","to","for","with","by","from","as","is","are","was","were","be","been","being","i","you","he","she","it","we","they","this","that","these","those","my","your","our","their","do","does","did","so","just","very","really","im"]});var ji={};ii(ji,{JdBuildConfirmModal:()=>Bi,buildJdIndexNotes:()=>pn,buildJdIndexPreview:()=>Xi,buildJdPreviewNotice:()=>Zi,scanForJdNotes:()=>Le});function hn(c,a){if(/^\d+-\d+$/.test(c))return null;if(c.includes(".")){let e=c.split(".").slice(0,-1).join(".");return a.has(e)?e:hn(e,a)}if(/^\d+$/.test(c)){let t=parseInt(c,10);for(let e of a){let i=e.match(/^(\d+)-(\d+)$/);if(!i)continue;let s=parseInt(i[1],10),n=parseInt(i[2],10);if(t>=s&&t<=n)return e}return null}return null}function Le(c,a,t){let e=c.vault.getMarkdownFiles(),i=Dr(e,t),s=t.jdIndexIncludeStashpadFolders===!0,n=s?new Set:new Set(a.discoverStashpadFolders()),o=h=>s?!1:Array.from(n).some(I=>h===I||h.startsWith(I+"/")),r=[],A=[],l=[];for(let h of i){let I=h.parent?.path?.replace(/\/+$/,"")??"";if(o(I)){l.push(h);continue}let u=h.basename.match(Po);u?r.push({prefix:u[1],segments:u[1].split("."),title:u[2],file:h,folder:null}):A.push(h)}let d=(t.jdIndexScope??"vault")==="folder"?(t.jdIndexScopeFolder??"").trim().replace(/^\/+|\/+$/g,""):"",p=h=>{let I=h.path.replace(/\/+$/,"");if(!(d&&I&&I!==d&&!I.startsWith(d+"/"))){if(I&&!o(I)){let u=h.name.match(Po);u&&r.push({prefix:u[1],segments:u[1].split("."),title:u[2],file:null,folder:h})}}for(let u of h.children)u instanceof gt.TFolder&&p(u)};p(c.vault.getRoot());let g=t.jdIndexSort??"natural";return r.sort((h,I)=>br(h,I,g)),{indexed:r,nonIndex:A,skippedStashpadNotes:l}}async function Xi(c,a,t){let e=gn(t.jdIndexStashpadFolder??"");if(!e)return{...Le(c,a,t),previewPath:null,error:"no-dest"};let i=Le(c,a,t),s=Sr(c,e);if(!s)return{...i,previewPath:null,error:"no-home"};let n=Nr(i.indexed,i.nonIndex,i.skippedStashpadNotes),r=(await c.vault.read(s)).match(/^---\r?\n[\s\S]*?\r?\n---\r?\n/),A=r?`${r[0]}${n}`:n;return await c.vault.modify(s,A),{...i,previewPath:s.path}}function Sr(c,a){let t=c.vault.getAbstractFileByPath(a);if(!(t instanceof gt.TFolder))return null;for(let e of t.children){if(!(e instanceof gt.TFile)||e.extension!=="md")continue;if((c.metadataCache.getFileCache(e)?.frontmatter??{}).id===F)return e}return null}async function pn(c,a,t){let e=gn(t.jdIndexStashpadFolder??"");if(!e)return{created:0,updated:0,skipped:0,destFolder:"",error:"no-dest"};if(!new Set(a.discoverStashpadFolders()).has(e))return{created:0,updated:0,skipped:0,destFolder:e,error:"dest-not-stashpad"};let s=Le(c,a,t),n=new Map;for(let f of s.indexed)n.set(f.prefix,f);for(let f of s.indexed)if(f.prefix.includes("."))for(let C=1;C<f.segments.length;C++){let B=f.segments.slice(0,C).join(".");n.has(B)||n.set(B,null)}let{roots:o,childrenOf:r}=Ro(n),A=[],l=f=>{A.push(f);for(let C of r.get(f)??[])l(C)};for(let f of o)l(f);let d=new Map,p=c.vault.getAbstractFileByPath(e);if(p instanceof gt.TFolder)for(let f of p.children){if(!(f instanceof gt.TFile)||f.extension!=="md")continue;let C=c.metadataCache.getFileCache(f)?.frontmatter??{};typeof C.jdPrefix=="string"&&d.set(C.jdPrefix,f)}let g=new Map,h=0,I=0,u=0;for(let f of A){let C=n.get(f)??null,B=hn(f,new Set(n.keys())),m=B?g.get(B)??F:F,y=C?`${f} ${C.title}`:f,Q=C?.file?`[[${C.file.basename}]]`:"",E=Q?`${Q} +`:`${y} +`,v=d.get(f);if(v){try{let w=null;await c.fileManager.processFrontMatter(v,H=>{H.jdPrefix=f,m&&(H.parent=m),(!H.id||typeof H.id!="string")&&(H.id=tt()),H.created||(H.created=new Date().toISOString()),H.attachments||(H.attachments=[]),w=H.id});let N=(await c.vault.read(v)).match(/^---\r?\n[\s\S]*?\r?\n---\r?\n/),P=N?`${N[0]}${E}`:E;await c.vault.modify(v,P),w&&g.set(f,w),I++}catch(w){console.error("[stashpad] buildJdIndexNotes: update failed",w),u++}continue}try{let w=tt();g.set(f,w);let D=Qt(y,t.slugStopWords),N=yt(D,w),P=`${e}/${N}`,H=["---",`id: ${w}`,`parent: ${m}`,`created: "${new Date().toISOString()}"`,"attachments: []",`jdPrefix: "${f}"`,"---",""].join(` +`);await c.vault.create(P,H+E),h++}catch(w){console.error("[stashpad] buildJdIndexNotes: create failed for",f,w),u++}}return{created:h,updated:I,skipped:u,destFolder:e}}function gn(c){return(c||"").trim().replace(/^\/+|\/+$/g,"")}function Dr(c,a){if((a.jdIndexScope??"vault")==="vault")return c;let t=gn(a.jdIndexScopeFolder??"");return t?c.filter(e=>{let i=e.parent?.path?.replace(/\/+$/,"")??"";return i===t||i.startsWith(t+"/")}):c}function br(c,a,t){if(t==="created"){let e=c.file?.stat?.ctime??0,i=a.file?.stat?.ctime??0;if(e!==i)return e-i}return Go(c.segments,a.segments)}function Uo(c,a){let t=c.match(/^(\d+)-(\d+)$/),e=a.match(/^(\d+)-(\d+)$/),i=t?[t[1]]:c.split("."),s=e?[e[1]]:a.split(".");return Go(i,s)}function Go(c,a){let t=Math.min(c.length,a.length);for(let e=0;e<t;e++){let i=c[e],s=a[e],n=/^\d+$/.test(i),o=/^\d+$/.test(s);if(n&&o){let r=parseInt(i,10)-parseInt(s,10);if(r!==0)return r}else{if(n&&!o)return-1;if(!n&&o)return 1;{let r=i.localeCompare(s,void 0,{numeric:!0,sensitivity:"base"});if(r!==0)return r}}}return c.length-a.length}function Ro(c){let a=new Set(c.keys()),t=new Map,e=new Map;for(let o of a){let r=hn(o,a);if(t.set(o,r),r!==null){let A=e.get(r)??[];A.push(o),e.set(r,A)}}let i=[];for(let o of a)t.get(o)===null&&i.push(o);i.sort(Uo);for(let o of e.values())o.sort(Uo);let s=new Map,n=(o,r)=>{s.set(o,r);for(let A of e.get(o)??[])n(A,r+1)};for(let o of i)n(o,0);return{roots:i,childrenOf:e,depthOf:s}}function Nr(c,a,t){let e=[],i=s=>"#".repeat(Math.min(s+1,6));if(e.push("# Indexed"),e.push(""),c.length===0){let s=t.length>0?`_No notes matched. ${t.length} note${t.length===1?" was":"s were"} excluded because they live inside a Stashpad folder \u2014 toggle "Include Stashpad folders in scan" in Settings \u2192 JD Index Builder if you want them included._`:"_No notes matched the JD-prefix convention. Check Scope and Designated folder in Settings \u2192 JD Index Builder._";e.push(s)}else{let s=new Map;for(let l of c)s.set(l.prefix,l);for(let l of c)if(l.prefix.includes("."))for(let d=1;d<l.segments.length;d++){let p=l.segments.slice(0,d).join(".");s.has(p)||s.set(p,null)}let{roots:n,childrenOf:o,depthOf:r}=Ro(s),A=l=>{let d=s.get(l),p=r.get(l)??0,g=" ".repeat(p),h=i(p),I=d?.folder?` ${d.title} _(folder)_`:(d?.file,"");d?.file?e.push(`${g}- ${h} [[${d.file.basename}|${d.prefix} ${d.title}]]`):d?.folder?e.push(`${g}- ${h} ${d.prefix}${I}`):e.push(`${g}- ${h} ${l}`);for(let u of o.get(l)??[])A(u)};for(let l of n)A(l)}if(a.length>0){e.push(""),e.push(`# Non-indexed (${a.length})`),e.push(""),e.push("_These notes don't match the JD-prefix convention. Rename them to `<prefix> <title>` and re-run to include them._"),e.push("");for(let s of a)e.push(`- # [[${s.basename}]] \xB7 \`${s.path}\``)}if(t.length>0){let s=new Map;for(let o of t){let r=o.parent?.path?.replace(/\/+$/,"")??"";s.set(r,(s.get(r)??0)+1)}let n=Array.from(s.entries()).sort((o,r)=>o[0].localeCompare(r[0]));e.push(""),e.push(`# Excluded folders (${n.length})`),e.push(""),e.push(`_Stashpad folders are excluded by default so the index doesn't reference itself. Toggle "Include Stashpad folders in scan" in Settings \u2192 JD Index Builder to include them._`),e.push("");for(let[o,r]of n)e.push(`- # All ${r} file${r===1?"":"s"} in \`${o||"(vault root)"}\``)}return e.join(` `)+` -`}function Oi(c,a){let t=document.createDocumentFragment();t.createEl("div",{text:"Home note updated"}).setCssStyles({fontWeight:"600",marginBottom:"6px"});let i=t.createEl("ul");i.setCssStyles({margin:"0 0 8px 0",paddingLeft:"18px"}),i.createEl("li",{text:`${a.indexed.length} indexed`}),i.createEl("li",{text:`${a.nonIndex.length+a.skippedStashpadNotes.length} excluded`});let s=t.createEl("button",{text:"Open",cls:"mod-cta"});s.setCssStyles({padding:"2px 10px",fontSize:"var(--font-ui-smaller)"});let n;return s.onclick=async o=>{if(o.stopPropagation(),a.previewPath){let r=c.vault.getAbstractFileByPath(a.previewPath);r instanceof pt.TFile&&await c.workspace.getLeaf("tab").openFile(r)}n?.hide()},n=new pt.Notice(t,0),n}var pt,vo,Ii,ui=Gt(()=>{"use strict";pt=require("obsidian");xt();Te();rt();vo=/^(\d+-\d+|\d+|[A-Za-z0-9]+(?:\.[A-Za-z0-9]+)+)\s+(.+)$/;Ii=class extends pt.Modal{constructor(t,e,i,s,n){super(t);this.plugin=e;this.settings=i;this.indexedCount=s;this.onBuild=n;this.LARGE_BUILD=50;this.previewRan=!1;this.previewPath=null}onOpen(){let{contentEl:t,titleEl:e}=this,i=!this.settings.jdIndexHasBuilt,s=this.indexedCount>this.LARGE_BUILD;e.setText(i?"Build JD index \u2014 first time?":"Build JD index");let n=this.settings.jdIndexStashpadFolder,o=t.createEl("p"),r=`${this.indexedCount} note${this.indexedCount===1?"":"s"}`;i?(o.appendText(`Stashpad is about to create ${r} (plus synthetic parents as needed) inside "`),o.createEl("code",{text:n}),o.appendText('". Existing notes with the same '),o.createEl("code",{text:"jdPrefix"}),o.appendText(" are updated, never deleted \u2014 but if the prefix detection picks up notes you didn't mean to index, you'll end up with a lot of unwanted notes."),t.createEl("p").setText("Running Preview first writes a single Markdown file showing exactly what would be built (and what wouldn't), so you can sanity-check before committing.")):s?(o.appendText(`You're about to create ${this.indexedCount} notes in "`),o.createEl("code",{text:n}),o.appendText(`". That's a big batch \u2014 if anything looks off, Preview the single-file output first.`)):(o.appendText('Build the JD index into "'),o.createEl("code",{text:n}),o.appendText(`"? Stashpad will create / update ${r}. Existing notes with matching `),o.createEl("code",{text:"jdPrefix"}),o.appendText(" are updated in place.")),this.previewRan&&this.previewPath&&t.createEl("p",{cls:"setting-item-description"}).setText(`\u2713 Preview written to home note (${this.previewPath}). Open it before building if you haven't.`);let A=new pt.Setting(t);(i||s)&&A.addButton(l=>{l.setButtonText(this.previewRan?"Re-run preview":"Run preview first"),l.setCta(),l.onClick(async()=>{try{let d=await Ki(this.app,this.plugin,this.settings);if(d.error==="no-dest"){new pt.Notice("Set a Designated Stashpad folder for Index first.",5e3),this.close();return}if(d.error==="no-home"){new pt.Notice(`"${this.settings.jdIndexStashpadFolder}" has no Stashpad home note. Open the folder in Stashpad first.`,7e3),this.close();return}this.previewRan=!0,this.previewPath=d.previewPath,Oi(this.app,d),this.contentEl.empty(),this.titleEl.empty(),this.onOpen()}catch(d){new pt.Notice(`Preview failed: ${d?.message??d}`,8e3)}})}),A.addButton(l=>{l.setButtonText(i?"Build anyway":"Build"),!i&&!s&&l.setCta(),l.onClick(async()=>{this.close(),await this.onBuild()})}),A.addButton(l=>{l.setButtonText("Cancel"),l.onClick(()=>this.close())})}onClose(){this.contentEl.empty()}}});function rA(c,a){return aA(c,a||{},0,0)}function AA(c,a){return eA(c,{i:2},a&&a.out,a&&a.dictionary)}function ns(c,a){if(a){for(var t=new At(c.length),e=0;e<c.length;++e)t[e]=c.charCodeAt(e);return t}if(_o)return _o.encode(c);for(var i=c.length,s=new At(c.length+(c.length>>1)),n=0,o=function(l){s[n++]=l},e=0;e<i;++e){if(n+5>s.length){var r=new At(n+8+(i-e<<1));r.set(s),s=r}var A=c.charCodeAt(e);A<128||a?o(A):A<2048?(o(192|A>>6),o(128|A&63)):A>55295&&A<57344?(A=65536+(A&1047552)|c.charCodeAt(++e)&1023,o(240|A>>18),o(128|A>>12&63),o(128|A>>6&63),o(128|A&63)):(o(224|A>>12),o(128|A>>6&63),o(128|A&63))}return ki(s,0,n)}function Gn(c,a){if(a){for(var t="",e=0;e<c.length;e+=16384)t+=String.fromCharCode.apply(null,c.subarray(e,e+16384));return t}else{if(Tn)return Tn.decode(c);var i=cA(c),s=i.s,t=i.r;return t.length&&ut(8),s}}function la(c,a){a||(a={});var t={},e=[];Aa(c,"",t,a);var i=0,s=0;for(var n in t){var o=t[n],r=o[0],A=o[1],l=A.level==0?0:8,d=ns(n),g=d.length,p=A.comment,h=p&&ns(p),I=h&&h.length,u=Hn(A.extra);g>65535&&ut(11);var f=l?rA(r,A):r,C=f.length,B=oA();B.p(r),e.push(ra(A,{size:r.length,crc:B.d(),c:f,f:d,m:h,u:g!=n.length||h&&p.length!=I,o:i,compression:l})),i+=30+g+u+C,s+=76+2*(g+u)+(I||0)+C}for(var m=new At(s+22),w=i,Q=s-i,E=0;E<e.length;++E){var d=e[E];ta(m,d.o,d,d.f,d.u,d.c.length);var v=30+d.f.length+Hn(d.extra);m.set(d.c,d.o+v),ta(m,i,d,d.f,d.u,d.c.length,d.o,d.m),i+=16+v+(d.m?d.m.length:0)}return pA(m,i,e.length,Q,w),m}function ca(c,a){for(var t={},e=c.length-22;St(c,e)!=101010256;--e)(!e||c.length-e>65558)&&ut(13);var i=qt(c,e+8);if(!i)return{};var s=St(c,e+16),n=St(c,e-20)==117853008;if(n){var o=St(c,e-12);n=St(c,o)==101075792,n&&(i=St(c,o+32),s=St(c,o+48))}for(var r=a&&a.filter,A=0;A<i;++A){var l=hA(c,s,n),d=l[0],g=l[1],p=l[2],h=l[3],I=l[4],u=l[5],f=dA(c,u);s=I,(!r||r({name:h,size:g,originalSize:p,compression:d}))&&(d?d==8?t[h]=AA(c.subarray(f,f+g),{out:new At(p)}):ut(14,"unknown compression type "+d):t[h]=ki(c,f,f+g))}return t}var At,Ft,Pn,os,as,bn,ea,ia,sa,Nn,na,Wr,Xo,xn,Xt,Z,Jt,re,Z,Z,Z,Z,Fi,Z,Xr,Zr,jr,_r,Fn,Pt,kn,Un,ki,tA,ut,eA,Zt,wi,Sn,Mn,Zo,vi,oa,jo,iA,aa,sA,nA,oA,aA,ra,qt,St,Dn,It,Aa,_o,Tn,lA,cA,dA,hA,gA,Hn,ta,pA,da=Gt(()=>{At=Uint8Array,Ft=Uint16Array,Pn=Int32Array,os=new At([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]),as=new At([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]),bn=new At([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),ea=function(c,a){for(var t=new Ft(31),e=0;e<31;++e)t[e]=a+=1<<c[e-1];for(var i=new Pn(t[30]),e=1;e<30;++e)for(var s=t[e];s<t[e+1];++s)i[s]=s-t[e]<<5|e;return{b:t,r:i}},ia=ea(os,2),sa=ia.b,Nn=ia.r;sa[28]=258,Nn[258]=28;na=ea(as,0),Wr=na.b,Xo=na.r,xn=new Ft(32768);for(Z=0;Z<32768;++Z)Xt=(Z&43690)>>1|(Z&21845)<<1,Xt=(Xt&52428)>>2|(Xt&13107)<<2,Xt=(Xt&61680)>>4|(Xt&3855)<<4,xn[Z]=((Xt&65280)>>8|(Xt&255)<<8)>>1;Jt=function(c,a,t){for(var e=c.length,i=0,s=new Ft(a);i<e;++i)c[i]&&++s[c[i]-1];var n=new Ft(a);for(i=1;i<a;++i)n[i]=n[i-1]+s[i-1]<<1;var o;if(t){o=new Ft(1<<a);var r=15-a;for(i=0;i<e;++i)if(c[i])for(var A=i<<4|c[i],l=a-c[i],d=n[c[i]-1]++<<l,g=d|(1<<l)-1;d<=g;++d)o[xn[d]>>r]=A}else for(o=new Ft(e),i=0;i<e;++i)c[i]&&(o[i]=xn[n[c[i]-1]++]>>15-c[i]);return o},re=new At(288);for(Z=0;Z<144;++Z)re[Z]=8;for(Z=144;Z<256;++Z)re[Z]=9;for(Z=256;Z<280;++Z)re[Z]=7;for(Z=280;Z<288;++Z)re[Z]=8;Fi=new At(32);for(Z=0;Z<32;++Z)Fi[Z]=5;Xr=Jt(re,9,0),Zr=Jt(re,9,1),jr=Jt(Fi,5,0),_r=Jt(Fi,5,1),Fn=function(c){for(var a=c[0],t=1;t<c.length;++t)c[t]>a&&(a=c[t]);return a},Pt=function(c,a,t){var e=a/8|0;return(c[e]|c[e+1]<<8)>>(a&7)&t},kn=function(c,a){var t=a/8|0;return(c[t]|c[t+1]<<8|c[t+2]<<16)>>(a&7)},Un=function(c){return(c+7)/8|0},ki=function(c,a,t){return(a==null||a<0)&&(a=0),(t==null||t>c.length)&&(t=c.length),new At(c.subarray(a,t))},tA=["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"],ut=function(c,a,t){var e=new Error(a||tA[c]);if(e.code=c,Error.captureStackTrace&&Error.captureStackTrace(e,ut),!t)throw e;return e},eA=function(c,a,t,e){var i=c.length,s=e?e.length:0;if(!i||a.f&&!a.l)return t||new At(0);var n=!t,o=n||a.i!=2,r=a.i;n&&(t=new At(i*3));var A=function(ct){var kt=t.length;if(ct>kt){var st=new At(Math.max(kt*2,ct));st.set(t),t=st}},l=a.f||0,d=a.p||0,g=a.b||0,p=a.l,h=a.d,I=a.m,u=a.n,f=i*8;do{if(!p){l=Pt(c,d,1);var C=Pt(c,d+1,3);if(d+=3,C)if(C==1)p=Zr,h=_r,I=9,u=5;else if(C==2){var Q=Pt(c,d,31)+257,E=Pt(c,d+10,15)+4,v=Q+Pt(c,d+5,31)+1;d+=14;for(var y=new At(v),b=new At(19),N=0;N<E;++N)b[bn[N]]=Pt(c,d+N*3,7);d+=E*3;for(var P=Fn(b),H=(1<<P)-1,D=Jt(b,P,1),N=0;N<v;){var S=D[Pt(c,d,H)];d+=S&15;var B=S>>4;if(B<16)y[N++]=B;else{var M=0,U=0;for(B==16?(U=3+Pt(c,d,3),d+=2,M=y[N-1]):B==17?(U=3+Pt(c,d,7),d+=3):B==18&&(U=11+Pt(c,d,127),d+=7);U--;)y[N++]=M}}var R=y.subarray(0,Q),W=y.subarray(Q);I=Fn(R),u=Fn(W),p=Jt(R,I,1),h=Jt(W,u,1)}else ut(1);else{var B=Un(d)+4,m=c[B-4]|c[B-3]<<8,w=B+m;if(w>i){r&&ut(0);break}o&&A(g+m),t.set(c.subarray(B,w),g),a.b=g+=m,a.p=d=w*8,a.f=l;continue}if(d>f){r&&ut(0);break}}o&&A(g+131072);for(var Y=(1<<I)-1,z=(1<<u)-1,G=d;;G=d){var M=p[kn(c,d)&Y],V=M>>4;if(d+=M&15,d>f){r&&ut(0);break}if(M||ut(2),V<256)t[g++]=V;else if(V==256){G=d,p=null;break}else{var K=V-254;if(V>264){var N=V-257,O=os[N];K=Pt(c,d,(1<<O)-1)+sa[N],d+=O}var it=h[kn(c,d)&z],at=it>>4;it||ut(3),d+=it&15;var W=Wr[at];if(at>3){var O=as[at];W+=kn(c,d)&(1<<O)-1,d+=O}if(d>f){r&&ut(0);break}o&&A(g+131072);var _=g+K;if(g<W){var X=s-W,Ct=Math.min(W,_);for(X+g<0&&ut(3);g<Ct;++g)t[g]=e[X+g]}for(;g<_;++g)t[g]=t[g-W]}}a.l=p,a.p=G,a.b=g,a.f=l,p&&(l=1,a.m=I,a.d=h,a.n=u)}while(!l);return g!=t.length&&n?ki(t,0,g):t.subarray(0,g)},Zt=function(c,a,t){t<<=a&7;var e=a/8|0;c[e]|=t,c[e+1]|=t>>8},wi=function(c,a,t){t<<=a&7;var e=a/8|0;c[e]|=t,c[e+1]|=t>>8,c[e+2]|=t>>16},Sn=function(c,a){for(var t=[],e=0;e<c.length;++e)c[e]&&t.push({s:e,f:c[e]});var i=t.length,s=t.slice();if(!i)return{t:aa,l:0};if(i==1){var n=new At(t[0].s+1);return n[t[0].s]=1,{t:n,l:1}}t.sort(function(w,Q){return w.f-Q.f}),t.push({s:-1,f:25001});var o=t[0],r=t[1],A=0,l=1,d=2;for(t[0]={s:-1,f:o.f+r.f,l:o,r};l!=i-1;)o=t[t[A].f<t[d].f?A++:d++],r=t[A!=l&&t[A].f<t[d].f?A++:d++],t[l++]={s:-1,f:o.f+r.f,l:o,r};for(var g=s[0].s,e=1;e<i;++e)s[e].s>g&&(g=s[e].s);var p=new Ft(g+1),h=Mn(t[l-1],p,0);if(h>a){var e=0,I=0,u=h-a,f=1<<u;for(s.sort(function(Q,E){return p[E.s]-p[Q.s]||Q.f-E.f});e<i;++e){var C=s[e].s;if(p[C]>a)I+=f-(1<<h-p[C]),p[C]=a;else break}for(I>>=u;I>0;){var B=s[e].s;p[B]<a?I-=1<<a-p[B]++-1:++e}for(;e>=0&&I;--e){var m=s[e].s;p[m]==a&&(--p[m],++I)}h=a}return{t:new At(p),l:h}},Mn=function(c,a,t){return c.s==-1?Math.max(Mn(c.l,a,t+1),Mn(c.r,a,t+1)):a[c.s]=t},Zo=function(c){for(var a=c.length;a&&!c[--a];);for(var t=new Ft(++a),e=0,i=c[0],s=1,n=function(r){t[e++]=r},o=1;o<=a;++o)if(c[o]==i&&o!=a)++s;else{if(!i&&s>2){for(;s>138;s-=138)n(32754);s>2&&(n(s>10?s-11<<5|28690:s-3<<5|12305),s=0)}else if(s>3){for(n(i),--s;s>6;s-=6)n(8304);s>2&&(n(s-3<<5|8208),s=0)}for(;s--;)n(i);s=1,i=c[o]}return{c:t.subarray(0,e),n:a}},vi=function(c,a){for(var t=0,e=0;e<a.length;++e)t+=c[e]*a[e];return t},oa=function(c,a,t){var e=t.length,i=Un(a+2);c[i]=e&255,c[i+1]=e>>8,c[i+2]=c[i]^255,c[i+3]=c[i+1]^255;for(var s=0;s<e;++s)c[i+s+4]=t[s];return(i+4+e)*8},jo=function(c,a,t,e,i,s,n,o,r,A,l){Zt(a,l++,t),++i[256];for(var d=Sn(i,15),g=d.t,p=d.l,h=Sn(s,15),I=h.t,u=h.l,f=Zo(g),C=f.c,B=f.n,m=Zo(I),w=m.c,Q=m.n,E=new Ft(19),v=0;v<C.length;++v)++E[C[v]&31];for(var v=0;v<w.length;++v)++E[w[v]&31];for(var y=Sn(E,7),b=y.t,N=y.l,P=19;P>4&&!b[bn[P-1]];--P);var H=A+5<<3,D=vi(i,re)+vi(s,Fi)+n,S=vi(i,g)+vi(s,I)+n+14+3*P+vi(E,b)+2*E[16]+3*E[17]+7*E[18];if(r>=0&&H<=D&&H<=S)return oa(a,l,c.subarray(r,r+A));var M,U,R,W;if(Zt(a,l,1+(S<D)),l+=2,S<D){M=Jt(g,p,0),U=g,R=Jt(I,u,0),W=I;var Y=Jt(b,N,0);Zt(a,l,B-257),Zt(a,l+5,Q-1),Zt(a,l+10,P-4),l+=14;for(var v=0;v<P;++v)Zt(a,l+3*v,b[bn[v]]);l+=3*P;for(var z=[C,w],G=0;G<2;++G)for(var V=z[G],v=0;v<V.length;++v){var K=V[v]&31;Zt(a,l,Y[K]),l+=b[K],K>15&&(Zt(a,l,V[v]>>5&127),l+=V[v]>>12)}}else M=Xr,U=re,R=jr,W=Fi;for(var v=0;v<o;++v){var O=e[v];if(O>255){var K=O>>18&31;wi(a,l,M[K+257]),l+=U[K+257],K>7&&(Zt(a,l,O>>23&31),l+=os[K]);var it=O&31;wi(a,l,R[it]),l+=W[it],it>3&&(wi(a,l,O>>5&8191),l+=as[it])}else wi(a,l,M[O]),l+=U[O]}return wi(a,l,M[256]),l+U[256]},iA=new Pn([65540,131080,131088,131104,262176,1048704,1048832,2114560,2117632]),aa=new At(0),sA=function(c,a,t,e,i,s){var n=s.z||c.length,o=new At(e+n+5*(1+Math.ceil(n/7e3))+i),r=o.subarray(e,o.length-i),A=s.l,l=(s.r||0)&7;if(a){l&&(r[0]=s.r>>3);for(var d=iA[a-1],g=d>>13,p=d&8191,h=(1<<t)-1,I=s.p||new Ft(32768),u=s.h||new Ft(h+1),f=Math.ceil(t/3),C=2*f,B=function(Bt){return(c[Bt]^c[Bt+1]<<f^c[Bt+2]<<C)&h},m=new Pn(25e3),w=new Ft(288),Q=new Ft(32),E=0,v=0,y=s.i||0,b=0,N=s.w||0,P=0;y+2<n;++y){var H=B(y),D=y&32767,S=u[H];if(I[D]=S,u[H]=D,N<=y){var M=n-y;if((E>7e3||b>24576)&&(M>423||!A)){l=jo(c,r,0,m,w,Q,v,b,P,y-P,l),b=E=v=0,P=y;for(var U=0;U<286;++U)w[U]=0;for(var U=0;U<30;++U)Q[U]=0}var R=2,W=0,Y=p,z=D-S&32767;if(M>2&&H==B(y-z))for(var G=Math.min(g,M)-1,V=Math.min(32767,y),K=Math.min(258,M);z<=V&&--Y&&D!=S;){if(c[y+R]==c[y+R-z]){for(var O=0;O<K&&c[y+O]==c[y+O-z];++O);if(O>R){if(R=O,W=z,O>G)break;for(var it=Math.min(z,O-2),at=0,U=0;U<it;++U){var _=y-z+U&32767,X=I[_],Ct=_-X&32767;Ct>at&&(at=Ct,S=_)}}}D=S,S=I[D],z+=D-S&32767}if(W){m[b++]=268435456|Nn[R]<<18|Xo[W];var ct=Nn[R]&31,kt=Xo[W]&31;v+=os[ct]+as[kt],++w[257+ct],++Q[kt],N=y+R,++E}else m[b++]=c[y],++w[c[y]]}}for(y=Math.max(y,N);y<n;++y)m[b++]=c[y],++w[c[y]];l=jo(c,r,A,m,w,Q,v,b,P,y-P,l),A||(s.r=l&7|r[l/8|0]<<3,l-=7,s.h=u,s.p=I,s.i=y,s.w=N)}else{for(var y=s.w||0;y<n+A;y+=65535){var st=y+65535;st>=n&&(r[l/8|0]=A,st=n),l=oa(r,l+1,c.subarray(y,st))}s.i=n}return ki(o,0,e+Un(l)+i)},nA=function(){for(var c=new Int32Array(256),a=0;a<256;++a){for(var t=a,e=9;--e;)t=(t&1&&-306674912)^t>>>1;c[a]=t}return c}(),oA=function(){var c=-1;return{p:function(a){for(var t=c,e=0;e<a.length;++e)t=nA[t&255^a[e]]^t>>>8;c=t},d:function(){return~c}}},aA=function(c,a,t,e,i){if(!i&&(i={l:1},a.dictionary)){var s=a.dictionary.subarray(-32768),n=new At(s.length+c.length);n.set(s),n.set(c,s.length),c=n,i.w=s.length}return sA(c,a.level==null?6:a.level,a.mem==null?i.l?Math.ceil(Math.max(8,Math.min(13,Math.log(c.length)))*1.5):20:12+a.mem,t,e,i)},ra=function(c,a){var t={};for(var e in c)t[e]=c[e];for(var e in a)t[e]=a[e];return t},qt=function(c,a){return c[a]|c[a+1]<<8},St=function(c,a){return(c[a]|c[a+1]<<8|c[a+2]<<16|c[a+3]<<24)>>>0},Dn=function(c,a){return St(c,a)+St(c,a+4)*4294967296},It=function(c,a,t){for(;t;++a)c[a]=t,t>>>=8};Aa=function(c,a,t,e){for(var i in c){var s=c[i],n=a+i,o=e;Array.isArray(s)&&(o=ra(e,s[1]),s=s[0]),ArrayBuffer.isView(s)?t[n]=[s,o]:(t[n+="/"]=[new At(0),o],Aa(s,n,t,e))}},_o=typeof TextEncoder<"u"&&new TextEncoder,Tn=typeof TextDecoder<"u"&&new TextDecoder,lA=0;try{Tn.decode(aa,{stream:!0}),lA=1}catch{}cA=function(c){for(var a="",t=0;;){var e=c[t++],i=(e>127)+(e>223)+(e>239);if(t+i>c.length)return{s:a,r:ki(c,t-1)};i?i==3?(e=((e&15)<<18|(c[t++]&63)<<12|(c[t++]&63)<<6|c[t++]&63)-65536,a+=String.fromCharCode(55296|e>>10,56320|e&1023)):i&1?a+=String.fromCharCode((e&31)<<6|c[t++]&63):a+=String.fromCharCode((e&15)<<12|(c[t++]&63)<<6|c[t++]&63):a+=String.fromCharCode(e)}};dA=function(c,a){return a+30+qt(c,a+26)+qt(c,a+28)},hA=function(c,a,t){var e=qt(c,a+28),i=qt(c,a+30),s=Gn(c.subarray(a+46,a+46+e),!(qt(c,a+8)&2048)),n=a+46+e,o=gA(c,n,i,t,St(c,a+20),St(c,a+24),St(c,a+42)),r=o[0],A=o[1],l=o[2];return[qt(c,a+10),r,A,s,n+i+qt(c,a+32),l]},gA=function(c,a,t,e,i,s,n){var o=i==4294967295,r=s==4294967295,A=n==4294967295,l=a+t,d=o+r+A;if(e&&d){for(;a+4<l;a+=4+qt(c,a+2))if(qt(c,a)==1)return[o?Dn(c,a+4+8*r):i,r?Dn(c,a+4):s,A?Dn(c,a+4+8*(r+o)):n,1];e<2&&ut(13)}return[i,s,n,0]},Hn=function(c){var a=0;if(c)for(var t in c){var e=c[t].length;e>65535&&ut(9),a+=e+4}return a},ta=function(c,a,t,e,i,s,n,o){var r=e.length,A=t.extra,l=o&&o.length,d=Hn(A);It(c,a,n!=null?33639248:67324752),a+=4,n!=null&&(c[a++]=20,c[a++]=t.os),c[a]=20,a+=2,c[a++]=t.flag<<1|(s<0&&8),c[a++]=i&&8,c[a++]=t.compression&255,c[a++]=t.compression>>8;var g=new Date(t.mtime==null?Date.now():t.mtime),p=g.getFullYear()-1980;if((p<0||p>119)&&ut(10),It(c,a,p<<25|g.getMonth()+1<<21|g.getDate()<<16|g.getHours()<<11|g.getMinutes()<<5|g.getSeconds()>>1),a+=4,s!=-1&&(It(c,a,t.crc),It(c,a+4,s<0?-s-2:s),It(c,a+8,t.size)),It(c,a+12,r),It(c,a+14,d),a+=16,n!=null&&(It(c,a,l),It(c,a+6,t.attrs),It(c,a+10,n),a+=14),c.set(e,a),a+=r,d)for(var h in A){var I=A[h],u=I.length;It(c,a,+h),It(c,a+2,u),c.set(I,a+4),a+=4+u}return l&&(c.set(o,a),a+=l),a},pA=function(c,a,t,e,i){It(c,a,101010256),It(c,a+8,t),It(c,a+10,t),It(c,a+12,e),It(c,a+16,i)}});var ha={};Xe(ha,{bytesToStr:()=>rs,unzipFiles:()=>Di,zipFiles:()=>Si});function IA(c){return typeof c=="string"?ns(c):c instanceof Uint8Array?c:new Uint8Array(c)}function Si(c,a=6){let t={};for(let e of c)t[e.name]=[IA(e.data),{level:a}];return Promise.resolve(la(t,{level:a}))}function rs(c){return Gn(c)}function Di(c){let a=c instanceof Uint8Array?c:new Uint8Array(c);return Promise.resolve(ca(a))}var As=Gt(()=>{"use strict";da()});var ZA={};Xe(ZA,{default:()=>zs});module.exports=rr(ZA);var T=require("obsidian");rt();var mt=require("obsidian");var ot=require("obsidian");rt();function Pi(c){let a=(c.dateDisplayTimezone||"").trim();return a?{timeZone:a}:{}}function Ot(c,a){try{return new Intl.DateTimeFormat(void 0,a).format(new Date(c))}catch{let{timeZone:t,...e}=a;return new Intl.DateTimeFormat(void 0,e).format(new Date(c))}}function Yt(c,a){let t=Pi(a);switch(a.dateDisplayFormat??"locale"){case"iso":return Io(c,a,!0);case"us":return Ot(c,{...t,month:"numeric",day:"numeric",year:"numeric",hour:"numeric",minute:"2-digit"});case"eu":return Ot(c,{...t,day:"numeric",month:"numeric",year:"numeric",hour:"2-digit",minute:"2-digit",hourCycle:"h23"});case"long":return Ot(c,{...t,dateStyle:"full",timeStyle:"short"});case"locale":default:return Ot(c,{...t,dateStyle:"medium",timeStyle:"short"})}}function go(c,a){let t=Pi(a);switch(a.dateDisplayFormat??"locale"){case"iso":return Io(c,a,!1);case"us":return Ot(c,{...t,month:"numeric",day:"numeric",year:"numeric"});case"eu":return Ot(c,{...t,day:"numeric",month:"numeric",year:"numeric"});case"long":return Ot(c,{...t,dateStyle:"full"});case"locale":default:{let e=new Date,i=new Date(c).getFullYear()===e.getFullYear();return Ot(c,i?{...t,month:"short",day:"numeric"}:{...t,month:"short",day:"numeric",year:"numeric"})}}}function po(c,a){let t=Pi(a),e=a.dateDisplayFormat==="iso"||a.dateDisplayFormat==="eu";return Ot(c,{...t,hour:e?"2-digit":"numeric",minute:"2-digit",...e?{hourCycle:"h23"}:{}})}function Io(c,a,t){let e=Pi(a),i=new Intl.DateTimeFormat("en-CA",{...e,year:"numeric",month:"2-digit",day:"2-digit",...t?{hour:"2-digit",minute:"2-digit",hourCycle:"h23"}:{}}).formatToParts(new Date(c)),s=o=>i.find(r=>r.type===o)?.value??"",n=`${s("year")}-${s("month")}-${s("day")}`;return t?`${n} ${s("hour")}:${s("minute")}`:n}function we(c,a,t){let e=c.createSpan({cls:"stashpad-count-badge"});t&&e.addClass("is-expanded"),e.setText(a>99?"99+":String(a))}var pi={pinned:{label:"Pinned",icon:"pin"},shared:{label:"Shared",icon:"users"},tasks:{label:"Tasks",icon:"check-circle-2"}},qi=class extends ot.ItemView{constructor(t,e){super(t);this.plugin=e;this.activePanel="pinned";this.taskFilter="all";this.taskAssignFilter="all";this.taskFolderFilter="all";this.expanded=new Set;this.renderTimer=null;this.sharedAuthorFilter="all";this.sharedContribOnly=!1}setActivePanel(t){this.activePanel=t,this.containerEl.isConnected&&this.render()}getViewType(){return ie}getDisplayText(){return"Stashpad panels"}getIcon(){return"panel-left"}async onOpen(){this.render(),this.registerEvent(this.app.metadataCache.on("changed",()=>this.scheduleRender())),this.registerEvent(this.app.vault.on("rename",()=>this.scheduleRender())),this.registerEvent(this.app.vault.on("delete",()=>this.scheduleRender())),this.registerEvent(this.app.workspace.on("active-leaf-change",t=>{t&&t.view.getViewType()===J&&this.scheduleRender()}))}scheduleRender(){this.renderTimer==null&&(this.renderTimer=window.setTimeout(()=>{this.renderTimer=null,this.containerEl.isConnected&&this.render()},80))}render(){let t=this.contentEl;t.empty(),t.addClass("stashpad-panels-root");let e=t.createDiv({cls:"stashpad-panels-globals"}),i=e.createEl("button",{cls:"stashpad-panels-global-btn"});(0,ot.setIcon)(i.createSpan({cls:"stashpad-panels-global-btn-icon"}),"search"),i.createSpan({cls:"stashpad-panels-global-btn-text",text:"Search"}),i.onclick=()=>this.openSearchFromPanel();let s=e.createEl("button",{cls:"stashpad-panels-global-btn"});(0,ot.setIcon)(s.createSpan({cls:"stashpad-panels-global-btn-icon"}),"folder-tree"),s.createSpan({cls:"stashpad-panels-global-btn-text",text:"Folder Switcher"}),s.onclick=()=>this.plugin.openFolderPicker();let n=e.createDiv({cls:"stashpad-panels-globals-row"}),o=n.createEl("button",{cls:"stashpad-panels-global-btn"});(0,ot.setIcon)(o.createSpan({cls:"stashpad-panels-global-btn-icon"}),"scroll-text"),o.createSpan({cls:"stashpad-panels-global-btn-text",text:"Log"}),o.onclick=()=>this.openLogFromPanel();let r=n.createEl("button",{cls:"stashpad-panels-global-btn"});(0,ot.setIcon)(r.createSpan({cls:"stashpad-panels-global-btn-icon"}),"bell"),r.createSpan({cls:"stashpad-panels-global-btn-text",text:"Notifications"}),r.onclick=()=>this.openNotificationsFromPanel();let A=t.createDiv({cls:"stashpad-panels-bar"});for(let d of Object.keys(pi)){let g=pi[d],p=A.createEl("button",{cls:"stashpad-panels-bar-btn"});(0,ot.setIcon)(p.createSpan({cls:"stashpad-panels-bar-btn-icon"}),g.icon),p.createSpan({cls:"stashpad-panels-bar-btn-text",text:g.label}),this.activePanel===d&&p.addClass("is-active"),p.onclick=()=>{this.activePanel!==d&&(this.activePanel=d,this.render())}}let l=t.createDiv({cls:"stashpad-panels-body"});this.activePanel==="pinned"?this.renderPinnedPanel(l):this.activePanel==="shared"?this.renderSharedPanel(l):this.activePanel==="tasks"&&this.renderTasksPanel(l)}openPinnedOptionsMenu(t){let e=this.plugin.settings.folderPanelPinnedGrouping??"pin-order",i=new ot.Menu;i.addItem(s=>s.setTitle("Sort by pin order").setChecked(e==="pin-order").onClick(()=>void this.setPinnedGrouping("pin-order"))),i.addItem(s=>s.setTitle("Group by folder").setChecked(e==="folder").onClick(()=>void this.setPinnedGrouping("folder"))),i.showAtMouseEvent(t)}async setPinnedGrouping(t){(this.plugin.settings.folderPanelPinnedGrouping??"pin-order")!==t&&(this.plugin.settings.folderPanelPinnedGrouping=t,await this.plugin.saveSettings(),this.render())}renderPinnedPanel(t){let e=t.createDiv({cls:"stashpad-panel-pinned"});(this.plugin.settings.folderPanelPinnedGrouping??"pin-order")!=="folder"&&e.addClass("is-flat");let i=e.createDiv({cls:"stashpad-pinned-headrow"}),s=i.createEl("button",{cls:"stashpad-pinned-row stashpad-pinned-home"}),n=s.createSpan({cls:"stashpad-pinned-icon"});(0,ot.setIcon)(n,"home"),s.createSpan({cls:"stashpad-pinned-label",text:"Home"}),s.onclick=()=>this.openHomeFromPanel();let o=i.createEl("button",{cls:"stashpad-folderpanel-iconbtn stashpad-pinned-opts"});(0,ot.setIcon)(o,"list"),o.setAttr("aria-label","Pinned view options"),o.onclick=p=>{p.stopPropagation(),this.openPinnedOptionsMenu(p)};let r=this.plugin.listPinnedNotes();if(r.length===0){e.createDiv({cls:"stashpad-pinned-empty"}).setText("No pinned notes yet \u2014 right-click a note and choose \u201CPin to sidebar.\u201D");return}if((this.plugin.settings.folderPanelPinnedGrouping??"pin-order")!=="folder"){r.forEach((p,h)=>this.renderPinnedRow(e,p,h));return}let l=new Map;r.forEach((p,h)=>{let I=l.get(p.folder);I||(I=[],l.set(p.folder,I)),I.push({pin:p,idx:h})});let d=this.plugin.lastActiveStashpadLeaf?.view?.noteFolder,g=Array.from(l.keys());d&&l.has(d)&&(g.splice(g.indexOf(d),1),g.unshift(d));for(let p of g){let h=p.split("/").pop()||p,I=e.createDiv({cls:"stashpad-pinned-group-header"});p===d&&I.addClass("is-active-folder"),I.createSpan({cls:"stashpad-pinned-group-name",text:h});let u=l.get(p)??[];for(let{pin:f,idx:C}of u)this.renderPinnedRow(e,f,C)}}renderPinnedRow(t,e,i){let s=this.findFileFor(e);if(!s)return;let n=this.app.metadataCache.getFileCache(s)?.frontmatter??{},o=this.titleFromFile(s),r=typeof n.color=="string"?n.color:null,A=n.completed===!0,l=this.childrenOf(e.folder,e.id).length,d=l>0,g=this.expanded.has(`${e.folder}|${e.id}`),p=t.createDiv({cls:"stashpad-pinned-row"});r&&p.addClass("has-color"),A&&p.addClass("is-completed"),p.draggable=!0,p.dataset.pinIdx=String(i),p.addEventListener("dragstart",C=>{C.dataTransfer?.setData("text/plain",String(i)),C.dataTransfer&&(C.dataTransfer.effectAllowed="move"),p.addClass("is-dragging")}),p.addEventListener("dragend",()=>p.removeClass("is-dragging")),p.addEventListener("dragover",C=>{C.preventDefault(),C.dataTransfer&&(C.dataTransfer.dropEffect="move");let B=p.getBoundingClientRect(),m=C.clientY-B.top<B.height/2;p.toggleClass("drop-before",m),p.toggleClass("drop-after",!m)}),p.addEventListener("dragleave",()=>{p.removeClass("drop-before"),p.removeClass("drop-after")}),p.addEventListener("drop",C=>{C.preventDefault(),p.removeClass("drop-before"),p.removeClass("drop-after");let B=parseInt(C.dataTransfer?.getData("text/plain")??"",10);if(!Number.isFinite(B)||B===i)return;let m=p.getBoundingClientRect(),w=C.clientY-m.top<m.height/2;this.reorderPin(B,w?i:i+1)});let h=p.createSpan({cls:"stashpad-pinned-toggle"});d&&(we(h,l,g),h.onclick=C=>{C.stopPropagation();let B=`${e.folder}|${e.id}`;this.expanded.has(B)?this.expanded.delete(B):this.expanded.add(B),this.render()});let I=p.createSpan({cls:"stashpad-pinned-icon"});(0,ot.setIcon)(I,d?"folder-tree":"file-text"),r&&(I.style.color=r);let u=p.createSpan({cls:"stashpad-pinned-label",text:o});u.onclick=()=>this.openPinFromPanel(e);let f=e.folder.split("/").pop()||e.folder;if(p.createSpan({cls:"stashpad-pinned-folder",text:f}),p.oncontextmenu=C=>{C.preventDefault();let B=new ot.Menu;B.addItem(m=>m.setTitle("Unpin from sidebar").setIcon("pin-off").onClick(()=>{this.plugin.unpinNote(e)})),B.showAtMouseEvent(C)},d&&g){let C=t.createDiv({cls:"stashpad-pinned-children"});this.renderPinnedSubtree(C,e.folder,e.id,1)}}async reorderPin(t,e){let i=this.plugin.listPinnedNotes();if(t<0||t>=i.length)return;let s=i[t],n=i.filter((d,g)=>g!==t),o=Math.max(0,Math.min(e>t?e-1:e,n.length)),r=n[o-1],A=n[o],l;!r&&!A?l=Date.now():r?A?l=(r.pinnedAt+A.pinnedAt)/2:l=r.pinnedAt+1e3:l=A.pinnedAt-1e3;try{await this.app.fileManager.processFrontMatter(s.file,d=>{d.pinnedAt=l})}catch(d){console.warn("[Stashpad] pin reorder failed",d)}this.render()}renderPinnedSubtree(t,e,i,s){let n=this.childrenOf(e,i);for(let o of n){let r=this.app.metadataCache.getFileCache(o)?.frontmatter??{},A=typeof r.id=="string"?r.id:null;if(!A)continue;let l=typeof r.color=="string"?r.color:null,d=r.completed===!0,g=this.childrenOf(e,A).length,p=g>0,h=this.expanded.has(`${e}|${A}`),I=t.createDiv({cls:"stashpad-pinned-subrow"});d&&I.addClass("is-completed"),I.style.paddingLeft=`${s*16}px`;let u=I.createSpan({cls:"stashpad-pinned-toggle"});p&&(we(u,g,h),u.onclick=B=>{B.stopPropagation();let m=`${e}|${A}`;this.expanded.has(m)?this.expanded.delete(m):this.expanded.add(m),this.render()});let f=I.createSpan({cls:"stashpad-pinned-icon"});(0,ot.setIcon)(f,"file-text"),l&&(f.style.color=l);let C=I.createSpan({cls:"stashpad-pinned-label",text:this.titleFromFile(o)});C.onclick=()=>this.openPinFromPanel({folder:e,id:A}),p&&h&&this.renderPinnedSubtree(t,e,A,s+1)}}findFileFor(t){for(let e of this.app.vault.getMarkdownFiles()){if((e.parent?.path?.replace(/\/+$/,"")??"")!==t.folder)continue;if(this.app.metadataCache.getFileCache(e)?.frontmatter?.id===t.id)return e}return null}childrenOf(t,e){let i=[];for(let s of this.app.vault.getMarkdownFiles()){if((s.parent?.path?.replace(/\/+$/,"")??"")!==t)continue;let o=this.app.metadataCache.getFileCache(s)?.frontmatter;if(!o||typeof o.id!="string")continue;let r=o.parent;if(r===e||e===F&&(r==null||r===F)){if(o.id===F)continue;i.push(s)}}return i.sort((s,n)=>{let o=this.app.metadataCache.getFileCache(s)?.frontmatter,r=this.app.metadataCache.getFileCache(n)?.frontmatter,A=o?.created??"",l=r?.created??"";return A.localeCompare(l)}),i}titleFromFile(t){return t.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||t.basename}async openSearchFromPanel(){let t=await this.resolveTargetStashpad();t&&typeof t.openSearchModal=="function"&&t.openSearchModal()}async openLogFromPanel(){let t=this.app.vault.adapter,e=this.plugin.pluginPrivatePath("log.jsonl");if(!await t.exists(e)){new ot.Notice("No log yet \u2014 make some changes first.");return}let i=await t.read(e),{LogModal:s}=await Promise.resolve().then(()=>(vt(),gi));new s(this.app,i,e).open()}openNotificationsFromPanel(){this.app.commands?.executeCommandById?.("stashpad:stashpad-open-notification-history")}async openHomeFromPanel(){let t=await this.resolveTargetStashpad();t&&typeof t.navigateTo=="function"&&t.navigateTo(F)}async openPinFromPanel(t){await this.plugin.revealNoteByRef(t.folder,t.id)}async resolveTargetStashpad(){let t=this.plugin.lastActiveStashpadLeaf;if(t&&t.view.getViewType()===J)return this.app.workspace.revealLeaf(t),t.view;let e=this.findActiveStashpad();if(e)return e;let i=this.app.workspace.getLeavesOfType(J);return i.length>0?(this.app.workspace.revealLeaf(i[0]),i[0].view):(await this.plugin.activateView({reveal:!0}),this.findActiveStashpad())}findActiveStashpad(){let t=this.app.workspace.activeLeaf;return t&&t.view.getViewType()===J?t.view:null}renderSharedPanel(t){let e=t.createDiv({cls:"stashpad-panel-shared"}),i=(this.plugin.settings.authorId??"").trim();if(!i){e.createDiv({cls:"stashpad-shared-empty"}).setText("Set an author name in Stashpad settings to populate Shared.");return}let s=this.collectSharedNotes(i),n=new Map;for(let d of s){let g=d.authorId;g&&!n.has(g)&&n.set(g,d.authorDisplay||g)}let o=e.createDiv({cls:"stashpad-shared-filters"}),r=(d,g,p)=>{let h=o.createEl("button",{cls:"stashpad-shared-chip",text:d});return g&&h.addClass("is-active"),h.onclick=p,h};if(r("All",this.sharedAuthorFilter==="all",()=>{this.sharedAuthorFilter="all",this.render()}),r("Mine",this.sharedAuthorFilter==="mine",()=>{this.sharedAuthorFilter="mine",this.render()}),r("Others",this.sharedAuthorFilter==="others",()=>{this.sharedAuthorFilter="others",this.render()}),n.size>1){let d=o.createEl("select",{cls:"stashpad-shared-author-select"}),g=d.createEl("option",{text:"Any author"});g.value="__any__";for(let[h,I]of n){let u=d.createEl("option",{text:I});u.value=h}let p=["all","mine","others"].includes(this.sharedAuthorFilter)?"__any__":this.sharedAuthorFilter;d.value=p,d.onchange=()=>{let h=d.value;h==="__any__"?this.sharedAuthorFilter="all":this.sharedAuthorFilter=h,this.render()}}let A=o.createEl("button",{cls:"stashpad-shared-chip",text:"Has contributors"});this.sharedContribOnly&&A.addClass("is-active"),A.onclick=()=>{this.sharedContribOnly=!this.sharedContribOnly,this.render()};let l=s.filter(d=>{if(this.sharedContribOnly&&d.contributorCount===0)return!1;switch(this.sharedAuthorFilter){case"all":return!0;case"mine":return d.authorId===i;case"others":return d.authorId!==i;default:return d.authorId===this.sharedAuthorFilter}});if(l.length===0){e.createDiv({cls:"stashpad-shared-empty"}).setText("No shared notes match the current filters.");return}for(let d of l){let g=e.createDiv({cls:"stashpad-pinned-row stashpad-shared-row"}),p=g.createSpan({cls:"stashpad-pinned-icon"});(0,ot.setIcon)(p,"users"),d.color&&(p.style.color=d.color);let h=g.createSpan({cls:"stashpad-pinned-label",text:d.title});h.onclick=()=>this.openSharedFromPanel(d.folder,d.id);let I=d.folder.split("/").pop()||d.folder;g.createSpan({cls:"stashpad-pinned-folder",text:I}),d.authorDisplay&&g.createSpan({cls:"stashpad-shared-meta"}).setText(d.authorId===i?`you \xB7 ${d.contributorCount} contributor${d.contributorCount===1?"":"s"}`:`by ${d.authorDisplay}${d.contributorCount>0?` \xB7 ${d.contributorCount} contributor${d.contributorCount===1?"":"s"}`:""}`)}}collectSharedNotes(t){let e=this.plugin.discoverStashpadFolders(),i=new Set(e),s=new Map;for(let o of this.app.vault.getMarkdownFiles()){let r=o.parent?.path?.replace(/\/+$/,"")??"";if(!i.has(r))continue;let A=this.app.metadataCache.getFileCache(o)?.frontmatter??{};A.id===F&&s.set(r,this.extractAuthorId(A.author))}let n=[];for(let o of this.app.vault.getMarkdownFiles()){let r=o.parent?.path?.replace(/\/+$/,"")??"";if(!i.has(r)||r.endsWith("/_authors")||o.path.includes("/_authors/"))continue;let A=this.app.metadataCache.getFileCache(o)?.frontmatter??{};if(typeof A.id!="string"||A.id===F)continue;let l=this.extractAuthorId(A.author),d=Array.isArray(A.contributors)?A.contributors.filter(B=>typeof B=="string"):[],g=s.get(r)??null;if(!(d.length>0||g===t&&(l!==null&&l!==t)))continue;let f=this.titleFromFile(o),C=typeof A.color=="string"?A.color:null;n.push({file:o,folder:r,id:A.id,title:f,color:C,authorId:l,authorDisplay:this.extractAuthorDisplay(A.author)||(l??""),contributorCount:d.length})}return n.sort((o,r)=>{let A=this.app.metadataCache.getFileCache(o.file)?.frontmatter??{},l=this.app.metadataCache.getFileCache(r.file)?.frontmatter??{},d=A.modified??A.created??"";return(l.modified??l.created??"").localeCompare(d)}),n}extractAuthorId(t){if(typeof t!="string")return null;let e=t.match(/-([a-z0-9]{4,12})(?:\.md)?(?:\||\]\])/i);return e?e[1]:null}extractAuthorDisplay(t){if(typeof t!="string")return"";let e=t.match(/\|([^\]]+)\]\]/);if(e)return e[1].trim();let i=t.match(/_authors\/([^\]|]+)-[a-z0-9]{4,12}/i);return i?i[1].replace(/[-_]/g," ").trim():""}async openSharedFromPanel(t,e){await this.plugin.revealNoteByRef(t,e)}renderTasksPanel(t){let e=t.createDiv({cls:"stashpad-panel-tasks"}),i=this.collectTasks();if(i.length===0){e.createDiv({cls:"stashpad-tasks-empty"}).setText("No tasks yet \u2014 press H on a note to mark it a task, or D to give it a due date.");return}let s=(this.plugin.settings.authorId??"").trim(),n=S=>!!s&&S.assignedTo.some(M=>M.id===s),o=S=>{let M=this.taskAssignFilter;if(M.startsWith("person:")){let U=M.slice(7);return S.assignedTo.some(R=>R.id===U)}switch(M){case"mine":return n(S);case"others":return S.assignedTo.length>0&&!n(S);case"byme":return!!s&&S.assignedBy?.id===s;case"unassigned":return S.assignedTo.length===0;default:return!0}},r=new Map;for(let S of i){for(let M of S.assignedTo)M.id!==s&&r.set(M.id,M.name);S.assignedBy&&S.assignedBy.id!==s&&r.set(S.assignedBy.id,S.assignedBy.name)}let A=[...r.entries()].map(([S,M])=>({id:S,name:M})).sort((S,M)=>S.name.localeCompare(M.name)),l=e.createDiv({cls:"stashpad-task-assign-bar"});l.createSpan({cls:"stashpad-task-assign-label",text:"Assignment"});let d=l.createEl("select",{cls:"stashpad-task-assign-select"}),g=S=>{let M={all:"Everyone",mine:"Assigned to me",others:"Assigned to others",byme:"Assigned by me",unassigned:"Unassigned"};return S.startsWith("person:")?r.get(S.slice(7))??"Person":M[S]??S},p=S=>{let M=d.createEl("option",{text:g(S),value:S});this.taskAssignFilter===S&&(M.selected=!0)};for(let S of["all","mine","others","byme","unassigned"])p(S);if(A.length>0){let S=d.createEl("optgroup");S.setAttr("label","By person");for(let M of A){let U=S.createEl("option",{text:M.name,value:`person:${M.id}`});this.taskAssignFilter===`person:${M.id}`&&(U.selected=!0)}}d.onchange=()=>{this.taskAssignFilter=d.value,this.render()};let h=[...new Set(i.map(S=>S.folder))].sort((S,M)=>S.localeCompare(M));this.taskFolderFilter!=="all"&&!h.includes(this.taskFolderFilter)&&(this.taskFolderFilter="all");let I=e.createDiv({cls:"stashpad-task-assign-bar"});I.createSpan({cls:"stashpad-task-assign-label",text:"Folder"});let u=I.createEl("select",{cls:"stashpad-task-assign-select"}),f=u.createEl("option",{text:"All folders",value:"all"});this.taskFolderFilter==="all"&&(f.selected=!0);for(let S of h){let M=u.createEl("option",{text:S.split("/").pop()||S,value:S});this.taskFolderFilter===S&&(M.selected=!0)}u.onchange=()=>{this.taskFolderFilter=u.value,this.render()};let C=S=>this.taskFolderFilter==="all"||S.folder===this.taskFolderFilter,B=i.filter(S=>o(S)&&C(S));if(B.length===0){e.createDiv({cls:"stashpad-tasks-empty"}).setText("No tasks match the current filters.");return}let m=new Date;m.setHours(0,0,0,0);let w=m.getTime(),Q=w+24*60*60*1e3,E={overdue:[],today:[],upcoming:[],nodate:[],completed:[]};for(let S of B){if(S.completed){E.completed.push(S);continue}if(S.due==null){E.nodate.push(S);continue}S.due<w?E.overdue.push(S):S.due<Q?E.today.push(S):E.upcoming.push(S)}let v=(S,M)=>S.due==null&&M.due==null?S.title.localeCompare(M.title):S.due==null?1:M.due==null?-1:S.due-M.due,y=[{key:"overdue",label:"Overdue",icon:"alert-circle"},{key:"today",label:"Due today",icon:"calendar-clock"},{key:"upcoming",label:"Upcoming",icon:"calendar"},{key:"nodate",label:"No date",icon:"inbox"},{key:"completed",label:"Completed",icon:"check-circle-2"}],b=e.createDiv({cls:"stashpad-task-filters"}),N=B.length,P=(S,M,U)=>{let R=b.createEl("button",{cls:"stashpad-task-filter"});this.taskFilter===S&&R.addClass("is-active"),R.createSpan({cls:"stashpad-task-filter-label",text:M}),R.createSpan({cls:"stashpad-task-filter-count",text:String(U)}),R.onclick=()=>{this.taskFilter=S,this.render()}};P("all","All",N),P("overdue","Overdue",E.overdue.length),P("today","Today",E.today.length),P("upcoming","Upcoming",E.upcoming.length),P("nodate","No date",E.nodate.length),P("completed","Done",E.completed.length);let H=this.taskFilter==="all"?y:y.filter(S=>S.key===this.taskFilter),D=!1;for(let S of H){let M=E[S.key];if(M.length!==0){if(D=!0,M.sort(S.key==="completed"?(U,R)=>v(R,U):v),this.taskFilter==="all"){let U=e.createDiv({cls:`stashpad-task-section-header is-${S.key}`});(0,ot.setIcon)(U.createSpan({cls:"stashpad-task-section-icon"}),S.icon),U.createSpan({cls:"stashpad-task-section-name",text:S.label}),U.createSpan({cls:"stashpad-task-section-count",text:String(M.length)})}for(let U of M)this.renderTaskRow(e,U,S.key==="today")}}if(!D&&this.taskFilter!=="all"){e.createDiv({cls:"stashpad-tasks-empty"}).setText(`Nothing in "${H[0]?.label??this.taskFilter}".`);return}D||e.createDiv({cls:"stashpad-tasks-empty"}).setText("No tasks to show.")}renderTaskRow(t,e,i){let s=t.createDiv({cls:"stashpad-pinned-row stashpad-task-row"});e.color&&s.addClass("has-color"),e.completed&&s.addClass("is-completed");let n=s.createSpan({cls:"stashpad-pinned-icon stashpad-task-checkbox"});(0,ot.setIcon)(n,e.completed?"check-square":"square"),e.color&&(n.style.color=e.color),n.title=e.completed?"Mark not done":"Mark done",n.onclick=r=>{r.stopPropagation(),this.toggleTaskCompleted(e)};let o=s.createSpan({cls:"stashpad-pinned-label",text:e.title});if(o.onclick=()=>this.openTaskFromPanel(e.folder,e.id),s.createSpan({cls:"stashpad-task-folder",text:e.folder.split("/").pop()||e.folder}),e.due!=null){let r=s.createSpan({cls:"stashpad-task-due",text:this.formatDueShort(e.due,i)});e.due<Date.now()&&!e.completed&&r.addClass("is-overdue")}else e.dueRaw&&s.createSpan({cls:"stashpad-task-due",text:e.dueRaw});if(e.assignedTo.length>0){let r=(this.plugin.settings.authorId??"").trim(),A=s.createSpan({cls:"stashpad-task-assignees"});for(let l of e.assignedTo){let d=A.createSpan({cls:"stashpad-task-assignee"});r&&l.id===r&&d.addClass("is-me"),d.setText(this.initials(l.name)),d.title=r&&l.id===r?`${l.name} (you)`:l.name}}s.oncontextmenu=r=>{r.preventDefault();let A=new ot.Menu;A.addItem(l=>l.setTitle("Open").setIcon("arrow-right").onClick(()=>{this.openTaskFromPanel(e.folder,e.id)})),A.showAtMouseEvent(r)}}formatDueShort(t,e){return e?po(t,this.plugin.settings):go(t,this.plugin.settings)}async openTaskFromPanel(t,e){await this.plugin.revealNoteByRef(t,e)}async toggleTaskCompleted(t){try{await this.app.fileManager.processFrontMatter(t.file,e=>{e.completed=e.completed!==!0})}catch(e){new ot.Notice(`Couldn't update task: ${e.message}`);return}this.scheduleRender()}initials(t){let e=t.trim().split(/\s+/).filter(Boolean);return e.length===0?"?":e.length===1?e[0].slice(0,2).toUpperCase():(e[0][0]+e[e.length-1][0]).toUpperCase()}collectTasks(){let t=this.plugin.discoverStashpadFolders(),e=new Set(t),i=[];for(let s of this.app.vault.getMarkdownFiles()){let n=s.parent?.path?.replace(/\/+$/,"")??"";if(!e.has(n))continue;let o=this.app.metadataCache.getFileCache(s)?.frontmatter??{},r=typeof o.id=="string"?o.id:null;if(!r||r===F)continue;let A=o.completed===!0,l=be(o,"task")||o.task===!0||o.completed!==void 0,d=typeof o.due=="string"||typeof o.due=="number"?String(o.due):null,g=null;if(d){let p=Date.parse(d);Number.isNaN(p)||(g=p)}!l&&!A&&g==null&&!d||i.push({file:s,folder:n,id:r,title:this.titleFromFile(s),task:l,completed:A,due:g,dueRaw:d,color:typeof o.color=="string"?o.color:null,assignedTo:me(o),assignedBy:ne(o.assignedBy)})}return i}};async function Ji(c){let a=c.workspace.getLeavesOfType(ie);if(a.length>0){c.workspace.revealLeaf(a[0]);return}let t=c.workspace.getLeftLeaf(!1);if(!t){new ot.Notice("Stashpad: couldn't open the panels view.");return}await t.setViewState({type:ie,active:!0}),c.workspace.revealLeaf(t)}var Na=require("obsidian");rt();var x=require("obsidian");ui();var zi=require("obsidian");rt();var Pe=class extends zi.AbstractInputSuggest{constructor(t,e){super(t,e);this.inputEl=e}getSuggestions(t){let e=t.toLowerCase().split(/\s+/).filter(Boolean),i=o=>e.every(r=>o.toLowerCase().includes(r)),s=[],n=o=>{if(!(o.path!=="/"&&Ze.has(o.name))){o.path!=="/"&&i(o.path)&&s.push(o);for(let r of o.children)r instanceof zi.TFolder&&n(r)}};return n(this.app.vault.getRoot()),s.slice(0,100)}renderSuggestion(t,e){e.setText(t.path)}selectSuggestion(t){this.setValue(t.path),this.inputEl.dispatchEvent(new Event("input",{bubbles:!0})),this.close()}};rt();vt();var Fe=require("obsidian"),An={create:{label:"Create",desc:"Confirmations after a new note is created."},edit:{label:"Edit",desc:"Edit-related toasts (currently rare)."},delete:{label:"Delete",desc:"Confirmations after deleting one or more notes."},move:{label:"Move",desc:"After reparenting or moving notes between folders."},merge:{label:"Merge",desc:"After combining multiple notes into one."},split:{label:"Split",desc:"After splitting a note in two."},clone:{label:"Clone",desc:"After duplicating notes or subtrees."},complete:{label:"Complete",desc:"When a note is marked complete."},uncomplete:{label:"Uncomplete",desc:"When a note's complete mark is removed."},export:{label:"Export",desc:".stash exports \u2014 success + the action buttons."},import:{label:"Import",desc:".stash imports (both manual and the drop-folder auto-import)."},attachment:{label:"Attachment",desc:"Attachment add / remove notifications."},color:{label:"Color",desc:"Per-note color changes."},reorder:{label:"Reorder",desc:"Drag-reorder and keyboard moveUp/Down/Top/Bottom."},multiplayer:{label:"Multiplayer",desc:"Cross-author activity (someone else touched your notes or vice versa)."},reminder:{label:"Reminder",desc:"Task due-date reminders \u2014 surfaced when a task comes due (fired at launch / periodically)."},system:{label:"System",desc:"Plumbing toasts: backfill progress, integrity warnings, errors not tied to a verb."}},fr={info:4e3,success:4e3,warning:6e3,error:1e4},Do=5e3,$i=class{constructor(a){this.app=a;this.history=[];this.nextId=1;this.historyLimit=Do;this.changeListeners=new Set;this.muted=new Set;this.defaultAuthorId=null}setDefaultAuthorId(a){this.defaultAuthorId=a||null}show(a){let t=a.kind??"info",e=a.category??"system",i={id:this.nextId++,ts:Date.now(),message:a.message,kind:t,category:e,authorId:a.authorId??this.defaultAuthorId??void 0,affectedIds:a.affectedIds?a.affectedIds.slice():[],affectedPaths:a.affectedPaths?a.affectedPaths.slice():[],affectedAuthorIds:a.affectedAuthorIds?a.affectedAuthorIds.slice():[],folder:a.folder,actionLabels:(a.actions??[]).map(o=>o.label)};if(this.pushHistory(i),this.muted.has(e))return null;let s=this.buildContent(a,t),n=a.duration??fr[t];return new Fe.Notice(s,n)}onChange(a){return this.changeListeners.add(a),()=>this.changeListeners.delete(a)}recent(){return this.history.slice().reverse()}clearHistory(){this.history=[],this.emit()}setMuted(a,t){t?this.muted.add(a):this.muted.delete(a)}isMuted(a){return this.muted.has(a)}loadMutedFromList(a){this.muted=new Set(a)}mutedList(){return Array.from(this.muted)}loadHistory(a){let t=this.applyLimit(a.slice());this.history=t;let e=0;for(let i of t)i.id>e&&(e=i.id);this.nextId=Math.max(this.nextId,e+1),this.emit()}setHistoryLimit(a){this.historyLimit=Number.isFinite(a)?a:Do,this.history=this.applyLimit(this.history),this.emit()}applyLimit(a){return this.historyLimit<=0||a.length<=this.historyLimit?a:a.slice(a.length-this.historyLimit)}pushHistory(a){this.history.push(a),this.history=this.applyLimit(this.history),this.emit()}emit(){for(let a of this.changeListeners)try{a()}catch(t){console.warn("[Stashpad] notification listener failed",t)}}buildContent(a,t){let e=document.createDocumentFragment(),i=document.createElement("div");i.className=`stashpad-notice stashpad-notice-${t}`;let s=document.createElement("div");s.className="stashpad-notice-message";let n=a.message.split(/(`[^`\n]+`)/);for(let o of n)if(o.length>1&&o.startsWith("`")&&o.endsWith("`")){let r=document.createElement("code");r.textContent=o.slice(1,-1),s.appendChild(r)}else o.length>0&&s.appendChild(document.createTextNode(o));if(i.appendChild(s),a.actions&&a.actions.length>0){let o=document.createElement("div");o.className="stashpad-notice-actions";for(let r of a.actions){let A=document.createElement("button");A.className="stashpad-notice-action",A.textContent=r.label,A.addEventListener("click",l=>{if(l.stopPropagation(),Promise.resolve().then(()=>r.onClick()).catch(d=>console.warn("[Stashpad] notification action failed",d)),!r.keepOpen){let d=A.closest(".notice");d&&d.parentElement&&d.parentElement.removeChild(d)}}),o.appendChild(A)}i.appendChild(o)}return e.appendChild(i),e}};function Vi(c,a,t){let e=c.vault.getAbstractFileByPath(a);if(!(e instanceof Fe.TFile))return[];let i=[{label:"Reveal",keepOpen:!0,onClick:()=>{let s=c.workspace.getLeavesOfType("file-explorer")[0];if(!s)return;c.workspace.revealLeaf(s),s.view?.revealInFolder?.(e)}}];if(!t){let s=Fe.Platform.isMacOS?"Finder":Fe.Platform.isWin?"File Explorer":"file manager";i.push({label:`Show in ${s}`,keepOpen:!0,onClick:()=>{try{let n=window.require?.("electron")?.shell,r=c.vault.adapter?.getFullPath?.(a);r&&n?.showItemInFolder&&n.showItemInFolder(r)}catch(n){console.warn("[Stashpad] showItemInFolder failed",n)}}})}return i}var bo=require("obsidian"),ln=bo.Platform.isMacOS;function fi(c){if(!c)return"(none)";let a=c.replace(/\bMod\b/g,ln?"Cmd":"Ctrl");return ln&&(a=a.replace(/\bAlt\b/g,"Option")),a}function No(c,a,t={allowSingleKey:!0}){let e=c.placeholder,i=c.value;c.placeholder="Press a key\u2026 (Backspace to cancel)",c.value="",c.classList.add("is-recording");let s=!1,n=()=>{c.placeholder=e,c.classList.remove("is-recording"),s||(c.value=i),c.removeEventListener("keydown",o,!0),c.removeEventListener("blur",r)},o=A=>{if(A.key==="Control"||A.key==="Shift"||A.key==="Alt"||A.key==="Meta"||A.key==="OS")return;let l=!!A.code&&(/^Key[A-Z]$/.test(A.code)||/^Digit\d$/.test(A.code));if((A.key==="Dead"||A.key==="Process"||A.key==="Unidentified")&&!l)return;if(A.preventDefault(),A.stopPropagation(),A.key==="Backspace"&&!A.metaKey&&!A.ctrlKey&&!A.altKey&&!A.shiftKey){n();return}let d=[];ln?(A.metaKey&&d.push("Mod"),A.ctrlKey&&d.push("Ctrl")):A.ctrlKey&&d.push("Mod"),A.altKey&&d.push("Alt"),A.shiftKey&&d.push("Shift");let g=Cr(A.key,A.code);if(!g||d.length===0&&!t.allowSingleKey)return;d.push(g);let p=d.join("+");s=!0,n(),a(p)},r=()=>n();return c.addEventListener("keydown",o,!0),c.addEventListener("blur",r),n}function Cr(c,a){if(!c)return"";if(a){let t=/^Key([A-Z])$/.exec(a);if(t)return t[1];let e=/^Digit(\d)$/.exec(a);if(e)return e[1]}return c.length===1?c.toUpperCase():c}Te();xt();function ke(c,a,t,e){function i(s){return s instanceof t?s:new t(function(n){n(s)})}return new(t||(t=Promise))(function(s,n){function o(l){try{A(e.next(l))}catch(d){n(d)}}function r(l){try{A(e.throw(l))}catch(d){n(d)}}function A(l){l.done?s(l.value):i(l.value).then(o,r)}A((e=e.apply(c,a||[])).next())})}var nt=class{constructor(){this.mutex=Promise.resolve()}lock(){let a=()=>{};return this.mutex=this.mutex.then(()=>new Promise(a)),new Promise(t=>{a=t})}dispatch(a){return ke(this,void 0,void 0,function*(){let t=yield this.lock();try{return yield Promise.resolve(a())}finally{t()}})}},cn;function Br(){return typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:global}var pn=Br(),dn=(cn=pn.Buffer)!==null&&cn!==void 0?cn:null,mr=pn.TextEncoder?new pn.TextEncoder:null;function Uo(c,a){return(c&15)+(c>>6|c>>3&8)<<4|(a&15)+(a>>6|a>>3&8)}function Go(c,a){let t=a.length>>1;for(let e=0;e<t;e++){let i=e<<1;c[e]=Uo(a.charCodeAt(i),a.charCodeAt(i+1))}}function Qr(c,a){if(c.length!==a.length*2)return!1;for(let t=0;t<a.length;t++){let e=t<<1;if(a[t]!==Uo(c.charCodeAt(e),c.charCodeAt(e+1)))return!1}return!0}var xo=87,Mo=48;function In(c,a,t){let e=0;for(let i=0;i<t;i++){let s=a[i]>>>4;c[e++]=s>9?s+xo:s+Mo,s=a[i]&15,c[e++]=s>9?s+xo:s+Mo}return String.fromCharCode.apply(null,c)}var $t=dn!==null?c=>{if(typeof c=="string"){let a=dn.from(c,"utf8");return new Uint8Array(a.buffer,a.byteOffset,a.length)}if(dn.isBuffer(c))return new Uint8Array(c.buffer,c.byteOffset,c.length);if(ArrayBuffer.isView(c))return new Uint8Array(c.buffer,c.byteOffset,c.byteLength);throw new Error("Invalid data type!")}:c=>{if(typeof c=="string")return mr.encode(c);if(ArrayBuffer.isView(c))return new Uint8Array(c.buffer,c.byteOffset,c.byteLength);throw new Error("Invalid data type!")},Mt="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",Bi=new Uint8Array(256);for(let c=0;c<Mt.length;c++)Bi[Mt.charCodeAt(c)]=c;function To(c,a=!0){let t=c.length,e=t%3,i=[],s=t-e;for(let n=0;n<s;n+=3){let o=(c[n]<<16&16711680)+(c[n+1]<<8&65280)+(c[n+2]&255),r=Mt.charAt(o>>18&63)+Mt.charAt(o>>12&63)+Mt.charAt(o>>6&63)+Mt.charAt(o&63);i.push(r)}if(e===1){let n=c[t-1],o=Mt.charAt(n>>2),r=Mt.charAt(n<<4&63);i.push(`${o}${r}`),a&&i.push("==")}else if(e===2){let n=(c[t-2]<<8)+c[t-1],o=Mt.charAt(n>>10),r=Mt.charAt(n>>4&63),A=Mt.charAt(n<<2&63);i.push(`${o}${r}${A}`),a&&i.push("=")}return i.join("")}function yr(c){let a=Math.floor(c.length*.75),t=c.length;return c[t-1]==="="&&(a-=1,c[t-2]==="="&&(a-=1)),a}function Er(c){let a=yr(c),t=c.length,e=new Uint8Array(a),i=0;for(let s=0;s<t;s+=4){let n=Bi[c.charCodeAt(s)],o=Bi[c.charCodeAt(s+1)],r=Bi[c.charCodeAt(s+2)],A=Bi[c.charCodeAt(s+3)];e[i]=n<<2|o>>4,i+=1,e[i]=(o&15)<<4|r>>2,i+=1,e[i]=(r&3)<<6|A&63,i+=1}return e}var Wi=16*1024,Ci=4,wr=new nt,hn=new Map;function Ro(c,a){return ke(this,void 0,void 0,function*(){let t=null,e=null,i=!1;if(typeof WebAssembly>"u")throw new Error("WebAssembly is not supported in this environment!");let s=(Q,E=0)=>{e.set(Q,E)},n=()=>e,o=()=>t.exports,r=Q=>{t.exports.Hash_SetMemorySize(Q);let E=t.exports.Hash_GetBuffer(),v=t.exports.memory.buffer;e=new Uint8Array(v,E,Q)},A=()=>new DataView(t.exports.memory.buffer).getUint32(t.exports.STATE_SIZE,!0),l=wr.dispatch(()=>ke(this,void 0,void 0,function*(){if(!hn.has(c.name)){let E=Er(c.data),v=WebAssembly.compile(E);hn.set(c.name,v)}let Q=yield hn.get(c.name);t=yield WebAssembly.instantiate(Q,{})})),d=()=>ke(this,void 0,void 0,function*(){t||(yield l);let Q=t.exports.Hash_GetBuffer(),E=t.exports.memory.buffer;e=new Uint8Array(E,Q,Wi)}),g=(Q=null)=>{i=!0,t.exports.Hash_Init(Q)},p=Q=>{let E=0;for(;E<Q.length;){let v=Q.subarray(E,E+Wi);E+=v.length,e.set(v),t.exports.Hash_Update(v.length)}},h=Q=>{if(!i)throw new Error("update() called before init()");let E=$t(Q);p(E)},I=new Uint8Array(a*2),u=(Q,E=null)=>{if(!i)throw new Error("digest() called before init()");return i=!1,t.exports.Hash_Final(E),Q==="binary"?e.slice(0,a):In(I,e,a)},f=()=>{if(!i)throw new Error("save() can only be called after init() and before digest()");let Q=t.exports.Hash_GetState(),E=A(),v=t.exports.memory.buffer,y=new Uint8Array(v,Q,E),b=new Uint8Array(Ci+E);return Go(b,c.hash),b.set(y,Ci),b},C=Q=>{if(!(Q instanceof Uint8Array))throw new Error("load() expects an Uint8Array generated by save()");let E=t.exports.Hash_GetState(),v=A(),y=Ci+v,b=t.exports.memory.buffer;if(Q.length!==y)throw new Error(`Bad state length (expected ${y} bytes, got ${Q.length})`);if(!Qr(c.hash,Q.subarray(0,Ci)))throw new Error("This state was written by an incompatible hash implementation");let N=Q.subarray(Ci);new Uint8Array(b,E,v).set(N),i=!0},B=Q=>typeof Q=="string"?Q.length<Wi/4:Q.byteLength<Wi,m=B;switch(c.name){case"argon2":case"scrypt":m=()=>!0;break;case"blake2b":case"blake2s":m=(Q,E)=>E<=512&&B(Q);break;case"blake3":m=(Q,E)=>E===0&&B(Q);break;case"xxhash64":case"xxhash3":case"xxhash128":case"crc64":m=()=>!1;break}let w=(Q,E=null,v=null)=>{if(!m(Q,E))return g(E),h(Q),u("hex",v);let y=$t(Q);return e.set(y),t.exports.Hash_Calculate(y.length,E,v),In(I,e,a)};return yield d(),{getMemory:n,writeMemory:s,getExports:o,setMemorySize:r,init:g,update:h,digest:u,save:f,load:C,calculate:w,hashLength:a}})}var Fl=new nt;var vr="argon2",Fr="AGFzbQEAAAABKQVgAX8Bf2AAAX9gEH9/f39/f39/f39/f39/f38AYAR/f39/AGACf38AAwYFAAECAwQFBgEBAoCAAgYIAX8BQZCoBAsHQQQGbWVtb3J5AgASSGFzaF9TZXRNZW1vcnlTaXplAAAOSGFzaF9HZXRCdWZmZXIAAQ5IYXNoX0NhbGN1bGF0ZQAECvEyBVgBAn9BACEBAkAgAEEAKAKICCICRg0AAkAgACACayIAQRB2IABBgIB8cSAASWoiAEAAQX9HDQBB/wHADwtBACEBQQBBACkDiAggAEEQdK18NwOICAsgAcALcAECfwJAQQAoAoAIIgANAEEAPwBBEHQiADYCgAhBACgCiAgiAUGAgCBGDQACQEGAgCAgAWsiAEEQdiAAQYCAfHEgAElqIgBAAEF/Rw0AQQAPC0EAQQApA4gIIABBEHStfDcDiAhBACgCgAghAAsgAAvcDgECfiAAIAQpAwAiECAAKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAMIBAgDCkDAIVCIIkiEDcDACAIIBAgCCkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgBCAQIAQpAwCFQiiJIhA3AwAgACAQIAApAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIAwgECAMKQMAhUIwiSIQNwMAIAggECAIKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAEIBAgBCkDAIVCAYk3AwAgASAFKQMAIhAgASkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgDSAQIA0pAwCFQiCJIhA3AwAgCSAQIAkpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAUgECAFKQMAhUIoiSIQNwMAIAEgECABKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACANIBAgDSkDAIVCMIkiEDcDACAJIBAgCSkDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgBSAQIAUpAwCFQgGJNwMAIAIgBikDACIQIAIpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIA4gECAOKQMAhUIgiSIQNwMAIAogECAKKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAGIBAgBikDAIVCKIkiEDcDACACIBAgAikDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgDiAQIA4pAwCFQjCJIhA3AwAgCiAQIAopAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIAYgECAGKQMAhUIBiTcDACADIAcpAwAiECADKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAPIBAgDykDAIVCIIkiEDcDACALIBAgCykDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgByAQIAcpAwCFQiiJIhA3AwAgAyAQIAMpAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIA8gECAPKQMAhUIwiSIQNwMAIAsgECALKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAHIBAgBykDAIVCAYk3AwAgACAFKQMAIhAgACkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgDyAQIA8pAwCFQiCJIhA3AwAgCiAQIAopAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAUgECAFKQMAhUIoiSIQNwMAIAAgECAAKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAPIBAgDykDAIVCMIkiEDcDACAKIBAgCikDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgBSAQIAUpAwCFQgGJNwMAIAEgBikDACIQIAEpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAwgECAMKQMAhUIgiSIQNwMAIAsgECALKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAGIBAgBikDAIVCKIkiEDcDACABIBAgASkDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgDCAQIAwpAwCFQjCJIhA3AwAgCyAQIAspAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIAYgECAGKQMAhUIBiTcDACACIAcpAwAiECACKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACANIBAgDSkDAIVCIIkiEDcDACAIIBAgCCkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgByAQIAcpAwCFQiiJIhA3AwAgAiAQIAIpAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIA0gECANKQMAhUIwiSIQNwMAIAggECAIKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAHIBAgBykDAIVCAYk3AwAgAyAEKQMAIhAgAykDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgDiAQIA4pAwCFQiCJIhA3AwAgCSAQIAkpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAQgECAEKQMAhUIoiSIQNwMAIAMgECADKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAOIBAgDikDAIVCMIkiEDcDACAJIBAgCSkDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgBCAQIAQpAwCFQgGJNwMAC98aAQN/QQAhBEEAIAIpAwAgASkDAIU3A5AIQQAgAikDCCABKQMIhTcDmAhBACACKQMQIAEpAxCFNwOgCEEAIAIpAxggASkDGIU3A6gIQQAgAikDICABKQMghTcDsAhBACACKQMoIAEpAyiFNwO4CEEAIAIpAzAgASkDMIU3A8AIQQAgAikDOCABKQM4hTcDyAhBACACKQNAIAEpA0CFNwPQCEEAIAIpA0ggASkDSIU3A9gIQQAgAikDUCABKQNQhTcD4AhBACACKQNYIAEpA1iFNwPoCEEAIAIpA2AgASkDYIU3A/AIQQAgAikDaCABKQNohTcD+AhBACACKQNwIAEpA3CFNwOACUEAIAIpA3ggASkDeIU3A4gJQQAgAikDgAEgASkDgAGFNwOQCUEAIAIpA4gBIAEpA4gBhTcDmAlBACACKQOQASABKQOQAYU3A6AJQQAgAikDmAEgASkDmAGFNwOoCUEAIAIpA6ABIAEpA6ABhTcDsAlBACACKQOoASABKQOoAYU3A7gJQQAgAikDsAEgASkDsAGFNwPACUEAIAIpA7gBIAEpA7gBhTcDyAlBACACKQPAASABKQPAAYU3A9AJQQAgAikDyAEgASkDyAGFNwPYCUEAIAIpA9ABIAEpA9ABhTcD4AlBACACKQPYASABKQPYAYU3A+gJQQAgAikD4AEgASkD4AGFNwPwCUEAIAIpA+gBIAEpA+gBhTcD+AlBACACKQPwASABKQPwAYU3A4AKQQAgAikD+AEgASkD+AGFNwOICkEAIAIpA4ACIAEpA4AChTcDkApBACACKQOIAiABKQOIAoU3A5gKQQAgAikDkAIgASkDkAKFNwOgCkEAIAIpA5gCIAEpA5gChTcDqApBACACKQOgAiABKQOgAoU3A7AKQQAgAikDqAIgASkDqAKFNwO4CkEAIAIpA7ACIAEpA7AChTcDwApBACACKQO4AiABKQO4AoU3A8gKQQAgAikDwAIgASkDwAKFNwPQCkEAIAIpA8gCIAEpA8gChTcD2ApBACACKQPQAiABKQPQAoU3A+AKQQAgAikD2AIgASkD2AKFNwPoCkEAIAIpA+ACIAEpA+AChTcD8ApBACACKQPoAiABKQPoAoU3A/gKQQAgAikD8AIgASkD8AKFNwOAC0EAIAIpA/gCIAEpA/gChTcDiAtBACACKQOAAyABKQOAA4U3A5ALQQAgAikDiAMgASkDiAOFNwOYC0EAIAIpA5ADIAEpA5ADhTcDoAtBACACKQOYAyABKQOYA4U3A6gLQQAgAikDoAMgASkDoAOFNwOwC0EAIAIpA6gDIAEpA6gDhTcDuAtBACACKQOwAyABKQOwA4U3A8ALQQAgAikDuAMgASkDuAOFNwPIC0EAIAIpA8ADIAEpA8ADhTcD0AtBACACKQPIAyABKQPIA4U3A9gLQQAgAikD0AMgASkD0AOFNwPgC0EAIAIpA9gDIAEpA9gDhTcD6AtBACACKQPgAyABKQPgA4U3A/ALQQAgAikD6AMgASkD6AOFNwP4C0EAIAIpA/ADIAEpA/ADhTcDgAxBACACKQP4AyABKQP4A4U3A4gMQQAgAikDgAQgASkDgASFNwOQDEEAIAIpA4gEIAEpA4gEhTcDmAxBACACKQOQBCABKQOQBIU3A6AMQQAgAikDmAQgASkDmASFNwOoDEEAIAIpA6AEIAEpA6AEhTcDsAxBACACKQOoBCABKQOoBIU3A7gMQQAgAikDsAQgASkDsASFNwPADEEAIAIpA7gEIAEpA7gEhTcDyAxBACACKQPABCABKQPABIU3A9AMQQAgAikDyAQgASkDyASFNwPYDEEAIAIpA9AEIAEpA9AEhTcD4AxBACACKQPYBCABKQPYBIU3A+gMQQAgAikD4AQgASkD4ASFNwPwDEEAIAIpA+gEIAEpA+gEhTcD+AxBACACKQPwBCABKQPwBIU3A4ANQQAgAikD+AQgASkD+ASFNwOIDUEAIAIpA4AFIAEpA4AFhTcDkA1BACACKQOIBSABKQOIBYU3A5gNQQAgAikDkAUgASkDkAWFNwOgDUEAIAIpA5gFIAEpA5gFhTcDqA1BACACKQOgBSABKQOgBYU3A7ANQQAgAikDqAUgASkDqAWFNwO4DUEAIAIpA7AFIAEpA7AFhTcDwA1BACACKQO4BSABKQO4BYU3A8gNQQAgAikDwAUgASkDwAWFNwPQDUEAIAIpA8gFIAEpA8gFhTcD2A1BACACKQPQBSABKQPQBYU3A+ANQQAgAikD2AUgASkD2AWFNwPoDUEAIAIpA+AFIAEpA+AFhTcD8A1BACACKQPoBSABKQPoBYU3A/gNQQAgAikD8AUgASkD8AWFNwOADkEAIAIpA/gFIAEpA/gFhTcDiA5BACACKQOABiABKQOABoU3A5AOQQAgAikDiAYgASkDiAaFNwOYDkEAIAIpA5AGIAEpA5AGhTcDoA5BACACKQOYBiABKQOYBoU3A6gOQQAgAikDoAYgASkDoAaFNwOwDkEAIAIpA6gGIAEpA6gGhTcDuA5BACACKQOwBiABKQOwBoU3A8AOQQAgAikDuAYgASkDuAaFNwPIDkEAIAIpA8AGIAEpA8AGhTcD0A5BACACKQPIBiABKQPIBoU3A9gOQQAgAikD0AYgASkD0AaFNwPgDkEAIAIpA9gGIAEpA9gGhTcD6A5BACACKQPgBiABKQPgBoU3A/AOQQAgAikD6AYgASkD6AaFNwP4DkEAIAIpA/AGIAEpA/AGhTcDgA9BACACKQP4BiABKQP4BoU3A4gPQQAgAikDgAcgASkDgAeFNwOQD0EAIAIpA4gHIAEpA4gHhTcDmA9BACACKQOQByABKQOQB4U3A6APQQAgAikDmAcgASkDmAeFNwOoD0EAIAIpA6AHIAEpA6AHhTcDsA9BACACKQOoByABKQOoB4U3A7gPQQAgAikDsAcgASkDsAeFNwPAD0EAIAIpA7gHIAEpA7gHhTcDyA9BACACKQPAByABKQPAB4U3A9APQQAgAikDyAcgASkDyAeFNwPYD0EAIAIpA9AHIAEpA9AHhTcD4A9BACACKQPYByABKQPYB4U3A+gPQQAgAikD4AcgASkD4AeFNwPwD0EAIAIpA+gHIAEpA+gHhTcD+A9BACACKQPwByABKQPwB4U3A4AQQQAgAikD+AcgASkD+AeFNwOIEEGQCEGYCEGgCEGoCEGwCEG4CEHACEHICEHQCEHYCEHgCEHoCEHwCEH4CEGACUGICRACQZAJQZgJQaAJQagJQbAJQbgJQcAJQcgJQdAJQdgJQeAJQegJQfAJQfgJQYAKQYgKEAJBkApBmApBoApBqApBsApBuApBwApByApB0ApB2ApB4ApB6ApB8ApB+ApBgAtBiAsQAkGQC0GYC0GgC0GoC0GwC0G4C0HAC0HIC0HQC0HYC0HgC0HoC0HwC0H4C0GADEGIDBACQZAMQZgMQaAMQagMQbAMQbgMQcAMQcgMQdAMQdgMQeAMQegMQfAMQfgMQYANQYgNEAJBkA1BmA1BoA1BqA1BsA1BuA1BwA1ByA1B0A1B2A1B4A1B6A1B8A1B+A1BgA5BiA4QAkGQDkGYDkGgDkGoDkGwDkG4DkHADkHIDkHQDkHYDkHgDkHoDkHwDkH4DkGAD0GIDxACQZAPQZgPQaAPQagPQbAPQbgPQcAPQcgPQdAPQdgPQeAPQegPQfAPQfgPQYAQQYgQEAJBkAhBmAhBkAlBmAlBkApBmApBkAtBmAtBkAxBmAxBkA1BmA1BkA5BmA5BkA9BmA8QAkGgCEGoCEGgCUGoCUGgCkGoCkGgC0GoC0GgDEGoDEGgDUGoDUGgDkGoDkGgD0GoDxACQbAIQbgIQbAJQbgJQbAKQbgKQbALQbgLQbAMQbgMQbANQbgNQbAOQbgOQbAPQbgPEAJBwAhByAhBwAlByAlBwApByApBwAtByAtBwAxByAxBwA1ByA1BwA5ByA5BwA9ByA8QAkHQCEHYCEHQCUHYCUHQCkHYCkHQC0HYC0HQDEHYDEHQDUHYDUHQDkHYDkHQD0HYDxACQeAIQegIQeAJQegJQeAKQegKQeALQegLQeAMQegMQeANQegNQeAOQegOQeAPQegPEAJB8AhB+AhB8AlB+AlB8ApB+ApB8AtB+AtB8AxB+AxB8A1B+A1B8A5B+A5B8A9B+A8QAkGACUGICUGACkGICkGAC0GIC0GADEGIDEGADUGIDUGADkGIDkGAD0GID0GAEEGIEBACAkACQCADRQ0AA0AgACAEaiIDIAIgBGoiBSkDACABIARqIgYpAwCFIARBkAhqKQMAhSADKQMAhTcDACADQQhqIgMgBUEIaikDACAGQQhqKQMAhSAEQZgIaikDAIUgAykDAIU3AwAgBEEQaiIEQYAIRw0ADAILC0EAIQQDQCAAIARqIgMgAiAEaiIFKQMAIAEgBGoiBikDAIUgBEGQCGopAwCFNwMAIANBCGogBUEIaikDACAGQQhqKQMAhSAEQZgIaikDAIU3AwAgBEEQaiIEQYAIRw0ACwsL5QcMBX8BfgR/An4BfwF+AX8Bfgd/AX4DfwF+AkBBACgCgAgiAiABQQp0aiIDKAIIIAFHDQAgAygCDCEEIAMoAgAhBUEAIAMoAhQiBq03A7gQQQAgBK0iBzcDsBBBACAFIAEgBUECdG4iCGwiCUECdK03A6gQAkACQAJAAkAgBEUNAEF/IQogBUUNASAIQQNsIQsgCEECdCIErSEMIAWtIQ0gBkF/akECSSEOQgAhDwNAQQAgDzcDkBAgD6chEEIAIRFBACEBA0BBACARNwOgECAPIBGEUCIDIA5xIRIgBkEBRiAPUCITIAZBAkYgEUICVHFxciEUQX8gAUEBakEDcSAIbEF/aiATGyEVIAEgEHIhFiABIAhsIRcgA0EBdCEYQgAhGQNAQQBCADcDwBBBACAZNwOYECAYIQECQCASRQ0AQQBCATcDwBBBkBhBkBBBkCBBABADQZAYQZAYQZAgQQAQA0ECIQELAkAgASAITw0AIAQgGaciGmwgF2ogAWohAwNAIANBACAEIAEbQQAgEVAiGxtqQX9qIRwCQAJAIBQNAEEAKAKACCICIBxBCnQiHGohCgwBCwJAIAFB/wBxIgINAEEAQQApA8AQQgF8NwPAEEGQGEGQEEGQIEEAEANBkBhBkBhBkCBBABADCyAcQQp0IRwgAkEDdEGQGGohCkEAKAKACCECCyACIANBCnRqIAIgHGogAiAKKQMAIh1CIIinIAVwIBogFhsiHCAEbCABIAFBACAZIBytUSIcGyIKIBsbIBdqIAogC2ogExsgAUUgHHJrIhsgFWqtIB1C/////w+DIh0gHX5CIIggG61+QiCIfSAMgqdqQQp0akEBEAMgA0EBaiEDIAggAUEBaiIBRw0ACwsgGUIBfCIZIA1SDQALIBFCAXwiEachASARQgRSDQALIA9CAXwiDyAHUg0AC0EAKAKACCECCyAJQQx0QYB4aiEXIAVBf2oiCkUNAgwBC0EAQgM3A6AQQQAgBEF/aq03A5AQQYB4IRcLIAIgF2ohGyAIQQx0IQhBACEcA0AgCCAcQQFqIhxsQYB4aiEEQQAhAQNAIBsgAWoiAyADKQMAIAIgBCABamopAwCFNwMAIANBCGoiAyADKQMAIAIgBCABQQhyamopAwCFNwMAIAFBCGohAyABQRBqIQEgA0H4B0kNAAsgHCAKRw0ACwsgAiAXaiEbQXghAQNAIAIgAWoiA0EIaiAbIAFqIgRBCGopAwA3AwAgA0EQaiAEQRBqKQMANwMAIANBGGogBEEYaikDADcDACADQSBqIARBIGopAwA3AwAgAUEgaiIBQfgHSQ0ACwsL",kr="e4cdc523",Sr={name:vr,data:Fr,hash:kr},Dr="blake2b",br="AGFzbQEAAAABEQRgAAF/YAJ/fwBgAX8AYAAAAwoJAAECAwECAgABBQQBAQICBg4CfwFBsIsFC38AQYAICwdwCAZtZW1vcnkCAA5IYXNoX0dldEJ1ZmZlcgAACkhhc2hfRmluYWwAAwlIYXNoX0luaXQABQtIYXNoX1VwZGF0ZQAGDUhhc2hfR2V0U3RhdGUABw5IYXNoX0NhbGN1bGF0ZQAIClNUQVRFX1NJWkUDAQrTOAkFAEGACQvrAgIFfwF+AkAgAUEBSA0AAkACQAJAIAFBgAFBACgC4IoBIgJrIgNKDQAgASEEDAELQQBBADYC4IoBAkAgAkH/AEoNACACQeCJAWohBSAAIQRBACEGA0AgBSAELQAAOgAAIARBAWohBCAFQQFqIQUgAyAGQQFqIgZB/wFxSg0ACwtBAEEAKQPAiQEiB0KAAXw3A8CJAUEAQQApA8iJASAHQv9+Vq18NwPIiQFB4IkBEAIgACADaiEAAkAgASADayIEQYEBSA0AIAIgAWohBQNAQQBBACkDwIkBIgdCgAF8NwPAiQFBAEEAKQPIiQEgB0L/flatfDcDyIkBIAAQAiAAQYABaiEAIAVBgH9qIgVBgAJLDQALIAVBgH9qIQQMAQsgBEEATA0BC0EAIQUDQCAFQQAoAuCKAWpB4IkBaiAAIAVqLQAAOgAAIAQgBUEBaiIFQf8BcUoNAAsLQQBBACgC4IoBIARqNgLgigELC78uASR+QQBBACkD0IkBQQApA7CJASIBQQApA5CJAXwgACkDICICfCIDhULr+obav7X2wR+FQiCJIgRCq/DT9K/uvLc8fCIFIAGFQiiJIgYgA3wgACkDKCIBfCIHIASFQjCJIgggBXwiCSAGhUIBiSIKQQApA8iJAUEAKQOoiQEiBEEAKQOIiQF8IAApAxAiA3wiBYVCn9j52cKR2oKbf4VCIIkiC0K7zqqm2NDrs7t/fCIMIASFQiiJIg0gBXwgACkDGCIEfCIOfCAAKQNQIgV8Ig9BACkDwIkBQQApA6CJASIQQQApA4CJASIRfCAAKQMAIgZ8IhKFQtGFmu/6z5SH0QCFQiCJIhNCiJLznf/M+YTqAHwiFCAQhUIoiSIVIBJ8IAApAwgiEHwiFiAThUIwiSIXhUIgiSIYQQApA9iJAUEAKQO4iQEiE0EAKQOYiQF8IAApAzAiEnwiGYVC+cL4m5Gjs/DbAIVCIIkiGkLx7fT4paf9p6V/fCIbIBOFQiiJIhwgGXwgACkDOCITfCIZIBqFQjCJIhogG3wiG3wiHSAKhUIoiSIeIA98IAApA1giCnwiDyAYhUIwiSIYIB18Ih0gDiALhUIwiSIOIAx8Ih8gDYVCAYkiDCAWfCAAKQNAIgt8Ig0gGoVCIIkiFiAJfCIaIAyFQiiJIiAgDXwgACkDSCIJfCIhIBaFQjCJIhYgGyAchUIBiSIMIAd8IAApA2AiB3wiDSAOhUIgiSIOIBcgFHwiFHwiFyAMhUIoiSIbIA18IAApA2giDHwiHCAOhUIwiSIOIBd8IhcgG4VCAYkiGyAZIBQgFYVCAYkiFHwgACkDcCINfCIVIAiFQiCJIhkgH3wiHyAUhUIoiSIUIBV8IAApA3giCHwiFXwgDHwiIoVCIIkiI3wiJCAbhUIoiSIbICJ8IBJ8IiIgFyAYIBUgGYVCMIkiFSAffCIZIBSFQgGJIhQgIXwgDXwiH4VCIIkiGHwiFyAUhUIoiSIUIB98IAV8Ih8gGIVCMIkiGCAXfCIXIBSFQgGJIhR8IAF8IiEgFiAafCIWIBUgHSAehUIBiSIaIBx8IAl8IhyFQiCJIhV8Ih0gGoVCKIkiGiAcfCAIfCIcIBWFQjCJIhWFQiCJIh4gGSAOIBYgIIVCAYkiFiAPfCACfCIPhUIgiSIOfCIZIBaFQiiJIhYgD3wgC3wiDyAOhUIwiSIOIBl8Ihl8IiAgFIVCKIkiFCAhfCAEfCIhIB6FQjCJIh4gIHwiICAiICOFQjCJIiIgJHwiIyAbhUIBiSIbIBx8IAp8IhwgDoVCIIkiDiAXfCIXIBuFQiiJIhsgHHwgE3wiHCAOhUIwiSIOIBkgFoVCAYkiFiAffCAQfCIZICKFQiCJIh8gFSAdfCIVfCIdIBaFQiiJIhYgGXwgB3wiGSAfhUIwiSIfIB18Ih0gFoVCAYkiFiAVIBqFQgGJIhUgD3wgBnwiDyAYhUIgiSIYICN8IhogFYVCKIkiFSAPfCADfCIPfCAHfCIihUIgiSIjfCIkIBaFQiiJIhYgInwgBnwiIiAjhUIwiSIjICR8IiQgFoVCAYkiFiAOIBd8Ig4gDyAYhUIwiSIPICAgFIVCAYkiFCAZfCAKfCIXhUIgiSIYfCIZIBSFQiiJIhQgF3wgC3wiF3wgBXwiICAPIBp8Ig8gHyAOIBuFQgGJIg4gIXwgCHwiGoVCIIkiG3wiHyAOhUIoiSIOIBp8IAx8IhogG4VCMIkiG4VCIIkiISAdIB4gDyAVhUIBiSIPIBx8IAF8IhWFQiCJIhx8Ih0gD4VCKIkiDyAVfCADfCIVIByFQjCJIhwgHXwiHXwiHiAWhUIoiSIWICB8IA18IiAgIYVCMIkiISAefCIeIBogFyAYhUIwiSIXIBl8IhggFIVCAYkiFHwgCXwiGSAchUIgiSIaICR8IhwgFIVCKIkiFCAZfCACfCIZIBqFQjCJIhogHSAPhUIBiSIPICJ8IAR8Ih0gF4VCIIkiFyAbIB98Iht8Ih8gD4VCKIkiDyAdfCASfCIdIBeFQjCJIhcgH3wiHyAPhUIBiSIPIBsgDoVCAYkiDiAVfCATfCIVICOFQiCJIhsgGHwiGCAOhUIoiSIOIBV8IBB8IhV8IAx8IiKFQiCJIiN8IiQgD4VCKIkiDyAifCAHfCIiICOFQjCJIiMgJHwiJCAPhUIBiSIPIBogHHwiGiAVIBuFQjCJIhUgHiAWhUIBiSIWIB18IAR8IhuFQiCJIhx8Ih0gFoVCKIkiFiAbfCAQfCIbfCABfCIeIBUgGHwiFSAXIBogFIVCAYkiFCAgfCATfCIYhUIgiSIXfCIaIBSFQiiJIhQgGHwgCXwiGCAXhUIwiSIXhUIgiSIgIB8gISAVIA6FQgGJIg4gGXwgCnwiFYVCIIkiGXwiHyAOhUIoiSIOIBV8IA18IhUgGYVCMIkiGSAffCIffCIhIA+FQiiJIg8gHnwgBXwiHiAghUIwiSIgICF8IiEgGyAchUIwiSIbIB18IhwgFoVCAYkiFiAYfCADfCIYIBmFQiCJIhkgJHwiHSAWhUIoiSIWIBh8IBJ8IhggGYVCMIkiGSAfIA6FQgGJIg4gInwgAnwiHyAbhUIgiSIbIBcgGnwiF3wiGiAOhUIoiSIOIB98IAZ8Ih8gG4VCMIkiGyAafCIaIA6FQgGJIg4gFSAXIBSFQgGJIhR8IAh8IhUgI4VCIIkiFyAcfCIcIBSFQiiJIhQgFXwgC3wiFXwgBXwiIoVCIIkiI3wiJCAOhUIoiSIOICJ8IAh8IiIgGiAgIBUgF4VCMIkiFSAcfCIXIBSFQgGJIhQgGHwgCXwiGIVCIIkiHHwiGiAUhUIoiSIUIBh8IAZ8IhggHIVCMIkiHCAafCIaIBSFQgGJIhR8IAR8IiAgGSAdfCIZIBUgISAPhUIBiSIPIB98IAN8Ih2FQiCJIhV8Ih8gD4VCKIkiDyAdfCACfCIdIBWFQjCJIhWFQiCJIiEgFyAbIBkgFoVCAYkiFiAefCABfCIZhUIgiSIbfCIXIBaFQiiJIhYgGXwgE3wiGSAbhUIwiSIbIBd8Ihd8Ih4gFIVCKIkiFCAgfCAMfCIgICGFQjCJIiEgHnwiHiAiICOFQjCJIiIgJHwiIyAOhUIBiSIOIB18IBJ8Ih0gG4VCIIkiGyAafCIaIA6FQiiJIg4gHXwgC3wiHSAbhUIwiSIbIBcgFoVCAYkiFiAYfCANfCIXICKFQiCJIhggFSAffCIVfCIfIBaFQiiJIhYgF3wgEHwiFyAYhUIwiSIYIB98Ih8gFoVCAYkiFiAVIA+FQgGJIg8gGXwgCnwiFSAchUIgiSIZICN8IhwgD4VCKIkiDyAVfCAHfCIVfCASfCIihUIgiSIjfCIkIBaFQiiJIhYgInwgBXwiIiAjhUIwiSIjICR8IiQgFoVCAYkiFiAbIBp8IhogFSAZhUIwiSIVIB4gFIVCAYkiFCAXfCADfCIXhUIgiSIZfCIbIBSFQiiJIhQgF3wgB3wiF3wgAnwiHiAVIBx8IhUgGCAaIA6FQgGJIg4gIHwgC3wiGoVCIIkiGHwiHCAOhUIoiSIOIBp8IAR8IhogGIVCMIkiGIVCIIkiICAfICEgFSAPhUIBiSIPIB18IAZ8IhWFQiCJIh18Ih8gD4VCKIkiDyAVfCAKfCIVIB2FQjCJIh0gH3wiH3wiISAWhUIoiSIWIB58IAx8Ih4gIIVCMIkiICAhfCIhIBogFyAZhUIwiSIXIBt8IhkgFIVCAYkiFHwgEHwiGiAdhUIgiSIbICR8Ih0gFIVCKIkiFCAafCAJfCIaIBuFQjCJIhsgHyAPhUIBiSIPICJ8IBN8Ih8gF4VCIIkiFyAYIBx8Ihh8IhwgD4VCKIkiDyAffCABfCIfIBeFQjCJIhcgHHwiHCAPhUIBiSIPIBggDoVCAYkiDiAVfCAIfCIVICOFQiCJIhggGXwiGSAOhUIoiSIOIBV8IA18IhV8IA18IiKFQiCJIiN8IiQgD4VCKIkiDyAifCAMfCIiICOFQjCJIiMgJHwiJCAPhUIBiSIPIBsgHXwiGyAVIBiFQjCJIhUgISAWhUIBiSIWIB98IBB8IhiFQiCJIh18Ih8gFoVCKIkiFiAYfCAIfCIYfCASfCIhIBUgGXwiFSAXIBsgFIVCAYkiFCAefCAHfCIZhUIgiSIXfCIbIBSFQiiJIhQgGXwgAXwiGSAXhUIwiSIXhUIgiSIeIBwgICAVIA6FQgGJIg4gGnwgAnwiFYVCIIkiGnwiHCAOhUIoiSIOIBV8IAV8IhUgGoVCMIkiGiAcfCIcfCIgIA+FQiiJIg8gIXwgBHwiISAehUIwiSIeICB8IiAgGCAdhUIwiSIYIB98Ih0gFoVCAYkiFiAZfCAGfCIZIBqFQiCJIhogJHwiHyAWhUIoiSIWIBl8IBN8IhkgGoVCMIkiGiAcIA6FQgGJIg4gInwgCXwiHCAYhUIgiSIYIBcgG3wiF3wiGyAOhUIoiSIOIBx8IAN8IhwgGIVCMIkiGCAbfCIbIA6FQgGJIg4gFSAXIBSFQgGJIhR8IAt8IhUgI4VCIIkiFyAdfCIdIBSFQiiJIhQgFXwgCnwiFXwgBHwiIoVCIIkiI3wiJCAOhUIoiSIOICJ8IAl8IiIgGyAeIBUgF4VCMIkiFSAdfCIXIBSFQgGJIhQgGXwgDHwiGYVCIIkiHXwiGyAUhUIoiSIUIBl8IAp8IhkgHYVCMIkiHSAbfCIbIBSFQgGJIhR8IAN8Ih4gGiAffCIaIBUgICAPhUIBiSIPIBx8IAd8IhyFQiCJIhV8Ih8gD4VCKIkiDyAcfCAQfCIcIBWFQjCJIhWFQiCJIiAgFyAYIBogFoVCAYkiFiAhfCATfCIahUIgiSIYfCIXIBaFQiiJIhYgGnwgDXwiGiAYhUIwiSIYIBd8Ihd8IiEgFIVCKIkiFCAefCAFfCIeICCFQjCJIiAgIXwiISAiICOFQjCJIiIgJHwiIyAOhUIBiSIOIBx8IAt8IhwgGIVCIIkiGCAbfCIbIA6FQiiJIg4gHHwgEnwiHCAYhUIwiSIYIBcgFoVCAYkiFiAZfCABfCIXICKFQiCJIhkgFSAffCIVfCIfIBaFQiiJIhYgF3wgBnwiFyAZhUIwiSIZIB98Ih8gFoVCAYkiFiAVIA+FQgGJIg8gGnwgCHwiFSAdhUIgiSIaICN8Ih0gD4VCKIkiDyAVfCACfCIVfCANfCIihUIgiSIjfCIkIBaFQiiJIhYgInwgCXwiIiAjhUIwiSIjICR8IiQgFoVCAYkiFiAYIBt8IhggFSAahUIwiSIVICEgFIVCAYkiFCAXfCASfCIXhUIgiSIafCIbIBSFQiiJIhQgF3wgCHwiF3wgB3wiISAVIB18IhUgGSAYIA6FQgGJIg4gHnwgBnwiGIVCIIkiGXwiHSAOhUIoiSIOIBh8IAt8IhggGYVCMIkiGYVCIIkiHiAfICAgFSAPhUIBiSIPIBx8IAp8IhWFQiCJIhx8Ih8gD4VCKIkiDyAVfCAEfCIVIByFQjCJIhwgH3wiH3wiICAWhUIoiSIWICF8IAN8IiEgHoVCMIkiHiAgfCIgIBggFyAahUIwiSIXIBt8IhogFIVCAYkiFHwgBXwiGCAchUIgiSIbICR8IhwgFIVCKIkiFCAYfCABfCIYIBuFQjCJIhsgHyAPhUIBiSIPICJ8IAx8Ih8gF4VCIIkiFyAZIB18Ihl8Ih0gD4VCKIkiDyAffCATfCIfIBeFQjCJIhcgHXwiHSAPhUIBiSIPIBkgDoVCAYkiDiAVfCAQfCIVICOFQiCJIhkgGnwiGiAOhUIoiSIOIBV8IAJ8IhV8IBN8IiKFQiCJIiN8IiQgD4VCKIkiDyAifCASfCIiICOFQjCJIiMgJHwiJCAPhUIBiSIPIBsgHHwiGyAVIBmFQjCJIhUgICAWhUIBiSIWIB98IAt8IhmFQiCJIhx8Ih8gFoVCKIkiFiAZfCACfCIZfCAJfCIgIBUgGnwiFSAXIBsgFIVCAYkiFCAhfCAFfCIahUIgiSIXfCIbIBSFQiiJIhQgGnwgA3wiGiAXhUIwiSIXhUIgiSIhIB0gHiAVIA6FQgGJIg4gGHwgEHwiFYVCIIkiGHwiHSAOhUIoiSIOIBV8IAF8IhUgGIVCMIkiGCAdfCIdfCIeIA+FQiiJIg8gIHwgDXwiICAhhUIwiSIhIB58Ih4gGSAchUIwiSIZIB98IhwgFoVCAYkiFiAafCAIfCIaIBiFQiCJIhggJHwiHyAWhUIoiSIWIBp8IAp8IhogGIVCMIkiGCAdIA6FQgGJIg4gInwgBHwiHSAZhUIgiSIZIBcgG3wiF3wiGyAOhUIoiSIOIB18IAd8Ih0gGYVCMIkiGSAbfCIbIA6FQgGJIg4gFSAXIBSFQgGJIhR8IAx8IhUgI4VCIIkiFyAcfCIcIBSFQiiJIhQgFXwgBnwiFXwgEnwiIoVCIIkiI3wiJCAOhUIoiSIOICJ8IBN8IiIgGyAhIBUgF4VCMIkiFSAcfCIXIBSFQgGJIhQgGnwgBnwiGoVCIIkiHHwiGyAUhUIoiSIUIBp8IBB8IhogHIVCMIkiHCAbfCIbIBSFQgGJIhR8IA18IiEgGCAffCIYIBUgHiAPhUIBiSIPIB18IAJ8Ih2FQiCJIhV8Ih4gD4VCKIkiDyAdfCABfCIdIBWFQjCJIhWFQiCJIh8gFyAZIBggFoVCAYkiFiAgfCADfCIYhUIgiSIZfCIXIBaFQiiJIhYgGHwgBHwiGCAZhUIwiSIZIBd8Ihd8IiAgFIVCKIkiFCAhfCAIfCIhIB+FQjCJIh8gIHwiICAiICOFQjCJIiIgJHwiIyAOhUIBiSIOIB18IAd8Ih0gGYVCIIkiGSAbfCIbIA6FQiiJIg4gHXwgDHwiHSAZhUIwiSIZIBcgFoVCAYkiFiAafCALfCIXICKFQiCJIhogFSAefCIVfCIeIBaFQiiJIhYgF3wgCXwiFyAahUIwiSIaIB58Ih4gFoVCAYkiFiAVIA+FQgGJIg8gGHwgBXwiFSAchUIgiSIYICN8IhwgD4VCKIkiDyAVfCAKfCIVfCACfCIChUIgiSIifCIjIBaFQiiJIhYgAnwgC3wiAiAihUIwiSILICN8IiIgFoVCAYkiFiAZIBt8IhkgFSAYhUIwiSIVICAgFIVCAYkiFCAXfCANfCINhUIgiSIXfCIYIBSFQiiJIhQgDXwgBXwiBXwgEHwiECAVIBx8Ig0gGiAZIA6FQgGJIg4gIXwgDHwiDIVCIIkiFXwiGSAOhUIoiSIOIAx8IBJ8IhIgFYVCMIkiDIVCIIkiFSAeIB8gDSAPhUIBiSINIB18IAl8IgmFQiCJIg98IhogDYVCKIkiDSAJfCAIfCIJIA+FQjCJIgggGnwiD3wiGiAWhUIoiSIWIBB8IAd8IhAgEYUgDCAZfCIHIA6FQgGJIgwgCXwgCnwiCiALhUIgiSILIAUgF4VCMIkiBSAYfCIJfCIOIAyFQiiJIgwgCnwgE3wiEyALhUIwiSIKIA58IguFNwOAiQFBACADIAYgDyANhUIBiSINIAJ8fCICIAWFQiCJIgUgB3wiBiANhUIoiSIHIAJ8fCICQQApA4iJAYUgBCABIBIgCSAUhUIBiSIDfHwiASAIhUIgiSISICJ8IgkgA4VCKIkiAyABfHwiASAShUIwiSIEIAl8IhKFNwOIiQFBACATQQApA5CJAYUgECAVhUIwiSIQIBp8IhOFNwOQiQFBACABQQApA5iJAYUgAiAFhUIwiSICIAZ8IgGFNwOYiQFBACASIAOFQgGJQQApA6CJAYUgAoU3A6CJAUEAIBMgFoVCAYlBACkDqIkBhSAKhTcDqIkBQQAgASAHhUIBiUEAKQOwiQGFIASFNwOwiQFBACALIAyFQgGJQQApA7iJAYUgEIU3A7iJAQvdAgUBfwF+AX8BfgJ/IwBBwABrIgAkAAJAQQApA9CJAUIAUg0AQQBBACkDwIkBIgFBACgC4IoBIgKsfCIDNwPAiQFBAEEAKQPIiQEgAyABVK18NwPIiQECQEEALQDoigFFDQBBAEJ/NwPYiQELQQBCfzcD0IkBAkAgAkH/AEoNAEEAIQQDQCACIARqQeCJAWpBADoAACAEQQFqIgRBgAFBACgC4IoBIgJrSA0ACwtB4IkBEAIgAEEAKQOAiQE3AwAgAEEAKQOIiQE3AwggAEEAKQOQiQE3AxAgAEEAKQOYiQE3AxggAEEAKQOgiQE3AyAgAEEAKQOoiQE3AyggAEEAKQOwiQE3AzAgAEEAKQO4iQE3AzhBACgC5IoBIgVBAUgNAEEAIQRBACECA0AgBEGACWogACAEai0AADoAACAEQQFqIQQgBSACQQFqIgJB/wFxSg0ACwsgAEHAAGokAAv9AwMBfwF+AX8jAEGAAWsiAiQAQQBBgQI7AfKKAUEAIAE6APGKAUEAIAA6APCKAUGQfiEAA0AgAEGAiwFqQgA3AAAgAEH4igFqQgA3AAAgAEHwigFqQgA3AAAgAEEYaiIADQALQQAhAEEAQQApA/CKASIDQoiS853/zPmE6gCFNwOAiQFBAEEAKQP4igFCu86qptjQ67O7f4U3A4iJAUEAQQApA4CLAUKr8NP0r+68tzyFNwOQiQFBAEEAKQOIiwFC8e30+KWn/aelf4U3A5iJAUEAQQApA5CLAULRhZrv+s+Uh9EAhTcDoIkBQQBBACkDmIsBQp/Y+dnCkdqCm3+FNwOoiQFBAEEAKQOgiwFC6/qG2r+19sEfhTcDsIkBQQBBACkDqIsBQvnC+JuRo7Pw2wCFNwO4iQFBACADp0H/AXE2AuSKAQJAIAFBAUgNACACQgA3A3ggAkIANwNwIAJCADcDaCACQgA3A2AgAkIANwNYIAJCADcDUCACQgA3A0ggAkIANwNAIAJCADcDOCACQgA3AzAgAkIANwMoIAJCADcDICACQgA3AxggAkIANwMQIAJCADcDCCACQgA3AwBBACEEA0AgAiAAaiAAQYAJai0AADoAACAAQQFqIQAgBEEBaiIEQf8BcSABSA0ACyACQYABEAELIAJBgAFqJAALEgAgAEEDdkH/P3EgAEEQdhAECwkAQYAJIAAQAQsGAEGAiQELGwAgAUEDdkH/P3EgAUEQdhAEQYAJIAAQARADCwsLAQBBgAgLBPAAAAA=",Nr="c6f286e6",xr={name:Dr,data:br,hash:Nr},kl=new nt;function Ho(c){return!Number.isInteger(c)||c<8||c>512||c%8!==0?new Error("Invalid variant! Valid values: 8, 16, ..., 512"):null}function Mr(c,a){return c|a<<16}function un(c=512,a=null){if(Ho(c))return Promise.reject(Ho(c));let t=null,e=c;if(a!==null){if(t=$t(a),t.length>64)return Promise.reject(new Error("Max key length is 64 bytes"));e=Mr(c,t.length)}let i=c/8;return Ro(xr,i).then(s=>{e>512&&s.writeMemory(t),s.init(e);let n={init:e>512?()=>(s.writeMemory(t),s.init(e),n):()=>(s.init(e),n),update:o=>(s.update(o),n),digest:o=>s.digest(o),save:()=>s.save(),load:o=>(s.load(o),n),blockSize:128,digestSize:i};return n})}function Tr(c,a,t){let e=[`m=${a.memorySize}`,`t=${a.iterations}`,`p=${a.parallelism}`].join(",");return`$argon2${a.hashType}$v=19$${e}$${To(c,!1)}$${To(t,!1)}`}var Po=new DataView(new ArrayBuffer(4));function zt(c){return Po.setInt32(0,c,!0),new Uint8Array(Po.buffer)}function gn(c,a,t){return ke(this,void 0,void 0,function*(){if(t<=64){let r=yield un(t*8);return r.update(zt(t)),r.update(a),r.digest("binary")}let e=Math.ceil(t/32)-2,i=new Uint8Array(t);c.init(),c.update(zt(t)),c.update(a);let s=c.digest("binary");i.set(s.subarray(0,32),0);for(let r=1;r<e;r++)c.init(),c.update(s),s=c.digest("binary"),i.set(s.subarray(0,32),r*32);let n=t-32*e,o;return n===64?(o=c,o.init()):o=yield un(n*8),o.update(s),s=o.digest("binary"),i.set(s.subarray(0,n),e*32),i})}function Hr(c){switch(c){case"d":return 0;case"i":return 1;default:return 2}}function Pr(c){return ke(this,void 0,void 0,function*(){var a;let{parallelism:t,iterations:e,hashLength:i}=c,s=$t(c.password),n=$t(c.salt),o=19,r=Hr(c.hashType),{memorySize:A}=c,l=$t((a=c.secret)!==null&&a!==void 0?a:""),[d,g]=yield Promise.all([Ro(Sr,1024),un(512)]);d.setMemorySize(A*1024+1024);let p=new Uint8Array(24),h=new DataView(p.buffer);h.setInt32(0,t,!0),h.setInt32(4,i,!0),h.setInt32(8,A,!0),h.setInt32(12,e,!0),h.setInt32(16,o,!0),h.setInt32(20,r,!0),d.writeMemory(p,A*1024),g.init(),g.update(p),g.update(zt(s.length)),g.update(s),g.update(zt(n.length)),g.update(n),g.update(zt(l.length)),g.update(l),g.update(zt(0));let u=Math.floor(A/(t*4))*4,f=new Uint8Array(72),C=g.digest("binary");f.set(C);for(let w=0;w<t;w++){f.set(zt(0),64),f.set(zt(w),68);let Q=w*u,E=yield gn(g,f,1024);d.writeMemory(E,Q*1024),Q+=1,f.set(zt(1),64),E=yield gn(g,f,1024),d.writeMemory(E,Q*1024)}let B=new Uint8Array(1024);Go(B,d.calculate(new Uint8Array([]),A));let m=yield gn(g,B,i);if(c.outputType==="hex"){let w=new Uint8Array(i*2);return In(w,m,i)}return c.outputType==="encoded"?Tr(n,c,m):m})}var Ur=c=>{var a;if(!c||typeof c!="object")throw new Error("Invalid options parameter. It requires an object.");if(!c.password)throw new Error("Password must be specified");if(c.password=$t(c.password),c.password.length<1)throw new Error("Password must be specified");if(!c.salt)throw new Error("Salt must be specified");if(c.salt=$t(c.salt),c.salt.length<8)throw new Error("Salt should be at least 8 bytes long");if(c.secret=$t((a=c.secret)!==null&&a!==void 0?a:""),!Number.isInteger(c.iterations)||c.iterations<1)throw new Error("Iterations should be a positive number");if(!Number.isInteger(c.parallelism)||c.parallelism<1)throw new Error("Parallelism should be a positive number");if(!Number.isInteger(c.hashLength)||c.hashLength<4)throw new Error("Hash length should be at least 4 bytes.");if(!Number.isInteger(c.memorySize))throw new Error("Memory size should be specified.");if(c.memorySize<8*c.parallelism)throw new Error("Memory size should be at least 8 * parallelism.");if(c.outputType===void 0&&(c.outputType="hex"),!["hex","binary","encoded"].includes(c.outputType))throw new Error(`Insupported output type ${c.outputType}. Valid values: ['hex', 'binary', 'encoded']`)};function fn(c){return ke(this,void 0,void 0,function*(){return Ur(c),Pr(Object.assign(Object.assign({},c),{hashType:"id"}))})}var Sl=new nt;var Dl=new nt;var bl=new nt;var Nl=new nt;var xl=new Uint8Array(8);var Ml=new nt;var Tl=new nt;var Hl=new nt;var Pl=new nt;var Ul=new nt;var Gl=new nt;var Rl=new nt;var Ll=new nt;var ql=new nt;var Jl=new nt;var Kl=new nt;var Ol=new Uint8Array(8);var Yl=new nt;var zl=new Uint8Array(8);var $l=new nt;var Vl=new Uint8Array(8);var Wl=new nt;var Xl=new nt;var Zl=new nt;vt();var Tt=new Uint8Array([83,84,65,83,72,69,78,67]),mn=2,Qn=1,yn=2,Jo=3,Gr=32,Ue=12,Cn=32,Rr=6e5,Lr=47104,qr=3,Jr=1,dt=c=>c;function Ht(c){if(c.length<Tt.length+1)return!1;for(let a=0;a<Tt.length;a++)if(c[a]!==Tt[a])return!1;return!0}function Lo(c,a,t){c[a]=t>>>24&255,c[a+1]=t>>>16&255,c[a+2]=t>>>8&255,c[a+3]=t&255}function qo(c,a){return c[a]*16777216+(c[a+1]<<16)+(c[a+2]<<8)+c[a+3]}async function Bn(c,a,t){if(t.id===yn)return await fn({password:c,salt:a,parallelism:t.c,iterations:t.b,memorySize:t.a,hashLength:Cn,outputType:"binary"});if(t.id===Qn){let e=await crypto.subtle.importKey("raw",dt(new TextEncoder().encode(c)),"PBKDF2",!1,["deriveBits"]),i=await crypto.subtle.deriveBits({name:"PBKDF2",salt:dt(a),iterations:t.a,hash:"SHA-256"},e,Cn*8);return new Uint8Array(i)}throw new Error(`Unsupported KDF id (${t.id}).`)}async function Xi(c){return crypto.subtle.importKey("raw",dt(c),{name:"AES-GCM"},!1,["encrypt","decrypt"])}var Ko={argon2id:{label:"Argon2id",strong:!0},pbkdf2:{label:"PBKDF2 (fallback)",strong:!1}};async function Ge(c,a){let t=crypto.getRandomValues(new Uint8Array(Gr)),e=crypto.getRandomValues(new Uint8Array(Ue)),i,s,n;try{i={id:yn,a:Lr,b:qr,c:Jr},n=await Bn(a,t,i),s="argon2id"}catch(d){console.warn("[Stashpad] Argon2id unavailable \u2014 encrypting with PBKDF2 fallback.",d),i={id:Qn,a:Rr,b:0,c:0},n=await Bn(a,t,i),s="pbkdf2"}let o=Oo(i,t,e),r=await Xi(n),A=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:dt(e),additionalData:dt(o)},r,dt(c))),l=new Uint8Array(o.length+A.length);return l.set(o,0),l.set(A,o.length),{data:l,kdf:s}}var mi=null;async function Zi(){if(mi!==null)return mi;try{await fn({password:"x",salt:new Uint8Array(16),parallelism:1,iterations:1,memorySize:8,hashLength:16,outputType:"binary"}),mi=!0}catch{mi=!1}return mi}function Oo(c,a,t){let e=new Uint8Array(Tt.length+1+1+4+4+1+1+a.length+t.length),i=0;return e.set(Tt,i),i+=Tt.length,e[i++]=mn,e[i++]=c.id,Lo(e,i,c.a),i+=4,Lo(e,i,c.b),i+=4,e[i++]=c.c,e[i++]=a.length,e.set(a,i),i+=a.length,e.set(t,i),i+=t.length,e}async function Vt(c,a){if(!Ht(c))throw new Error("Not an encrypted Stashpad file.");let t=c[Tt.length];if(t===1)return Kr(c,a);if(t!==mn)throw new Error(`Unsupported encrypted .stash version (${t}).`);let e=Tt.length+1,i={id:c[e++],a:0,b:0,c:0};if(i.a=qo(c,e),e+=4,i.b=qo(c,e),e+=4,i.c=c[e++],i.id===yn){if(i.a>2097152||i.b>64||i.c<1||i.c>8)throw new Error("Unsupported KDF parameters (file may be corrupted or malicious).")}else if(i.id===Qn&&i.a>1e7)throw new Error("Unsupported KDF parameters (file may be corrupted or malicious).");let s=c[e++];if(s<8||s>64)throw new Error("Unsupported KDF parameters (file may be corrupted or malicious).");let n=c.slice(e,e+s);e+=s;let o=c.slice(e,e+Ue);e+=Ue;let r=c.slice(0,e),A=c.slice(e),l=await Bn(a,n,i),d=await Xi(l),g=await crypto.subtle.decrypt({name:"AES-GCM",iv:dt(o),additionalData:dt(r)},d,dt(A));return new Uint8Array(g)}async function Kr(c,a){let t=Tt.length+1,e=c.slice(t,t+16);t+=16;let i=c.slice(t,t+12);t+=12;let s=c.slice(t),n=await crypto.subtle.importKey("raw",dt(new TextEncoder().encode(a)),"PBKDF2",!1,["deriveKey"]),o=await crypto.subtle.deriveKey({name:"PBKDF2",salt:dt(e),iterations:21e4,hash:"SHA-256"},n,{name:"AES-GCM",length:256},!1,["decrypt"]),r=await crypto.subtle.decrypt({name:"AES-GCM",iv:dt(i)},o,dt(s));return new Uint8Array(r)}async function Qi(c,a){if(a.length!==Cn)throw new Error("Encryption key must be 32 bytes.");let t=crypto.getRandomValues(new Uint8Array(Ue)),i=Oo({id:Jo,a:0,b:0,c:0},new Uint8Array(0),t),s=await Xi(a),n=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:dt(t),additionalData:dt(i)},s,dt(c))),o=new Uint8Array(i.length+n.length);return o.set(i,0),o.set(n,i.length),o}async function ae(c,a){if(!Ht(c))throw new Error("Not an encrypted Stashpad file.");let t=c[Tt.length];if(t!==mn)throw new Error(`Unsupported encrypted version (${t}).`);let e=Tt.length+1;if(c[e++]!==Jo)throw new Error("Not a raw-key (.stashenc) envelope.");e+=9;let s=c[e++];e+=s;let n=c.slice(e,e+Ue);e+=Ue;let o=c.slice(0,e),r=c.slice(e),A=await Xi(a),l=await crypto.subtle.decrypt({name:"AES-GCM",iv:dt(n),additionalData:dt(o)},A,dt(r));return new Uint8Array(l)}async function Re(c,a,t={}){if(!Ht(a))return a;if(t.secretId){let i=c.secretStorage,s=null;try{s=i?.getSecret(t.secretId)??null}catch{s=null}if(s)try{return await Vt(a,s)}catch{}}let e;for(;;){let i=await new Promise(s=>{new ai(c,e,!!t.allowLater,s).open()});if(i.kind==="cancel")return null;if(i.kind==="later")return t.onLater?.(),null;try{return await Vt(a,i.value)}catch{e="Wrong password or corrupted file. Try again."}}}xt();var ji={name:"ECDH",namedCurve:"P-256"},Or="stashpad-vault-dek-wrap",Yr=new TextEncoder;function En(c){let a="";for(let t=0;t<c.length;t++)a+=String.fromCharCode(c[t]);return btoa(a)}function wn(c){let a=atob(c),t=new Uint8Array(a.length);for(let e=0;e<a.length;e++)t[e]=a.charCodeAt(e);return t}async function Yo(){let c=await crypto.subtle.generateKey(ji,!0,["deriveBits"]);return{pubKeySpki:new Uint8Array(await crypto.subtle.exportKey("spki",c.publicKey)),privKeyPkcs8:new Uint8Array(await crypto.subtle.exportKey("pkcs8",c.privateKey))}}function zo(c){return crypto.subtle.importKey("spki",c,ji,!1,[])}function zr(c){return crypto.subtle.importKey("pkcs8",c,ji,!1,["deriveBits"])}async function $o(c,a){let t=await crypto.subtle.deriveBits({name:"ECDH",public:a},c,256),e=await crypto.subtle.importKey("raw",t,"HKDF",!1,["deriveKey"]);return crypto.subtle.deriveKey({name:"HKDF",hash:"SHA-256",salt:new Uint8Array(0),info:Yr.encode(Or)},e,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}async function _i(c,a,t){let e=await crypto.subtle.generateKey(ji,!0,["deriveBits"]),i=await $o(e.privateKey,await zo(a)),s=crypto.getRandomValues(new Uint8Array(12)),n=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:s},i,c)),o=new Uint8Array(await crypto.subtle.exportKey("spki",e.publicKey));return{recipientId:t,ephPub:En(o),iv:En(s),ct:En(n)}}async function Vo(c,a){let t=await $o(await zr(a),await zo(wn(c.ephPub)));return new Uint8Array(await crypto.subtle.decrypt({name:"AES-GCM",iv:wn(c.iv)},t,wn(c.ct)))}var Wo=".stashpad/keys.json",$r=".stashpad",yi="_keys";function vn(c){return{v:2,keyId:c,identities:[],slots:[],joinRequests:[]}}var ts=class{constructor(a){this.app=a}get a(){return this.app.vault.adapter}validate(a){let t=a;return!!t&&t.v===2&&typeof t.keyId=="string"&&Array.isArray(t.identities)&&Array.isArray(t.slots)&&Array.isArray(t.joinRequests)}async readValid(a){try{if(!await this.a.exists(a))return null;let t=JSON.parse(await this.a.read(a));return this.validate(t)?t:null}catch{return null}}async load(){let a=await this.readValid(Wo);if(a)return a;try{let e=((await this.a.list(yi)).files||[]).filter(i=>/\/keys-\d+\.json$/.test(i)).sort();for(let i of e.reverse()){let s=await this.readValid(i);if(s)return s}}catch{}return null}async exists(){return await this.load()!==null}async ensureDir(a){try{await this.a.exists(a)||await this.a.mkdir(a)}catch{}}async save(a){let t=JSON.stringify(a,null,2);await this.ensureDir($r),await this.a.write(Wo,t),await this.ensureDir(yi);for(let e=4;e>=1;e--){let i=`${yi}/keys-${e}.json`,s=`${yi}/keys-${e+1}.json`;try{await this.a.exists(i)&&await this.a.write(s,await this.a.read(i))}catch{}}try{await this.a.write(`${yi}/keys-1.json`,t)}catch{}}};var es="stashpad-vault-encryption";function Ei(){return{wrappedKey:null,kdf:null,identityId:null,identityLabel:null,identityPub:null,identityPrivWrapped:null,identityPrivKdf:null}}function is(c){let a="";for(let t=0;t<c.length;t++)a+=String.fromCharCode(c[t]);return btoa(a)}function Wt(c){let a=atob(c),t=new Uint8Array(a.length);for(let e=0;e<a.length;e++)t[e]=a.charCodeAt(e);return t}var Vr=32,ss=class{constructor(a,t,e,i=()=>0){this.app=a;this.load=t;this.save=e;this.idleMinutes=i;this.sessionKey=null;this.idleTimer=null;this.kf=null;this.keyfiles=new ts(a)}argonProbe(){return Zi()}async init(){await this.refresh()}async refresh(){this.kf=await this.keyfiles.load()}secretStore(){return this.app.secretStorage??null}keychainAvailable(){return!!this.secretStore()}keychainId(){let a=this.app.appId||"default";return`${es}-${a}`}isRemembered(){try{return!!this.secretStore()?.getSecret(this.keychainId())}catch{return!1}}async remember(a){try{await this.secretStore()?.setSecret(this.keychainId(),a)}catch(t){console.warn("[Stashpad] couldn't save password to keychain",t)}}async forgetKeychain(){let a=this.secretStore();if(a)try{a.removeSecret?await a.removeSecret(this.keychainId()):await a.setSecret(this.keychainId(),"")}catch(t){console.warn("[Stashpad] couldn't clear keychain",t)}}async tryAutoUnlock(){if(!this.isConfigured()||this.isUnlocked())return this.isUnlocked();if(this.accessState()!=="member"&&!this.hasSharedPassword())return!1;let a=this.secretStore(),t=null;try{t=a?.getSecret(this.keychainId())??null}catch{t=null}if(t)return this.unlock(t);let e=null;try{e=a?.getSecret(es)??null}catch{e=null}if(!e)return!1;let i=await this.unlock(e);if(i){await this.remember(e);try{a?.removeSecret?await a.removeSecret(es):await a?.setSecret(es,"")}catch{}}return i}isConfigured(){return!!this.kf||!!this.load().wrappedKey}isUnlocked(){return this.sessionKey!==null}kdf(){return this.load().identityPrivKdf??this.load().kdf}hasIdentity(){return!!this.load().identityPrivWrapped&&!!this.load().identityId}mySlot(){let a=this.load().identityId;return a?this.kf?.slots.find(t=>t.recipientId===a)??null:null}accessState(){let a=this.load();return!this.kf&&a.wrappedKey?"member":this.kf?this.hasIdentity()&&this.mySlot()?"member":a.identityId&&this.kf.joinRequests.some(t=>t.id===a.identityId)?"pending":"outsider":"none"}amIMember(){return this.accessState()==="member"}async setup(a,t=!1,e){if(await this.refresh(),this.isConfigured())throw new Error("Encryption is already set up in this vault.");if(!a)throw new Error("Password required.");let i=crypto.getRandomValues(new Uint8Array(Vr)),s=await this.mintIdentity(a,e),n=vn(tt(8));n.identities.push(this.identityRecord(s)),n.slots.push(await _i(i,Wt(s.pub),s.id)),await this.keyfiles.save(n),this.kf=n,this.sessionKey=i,t?await this.remember(a):await this.forgetKeychain(),this.armIdle()}async unlock(a,t=!1){await this.refresh();let e=this.load();if(!this.kf&&e.wrappedKey){let s;try{s=await Vt(Wt(e.wrappedKey),a)}catch{return!1}let n=await this.mintIdentity(a,e.identityLabel??void 0),o=vn(tt(8));return o.identities.push(this.identityRecord(n)),o.slots.push(await _i(s,Wt(n.pub),n.id)),await this.keyfiles.save(o),this.kf=o,this.sessionKey=s,t&&await this.remember(a),this.armIdle(),!0}let i=this.hasIdentity()?this.mySlot():null;if(i)try{let s=await Vt(Wt(e.identityPrivWrapped),a);try{let n=await Vo(i,s);return s.fill(0),this.sessionKey=n,t&&await this.remember(a),this.armIdle(),!0}catch{s.fill(0)}}catch{}for(let s of this.kf?.passwordSlots??[])try{let n=await Vt(Wt(s.wrapped),a);return this.sessionKey=n,t&&await this.remember(a),this.armIdle(),!0}catch{}return!1}hasSharedPassword(){return(this.kf?.passwordSlots?.length??0)>0}async setSharedPassword(a){if(!this.sessionKey)throw new Error("Unlock encryption first.");if(!a)throw new Error("Password required.");if(await this.refresh(),!this.kf)throw new Error("Encryption is not set up.");let t=await Ge(this.sessionKey,a);this.kf.passwordSlots=[{id:tt(8),label:"Shared password",wrapped:is(t.data),kdf:t.kdf,createdAt:new Date().toISOString()}],await this.keyfiles.save(this.kf)}async removeSharedPassword(){await this.refresh(),!(!this.kf||!this.kf.passwordSlots?.length)&&(this.kf.passwordSlots=[],await this.keyfiles.save(this.kf))}async verifyPassword(a){let t=this.load();try{if(t.identityPrivWrapped)return(await Vt(Wt(t.identityPrivWrapped),a)).fill(0),!0;if(t.wrappedKey)return(await Vt(Wt(t.wrappedKey),a)).fill(0),!0}catch{}return!1}async changePassword(a,t,e=!1){let i=this.load();if(!t)throw new Error("New password required.");if(!i.identityPrivWrapped&&!await this.unlock(a,!1))return!1;let s=this.load(),n;try{n=await Vt(Wt(s.identityPrivWrapped),a)}catch{return!1}let o=await Ge(n,t);return n.fill(0),await this.save({...s,identityPrivWrapped:is(o.data),identityPrivKdf:o.kdf}),e?await this.remember(t):await this.forgetKeychain(),this.armIdle(),!0}async requestAccess(a,t,e=!1){if(await this.refresh(),!this.kf)throw new Error("This vault has no encryption set up yet.");if(this.amIMember())return;if(!t)throw new Error("Password required.");let i=this.hasIdentity()?{id:this.load().identityId,label:this.load().identityLabel??a,pub:this.load().identityPub}:await this.mintIdentity(t,a);a&&i.label!==a&&(await this.save({...this.load(),identityLabel:a}),i.label=a);let s={id:i.id,label:i.label,pubKey:i.pub,requestedAt:new Date().toISOString()};this.kf.joinRequests=[...this.kf.joinRequests.filter(n=>n.id!==i.id),s],await this.keyfiles.save(this.kf),e?await this.remember(t):await this.forgetKeychain()}pendingJoinRequests(){return this.kf?.joinRequests??[]}members(){return this.kf?.identities??[]}myIdentityId(){return this.load().identityId}async approveJoinRequest(a,t){if(!this.sessionKey)throw new Error("Unlock encryption first.");if(await this.refresh(),!this.kf)return!1;let e=this.kf.joinRequests.find(i=>i.id===a);return e?(this.kf.slots=[...this.kf.slots.filter(i=>i.recipientId!==e.id),await _i(this.sessionKey,Wt(e.pubKey),e.id)],this.kf.identities=[...this.kf.identities.filter(i=>i.id!==e.id),{id:e.id,label:t??e.label,pubKey:e.pubKey,addedAt:new Date().toISOString()}],this.kf.joinRequests=this.kf.joinRequests.filter(i=>i.id!==a),await this.keyfiles.save(this.kf),!0):!1}async removeMember(a){await this.refresh(),this.kf&&(this.kf.slots=this.kf.slots.filter(t=>t.recipientId!==a),this.kf.identities=this.kf.identities.filter(t=>t.id!==a),this.kf.joinRequests=this.kf.joinRequests.filter(t=>t.id!==a),await this.keyfiles.save(this.kf))}async denyJoinRequest(a){await this.refresh(),this.kf&&(this.kf.joinRequests=this.kf.joinRequests.filter(t=>t.id!==a),await this.keyfiles.save(this.kf))}lock(){this.sessionKey&&this.sessionKey.fill(0),this.sessionKey=null,this.clearIdle()}async clear(){this.lock(),await this.forgetKeychain();try{let a=this.app.vault.adapter;for(let t of[".stashpad/keys.json"])try{await a.exists(t)&&await a.remove(t)}catch{}try{let t=await a.list("_keys");for(let e of t.files||[])if(/\/keys-\d+\.json$/.test(e))try{await a.remove(e)}catch{}}catch{}}catch{}this.kf=null,await this.save(Ei())}getSessionKey(){return this.sessionKey&&this.armIdle(),this.sessionKey?this.sessionKey.slice():null}async mintIdentity(a,t){let e=await Yo(),i=await Ge(e.privKeyPkcs8,a);e.privKeyPkcs8.fill(0);let s=this.load(),n=s.identityId??tt(8),o=t??s.identityLabel??"This device",r=is(e.pubKeySpki);return await this.save({...s,identityId:n,identityLabel:o,identityPub:r,identityPrivWrapped:is(i.data),identityPrivKdf:i.kdf}),{id:n,label:o,pub:r}}identityRecord(a){return{id:a.id,label:a.label,pubKey:a.pub,addedAt:new Date().toISOString()}}armIdle(){this.clearIdle();let a=this.idleMinutes();a>0&&(this.idleTimer=window.setTimeout(()=>this.lock(),a*6e4))}clearIdle(){this.idleTimer!=null&&(window.clearTimeout(this.idleTimer),this.idleTimer=null)}dispose(){this.lock()}};var ls=require("obsidian");As();xt();rt();var jt="stash",Ia=1;function ga(c){let t=(c.split(/[\\/]/).pop()??"").trim();return!t||t==="."||t===".."||t.includes("/")||t.includes("\\")||t.includes("..")?"":t}var Rn=/!\[\[([^\]\|]+)(?:\|[^\]]+)?\]\]/g;async function Ae(c,a){let t=[],e=uA([...a.rootNotes,...a.allDescendants]),i=new Map,s=[];for(let o of e){let r=await c.vault.read(o.file),A=r,l=ua(r);for(let d of l){let g=c.metadataCache.getFirstLinkpathDest(d,o.file.path);if(!g){s.push(`Missing attachment "${d}" in ${o.file.path}`);continue}let p=g.name;i.has(p)||i.set(p,await c.vault.readBinary(g)),A=fA(A,d,p)}A=mA(A,c,o.file.path),t.push({name:`notes/${o.file.name}`,data:A})}for(let[o,r]of i)t.push({name:`attachments/${o}`,data:r});let n={stashSchema:Ia,exportedAt:new Date().toISOString(),sourceFolder:a.sourceFolder,noteCount:e.length,rootIds:a.rootNotes.map(o=>o.id)};return t.push({name:"manifest.json",data:JSON.stringify(n,null,2)}),s.length&&t.push({name:"warnings.txt",data:s.join(` -`)}),Si(t,6)}async function Kt(c,a,t,e,i={}){let s=await Di(a),n=s["manifest.json"];if(!n)throw new Error("Not a valid .stash package: missing manifest.json");let o=JSON.parse(rs(n));if(typeof o.stashSchema!="number"||o.stashSchema>Ia)throw new Error(`Unsupported .stash schema: v${o.stashSchema}`);await pa(c,t);let r=Object.entries(s).filter(([E])=>E.startsWith("notes/")&&E.endsWith(".md")),A=[];for(let[E,v]of r){let y=rs(v),{fm:b,body:N}=lt(y),P=ga(E.slice(6))||`${b.id||"imported-"+tt(4)}.md`;A.push({originalName:P,fm:b,body:N})}let l=new Map,d=0;for(let E of A){let v=E.fm.id;v&&(i.forceNewIds?l.set(v,tt(6)):e.has(v)||l.has(v)?(l.set(v,`${v}-${tt(4)}-Imported`),d++):l.set(v,v))}let g=new Date().toISOString(),p=[],h=`${t}/_attachments`,I=0,u=Object.entries(s).filter(([E])=>E.startsWith("attachments/")),f=new Map,C=null;if(i.dedupeExisting){C=new Map;for(let E of c.vault.getFiles())C.has(E.name)||C.set(E.name,E.path)}let B=(E,v)=>{if(E.length!==v.length)return!1;for(let y=0;y<E.length;y++)if(E[y]!==v[y])return!1;return!0},m=!1;for(let[E,v]of u){let y=ga(E.slice(12));if(!y)continue;let b=v,N=[],P=C?.get(y);P&&N.push(P);let H=`${h}/${y}`;await c.vault.adapter.exists(H)&&N.push(H);let D=null;for(let M of N)try{if(B(new Uint8Array(await c.vault.adapter.readBinary(M)),b)){D=M;break}}catch{}if(D){f.set(y,D);continue}let S=H;for(let M=1;await c.vault.adapter.exists(S);M++)S=`${h}/${CA(y,M)}`;f.set(y,S),m||(await pa(c,h),m=!0),await c.vault.createBinary(S,b.buffer),I++}let w=0;for(let E of A){let v=E.fm.id;if(!v){p.push(`Skipped ${E.originalName} \u2014 no id in frontmatter`);continue}let y=l.get(v),b=E.fm.parent??null,N=b;!b||b===F?N=i.reparentRootsTo??b??F:l.has(b)?N=l.get(b):N=e.has(b)?b:i.reparentRootsTo??F;let P=BA(E.body,f,h),H={...E.fm,id:y,parent:N,import_date:g};Array.isArray(H.attachments)&&(H.attachments=H.attachments.map(U=>{let R=fa(Be(U));return Rt(f.get(R)??`${h}/${R}`)}));let D=le(H,P),S=y===v?E.originalName:yA(E.originalName,v,y),M=`${t}/${S}`;await c.vault.adapter.exists(M)&&(S=`${S.replace(/\.md$/,"")}-${tt(4)}.md`,M=`${t}/${S}`),await c.vault.create(M,D),w++}let Q;if(o.colorAliases&&typeof o.colorAliases=="object"){let E={};for(let[v,y]of Object.entries(o.colorAliases)){let b=String(v).trim().toLowerCase(),N=String(y??"").trim();/^#([0-9a-f]{6})$/.test(b)&&N&&(E[b]=N.slice(0,60))}Object.keys(E).length&&(Q=E)}return{notesWritten:w,attachmentsWritten:I,collisionsRenamed:d,warnings:p,colorAliases:Q,idRemap:Object.fromEntries(l)}}function uA(c){let a=new Set,t=[];for(let e of c)a.has(e.id)||(a.add(e.id),t.push(e));return t}function ua(c){let a=new Set,t;for(Rn.lastIndex=0;(t=Rn.exec(c))!==null;)a.add(t[1]);return[...a]}async function cs(c,a){let t=await c.vault.read(a),e=[],i=new Set;for(let s of ua(t)){let n=c.metadataCache.getFirstLinkpathDest(s,a.path);n&&!i.has(n.path)&&(i.add(n.path),e.push(n))}return e}function fA(c,a,t){return c.replace(new RegExp(`!\\[\\[${QA(a)}(\\|[^\\]]+)?\\]\\]`,"g"),(e,i)=>`![[${t}${i??""}]]`)}function CA(c,a){let t=c.lastIndexOf(".");return t>0?`${c.slice(0,t)}-${a}${c.slice(t)}`:`${c}-${a}`}function BA(c,a,t){return c.replace(Rn,(e,i,s)=>{if(i.includes("/"))return e;let n=a.get(i)??`${t}/${i}`;return e.replace(i,n)})}function mA(c,a,t){let e=lt(c);if(!e.fm.attachments||!Array.isArray(e.fm.attachments))return c;let i=e.fm.attachments.map(n=>{let o=a.metadataCache.getFirstLinkpathDest(n,t);return o?o.name:fa(n)}),s={...e.fm,attachments:i};return le(s,e.body)}function QA(c){return c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function fa(c){let a=c.lastIndexOf("/");return a<0?c:c.slice(a+1)}function yA(c,a,t){return c.includes(a)?c.replace(a,t):c.replace(/\.md$/,`-${t}.md`)}function lt(c){if(!c.startsWith("---"))return{fm:{},body:c};let a=c.indexOf(` ----`,3);if(a<0)return{fm:{},body:c};let t=c.slice(3,a).replace(/^\n/,""),e=c.slice(a+4),i={};try{i=(0,ls.parseYaml)(t)??{}}catch{i={}}let s=e.startsWith(` -`)?e.slice(1):e;return{fm:i,body:s}}function le(c,a){return`--- -${(0,ls.stringifyYaml)(c).trimEnd()} +`}function Zi(c,a){let t=document.createDocumentFragment();t.createEl("div",{text:"Home note updated"}).setCssStyles({fontWeight:"600",marginBottom:"6px"});let i=t.createEl("ul");i.setCssStyles({margin:"0 0 8px 0",paddingLeft:"18px"}),i.createEl("li",{text:`${a.indexed.length} indexed`}),i.createEl("li",{text:`${a.nonIndex.length+a.skippedStashpadNotes.length} excluded`});let s=t.createEl("button",{text:"Open",cls:"mod-cta"});s.setCssStyles({padding:"2px 10px",fontSize:"var(--font-ui-smaller)"});let n;return s.onclick=async o=>{if(o.stopPropagation(),a.previewPath){let r=c.vault.getAbstractFileByPath(a.previewPath);r instanceof gt.TFile&&await c.workspace.getLeaf("tab").openFile(r)}n?.hide()},n=new gt.Notice(t,0),n}var gt,Po,Bi,mi=Lt(()=>{"use strict";gt=require("obsidian");Tt();Re();rt();Po=/^(\d+-\d+|\d+|[A-Za-z0-9]+(?:\.[A-Za-z0-9]+)+)\s+(.+)$/;Bi=class extends gt.Modal{constructor(t,e,i,s,n){super(t);this.plugin=e;this.settings=i;this.indexedCount=s;this.onBuild=n;this.LARGE_BUILD=50;this.previewRan=!1;this.previewPath=null}onOpen(){let{contentEl:t,titleEl:e}=this,i=!this.settings.jdIndexHasBuilt,s=this.indexedCount>this.LARGE_BUILD;e.setText(i?"Build JD index \u2014 first time?":"Build JD index");let n=this.settings.jdIndexStashpadFolder,o=t.createEl("p"),r=`${this.indexedCount} note${this.indexedCount===1?"":"s"}`;i?(o.appendText(`Stashpad is about to create ${r} (plus synthetic parents as needed) inside "`),o.createEl("code",{text:n}),o.appendText('". Existing notes with the same '),o.createEl("code",{text:"jdPrefix"}),o.appendText(" are updated, never deleted \u2014 but if the prefix detection picks up notes you didn't mean to index, you'll end up with a lot of unwanted notes."),t.createEl("p").setText("Running Preview first writes a single Markdown file showing exactly what would be built (and what wouldn't), so you can sanity-check before committing.")):s?(o.appendText(`You're about to create ${this.indexedCount} notes in "`),o.createEl("code",{text:n}),o.appendText(`". That's a big batch \u2014 if anything looks off, Preview the single-file output first.`)):(o.appendText('Build the JD index into "'),o.createEl("code",{text:n}),o.appendText(`"? Stashpad will create / update ${r}. Existing notes with matching `),o.createEl("code",{text:"jdPrefix"}),o.appendText(" are updated in place.")),this.previewRan&&this.previewPath&&t.createEl("p",{cls:"setting-item-description"}).setText(`\u2713 Preview written to home note (${this.previewPath}). Open it before building if you haven't.`);let A=new gt.Setting(t);(i||s)&&A.addButton(l=>{l.setButtonText(this.previewRan?"Re-run preview":"Run preview first"),l.setCta(),l.onClick(async()=>{try{let d=await Xi(this.app,this.plugin,this.settings);if(d.error==="no-dest"){new gt.Notice("Set a Designated Stashpad folder for Index first.",5e3),this.close();return}if(d.error==="no-home"){new gt.Notice(`"${this.settings.jdIndexStashpadFolder}" has no Stashpad home note. Open the folder in Stashpad first.`,7e3),this.close();return}this.previewRan=!0,this.previewPath=d.previewPath,Zi(this.app,d),this.contentEl.empty(),this.titleEl.empty(),this.onOpen()}catch(d){new gt.Notice(`Preview failed: ${d?.message??d}`,8e3)}})}),A.addButton(l=>{l.setButtonText(i?"Build anyway":"Build"),!i&&!s&&l.setCta(),l.onClick(async()=>{this.close(),await this.onBuild()})}),A.addButton(l=>{l.setButtonText("Cancel"),l.onClick(()=>this.close())})}onClose(){this.contentEl.empty()}}});function yA(c,a){return QA(c,a||{},0,0)}function EA(c,a){return uA(c,{i:2},a&&a.out,a&&a.dictionary)}function ds(c,a){if(a){for(var t=new At(c.length),e=0;e<c.length;++e)t[e]=c.charCodeAt(e);return t}if(ca)return ca.encode(c);for(var i=c.length,s=new At(c.length+(c.length>>1)),n=0,o=function(l){s[n++]=l},e=0;e<i;++e){if(n+5>s.length){var r=new At(n+8+(i-e<<1));r.set(s),s=r}var A=c.charCodeAt(e);A<128||a?o(A):A<2048?(o(192|A>>6),o(128|A&63)):A>55295&&A<57344?(A=65536+(A&1047552)|c.charCodeAt(++e)&1023,o(240|A>>18),o(128|A>>12&63),o(128|A>>6&63),o(128|A&63)):(o(224|A>>12),o(128|A>>6&63),o(128|A&63))}return Ni(s,0,n)}function Yn(c,a){if(a){for(var t="",e=0;e<c.length;e+=16384)t+=String.fromCharCode.apply(null,c.subarray(e,e+16384));return t}else{if(qn)return qn.decode(c);var i=vA(c),s=i.s,t=i.r;return t.length&&ut(8),s}}function ma(c,a){a||(a={});var t={},e=[];Ba(c,"",t,a);var i=0,s=0;for(var n in t){var o=t[n],r=o[0],A=o[1],l=A.level==0?0:8,d=ds(n),p=d.length,g=A.comment,h=g&&ds(g),I=h&&h.length,u=Jn(A.extra);p>65535&&ut(11);var f=l?yA(r,A):r,C=f.length,B=mA();B.p(r),e.push(Ca(A,{size:r.length,crc:B.d(),c:f,f:d,m:h,u:p!=n.length||h&&g.length!=I,o:i,compression:l})),i+=30+p+u+C,s+=76+2*(p+u)+(I||0)+C}for(var m=new At(s+22),y=i,Q=s-i,E=0;E<e.length;++E){var d=e[E];da(m,d.o,d,d.f,d.u,d.c.length);var v=30+d.f.length+Jn(d.extra);m.set(d.c,d.o+v),da(m,i,d,d.f,d.u,d.c.length,d.o,d.m),i+=16+v+(d.m?d.m.length:0)}return DA(m,i,e.length,Q,y),m}function Qa(c,a){for(var t={},e=c.length-22;Dt(c,e)!=101010256;--e)(!e||c.length-e>65558)&&ut(13);var i=Kt(c,e+8);if(!i)return{};var s=Dt(c,e+16),n=Dt(c,e-20)==117853008;if(n){var o=Dt(c,e-12);n=Dt(c,o)==101075792,n&&(i=Dt(c,o+32),s=Dt(c,o+48))}for(var r=a&&a.filter,A=0;A<i;++A){var l=kA(c,s,n),d=l[0],p=l[1],g=l[2],h=l[3],I=l[4],u=l[5],f=FA(c,u);s=I,(!r||r({name:h,size:p,originalSize:g,compression:d}))&&(d?d==8?t[h]=EA(c.subarray(f,f+p),{out:new At(g)}):ut(14,"unknown compression type "+d):t[h]=Ni(c,f,f+p))}return t}var At,kt,Kn,hs,ps,Un,ha,pa,ga,Gn,Ia,cA,ra,Rn,_t,Z,Ot,de,Z,Z,Z,Z,bi,Z,dA,hA,pA,gA,Mn,Gt,Tn,On,Ni,IA,ut,uA,te,Si,Hn,Ln,Aa,Di,ua,la,fA,fa,CA,BA,mA,QA,Ca,Kt,Dt,Pn,It,Ba,ca,qn,wA,vA,FA,kA,SA,Jn,da,DA,ya=Lt(()=>{At=Uint8Array,kt=Uint16Array,Kn=Int32Array,hs=new At([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]),ps=new At([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]),Un=new At([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),ha=function(c,a){for(var t=new kt(31),e=0;e<31;++e)t[e]=a+=1<<c[e-1];for(var i=new Kn(t[30]),e=1;e<30;++e)for(var s=t[e];s<t[e+1];++s)i[s]=s-t[e]<<5|e;return{b:t,r:i}},pa=ha(hs,2),ga=pa.b,Gn=pa.r;ga[28]=258,Gn[258]=28;Ia=ha(ps,0),cA=Ia.b,ra=Ia.r,Rn=new kt(32768);for(Z=0;Z<32768;++Z)_t=(Z&43690)>>1|(Z&21845)<<1,_t=(_t&52428)>>2|(_t&13107)<<2,_t=(_t&61680)>>4|(_t&3855)<<4,Rn[Z]=((_t&65280)>>8|(_t&255)<<8)>>1;Ot=function(c,a,t){for(var e=c.length,i=0,s=new kt(a);i<e;++i)c[i]&&++s[c[i]-1];var n=new kt(a);for(i=1;i<a;++i)n[i]=n[i-1]+s[i-1]<<1;var o;if(t){o=new kt(1<<a);var r=15-a;for(i=0;i<e;++i)if(c[i])for(var A=i<<4|c[i],l=a-c[i],d=n[c[i]-1]++<<l,p=d|(1<<l)-1;d<=p;++d)o[Rn[d]>>r]=A}else for(o=new kt(e),i=0;i<e;++i)c[i]&&(o[i]=Rn[n[c[i]-1]++]>>15-c[i]);return o},de=new At(288);for(Z=0;Z<144;++Z)de[Z]=8;for(Z=144;Z<256;++Z)de[Z]=9;for(Z=256;Z<280;++Z)de[Z]=7;for(Z=280;Z<288;++Z)de[Z]=8;bi=new At(32);for(Z=0;Z<32;++Z)bi[Z]=5;dA=Ot(de,9,0),hA=Ot(de,9,1),pA=Ot(bi,5,0),gA=Ot(bi,5,1),Mn=function(c){for(var a=c[0],t=1;t<c.length;++t)c[t]>a&&(a=c[t]);return a},Gt=function(c,a,t){var e=a/8|0;return(c[e]|c[e+1]<<8)>>(a&7)&t},Tn=function(c,a){var t=a/8|0;return(c[t]|c[t+1]<<8|c[t+2]<<16)>>(a&7)},On=function(c){return(c+7)/8|0},Ni=function(c,a,t){return(a==null||a<0)&&(a=0),(t==null||t>c.length)&&(t=c.length),new At(c.subarray(a,t))},IA=["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"],ut=function(c,a,t){var e=new Error(a||IA[c]);if(e.code=c,Error.captureStackTrace&&Error.captureStackTrace(e,ut),!t)throw e;return e},uA=function(c,a,t,e){var i=c.length,s=e?e.length:0;if(!i||a.f&&!a.l)return t||new At(0);var n=!t,o=n||a.i!=2,r=a.i;n&&(t=new At(i*3));var A=function(ct){var St=t.length;if(ct>St){var st=new At(Math.max(St*2,ct));st.set(t),t=st}},l=a.f||0,d=a.p||0,p=a.b||0,g=a.l,h=a.d,I=a.m,u=a.n,f=i*8;do{if(!g){l=Gt(c,d,1);var C=Gt(c,d+1,3);if(d+=3,C)if(C==1)g=hA,h=gA,I=9,u=5;else if(C==2){var Q=Gt(c,d,31)+257,E=Gt(c,d+10,15)+4,v=Q+Gt(c,d+5,31)+1;d+=14;for(var w=new At(v),D=new At(19),N=0;N<E;++N)D[Un[N]]=Gt(c,d+N*3,7);d+=E*3;for(var P=Mn(D),H=(1<<P)-1,b=Ot(D,P,1),N=0;N<v;){var S=b[Gt(c,d,H)];d+=S&15;var B=S>>4;if(B<16)w[N++]=B;else{var M=0,U=0;for(B==16?(U=3+Gt(c,d,3),d+=2,M=w[N-1]):B==17?(U=3+Gt(c,d,7),d+=3):B==18&&(U=11+Gt(c,d,127),d+=7);U--;)w[N++]=M}}var L=w.subarray(0,Q),W=w.subarray(Q);I=Mn(L),u=Mn(W),g=Ot(L,I,1),h=Ot(W,u,1)}else ut(1);else{var B=On(d)+4,m=c[B-4]|c[B-3]<<8,y=B+m;if(y>i){r&&ut(0);break}o&&A(p+m),t.set(c.subarray(B,y),p),a.b=p+=m,a.p=d=y*8,a.f=l;continue}if(d>f){r&&ut(0);break}}o&&A(p+131072);for(var z=(1<<I)-1,V=(1<<u)-1,R=d;;R=d){var M=g[Tn(c,d)&z],$=M>>4;if(d+=M&15,d>f){r&&ut(0);break}if(M||ut(2),$<256)t[p++]=$;else if($==256){R=d,g=null;break}else{var K=$-254;if($>264){var N=$-257,O=hs[N];K=Gt(c,d,(1<<O)-1)+ga[N],d+=O}var it=h[Tn(c,d)&V],at=it>>4;it||ut(3),d+=it&15;var W=cA[at];if(at>3){var O=ps[at];W+=Tn(c,d)&(1<<O)-1,d+=O}if(d>f){r&&ut(0);break}o&&A(p+131072);var _=p+K;if(p<W){var X=s-W,Bt=Math.min(W,_);for(X+p<0&&ut(3);p<Bt;++p)t[p]=e[X+p]}for(;p<_;++p)t[p]=t[p-W]}}a.l=g,a.p=R,a.b=p,a.f=l,g&&(l=1,a.m=I,a.d=h,a.n=u)}while(!l);return p!=t.length&&n?Ni(t,0,p):t.subarray(0,p)},te=function(c,a,t){t<<=a&7;var e=a/8|0;c[e]|=t,c[e+1]|=t>>8},Si=function(c,a,t){t<<=a&7;var e=a/8|0;c[e]|=t,c[e+1]|=t>>8,c[e+2]|=t>>16},Hn=function(c,a){for(var t=[],e=0;e<c.length;++e)c[e]&&t.push({s:e,f:c[e]});var i=t.length,s=t.slice();if(!i)return{t:fa,l:0};if(i==1){var n=new At(t[0].s+1);return n[t[0].s]=1,{t:n,l:1}}t.sort(function(y,Q){return y.f-Q.f}),t.push({s:-1,f:25001});var o=t[0],r=t[1],A=0,l=1,d=2;for(t[0]={s:-1,f:o.f+r.f,l:o,r};l!=i-1;)o=t[t[A].f<t[d].f?A++:d++],r=t[A!=l&&t[A].f<t[d].f?A++:d++],t[l++]={s:-1,f:o.f+r.f,l:o,r};for(var p=s[0].s,e=1;e<i;++e)s[e].s>p&&(p=s[e].s);var g=new kt(p+1),h=Ln(t[l-1],g,0);if(h>a){var e=0,I=0,u=h-a,f=1<<u;for(s.sort(function(Q,E){return g[E.s]-g[Q.s]||Q.f-E.f});e<i;++e){var C=s[e].s;if(g[C]>a)I+=f-(1<<h-g[C]),g[C]=a;else break}for(I>>=u;I>0;){var B=s[e].s;g[B]<a?I-=1<<a-g[B]++-1:++e}for(;e>=0&&I;--e){var m=s[e].s;g[m]==a&&(--g[m],++I)}h=a}return{t:new At(g),l:h}},Ln=function(c,a,t){return c.s==-1?Math.max(Ln(c.l,a,t+1),Ln(c.r,a,t+1)):a[c.s]=t},Aa=function(c){for(var a=c.length;a&&!c[--a];);for(var t=new kt(++a),e=0,i=c[0],s=1,n=function(r){t[e++]=r},o=1;o<=a;++o)if(c[o]==i&&o!=a)++s;else{if(!i&&s>2){for(;s>138;s-=138)n(32754);s>2&&(n(s>10?s-11<<5|28690:s-3<<5|12305),s=0)}else if(s>3){for(n(i),--s;s>6;s-=6)n(8304);s>2&&(n(s-3<<5|8208),s=0)}for(;s--;)n(i);s=1,i=c[o]}return{c:t.subarray(0,e),n:a}},Di=function(c,a){for(var t=0,e=0;e<a.length;++e)t+=c[e]*a[e];return t},ua=function(c,a,t){var e=t.length,i=On(a+2);c[i]=e&255,c[i+1]=e>>8,c[i+2]=c[i]^255,c[i+3]=c[i+1]^255;for(var s=0;s<e;++s)c[i+s+4]=t[s];return(i+4+e)*8},la=function(c,a,t,e,i,s,n,o,r,A,l){te(a,l++,t),++i[256];for(var d=Hn(i,15),p=d.t,g=d.l,h=Hn(s,15),I=h.t,u=h.l,f=Aa(p),C=f.c,B=f.n,m=Aa(I),y=m.c,Q=m.n,E=new kt(19),v=0;v<C.length;++v)++E[C[v]&31];for(var v=0;v<y.length;++v)++E[y[v]&31];for(var w=Hn(E,7),D=w.t,N=w.l,P=19;P>4&&!D[Un[P-1]];--P);var H=A+5<<3,b=Di(i,de)+Di(s,bi)+n,S=Di(i,p)+Di(s,I)+n+14+3*P+Di(E,D)+2*E[16]+3*E[17]+7*E[18];if(r>=0&&H<=b&&H<=S)return ua(a,l,c.subarray(r,r+A));var M,U,L,W;if(te(a,l,1+(S<b)),l+=2,S<b){M=Ot(p,g,0),U=p,L=Ot(I,u,0),W=I;var z=Ot(D,N,0);te(a,l,B-257),te(a,l+5,Q-1),te(a,l+10,P-4),l+=14;for(var v=0;v<P;++v)te(a,l+3*v,D[Un[v]]);l+=3*P;for(var V=[C,y],R=0;R<2;++R)for(var $=V[R],v=0;v<$.length;++v){var K=$[v]&31;te(a,l,z[K]),l+=D[K],K>15&&(te(a,l,$[v]>>5&127),l+=$[v]>>12)}}else M=dA,U=de,L=pA,W=bi;for(var v=0;v<o;++v){var O=e[v];if(O>255){var K=O>>18&31;Si(a,l,M[K+257]),l+=U[K+257],K>7&&(te(a,l,O>>23&31),l+=hs[K]);var it=O&31;Si(a,l,L[it]),l+=W[it],it>3&&(Si(a,l,O>>5&8191),l+=ps[it])}else Si(a,l,M[O]),l+=U[O]}return Si(a,l,M[256]),l+U[256]},fA=new Kn([65540,131080,131088,131104,262176,1048704,1048832,2114560,2117632]),fa=new At(0),CA=function(c,a,t,e,i,s){var n=s.z||c.length,o=new At(e+n+5*(1+Math.ceil(n/7e3))+i),r=o.subarray(e,o.length-i),A=s.l,l=(s.r||0)&7;if(a){l&&(r[0]=s.r>>3);for(var d=fA[a-1],p=d>>13,g=d&8191,h=(1<<t)-1,I=s.p||new kt(32768),u=s.h||new kt(h+1),f=Math.ceil(t/3),C=2*f,B=function(mt){return(c[mt]^c[mt+1]<<f^c[mt+2]<<C)&h},m=new Kn(25e3),y=new kt(288),Q=new kt(32),E=0,v=0,w=s.i||0,D=0,N=s.w||0,P=0;w+2<n;++w){var H=B(w),b=w&32767,S=u[H];if(I[b]=S,u[H]=b,N<=w){var M=n-w;if((E>7e3||D>24576)&&(M>423||!A)){l=la(c,r,0,m,y,Q,v,D,P,w-P,l),D=E=v=0,P=w;for(var U=0;U<286;++U)y[U]=0;for(var U=0;U<30;++U)Q[U]=0}var L=2,W=0,z=g,V=b-S&32767;if(M>2&&H==B(w-V))for(var R=Math.min(p,M)-1,$=Math.min(32767,w),K=Math.min(258,M);V<=$&&--z&&b!=S;){if(c[w+L]==c[w+L-V]){for(var O=0;O<K&&c[w+O]==c[w+O-V];++O);if(O>L){if(L=O,W=V,O>R)break;for(var it=Math.min(V,O-2),at=0,U=0;U<it;++U){var _=w-V+U&32767,X=I[_],Bt=_-X&32767;Bt>at&&(at=Bt,S=_)}}}b=S,S=I[b],V+=b-S&32767}if(W){m[D++]=268435456|Gn[L]<<18|ra[W];var ct=Gn[L]&31,St=ra[W]&31;v+=hs[ct]+ps[St],++y[257+ct],++Q[St],N=w+L,++E}else m[D++]=c[w],++y[c[w]]}}for(w=Math.max(w,N);w<n;++w)m[D++]=c[w],++y[c[w]];l=la(c,r,A,m,y,Q,v,D,P,w-P,l),A||(s.r=l&7|r[l/8|0]<<3,l-=7,s.h=u,s.p=I,s.i=w,s.w=N)}else{for(var w=s.w||0;w<n+A;w+=65535){var st=w+65535;st>=n&&(r[l/8|0]=A,st=n),l=ua(r,l+1,c.subarray(w,st))}s.i=n}return Ni(o,0,e+On(l)+i)},BA=function(){for(var c=new Int32Array(256),a=0;a<256;++a){for(var t=a,e=9;--e;)t=(t&1&&-306674912)^t>>>1;c[a]=t}return c}(),mA=function(){var c=-1;return{p:function(a){for(var t=c,e=0;e<a.length;++e)t=BA[t&255^a[e]]^t>>>8;c=t},d:function(){return~c}}},QA=function(c,a,t,e,i){if(!i&&(i={l:1},a.dictionary)){var s=a.dictionary.subarray(-32768),n=new At(s.length+c.length);n.set(s),n.set(c,s.length),c=n,i.w=s.length}return CA(c,a.level==null?6:a.level,a.mem==null?i.l?Math.ceil(Math.max(8,Math.min(13,Math.log(c.length)))*1.5):20:12+a.mem,t,e,i)},Ca=function(c,a){var t={};for(var e in c)t[e]=c[e];for(var e in a)t[e]=a[e];return t},Kt=function(c,a){return c[a]|c[a+1]<<8},Dt=function(c,a){return(c[a]|c[a+1]<<8|c[a+2]<<16|c[a+3]<<24)>>>0},Pn=function(c,a){return Dt(c,a)+Dt(c,a+4)*4294967296},It=function(c,a,t){for(;t;++a)c[a]=t,t>>>=8};Ba=function(c,a,t,e){for(var i in c){var s=c[i],n=a+i,o=e;Array.isArray(s)&&(o=Ca(e,s[1]),s=s[0]),ArrayBuffer.isView(s)?t[n]=[s,o]:(t[n+="/"]=[new At(0),o],Ba(s,n,t,e))}},ca=typeof TextEncoder<"u"&&new TextEncoder,qn=typeof TextDecoder<"u"&&new TextDecoder,wA=0;try{qn.decode(fa,{stream:!0}),wA=1}catch{}vA=function(c){for(var a="",t=0;;){var e=c[t++],i=(e>127)+(e>223)+(e>239);if(t+i>c.length)return{s:a,r:Ni(c,t-1)};i?i==3?(e=((e&15)<<18|(c[t++]&63)<<12|(c[t++]&63)<<6|c[t++]&63)-65536,a+=String.fromCharCode(55296|e>>10,56320|e&1023)):i&1?a+=String.fromCharCode((e&31)<<6|c[t++]&63):a+=String.fromCharCode((e&15)<<12|(c[t++]&63)<<6|c[t++]&63):a+=String.fromCharCode(e)}};FA=function(c,a){return a+30+Kt(c,a+26)+Kt(c,a+28)},kA=function(c,a,t){var e=Kt(c,a+28),i=Kt(c,a+30),s=Yn(c.subarray(a+46,a+46+e),!(Kt(c,a+8)&2048)),n=a+46+e,o=SA(c,n,i,t,Dt(c,a+20),Dt(c,a+24),Dt(c,a+42)),r=o[0],A=o[1],l=o[2];return[Kt(c,a+10),r,A,s,n+i+Kt(c,a+32),l]},SA=function(c,a,t,e,i,s,n){var o=i==4294967295,r=s==4294967295,A=n==4294967295,l=a+t,d=o+r+A;if(e&&d){for(;a+4<l;a+=4+Kt(c,a+2))if(Kt(c,a)==1)return[o?Pn(c,a+4+8*r):i,r?Pn(c,a+4):s,A?Pn(c,a+4+8*(r+o)):n,1];e<2&&ut(13)}return[i,s,n,0]},Jn=function(c){var a=0;if(c)for(var t in c){var e=c[t].length;e>65535&&ut(9),a+=e+4}return a},da=function(c,a,t,e,i,s,n,o){var r=e.length,A=t.extra,l=o&&o.length,d=Jn(A);It(c,a,n!=null?33639248:67324752),a+=4,n!=null&&(c[a++]=20,c[a++]=t.os),c[a]=20,a+=2,c[a++]=t.flag<<1|(s<0&&8),c[a++]=i&&8,c[a++]=t.compression&255,c[a++]=t.compression>>8;var p=new Date(t.mtime==null?Date.now():t.mtime),g=p.getFullYear()-1980;if((g<0||g>119)&&ut(10),It(c,a,g<<25|p.getMonth()+1<<21|p.getDate()<<16|p.getHours()<<11|p.getMinutes()<<5|p.getSeconds()>>1),a+=4,s!=-1&&(It(c,a,t.crc),It(c,a+4,s<0?-s-2:s),It(c,a+8,t.size)),It(c,a+12,r),It(c,a+14,d),a+=16,n!=null&&(It(c,a,l),It(c,a+6,t.attrs),It(c,a+10,n),a+=14),c.set(e,a),a+=r,d)for(var h in A){var I=A[h],u=I.length;It(c,a,+h),It(c,a+2,u),c.set(I,a+4),a+=4+u}return l&&(c.set(o,a),a+=l),a},DA=function(c,a,t,e,i){It(c,a,101010256),It(c,a+8,t),It(c,a+10,t),It(c,a+12,e),It(c,a+16,i)}});var Ea={};ii(Ea,{bytesToStr:()=>gs,unzipFiles:()=>Mi,zipFiles:()=>xi});function bA(c){return typeof c=="string"?ds(c):c instanceof Uint8Array?c:new Uint8Array(c)}function xi(c,a=6){let t={};for(let e of c)t[e.name]=[bA(e.data),{level:a}];return Promise.resolve(ma(t,{level:a}))}function gs(c){return Yn(c)}function Mi(c){let a=c instanceof Uint8Array?c:new Uint8Array(c);return Promise.resolve(Qa(a))}var Is=Lt(()=>{"use strict";ya()});var gl={};ii(gl,{default:()=>tn});module.exports=Qr(gl);var T=require("obsidian");rt();var Et=require("obsidian");var ot=require("obsidian");rt();function Ki(c){let a=(c.dateDisplayTimezone||"").trim();return a?{timeZone:a}:{}}function Vt(c,a){try{return new Intl.DateTimeFormat(void 0,a).format(new Date(c))}catch{let{timeZone:t,...e}=a;return new Intl.DateTimeFormat(void 0,e).format(new Date(c))}}function $t(c,a){let t=Ki(a);switch(a.dateDisplayFormat??"locale"){case"iso":return wo(c,a,!0);case"us":return Vt(c,{...t,month:"numeric",day:"numeric",year:"numeric",hour:"numeric",minute:"2-digit"});case"eu":return Vt(c,{...t,day:"numeric",month:"numeric",year:"numeric",hour:"2-digit",minute:"2-digit",hourCycle:"h23"});case"long":return Vt(c,{...t,dateStyle:"full",timeStyle:"short"});case"locale":default:return Vt(c,{...t,dateStyle:"medium",timeStyle:"short"})}}function yo(c,a){let t=Ki(a);switch(a.dateDisplayFormat??"locale"){case"iso":return wo(c,a,!1);case"us":return Vt(c,{...t,month:"numeric",day:"numeric",year:"numeric"});case"eu":return Vt(c,{...t,day:"numeric",month:"numeric",year:"numeric"});case"long":return Vt(c,{...t,dateStyle:"full"});case"locale":default:{let e=new Date,i=new Date(c).getFullYear()===e.getFullYear();return Vt(c,i?{...t,month:"short",day:"numeric"}:{...t,month:"short",day:"numeric",year:"numeric"})}}}function Eo(c,a){let t=Ki(a),e=a.dateDisplayFormat==="iso"||a.dateDisplayFormat==="eu";return Vt(c,{...t,hour:e?"2-digit":"numeric",minute:"2-digit",...e?{hourCycle:"h23"}:{}})}function wo(c,a,t){let e=Ki(a),i=new Intl.DateTimeFormat("en-CA",{...e,year:"numeric",month:"2-digit",day:"2-digit",...t?{hour:"2-digit",minute:"2-digit",hourCycle:"h23"}:{}}).formatToParts(new Date(c)),s=o=>i.find(r=>r.type===o)?.value??"",n=`${s("year")}-${s("month")}-${s("day")}`;return t?`${n} ${s("hour")}:${s("minute")}`:n}function Ae(c,a,t){let e=c.createSpan({cls:"stashpad-count-badge"});t&&e.addClass("is-expanded"),e.setText(a>99?"99+":String(a))}var Ci={pinned:{label:"Pinned",icon:"pin"},shared:{label:"Shared",icon:"users"},tasks:{label:"Tasks",icon:"check-circle-2"}},$i=class extends ot.ItemView{constructor(t,e){super(t);this.plugin=e;this.activePanel="pinned";this.taskFilter="all";this.taskAssignFilter="all";this.taskFolderFilter="all";this.expanded=new Set;this.renderTimer=null;this.sharedAuthorFilter="all";this.sharedContribOnly=!1}setActivePanel(t){this.activePanel=t,this.containerEl.isConnected&&this.render()}getViewType(){return oe}getDisplayText(){return"Stashpad panels"}getIcon(){return"panel-left"}async onOpen(){this.render(),this.registerEvent(this.app.metadataCache.on("changed",()=>this.scheduleRender())),this.registerEvent(this.app.vault.on("rename",()=>this.scheduleRender())),this.registerEvent(this.app.vault.on("delete",()=>this.scheduleRender())),this.registerEvent(this.app.workspace.on("active-leaf-change",t=>{t&&t.view.getViewType()===J&&this.scheduleRender()}))}scheduleRender(){this.renderTimer==null&&(this.renderTimer=window.setTimeout(()=>{this.renderTimer=null,this.containerEl.isConnected&&this.render()},80))}render(){let t=this.contentEl;t.empty(),t.addClass("stashpad-panels-root");let e=t.createDiv({cls:"stashpad-panels-globals"}),i=e.createEl("button",{cls:"stashpad-panels-global-btn"});(0,ot.setIcon)(i.createSpan({cls:"stashpad-panels-global-btn-icon"}),"search"),i.createSpan({cls:"stashpad-panels-global-btn-text",text:"Search"}),i.onclick=()=>this.openSearchFromPanel();let s=e.createEl("button",{cls:"stashpad-panels-global-btn"});(0,ot.setIcon)(s.createSpan({cls:"stashpad-panels-global-btn-icon"}),"folder-tree"),s.createSpan({cls:"stashpad-panels-global-btn-text",text:"Folder Switcher"}),s.onclick=()=>this.plugin.openFolderPicker();let n=e.createDiv({cls:"stashpad-panels-globals-row"}),o=n.createEl("button",{cls:"stashpad-panels-global-btn"});(0,ot.setIcon)(o.createSpan({cls:"stashpad-panels-global-btn-icon"}),"scroll-text"),o.createSpan({cls:"stashpad-panels-global-btn-text",text:"Log"}),o.onclick=()=>this.openLogFromPanel();let r=n.createEl("button",{cls:"stashpad-panels-global-btn"});(0,ot.setIcon)(r.createSpan({cls:"stashpad-panels-global-btn-icon"}),"bell"),r.createSpan({cls:"stashpad-panels-global-btn-text",text:"Notifications"}),r.onclick=()=>this.openNotificationsFromPanel();let A=t.createDiv({cls:"stashpad-panels-bar"});for(let d of Object.keys(Ci)){let p=Ci[d],g=A.createEl("button",{cls:"stashpad-panels-bar-btn"});(0,ot.setIcon)(g.createSpan({cls:"stashpad-panels-bar-btn-icon"}),p.icon),g.createSpan({cls:"stashpad-panels-bar-btn-text",text:p.label}),this.activePanel===d&&g.addClass("is-active"),g.onclick=()=>{this.activePanel!==d&&(this.activePanel=d,this.render())}}let l=t.createDiv({cls:"stashpad-panels-body"});this.activePanel==="pinned"?this.renderPinnedPanel(l):this.activePanel==="shared"?this.renderSharedPanel(l):this.activePanel==="tasks"&&this.renderTasksPanel(l)}openPinnedOptionsMenu(t){let e=this.plugin.settings.folderPanelPinnedGrouping??"pin-order",i=new ot.Menu;i.addItem(s=>s.setTitle("Sort by pin order").setChecked(e==="pin-order").onClick(()=>void this.setPinnedGrouping("pin-order"))),i.addItem(s=>s.setTitle("Group by folder").setChecked(e==="folder").onClick(()=>void this.setPinnedGrouping("folder"))),i.showAtMouseEvent(t)}async setPinnedGrouping(t){(this.plugin.settings.folderPanelPinnedGrouping??"pin-order")!==t&&(this.plugin.settings.folderPanelPinnedGrouping=t,await this.plugin.saveSettings(),this.render())}renderPinnedPanel(t){let e=t.createDiv({cls:"stashpad-panel-pinned"});(this.plugin.settings.folderPanelPinnedGrouping??"pin-order")!=="folder"&&e.addClass("is-flat");let i=e.createDiv({cls:"stashpad-pinned-headrow"}),s=i.createEl("button",{cls:"stashpad-pinned-row stashpad-pinned-home"}),n=s.createSpan({cls:"stashpad-pinned-icon"});(0,ot.setIcon)(n,"home"),s.createSpan({cls:"stashpad-pinned-label",text:"Home"}),s.onclick=()=>this.openHomeFromPanel();let o=i.createEl("button",{cls:"stashpad-folderpanel-iconbtn stashpad-pinned-opts"});(0,ot.setIcon)(o,"list"),o.setAttr("aria-label","Pinned view options"),o.onclick=g=>{g.stopPropagation(),this.openPinnedOptionsMenu(g)};let r=this.plugin.listPinnedNotes();if(r.length===0){e.createDiv({cls:"stashpad-pinned-empty"}).setText("No pinned notes yet \u2014 right-click a note and choose \u201CPin to sidebar.\u201D");return}if((this.plugin.settings.folderPanelPinnedGrouping??"pin-order")!=="folder"){r.forEach((g,h)=>this.renderPinnedRow(e,g,h));return}let l=new Map;r.forEach((g,h)=>{let I=l.get(g.folder);I||(I=[],l.set(g.folder,I)),I.push({pin:g,idx:h})});let d=this.plugin.lastActiveStashpadLeaf?.view?.noteFolder,p=Array.from(l.keys());d&&l.has(d)&&(p.splice(p.indexOf(d),1),p.unshift(d));for(let g of p){let h=g.split("/").pop()||g,I=e.createDiv({cls:"stashpad-pinned-group-header"});g===d&&I.addClass("is-active-folder"),I.createSpan({cls:"stashpad-pinned-group-name",text:h});let u=l.get(g)??[];for(let{pin:f,idx:C}of u)this.renderPinnedRow(e,f,C)}}renderPinnedRow(t,e,i){let s=this.findFileFor(e);if(!s)return;let n=this.app.metadataCache.getFileCache(s)?.frontmatter??{},o=this.titleFromFile(s),r=typeof n.color=="string"?n.color:null,A=n.completed===!0,l=this.childrenOf(e.folder,e.id).length,d=l>0,p=this.expanded.has(`${e.folder}|${e.id}`),g=t.createDiv({cls:"stashpad-pinned-row"});r&&g.addClass("has-color"),A&&g.addClass("is-completed"),g.draggable=!0,g.dataset.pinIdx=String(i),g.addEventListener("dragstart",C=>{C.dataTransfer?.setData("text/plain",String(i)),C.dataTransfer&&(C.dataTransfer.effectAllowed="move"),g.addClass("is-dragging")}),g.addEventListener("dragend",()=>g.removeClass("is-dragging")),g.addEventListener("dragover",C=>{C.preventDefault(),C.dataTransfer&&(C.dataTransfer.dropEffect="move");let B=g.getBoundingClientRect(),m=C.clientY-B.top<B.height/2;g.toggleClass("drop-before",m),g.toggleClass("drop-after",!m)}),g.addEventListener("dragleave",()=>{g.removeClass("drop-before"),g.removeClass("drop-after")}),g.addEventListener("drop",C=>{C.preventDefault(),g.removeClass("drop-before"),g.removeClass("drop-after");let B=parseInt(C.dataTransfer?.getData("text/plain")??"",10);if(!Number.isFinite(B)||B===i)return;let m=g.getBoundingClientRect(),y=C.clientY-m.top<m.height/2;this.reorderPin(B,y?i:i+1)});let h=g.createSpan({cls:"stashpad-pinned-toggle"});d&&(Ae(h,l,p),h.onclick=C=>{C.stopPropagation();let B=`${e.folder}|${e.id}`;this.expanded.has(B)?this.expanded.delete(B):this.expanded.add(B),this.render()});let I=g.createSpan({cls:"stashpad-pinned-icon"});(0,ot.setIcon)(I,d?"folder-tree":"file-text"),r&&(I.style.color=r);let u=g.createSpan({cls:"stashpad-pinned-label",text:o});u.onclick=()=>this.openPinFromPanel(e);let f=e.folder.split("/").pop()||e.folder;if(g.createSpan({cls:"stashpad-pinned-folder",text:f}),g.oncontextmenu=C=>{C.preventDefault();let B=new ot.Menu;B.addItem(m=>m.setTitle("Unpin from sidebar").setIcon("pin-off").onClick(()=>{this.plugin.unpinNote(e)})),B.showAtMouseEvent(C)},d&&p){let C=t.createDiv({cls:"stashpad-pinned-children"});this.renderPinnedSubtree(C,e.folder,e.id,1)}}async reorderPin(t,e){let i=this.plugin.listPinnedNotes();if(t<0||t>=i.length)return;let s=i[t],n=i.filter((d,p)=>p!==t),o=Math.max(0,Math.min(e>t?e-1:e,n.length)),r=n[o-1],A=n[o],l;!r&&!A?l=Date.now():r?A?l=(r.pinnedAt+A.pinnedAt)/2:l=r.pinnedAt+1e3:l=A.pinnedAt-1e3;try{await this.app.fileManager.processFrontMatter(s.file,d=>{d.pinnedAt=l})}catch(d){console.warn("[Stashpad] pin reorder failed",d)}this.render()}renderPinnedSubtree(t,e,i,s){let n=this.childrenOf(e,i);for(let o of n){let r=this.app.metadataCache.getFileCache(o)?.frontmatter??{},A=typeof r.id=="string"?r.id:null;if(!A)continue;let l=typeof r.color=="string"?r.color:null,d=r.completed===!0,p=this.childrenOf(e,A).length,g=p>0,h=this.expanded.has(`${e}|${A}`),I=t.createDiv({cls:"stashpad-pinned-subrow"});d&&I.addClass("is-completed"),I.style.paddingLeft=`${s*16}px`;let u=I.createSpan({cls:"stashpad-pinned-toggle"});g&&(Ae(u,p,h),u.onclick=B=>{B.stopPropagation();let m=`${e}|${A}`;this.expanded.has(m)?this.expanded.delete(m):this.expanded.add(m),this.render()});let f=I.createSpan({cls:"stashpad-pinned-icon"});(0,ot.setIcon)(f,"file-text"),l&&(f.style.color=l);let C=I.createSpan({cls:"stashpad-pinned-label",text:this.titleFromFile(o)});C.onclick=()=>this.openPinFromPanel({folder:e,id:A}),g&&h&&this.renderPinnedSubtree(t,e,A,s+1)}}findFileFor(t){for(let e of this.app.vault.getMarkdownFiles()){if((e.parent?.path?.replace(/\/+$/,"")??"")!==t.folder)continue;if(this.app.metadataCache.getFileCache(e)?.frontmatter?.id===t.id)return e}return null}childrenOf(t,e){let i=[];for(let s of this.app.vault.getMarkdownFiles()){if((s.parent?.path?.replace(/\/+$/,"")??"")!==t)continue;let o=this.app.metadataCache.getFileCache(s)?.frontmatter;if(!o||typeof o.id!="string")continue;let r=o.parent;if(r===e||e===F&&(r==null||r===F)){if(o.id===F)continue;i.push(s)}}return i.sort((s,n)=>{let o=this.app.metadataCache.getFileCache(s)?.frontmatter,r=this.app.metadataCache.getFileCache(n)?.frontmatter,A=o?.created??"",l=r?.created??"";return A.localeCompare(l)}),i}titleFromFile(t){return t.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||t.basename}async openSearchFromPanel(){let t=await this.resolveTargetStashpad();t&&typeof t.openSearchModal=="function"&&t.openSearchModal()}async openLogFromPanel(){let t=this.app.vault.adapter,e=this.plugin.pluginPrivatePath("log.jsonl");if(!await t.exists(e)){new ot.Notice("No log yet \u2014 make some changes first.");return}let i=await t.read(e),{LogModal:s}=await Promise.resolve().then(()=>(Ft(),fi));new s(this.app,i,e).open()}openNotificationsFromPanel(){this.app.commands?.executeCommandById?.("stashpad:stashpad-open-notification-history")}async openHomeFromPanel(){let t=await this.resolveTargetStashpad();t&&typeof t.navigateTo=="function"&&t.navigateTo(F)}async openPinFromPanel(t){await this.plugin.revealNoteByRef(t.folder,t.id)}async resolveTargetStashpad(){let t=this.plugin.lastActiveStashpadLeaf;if(t&&t.view.getViewType()===J)return this.app.workspace.revealLeaf(t),t.view;let e=this.findActiveStashpad();if(e)return e;let i=this.app.workspace.getLeavesOfType(J);return i.length>0?(this.app.workspace.revealLeaf(i[0]),i[0].view):(await this.plugin.activateView({reveal:!0}),this.findActiveStashpad())}findActiveStashpad(){let t=this.app.workspace.activeLeaf;return t&&t.view.getViewType()===J?t.view:null}renderSharedPanel(t){let e=t.createDiv({cls:"stashpad-panel-shared"}),i=(this.plugin.settings.authorId??"").trim();if(!i){e.createDiv({cls:"stashpad-shared-empty"}).setText("Set an author name in Stashpad settings to populate Shared.");return}let s=this.collectSharedNotes(i),n=new Map;for(let d of s){let p=d.authorId;p&&!n.has(p)&&n.set(p,d.authorDisplay||p)}let o=e.createDiv({cls:"stashpad-shared-filters"}),r=(d,p,g)=>{let h=o.createEl("button",{cls:"stashpad-shared-chip",text:d});return p&&h.addClass("is-active"),h.onclick=g,h};if(r("All",this.sharedAuthorFilter==="all",()=>{this.sharedAuthorFilter="all",this.render()}),r("Mine",this.sharedAuthorFilter==="mine",()=>{this.sharedAuthorFilter="mine",this.render()}),r("Others",this.sharedAuthorFilter==="others",()=>{this.sharedAuthorFilter="others",this.render()}),n.size>1){let d=o.createEl("select",{cls:"stashpad-shared-author-select"}),p=d.createEl("option",{text:"Any author"});p.value="__any__";for(let[h,I]of n){let u=d.createEl("option",{text:I});u.value=h}let g=["all","mine","others"].includes(this.sharedAuthorFilter)?"__any__":this.sharedAuthorFilter;d.value=g,d.onchange=()=>{let h=d.value;h==="__any__"?this.sharedAuthorFilter="all":this.sharedAuthorFilter=h,this.render()}}let A=o.createEl("button",{cls:"stashpad-shared-chip",text:"Has contributors"});this.sharedContribOnly&&A.addClass("is-active"),A.onclick=()=>{this.sharedContribOnly=!this.sharedContribOnly,this.render()};let l=s.filter(d=>{if(this.sharedContribOnly&&d.contributorCount===0)return!1;switch(this.sharedAuthorFilter){case"all":return!0;case"mine":return d.authorId===i;case"others":return d.authorId!==i;default:return d.authorId===this.sharedAuthorFilter}});if(l.length===0){e.createDiv({cls:"stashpad-shared-empty"}).setText("No shared notes match the current filters.");return}for(let d of l){let p=e.createDiv({cls:"stashpad-pinned-row stashpad-shared-row"}),g=p.createSpan({cls:"stashpad-pinned-icon"});(0,ot.setIcon)(g,"users"),d.color&&(g.style.color=d.color);let h=p.createSpan({cls:"stashpad-pinned-label",text:d.title});h.onclick=()=>this.openSharedFromPanel(d.folder,d.id);let I=d.folder.split("/").pop()||d.folder;p.createSpan({cls:"stashpad-pinned-folder",text:I}),d.authorDisplay&&p.createSpan({cls:"stashpad-shared-meta"}).setText(d.authorId===i?`you \xB7 ${d.contributorCount} contributor${d.contributorCount===1?"":"s"}`:`by ${d.authorDisplay}${d.contributorCount>0?` \xB7 ${d.contributorCount} contributor${d.contributorCount===1?"":"s"}`:""}`)}}collectSharedNotes(t){let e=this.plugin.discoverStashpadFolders(),i=new Set(e),s=new Map;for(let o of this.app.vault.getMarkdownFiles()){let r=o.parent?.path?.replace(/\/+$/,"")??"";if(!i.has(r))continue;let A=this.app.metadataCache.getFileCache(o)?.frontmatter??{};A.id===F&&s.set(r,this.extractAuthorId(A.author))}let n=[];for(let o of this.app.vault.getMarkdownFiles()){let r=o.parent?.path?.replace(/\/+$/,"")??"";if(!i.has(r)||r.endsWith("/_authors")||o.path.includes("/_authors/"))continue;let A=this.app.metadataCache.getFileCache(o)?.frontmatter??{};if(typeof A.id!="string"||A.id===F)continue;let l=this.extractAuthorId(A.author),d=Array.isArray(A.contributors)?A.contributors.filter(B=>typeof B=="string"):[],p=s.get(r)??null;if(!(d.length>0||p===t&&(l!==null&&l!==t)))continue;let f=this.titleFromFile(o),C=typeof A.color=="string"?A.color:null;n.push({file:o,folder:r,id:A.id,title:f,color:C,authorId:l,authorDisplay:this.extractAuthorDisplay(A.author)||(l??""),contributorCount:d.length})}return n.sort((o,r)=>{let A=this.app.metadataCache.getFileCache(o.file)?.frontmatter??{},l=this.app.metadataCache.getFileCache(r.file)?.frontmatter??{},d=A.modified??A.created??"";return(l.modified??l.created??"").localeCompare(d)}),n}extractAuthorId(t){if(typeof t!="string")return null;let e=t.match(/-([a-z0-9]{4,12})(?:\.md)?(?:\||\]\])/i);return e?e[1]:null}extractAuthorDisplay(t){if(typeof t!="string")return"";let e=t.match(/\|([^\]]+)\]\]/);if(e)return e[1].trim();let i=t.match(/_authors\/([^\]|]+)-[a-z0-9]{4,12}/i);return i?i[1].replace(/[-_]/g," ").trim():""}async openSharedFromPanel(t,e){await this.plugin.revealNoteByRef(t,e)}renderTasksPanel(t){let e=t.createDiv({cls:"stashpad-panel-tasks"}),i=this.collectTasks();if(i.length===0){e.createDiv({cls:"stashpad-tasks-empty"}).setText("No tasks yet \u2014 press H on a note to mark it a task, or D to give it a due date.");return}let s=(this.plugin.settings.authorId??"").trim(),n=S=>!!s&&S.assignedTo.some(M=>M.id===s),o=S=>{let M=this.taskAssignFilter;if(M.startsWith("person:")){let U=M.slice(7);return S.assignedTo.some(L=>L.id===U)}switch(M){case"mine":return n(S);case"others":return S.assignedTo.length>0&&!n(S);case"byme":return!!s&&S.assignedBy?.id===s;case"unassigned":return S.assignedTo.length===0;default:return!0}},r=new Map;for(let S of i){for(let M of S.assignedTo)M.id!==s&&r.set(M.id,M.name);S.assignedBy&&S.assignedBy.id!==s&&r.set(S.assignedBy.id,S.assignedBy.name)}let A=[...r.entries()].map(([S,M])=>({id:S,name:M})).sort((S,M)=>S.name.localeCompare(M.name)),l=e.createDiv({cls:"stashpad-task-assign-bar"});l.createSpan({cls:"stashpad-task-assign-label",text:"Assignment"});let d=l.createEl("select",{cls:"stashpad-task-assign-select"}),p=S=>{let M={all:"Everyone",mine:"Assigned to me",others:"Assigned to others",byme:"Assigned by me",unassigned:"Unassigned"};return S.startsWith("person:")?r.get(S.slice(7))??"Person":M[S]??S},g=S=>{let M=d.createEl("option",{text:p(S),value:S});this.taskAssignFilter===S&&(M.selected=!0)};for(let S of["all","mine","others","byme","unassigned"])g(S);if(A.length>0){let S=d.createEl("optgroup");S.setAttr("label","By person");for(let M of A){let U=S.createEl("option",{text:M.name,value:`person:${M.id}`});this.taskAssignFilter===`person:${M.id}`&&(U.selected=!0)}}d.onchange=()=>{this.taskAssignFilter=d.value,this.render()};let h=[...new Set(i.map(S=>S.folder))].sort((S,M)=>S.localeCompare(M));this.taskFolderFilter!=="all"&&!h.includes(this.taskFolderFilter)&&(this.taskFolderFilter="all");let I=e.createDiv({cls:"stashpad-task-assign-bar"});I.createSpan({cls:"stashpad-task-assign-label",text:"Folder"});let u=I.createEl("select",{cls:"stashpad-task-assign-select"}),f=u.createEl("option",{text:"All folders",value:"all"});this.taskFolderFilter==="all"&&(f.selected=!0);for(let S of h){let M=u.createEl("option",{text:S.split("/").pop()||S,value:S});this.taskFolderFilter===S&&(M.selected=!0)}u.onchange=()=>{this.taskFolderFilter=u.value,this.render()};let C=S=>this.taskFolderFilter==="all"||S.folder===this.taskFolderFilter,B=i.filter(S=>o(S)&&C(S));if(B.length===0){e.createDiv({cls:"stashpad-tasks-empty"}).setText("No tasks match the current filters.");return}let m=new Date;m.setHours(0,0,0,0);let y=m.getTime(),Q=y+24*60*60*1e3,E={overdue:[],today:[],upcoming:[],nodate:[],completed:[]};for(let S of B){if(S.completed){E.completed.push(S);continue}if(S.due==null){E.nodate.push(S);continue}S.due<y?E.overdue.push(S):S.due<Q?E.today.push(S):E.upcoming.push(S)}let v=(S,M)=>S.due==null&&M.due==null?S.title.localeCompare(M.title):S.due==null?1:M.due==null?-1:S.due-M.due,w=[{key:"overdue",label:"Overdue",icon:"alert-circle"},{key:"today",label:"Due today",icon:"calendar-clock"},{key:"upcoming",label:"Upcoming",icon:"calendar"},{key:"nodate",label:"No date",icon:"inbox"},{key:"completed",label:"Completed",icon:"check-circle-2"}],D=e.createDiv({cls:"stashpad-task-filters"}),N=B.length,P=(S,M,U)=>{let L=D.createEl("button",{cls:"stashpad-task-filter"});this.taskFilter===S&&L.addClass("is-active"),L.createSpan({cls:"stashpad-task-filter-label",text:M}),L.createSpan({cls:"stashpad-task-filter-count",text:String(U)}),L.onclick=()=>{this.taskFilter=S,this.render()}};P("all","All",N),P("overdue","Overdue",E.overdue.length),P("today","Today",E.today.length),P("upcoming","Upcoming",E.upcoming.length),P("nodate","No date",E.nodate.length),P("completed","Done",E.completed.length);let H=this.taskFilter==="all"?w:w.filter(S=>S.key===this.taskFilter),b=!1;for(let S of H){let M=E[S.key];if(M.length!==0){if(b=!0,M.sort(S.key==="completed"?(U,L)=>v(L,U):v),this.taskFilter==="all"){let U=e.createDiv({cls:`stashpad-task-section-header is-${S.key}`});(0,ot.setIcon)(U.createSpan({cls:"stashpad-task-section-icon"}),S.icon),U.createSpan({cls:"stashpad-task-section-name",text:S.label}),U.createSpan({cls:"stashpad-task-section-count",text:String(M.length)})}for(let U of M)this.renderTaskRow(e,U,S.key==="today")}}if(!b&&this.taskFilter!=="all"){e.createDiv({cls:"stashpad-tasks-empty"}).setText(`Nothing in "${H[0]?.label??this.taskFilter}".`);return}b||e.createDiv({cls:"stashpad-tasks-empty"}).setText("No tasks to show.")}renderTaskRow(t,e,i){let s=t.createDiv({cls:"stashpad-pinned-row stashpad-task-row"});e.color&&s.addClass("has-color"),e.completed&&s.addClass("is-completed");let n=s.createSpan({cls:"stashpad-pinned-icon stashpad-task-checkbox"});(0,ot.setIcon)(n,e.completed?"check-square":"square"),e.color&&(n.style.color=e.color),n.title=e.completed?"Mark not done":"Mark done",n.onclick=r=>{r.stopPropagation(),this.toggleTaskCompleted(e)};let o=s.createSpan({cls:"stashpad-pinned-label",text:e.title});if(o.onclick=()=>this.openTaskFromPanel(e.folder,e.id),s.createSpan({cls:"stashpad-task-folder",text:e.folder.split("/").pop()||e.folder}),e.due!=null){let r=s.createSpan({cls:"stashpad-task-due",text:this.formatDueShort(e.due,i)});e.due<Date.now()&&!e.completed&&r.addClass("is-overdue")}else e.dueRaw&&s.createSpan({cls:"stashpad-task-due",text:e.dueRaw});if(e.assignedTo.length>0){let r=(this.plugin.settings.authorId??"").trim(),A=s.createSpan({cls:"stashpad-task-assignees"});for(let l of e.assignedTo){let d=A.createSpan({cls:"stashpad-task-assignee"});r&&l.id===r&&d.addClass("is-me"),d.setText(this.initials(l.name)),d.title=r&&l.id===r?`${l.name} (you)`:l.name}}s.oncontextmenu=r=>{r.preventDefault();let A=new ot.Menu;A.addItem(l=>l.setTitle("Open").setIcon("arrow-right").onClick(()=>{this.openTaskFromPanel(e.folder,e.id)})),A.showAtMouseEvent(r)}}formatDueShort(t,e){return e?Eo(t,this.plugin.settings):yo(t,this.plugin.settings)}async openTaskFromPanel(t,e){await this.plugin.revealNoteByRef(t,e)}async toggleTaskCompleted(t){try{await this.app.fileManager.processFrontMatter(t.file,e=>{e.completed=e.completed!==!0})}catch(e){new ot.Notice(`Couldn't update task: ${e.message}`);return}this.scheduleRender()}initials(t){let e=t.trim().split(/\s+/).filter(Boolean);return e.length===0?"?":e.length===1?e[0].slice(0,2).toUpperCase():(e[0][0]+e[e.length-1][0]).toUpperCase()}collectTasks(){let t=this.plugin.discoverStashpadFolders(),e=new Set(t),i=[];for(let s of this.app.vault.getMarkdownFiles()){let n=s.parent?.path?.replace(/\/+$/,"")??"";if(!e.has(n))continue;let o=this.app.metadataCache.getFileCache(s)?.frontmatter??{},r=typeof o.id=="string"?o.id:null;if(!r||r===F)continue;let A=o.completed===!0,l=Te(o,"task")||o.task===!0||o.completed!==void 0,d=typeof o.due=="string"||typeof o.due=="number"?String(o.due):null,p=null;if(d){let g=Date.parse(d);Number.isNaN(g)||(p=g)}!l&&!A&&p==null&&!d||i.push({file:s,folder:n,id:r,title:this.titleFromFile(s),task:l,completed:A,due:p,dueRaw:d,color:typeof o.color=="string"?o.color:null,assignedTo:we(o),assignedBy:re(o.assignedBy)})}return i}};async function Wi(c){let a=c.workspace.getLeavesOfType(oe);if(a.length>0){c.workspace.revealLeaf(a[0]);return}let t=c.workspace.getLeftLeaf(!1);if(!t){new ot.Notice("Stashpad: couldn't open the panels view.");return}await t.setViewState({type:oe,active:!0}),c.workspace.revealLeaf(t)}var Ja=require("obsidian");rt();var x=require("obsidian");mi();var _i=require("obsidian");rt();var qe=class extends _i.AbstractInputSuggest{constructor(t,e){super(t,e);this.inputEl=e}getSuggestions(t){let e=t.toLowerCase().split(/\s+/).filter(Boolean),i=o=>e.every(r=>o.toLowerCase().includes(r)),s=[],n=o=>{if(!(o.path!=="/"&&si.has(o.name))){o.path!=="/"&&i(o.path)&&s.push(o);for(let r of o.children)r instanceof _i.TFolder&&n(r)}};return n(this.app.vault.getRoot()),s.slice(0,100)}renderSuggestion(t,e){e.setText(t.path)}selectSuggestion(t){this.setValue(t.path),this.inputEl.dispatchEvent(new Event("input",{bubbles:!0})),this.close()}};rt();Ft();var be=require("obsidian"),In={create:{label:"Create",desc:"Confirmations after a new note is created."},edit:{label:"Edit",desc:"Edit-related toasts (currently rare)."},delete:{label:"Delete",desc:"Confirmations after deleting one or more notes."},move:{label:"Move",desc:"After reparenting or moving notes between folders."},merge:{label:"Merge",desc:"After combining multiple notes into one."},split:{label:"Split",desc:"After splitting a note in two."},clone:{label:"Clone",desc:"After duplicating notes or subtrees."},complete:{label:"Complete",desc:"When a note is marked complete."},uncomplete:{label:"Uncomplete",desc:"When a note's complete mark is removed."},export:{label:"Export",desc:".stash exports \u2014 success + the action buttons."},import:{label:"Import",desc:".stash imports (both manual and the drop-folder auto-import)."},attachment:{label:"Attachment",desc:"Attachment add / remove notifications."},color:{label:"Color",desc:"Per-note color changes."},reorder:{label:"Reorder",desc:"Drag-reorder and keyboard moveUp/Down/Top/Bottom."},multiplayer:{label:"Multiplayer",desc:"Cross-author activity (someone else touched your notes or vice versa)."},reminder:{label:"Reminder",desc:"Task due-date reminders \u2014 surfaced when a task comes due (fired at launch / periodically)."},system:{label:"System",desc:"Plumbing toasts: backfill progress, integrity warnings, errors not tied to a verb."}},xr={info:4e3,success:4e3,warning:6e3,error:1e4},Lo=5e3,ts=class{constructor(a){this.app=a;this.history=[];this.nextId=1;this.historyLimit=Lo;this.changeListeners=new Set;this.muted=new Set;this.defaultAuthorId=null}setDefaultAuthorId(a){this.defaultAuthorId=a||null}show(a){let t=a.kind??"info",e=a.category??"system",i={id:this.nextId++,ts:Date.now(),message:a.message,kind:t,category:e,authorId:a.authorId??this.defaultAuthorId??void 0,affectedIds:a.affectedIds?a.affectedIds.slice():[],affectedPaths:a.affectedPaths?a.affectedPaths.slice():[],affectedAuthorIds:a.affectedAuthorIds?a.affectedAuthorIds.slice():[],folder:a.folder,actionLabels:(a.actions??[]).map(o=>o.label)};if(this.pushHistory(i),this.muted.has(e))return null;let s=this.buildContent(a,t),n=a.duration??xr[t];return new be.Notice(s,n)}onChange(a){return this.changeListeners.add(a),()=>this.changeListeners.delete(a)}recent(){return this.history.slice().reverse()}clearHistory(){this.history=[],this.emit()}setMuted(a,t){t?this.muted.add(a):this.muted.delete(a)}isMuted(a){return this.muted.has(a)}loadMutedFromList(a){this.muted=new Set(a)}mutedList(){return Array.from(this.muted)}loadHistory(a){let t=this.applyLimit(a.slice());this.history=t;let e=0;for(let i of t)i.id>e&&(e=i.id);this.nextId=Math.max(this.nextId,e+1),this.emit()}setHistoryLimit(a){this.historyLimit=Number.isFinite(a)?a:Lo,this.history=this.applyLimit(this.history),this.emit()}applyLimit(a){return this.historyLimit<=0||a.length<=this.historyLimit?a:a.slice(a.length-this.historyLimit)}pushHistory(a){this.history.push(a),this.history=this.applyLimit(this.history),this.emit()}emit(){for(let a of this.changeListeners)try{a()}catch(t){console.warn("[Stashpad] notification listener failed",t)}}buildContent(a,t){let e=document.createDocumentFragment(),i=document.createElement("div");i.className=`stashpad-notice stashpad-notice-${t}`;let s=document.createElement("div");s.className="stashpad-notice-message";let n=a.message.split(/(`[^`\n]+`)/);for(let o of n)if(o.length>1&&o.startsWith("`")&&o.endsWith("`")){let r=document.createElement("code");r.textContent=o.slice(1,-1),s.appendChild(r)}else o.length>0&&s.appendChild(document.createTextNode(o));if(i.appendChild(s),a.actions&&a.actions.length>0){let o=document.createElement("div");o.className="stashpad-notice-actions";for(let r of a.actions){let A=document.createElement("button");A.className="stashpad-notice-action",A.textContent=r.label,A.addEventListener("click",l=>{if(l.stopPropagation(),Promise.resolve().then(()=>r.onClick()).catch(d=>console.warn("[Stashpad] notification action failed",d)),!r.keepOpen){let d=A.closest(".notice");d&&d.parentElement&&d.parentElement.removeChild(d)}}),o.appendChild(A)}i.appendChild(o)}return e.appendChild(i),e}};function es(c,a,t){let e=c.vault.getAbstractFileByPath(a);if(!(e instanceof be.TFile))return[];let i=[{label:"Reveal",keepOpen:!0,onClick:()=>{let s=c.workspace.getLeavesOfType("file-explorer")[0];if(!s)return;c.workspace.revealLeaf(s),s.view?.revealInFolder?.(e)}}];if(!t){let s=be.Platform.isMacOS?"Finder":be.Platform.isWin?"File Explorer":"file manager";i.push({label:`Show in ${s}`,keepOpen:!0,onClick:()=>{try{let n=window.require?.("electron")?.shell,r=c.vault.adapter?.getFullPath?.(a);r&&n?.showItemInFolder&&n.showItemInFolder(r)}catch(n){console.warn("[Stashpad] showItemInFolder failed",n)}}})}return i}var qo=require("obsidian"),un=qo.Platform.isMacOS;function Qi(c){if(!c)return"(none)";let a=c.replace(/\bMod\b/g,un?"Cmd":"Ctrl");return un&&(a=a.replace(/\bAlt\b/g,"Option")),a}function Jo(c,a,t={allowSingleKey:!0}){let e=c.placeholder,i=c.value;c.placeholder="Press a key\u2026 (Backspace to cancel)",c.value="",c.classList.add("is-recording");let s=!1,n=()=>{c.placeholder=e,c.classList.remove("is-recording"),s||(c.value=i),c.removeEventListener("keydown",o,!0),c.removeEventListener("blur",r)},o=A=>{if(A.key==="Control"||A.key==="Shift"||A.key==="Alt"||A.key==="Meta"||A.key==="OS")return;let l=!!A.code&&(/^Key[A-Z]$/.test(A.code)||/^Digit\d$/.test(A.code));if((A.key==="Dead"||A.key==="Process"||A.key==="Unidentified")&&!l)return;if(A.preventDefault(),A.stopPropagation(),A.key==="Backspace"&&!A.metaKey&&!A.ctrlKey&&!A.altKey&&!A.shiftKey){n();return}let d=[];un?(A.metaKey&&d.push("Mod"),A.ctrlKey&&d.push("Ctrl")):A.ctrlKey&&d.push("Mod"),A.altKey&&d.push("Alt"),A.shiftKey&&d.push("Shift");let p=Mr(A.key,A.code);if(!p||d.length===0&&!t.allowSingleKey)return;d.push(p);let g=d.join("+");s=!0,n(),a(g)},r=()=>n();return c.addEventListener("keydown",o,!0),c.addEventListener("blur",r),n}function Mr(c,a){if(!c)return"";if(a){let t=/^Key([A-Z])$/.exec(a);if(t)return t[1];let e=/^Digit(\d)$/.exec(a);if(e)return e[1]}return c.length===1?c.toUpperCase():c}Re();Tt();function Ne(c,a,t,e){function i(s){return s instanceof t?s:new t(function(n){n(s)})}return new(t||(t=Promise))(function(s,n){function o(l){try{A(e.next(l))}catch(d){n(d)}}function r(l){try{A(e.throw(l))}catch(d){n(d)}}function A(l){l.done?s(l.value):i(l.value).then(o,r)}A((e=e.apply(c,a||[])).next())})}var nt=class{constructor(){this.mutex=Promise.resolve()}lock(){let a=()=>{};return this.mutex=this.mutex.then(()=>new Promise(a)),new Promise(t=>{a=t})}dispatch(a){return Ne(this,void 0,void 0,function*(){let t=yield this.lock();try{return yield Promise.resolve(a())}finally{t()}})}},fn;function Tr(){return typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:global}var Qn=Tr(),Cn=(fn=Qn.Buffer)!==null&&fn!==void 0?fn:null,Hr=Qn.TextEncoder?new Qn.TextEncoder:null;function $o(c,a){return(c&15)+(c>>6|c>>3&8)<<4|(a&15)+(a>>6|a>>3&8)}function Wo(c,a){let t=a.length>>1;for(let e=0;e<t;e++){let i=e<<1;c[e]=$o(a.charCodeAt(i),a.charCodeAt(i+1))}}function Pr(c,a){if(c.length!==a.length*2)return!1;for(let t=0;t<a.length;t++){let e=t<<1;if(a[t]!==$o(c.charCodeAt(e),c.charCodeAt(e+1)))return!1}return!0}var Ko=87,Oo=48;function yn(c,a,t){let e=0;for(let i=0;i<t;i++){let s=a[i]>>>4;c[e++]=s>9?s+Ko:s+Oo,s=a[i]&15,c[e++]=s>9?s+Ko:s+Oo}return String.fromCharCode.apply(null,c)}var Xt=Cn!==null?c=>{if(typeof c=="string"){let a=Cn.from(c,"utf8");return new Uint8Array(a.buffer,a.byteOffset,a.length)}if(Cn.isBuffer(c))return new Uint8Array(c.buffer,c.byteOffset,c.length);if(ArrayBuffer.isView(c))return new Uint8Array(c.buffer,c.byteOffset,c.byteLength);throw new Error("Invalid data type!")}:c=>{if(typeof c=="string")return Hr.encode(c);if(ArrayBuffer.isView(c))return new Uint8Array(c.buffer,c.byteOffset,c.byteLength);throw new Error("Invalid data type!")},Ht="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",Ei=new Uint8Array(256);for(let c=0;c<Ht.length;c++)Ei[Ht.charCodeAt(c)]=c;function Yo(c,a=!0){let t=c.length,e=t%3,i=[],s=t-e;for(let n=0;n<s;n+=3){let o=(c[n]<<16&16711680)+(c[n+1]<<8&65280)+(c[n+2]&255),r=Ht.charAt(o>>18&63)+Ht.charAt(o>>12&63)+Ht.charAt(o>>6&63)+Ht.charAt(o&63);i.push(r)}if(e===1){let n=c[t-1],o=Ht.charAt(n>>2),r=Ht.charAt(n<<4&63);i.push(`${o}${r}`),a&&i.push("==")}else if(e===2){let n=(c[t-2]<<8)+c[t-1],o=Ht.charAt(n>>10),r=Ht.charAt(n>>4&63),A=Ht.charAt(n<<2&63);i.push(`${o}${r}${A}`),a&&i.push("=")}return i.join("")}function Ur(c){let a=Math.floor(c.length*.75),t=c.length;return c[t-1]==="="&&(a-=1,c[t-2]==="="&&(a-=1)),a}function Gr(c){let a=Ur(c),t=c.length,e=new Uint8Array(a),i=0;for(let s=0;s<t;s+=4){let n=Ei[c.charCodeAt(s)],o=Ei[c.charCodeAt(s+1)],r=Ei[c.charCodeAt(s+2)],A=Ei[c.charCodeAt(s+3)];e[i]=n<<2|o>>4,i+=1,e[i]=(o&15)<<4|r>>2,i+=1,e[i]=(r&3)<<6|A&63,i+=1}return e}var is=16*1024,yi=4,Rr=new nt,Bn=new Map;function Xo(c,a){return Ne(this,void 0,void 0,function*(){let t=null,e=null,i=!1;if(typeof WebAssembly>"u")throw new Error("WebAssembly is not supported in this environment!");let s=(Q,E=0)=>{e.set(Q,E)},n=()=>e,o=()=>t.exports,r=Q=>{t.exports.Hash_SetMemorySize(Q);let E=t.exports.Hash_GetBuffer(),v=t.exports.memory.buffer;e=new Uint8Array(v,E,Q)},A=()=>new DataView(t.exports.memory.buffer).getUint32(t.exports.STATE_SIZE,!0),l=Rr.dispatch(()=>Ne(this,void 0,void 0,function*(){if(!Bn.has(c.name)){let E=Gr(c.data),v=WebAssembly.compile(E);Bn.set(c.name,v)}let Q=yield Bn.get(c.name);t=yield WebAssembly.instantiate(Q,{})})),d=()=>Ne(this,void 0,void 0,function*(){t||(yield l);let Q=t.exports.Hash_GetBuffer(),E=t.exports.memory.buffer;e=new Uint8Array(E,Q,is)}),p=(Q=null)=>{i=!0,t.exports.Hash_Init(Q)},g=Q=>{let E=0;for(;E<Q.length;){let v=Q.subarray(E,E+is);E+=v.length,e.set(v),t.exports.Hash_Update(v.length)}},h=Q=>{if(!i)throw new Error("update() called before init()");let E=Xt(Q);g(E)},I=new Uint8Array(a*2),u=(Q,E=null)=>{if(!i)throw new Error("digest() called before init()");return i=!1,t.exports.Hash_Final(E),Q==="binary"?e.slice(0,a):yn(I,e,a)},f=()=>{if(!i)throw new Error("save() can only be called after init() and before digest()");let Q=t.exports.Hash_GetState(),E=A(),v=t.exports.memory.buffer,w=new Uint8Array(v,Q,E),D=new Uint8Array(yi+E);return Wo(D,c.hash),D.set(w,yi),D},C=Q=>{if(!(Q instanceof Uint8Array))throw new Error("load() expects an Uint8Array generated by save()");let E=t.exports.Hash_GetState(),v=A(),w=yi+v,D=t.exports.memory.buffer;if(Q.length!==w)throw new Error(`Bad state length (expected ${w} bytes, got ${Q.length})`);if(!Pr(c.hash,Q.subarray(0,yi)))throw new Error("This state was written by an incompatible hash implementation");let N=Q.subarray(yi);new Uint8Array(D,E,v).set(N),i=!0},B=Q=>typeof Q=="string"?Q.length<is/4:Q.byteLength<is,m=B;switch(c.name){case"argon2":case"scrypt":m=()=>!0;break;case"blake2b":case"blake2s":m=(Q,E)=>E<=512&&B(Q);break;case"blake3":m=(Q,E)=>E===0&&B(Q);break;case"xxhash64":case"xxhash3":case"xxhash128":case"crc64":m=()=>!1;break}let y=(Q,E=null,v=null)=>{if(!m(Q,E))return p(E),h(Q),u("hex",v);let w=Xt(Q);return e.set(w),t.exports.Hash_Calculate(w.length,E,v),yn(I,e,a)};return yield d(),{getMemory:n,writeMemory:s,getExports:o,setMemorySize:r,init:p,update:h,digest:u,save:f,load:C,calculate:y,hashLength:a}})}var Kl=new nt;var Lr="argon2",qr="AGFzbQEAAAABKQVgAX8Bf2AAAX9gEH9/f39/f39/f39/f39/f38AYAR/f39/AGACf38AAwYFAAECAwQFBgEBAoCAAgYIAX8BQZCoBAsHQQQGbWVtb3J5AgASSGFzaF9TZXRNZW1vcnlTaXplAAAOSGFzaF9HZXRCdWZmZXIAAQ5IYXNoX0NhbGN1bGF0ZQAECvEyBVgBAn9BACEBAkAgAEEAKAKICCICRg0AAkAgACACayIAQRB2IABBgIB8cSAASWoiAEAAQX9HDQBB/wHADwtBACEBQQBBACkDiAggAEEQdK18NwOICAsgAcALcAECfwJAQQAoAoAIIgANAEEAPwBBEHQiADYCgAhBACgCiAgiAUGAgCBGDQACQEGAgCAgAWsiAEEQdiAAQYCAfHEgAElqIgBAAEF/Rw0AQQAPC0EAQQApA4gIIABBEHStfDcDiAhBACgCgAghAAsgAAvcDgECfiAAIAQpAwAiECAAKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAMIBAgDCkDAIVCIIkiEDcDACAIIBAgCCkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgBCAQIAQpAwCFQiiJIhA3AwAgACAQIAApAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIAwgECAMKQMAhUIwiSIQNwMAIAggECAIKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAEIBAgBCkDAIVCAYk3AwAgASAFKQMAIhAgASkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgDSAQIA0pAwCFQiCJIhA3AwAgCSAQIAkpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAUgECAFKQMAhUIoiSIQNwMAIAEgECABKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACANIBAgDSkDAIVCMIkiEDcDACAJIBAgCSkDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgBSAQIAUpAwCFQgGJNwMAIAIgBikDACIQIAIpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIA4gECAOKQMAhUIgiSIQNwMAIAogECAKKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAGIBAgBikDAIVCKIkiEDcDACACIBAgAikDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgDiAQIA4pAwCFQjCJIhA3AwAgCiAQIAopAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIAYgECAGKQMAhUIBiTcDACADIAcpAwAiECADKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAPIBAgDykDAIVCIIkiEDcDACALIBAgCykDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgByAQIAcpAwCFQiiJIhA3AwAgAyAQIAMpAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIA8gECAPKQMAhUIwiSIQNwMAIAsgECALKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAHIBAgBykDAIVCAYk3AwAgACAFKQMAIhAgACkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgDyAQIA8pAwCFQiCJIhA3AwAgCiAQIAopAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAUgECAFKQMAhUIoiSIQNwMAIAAgECAAKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAPIBAgDykDAIVCMIkiEDcDACAKIBAgCikDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgBSAQIAUpAwCFQgGJNwMAIAEgBikDACIQIAEpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAwgECAMKQMAhUIgiSIQNwMAIAsgECALKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAGIBAgBikDAIVCKIkiEDcDACABIBAgASkDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgDCAQIAwpAwCFQjCJIhA3AwAgCyAQIAspAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIAYgECAGKQMAhUIBiTcDACACIAcpAwAiECACKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACANIBAgDSkDAIVCIIkiEDcDACAIIBAgCCkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgByAQIAcpAwCFQiiJIhA3AwAgAiAQIAIpAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIA0gECANKQMAhUIwiSIQNwMAIAggECAIKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAHIBAgBykDAIVCAYk3AwAgAyAEKQMAIhAgAykDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgDiAQIA4pAwCFQiCJIhA3AwAgCSAQIAkpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAQgECAEKQMAhUIoiSIQNwMAIAMgECADKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAOIBAgDikDAIVCMIkiEDcDACAJIBAgCSkDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgBCAQIAQpAwCFQgGJNwMAC98aAQN/QQAhBEEAIAIpAwAgASkDAIU3A5AIQQAgAikDCCABKQMIhTcDmAhBACACKQMQIAEpAxCFNwOgCEEAIAIpAxggASkDGIU3A6gIQQAgAikDICABKQMghTcDsAhBACACKQMoIAEpAyiFNwO4CEEAIAIpAzAgASkDMIU3A8AIQQAgAikDOCABKQM4hTcDyAhBACACKQNAIAEpA0CFNwPQCEEAIAIpA0ggASkDSIU3A9gIQQAgAikDUCABKQNQhTcD4AhBACACKQNYIAEpA1iFNwPoCEEAIAIpA2AgASkDYIU3A/AIQQAgAikDaCABKQNohTcD+AhBACACKQNwIAEpA3CFNwOACUEAIAIpA3ggASkDeIU3A4gJQQAgAikDgAEgASkDgAGFNwOQCUEAIAIpA4gBIAEpA4gBhTcDmAlBACACKQOQASABKQOQAYU3A6AJQQAgAikDmAEgASkDmAGFNwOoCUEAIAIpA6ABIAEpA6ABhTcDsAlBACACKQOoASABKQOoAYU3A7gJQQAgAikDsAEgASkDsAGFNwPACUEAIAIpA7gBIAEpA7gBhTcDyAlBACACKQPAASABKQPAAYU3A9AJQQAgAikDyAEgASkDyAGFNwPYCUEAIAIpA9ABIAEpA9ABhTcD4AlBACACKQPYASABKQPYAYU3A+gJQQAgAikD4AEgASkD4AGFNwPwCUEAIAIpA+gBIAEpA+gBhTcD+AlBACACKQPwASABKQPwAYU3A4AKQQAgAikD+AEgASkD+AGFNwOICkEAIAIpA4ACIAEpA4AChTcDkApBACACKQOIAiABKQOIAoU3A5gKQQAgAikDkAIgASkDkAKFNwOgCkEAIAIpA5gCIAEpA5gChTcDqApBACACKQOgAiABKQOgAoU3A7AKQQAgAikDqAIgASkDqAKFNwO4CkEAIAIpA7ACIAEpA7AChTcDwApBACACKQO4AiABKQO4AoU3A8gKQQAgAikDwAIgASkDwAKFNwPQCkEAIAIpA8gCIAEpA8gChTcD2ApBACACKQPQAiABKQPQAoU3A+AKQQAgAikD2AIgASkD2AKFNwPoCkEAIAIpA+ACIAEpA+AChTcD8ApBACACKQPoAiABKQPoAoU3A/gKQQAgAikD8AIgASkD8AKFNwOAC0EAIAIpA/gCIAEpA/gChTcDiAtBACACKQOAAyABKQOAA4U3A5ALQQAgAikDiAMgASkDiAOFNwOYC0EAIAIpA5ADIAEpA5ADhTcDoAtBACACKQOYAyABKQOYA4U3A6gLQQAgAikDoAMgASkDoAOFNwOwC0EAIAIpA6gDIAEpA6gDhTcDuAtBACACKQOwAyABKQOwA4U3A8ALQQAgAikDuAMgASkDuAOFNwPIC0EAIAIpA8ADIAEpA8ADhTcD0AtBACACKQPIAyABKQPIA4U3A9gLQQAgAikD0AMgASkD0AOFNwPgC0EAIAIpA9gDIAEpA9gDhTcD6AtBACACKQPgAyABKQPgA4U3A/ALQQAgAikD6AMgASkD6AOFNwP4C0EAIAIpA/ADIAEpA/ADhTcDgAxBACACKQP4AyABKQP4A4U3A4gMQQAgAikDgAQgASkDgASFNwOQDEEAIAIpA4gEIAEpA4gEhTcDmAxBACACKQOQBCABKQOQBIU3A6AMQQAgAikDmAQgASkDmASFNwOoDEEAIAIpA6AEIAEpA6AEhTcDsAxBACACKQOoBCABKQOoBIU3A7gMQQAgAikDsAQgASkDsASFNwPADEEAIAIpA7gEIAEpA7gEhTcDyAxBACACKQPABCABKQPABIU3A9AMQQAgAikDyAQgASkDyASFNwPYDEEAIAIpA9AEIAEpA9AEhTcD4AxBACACKQPYBCABKQPYBIU3A+gMQQAgAikD4AQgASkD4ASFNwPwDEEAIAIpA+gEIAEpA+gEhTcD+AxBACACKQPwBCABKQPwBIU3A4ANQQAgAikD+AQgASkD+ASFNwOIDUEAIAIpA4AFIAEpA4AFhTcDkA1BACACKQOIBSABKQOIBYU3A5gNQQAgAikDkAUgASkDkAWFNwOgDUEAIAIpA5gFIAEpA5gFhTcDqA1BACACKQOgBSABKQOgBYU3A7ANQQAgAikDqAUgASkDqAWFNwO4DUEAIAIpA7AFIAEpA7AFhTcDwA1BACACKQO4BSABKQO4BYU3A8gNQQAgAikDwAUgASkDwAWFNwPQDUEAIAIpA8gFIAEpA8gFhTcD2A1BACACKQPQBSABKQPQBYU3A+ANQQAgAikD2AUgASkD2AWFNwPoDUEAIAIpA+AFIAEpA+AFhTcD8A1BACACKQPoBSABKQPoBYU3A/gNQQAgAikD8AUgASkD8AWFNwOADkEAIAIpA/gFIAEpA/gFhTcDiA5BACACKQOABiABKQOABoU3A5AOQQAgAikDiAYgASkDiAaFNwOYDkEAIAIpA5AGIAEpA5AGhTcDoA5BACACKQOYBiABKQOYBoU3A6gOQQAgAikDoAYgASkDoAaFNwOwDkEAIAIpA6gGIAEpA6gGhTcDuA5BACACKQOwBiABKQOwBoU3A8AOQQAgAikDuAYgASkDuAaFNwPIDkEAIAIpA8AGIAEpA8AGhTcD0A5BACACKQPIBiABKQPIBoU3A9gOQQAgAikD0AYgASkD0AaFNwPgDkEAIAIpA9gGIAEpA9gGhTcD6A5BACACKQPgBiABKQPgBoU3A/AOQQAgAikD6AYgASkD6AaFNwP4DkEAIAIpA/AGIAEpA/AGhTcDgA9BACACKQP4BiABKQP4BoU3A4gPQQAgAikDgAcgASkDgAeFNwOQD0EAIAIpA4gHIAEpA4gHhTcDmA9BACACKQOQByABKQOQB4U3A6APQQAgAikDmAcgASkDmAeFNwOoD0EAIAIpA6AHIAEpA6AHhTcDsA9BACACKQOoByABKQOoB4U3A7gPQQAgAikDsAcgASkDsAeFNwPAD0EAIAIpA7gHIAEpA7gHhTcDyA9BACACKQPAByABKQPAB4U3A9APQQAgAikDyAcgASkDyAeFNwPYD0EAIAIpA9AHIAEpA9AHhTcD4A9BACACKQPYByABKQPYB4U3A+gPQQAgAikD4AcgASkD4AeFNwPwD0EAIAIpA+gHIAEpA+gHhTcD+A9BACACKQPwByABKQPwB4U3A4AQQQAgAikD+AcgASkD+AeFNwOIEEGQCEGYCEGgCEGoCEGwCEG4CEHACEHICEHQCEHYCEHgCEHoCEHwCEH4CEGACUGICRACQZAJQZgJQaAJQagJQbAJQbgJQcAJQcgJQdAJQdgJQeAJQegJQfAJQfgJQYAKQYgKEAJBkApBmApBoApBqApBsApBuApBwApByApB0ApB2ApB4ApB6ApB8ApB+ApBgAtBiAsQAkGQC0GYC0GgC0GoC0GwC0G4C0HAC0HIC0HQC0HYC0HgC0HoC0HwC0H4C0GADEGIDBACQZAMQZgMQaAMQagMQbAMQbgMQcAMQcgMQdAMQdgMQeAMQegMQfAMQfgMQYANQYgNEAJBkA1BmA1BoA1BqA1BsA1BuA1BwA1ByA1B0A1B2A1B4A1B6A1B8A1B+A1BgA5BiA4QAkGQDkGYDkGgDkGoDkGwDkG4DkHADkHIDkHQDkHYDkHgDkHoDkHwDkH4DkGAD0GIDxACQZAPQZgPQaAPQagPQbAPQbgPQcAPQcgPQdAPQdgPQeAPQegPQfAPQfgPQYAQQYgQEAJBkAhBmAhBkAlBmAlBkApBmApBkAtBmAtBkAxBmAxBkA1BmA1BkA5BmA5BkA9BmA8QAkGgCEGoCEGgCUGoCUGgCkGoCkGgC0GoC0GgDEGoDEGgDUGoDUGgDkGoDkGgD0GoDxACQbAIQbgIQbAJQbgJQbAKQbgKQbALQbgLQbAMQbgMQbANQbgNQbAOQbgOQbAPQbgPEAJBwAhByAhBwAlByAlBwApByApBwAtByAtBwAxByAxBwA1ByA1BwA5ByA5BwA9ByA8QAkHQCEHYCEHQCUHYCUHQCkHYCkHQC0HYC0HQDEHYDEHQDUHYDUHQDkHYDkHQD0HYDxACQeAIQegIQeAJQegJQeAKQegKQeALQegLQeAMQegMQeANQegNQeAOQegOQeAPQegPEAJB8AhB+AhB8AlB+AlB8ApB+ApB8AtB+AtB8AxB+AxB8A1B+A1B8A5B+A5B8A9B+A8QAkGACUGICUGACkGICkGAC0GIC0GADEGIDEGADUGIDUGADkGIDkGAD0GID0GAEEGIEBACAkACQCADRQ0AA0AgACAEaiIDIAIgBGoiBSkDACABIARqIgYpAwCFIARBkAhqKQMAhSADKQMAhTcDACADQQhqIgMgBUEIaikDACAGQQhqKQMAhSAEQZgIaikDAIUgAykDAIU3AwAgBEEQaiIEQYAIRw0ADAILC0EAIQQDQCAAIARqIgMgAiAEaiIFKQMAIAEgBGoiBikDAIUgBEGQCGopAwCFNwMAIANBCGogBUEIaikDACAGQQhqKQMAhSAEQZgIaikDAIU3AwAgBEEQaiIEQYAIRw0ACwsL5QcMBX8BfgR/An4BfwF+AX8Bfgd/AX4DfwF+AkBBACgCgAgiAiABQQp0aiIDKAIIIAFHDQAgAygCDCEEIAMoAgAhBUEAIAMoAhQiBq03A7gQQQAgBK0iBzcDsBBBACAFIAEgBUECdG4iCGwiCUECdK03A6gQAkACQAJAAkAgBEUNAEF/IQogBUUNASAIQQNsIQsgCEECdCIErSEMIAWtIQ0gBkF/akECSSEOQgAhDwNAQQAgDzcDkBAgD6chEEIAIRFBACEBA0BBACARNwOgECAPIBGEUCIDIA5xIRIgBkEBRiAPUCITIAZBAkYgEUICVHFxciEUQX8gAUEBakEDcSAIbEF/aiATGyEVIAEgEHIhFiABIAhsIRcgA0EBdCEYQgAhGQNAQQBCADcDwBBBACAZNwOYECAYIQECQCASRQ0AQQBCATcDwBBBkBhBkBBBkCBBABADQZAYQZAYQZAgQQAQA0ECIQELAkAgASAITw0AIAQgGaciGmwgF2ogAWohAwNAIANBACAEIAEbQQAgEVAiGxtqQX9qIRwCQAJAIBQNAEEAKAKACCICIBxBCnQiHGohCgwBCwJAIAFB/wBxIgINAEEAQQApA8AQQgF8NwPAEEGQGEGQEEGQIEEAEANBkBhBkBhBkCBBABADCyAcQQp0IRwgAkEDdEGQGGohCkEAKAKACCECCyACIANBCnRqIAIgHGogAiAKKQMAIh1CIIinIAVwIBogFhsiHCAEbCABIAFBACAZIBytUSIcGyIKIBsbIBdqIAogC2ogExsgAUUgHHJrIhsgFWqtIB1C/////w+DIh0gHX5CIIggG61+QiCIfSAMgqdqQQp0akEBEAMgA0EBaiEDIAggAUEBaiIBRw0ACwsgGUIBfCIZIA1SDQALIBFCAXwiEachASARQgRSDQALIA9CAXwiDyAHUg0AC0EAKAKACCECCyAJQQx0QYB4aiEXIAVBf2oiCkUNAgwBC0EAQgM3A6AQQQAgBEF/aq03A5AQQYB4IRcLIAIgF2ohGyAIQQx0IQhBACEcA0AgCCAcQQFqIhxsQYB4aiEEQQAhAQNAIBsgAWoiAyADKQMAIAIgBCABamopAwCFNwMAIANBCGoiAyADKQMAIAIgBCABQQhyamopAwCFNwMAIAFBCGohAyABQRBqIQEgA0H4B0kNAAsgHCAKRw0ACwsgAiAXaiEbQXghAQNAIAIgAWoiA0EIaiAbIAFqIgRBCGopAwA3AwAgA0EQaiAEQRBqKQMANwMAIANBGGogBEEYaikDADcDACADQSBqIARBIGopAwA3AwAgAUEgaiIBQfgHSQ0ACwsL",Jr="e4cdc523",Kr={name:Lr,data:qr,hash:Jr},Or="blake2b",Yr="AGFzbQEAAAABEQRgAAF/YAJ/fwBgAX8AYAAAAwoJAAECAwECAgABBQQBAQICBg4CfwFBsIsFC38AQYAICwdwCAZtZW1vcnkCAA5IYXNoX0dldEJ1ZmZlcgAACkhhc2hfRmluYWwAAwlIYXNoX0luaXQABQtIYXNoX1VwZGF0ZQAGDUhhc2hfR2V0U3RhdGUABw5IYXNoX0NhbGN1bGF0ZQAIClNUQVRFX1NJWkUDAQrTOAkFAEGACQvrAgIFfwF+AkAgAUEBSA0AAkACQAJAIAFBgAFBACgC4IoBIgJrIgNKDQAgASEEDAELQQBBADYC4IoBAkAgAkH/AEoNACACQeCJAWohBSAAIQRBACEGA0AgBSAELQAAOgAAIARBAWohBCAFQQFqIQUgAyAGQQFqIgZB/wFxSg0ACwtBAEEAKQPAiQEiB0KAAXw3A8CJAUEAQQApA8iJASAHQv9+Vq18NwPIiQFB4IkBEAIgACADaiEAAkAgASADayIEQYEBSA0AIAIgAWohBQNAQQBBACkDwIkBIgdCgAF8NwPAiQFBAEEAKQPIiQEgB0L/flatfDcDyIkBIAAQAiAAQYABaiEAIAVBgH9qIgVBgAJLDQALIAVBgH9qIQQMAQsgBEEATA0BC0EAIQUDQCAFQQAoAuCKAWpB4IkBaiAAIAVqLQAAOgAAIAQgBUEBaiIFQf8BcUoNAAsLQQBBACgC4IoBIARqNgLgigELC78uASR+QQBBACkD0IkBQQApA7CJASIBQQApA5CJAXwgACkDICICfCIDhULr+obav7X2wR+FQiCJIgRCq/DT9K/uvLc8fCIFIAGFQiiJIgYgA3wgACkDKCIBfCIHIASFQjCJIgggBXwiCSAGhUIBiSIKQQApA8iJAUEAKQOoiQEiBEEAKQOIiQF8IAApAxAiA3wiBYVCn9j52cKR2oKbf4VCIIkiC0K7zqqm2NDrs7t/fCIMIASFQiiJIg0gBXwgACkDGCIEfCIOfCAAKQNQIgV8Ig9BACkDwIkBQQApA6CJASIQQQApA4CJASIRfCAAKQMAIgZ8IhKFQtGFmu/6z5SH0QCFQiCJIhNCiJLznf/M+YTqAHwiFCAQhUIoiSIVIBJ8IAApAwgiEHwiFiAThUIwiSIXhUIgiSIYQQApA9iJAUEAKQO4iQEiE0EAKQOYiQF8IAApAzAiEnwiGYVC+cL4m5Gjs/DbAIVCIIkiGkLx7fT4paf9p6V/fCIbIBOFQiiJIhwgGXwgACkDOCITfCIZIBqFQjCJIhogG3wiG3wiHSAKhUIoiSIeIA98IAApA1giCnwiDyAYhUIwiSIYIB18Ih0gDiALhUIwiSIOIAx8Ih8gDYVCAYkiDCAWfCAAKQNAIgt8Ig0gGoVCIIkiFiAJfCIaIAyFQiiJIiAgDXwgACkDSCIJfCIhIBaFQjCJIhYgGyAchUIBiSIMIAd8IAApA2AiB3wiDSAOhUIgiSIOIBcgFHwiFHwiFyAMhUIoiSIbIA18IAApA2giDHwiHCAOhUIwiSIOIBd8IhcgG4VCAYkiGyAZIBQgFYVCAYkiFHwgACkDcCINfCIVIAiFQiCJIhkgH3wiHyAUhUIoiSIUIBV8IAApA3giCHwiFXwgDHwiIoVCIIkiI3wiJCAbhUIoiSIbICJ8IBJ8IiIgFyAYIBUgGYVCMIkiFSAffCIZIBSFQgGJIhQgIXwgDXwiH4VCIIkiGHwiFyAUhUIoiSIUIB98IAV8Ih8gGIVCMIkiGCAXfCIXIBSFQgGJIhR8IAF8IiEgFiAafCIWIBUgHSAehUIBiSIaIBx8IAl8IhyFQiCJIhV8Ih0gGoVCKIkiGiAcfCAIfCIcIBWFQjCJIhWFQiCJIh4gGSAOIBYgIIVCAYkiFiAPfCACfCIPhUIgiSIOfCIZIBaFQiiJIhYgD3wgC3wiDyAOhUIwiSIOIBl8Ihl8IiAgFIVCKIkiFCAhfCAEfCIhIB6FQjCJIh4gIHwiICAiICOFQjCJIiIgJHwiIyAbhUIBiSIbIBx8IAp8IhwgDoVCIIkiDiAXfCIXIBuFQiiJIhsgHHwgE3wiHCAOhUIwiSIOIBkgFoVCAYkiFiAffCAQfCIZICKFQiCJIh8gFSAdfCIVfCIdIBaFQiiJIhYgGXwgB3wiGSAfhUIwiSIfIB18Ih0gFoVCAYkiFiAVIBqFQgGJIhUgD3wgBnwiDyAYhUIgiSIYICN8IhogFYVCKIkiFSAPfCADfCIPfCAHfCIihUIgiSIjfCIkIBaFQiiJIhYgInwgBnwiIiAjhUIwiSIjICR8IiQgFoVCAYkiFiAOIBd8Ig4gDyAYhUIwiSIPICAgFIVCAYkiFCAZfCAKfCIXhUIgiSIYfCIZIBSFQiiJIhQgF3wgC3wiF3wgBXwiICAPIBp8Ig8gHyAOIBuFQgGJIg4gIXwgCHwiGoVCIIkiG3wiHyAOhUIoiSIOIBp8IAx8IhogG4VCMIkiG4VCIIkiISAdIB4gDyAVhUIBiSIPIBx8IAF8IhWFQiCJIhx8Ih0gD4VCKIkiDyAVfCADfCIVIByFQjCJIhwgHXwiHXwiHiAWhUIoiSIWICB8IA18IiAgIYVCMIkiISAefCIeIBogFyAYhUIwiSIXIBl8IhggFIVCAYkiFHwgCXwiGSAchUIgiSIaICR8IhwgFIVCKIkiFCAZfCACfCIZIBqFQjCJIhogHSAPhUIBiSIPICJ8IAR8Ih0gF4VCIIkiFyAbIB98Iht8Ih8gD4VCKIkiDyAdfCASfCIdIBeFQjCJIhcgH3wiHyAPhUIBiSIPIBsgDoVCAYkiDiAVfCATfCIVICOFQiCJIhsgGHwiGCAOhUIoiSIOIBV8IBB8IhV8IAx8IiKFQiCJIiN8IiQgD4VCKIkiDyAifCAHfCIiICOFQjCJIiMgJHwiJCAPhUIBiSIPIBogHHwiGiAVIBuFQjCJIhUgHiAWhUIBiSIWIB18IAR8IhuFQiCJIhx8Ih0gFoVCKIkiFiAbfCAQfCIbfCABfCIeIBUgGHwiFSAXIBogFIVCAYkiFCAgfCATfCIYhUIgiSIXfCIaIBSFQiiJIhQgGHwgCXwiGCAXhUIwiSIXhUIgiSIgIB8gISAVIA6FQgGJIg4gGXwgCnwiFYVCIIkiGXwiHyAOhUIoiSIOIBV8IA18IhUgGYVCMIkiGSAffCIffCIhIA+FQiiJIg8gHnwgBXwiHiAghUIwiSIgICF8IiEgGyAchUIwiSIbIB18IhwgFoVCAYkiFiAYfCADfCIYIBmFQiCJIhkgJHwiHSAWhUIoiSIWIBh8IBJ8IhggGYVCMIkiGSAfIA6FQgGJIg4gInwgAnwiHyAbhUIgiSIbIBcgGnwiF3wiGiAOhUIoiSIOIB98IAZ8Ih8gG4VCMIkiGyAafCIaIA6FQgGJIg4gFSAXIBSFQgGJIhR8IAh8IhUgI4VCIIkiFyAcfCIcIBSFQiiJIhQgFXwgC3wiFXwgBXwiIoVCIIkiI3wiJCAOhUIoiSIOICJ8IAh8IiIgGiAgIBUgF4VCMIkiFSAcfCIXIBSFQgGJIhQgGHwgCXwiGIVCIIkiHHwiGiAUhUIoiSIUIBh8IAZ8IhggHIVCMIkiHCAafCIaIBSFQgGJIhR8IAR8IiAgGSAdfCIZIBUgISAPhUIBiSIPIB98IAN8Ih2FQiCJIhV8Ih8gD4VCKIkiDyAdfCACfCIdIBWFQjCJIhWFQiCJIiEgFyAbIBkgFoVCAYkiFiAefCABfCIZhUIgiSIbfCIXIBaFQiiJIhYgGXwgE3wiGSAbhUIwiSIbIBd8Ihd8Ih4gFIVCKIkiFCAgfCAMfCIgICGFQjCJIiEgHnwiHiAiICOFQjCJIiIgJHwiIyAOhUIBiSIOIB18IBJ8Ih0gG4VCIIkiGyAafCIaIA6FQiiJIg4gHXwgC3wiHSAbhUIwiSIbIBcgFoVCAYkiFiAYfCANfCIXICKFQiCJIhggFSAffCIVfCIfIBaFQiiJIhYgF3wgEHwiFyAYhUIwiSIYIB98Ih8gFoVCAYkiFiAVIA+FQgGJIg8gGXwgCnwiFSAchUIgiSIZICN8IhwgD4VCKIkiDyAVfCAHfCIVfCASfCIihUIgiSIjfCIkIBaFQiiJIhYgInwgBXwiIiAjhUIwiSIjICR8IiQgFoVCAYkiFiAbIBp8IhogFSAZhUIwiSIVIB4gFIVCAYkiFCAXfCADfCIXhUIgiSIZfCIbIBSFQiiJIhQgF3wgB3wiF3wgAnwiHiAVIBx8IhUgGCAaIA6FQgGJIg4gIHwgC3wiGoVCIIkiGHwiHCAOhUIoiSIOIBp8IAR8IhogGIVCMIkiGIVCIIkiICAfICEgFSAPhUIBiSIPIB18IAZ8IhWFQiCJIh18Ih8gD4VCKIkiDyAVfCAKfCIVIB2FQjCJIh0gH3wiH3wiISAWhUIoiSIWIB58IAx8Ih4gIIVCMIkiICAhfCIhIBogFyAZhUIwiSIXIBt8IhkgFIVCAYkiFHwgEHwiGiAdhUIgiSIbICR8Ih0gFIVCKIkiFCAafCAJfCIaIBuFQjCJIhsgHyAPhUIBiSIPICJ8IBN8Ih8gF4VCIIkiFyAYIBx8Ihh8IhwgD4VCKIkiDyAffCABfCIfIBeFQjCJIhcgHHwiHCAPhUIBiSIPIBggDoVCAYkiDiAVfCAIfCIVICOFQiCJIhggGXwiGSAOhUIoiSIOIBV8IA18IhV8IA18IiKFQiCJIiN8IiQgD4VCKIkiDyAifCAMfCIiICOFQjCJIiMgJHwiJCAPhUIBiSIPIBsgHXwiGyAVIBiFQjCJIhUgISAWhUIBiSIWIB98IBB8IhiFQiCJIh18Ih8gFoVCKIkiFiAYfCAIfCIYfCASfCIhIBUgGXwiFSAXIBsgFIVCAYkiFCAefCAHfCIZhUIgiSIXfCIbIBSFQiiJIhQgGXwgAXwiGSAXhUIwiSIXhUIgiSIeIBwgICAVIA6FQgGJIg4gGnwgAnwiFYVCIIkiGnwiHCAOhUIoiSIOIBV8IAV8IhUgGoVCMIkiGiAcfCIcfCIgIA+FQiiJIg8gIXwgBHwiISAehUIwiSIeICB8IiAgGCAdhUIwiSIYIB98Ih0gFoVCAYkiFiAZfCAGfCIZIBqFQiCJIhogJHwiHyAWhUIoiSIWIBl8IBN8IhkgGoVCMIkiGiAcIA6FQgGJIg4gInwgCXwiHCAYhUIgiSIYIBcgG3wiF3wiGyAOhUIoiSIOIBx8IAN8IhwgGIVCMIkiGCAbfCIbIA6FQgGJIg4gFSAXIBSFQgGJIhR8IAt8IhUgI4VCIIkiFyAdfCIdIBSFQiiJIhQgFXwgCnwiFXwgBHwiIoVCIIkiI3wiJCAOhUIoiSIOICJ8IAl8IiIgGyAeIBUgF4VCMIkiFSAdfCIXIBSFQgGJIhQgGXwgDHwiGYVCIIkiHXwiGyAUhUIoiSIUIBl8IAp8IhkgHYVCMIkiHSAbfCIbIBSFQgGJIhR8IAN8Ih4gGiAffCIaIBUgICAPhUIBiSIPIBx8IAd8IhyFQiCJIhV8Ih8gD4VCKIkiDyAcfCAQfCIcIBWFQjCJIhWFQiCJIiAgFyAYIBogFoVCAYkiFiAhfCATfCIahUIgiSIYfCIXIBaFQiiJIhYgGnwgDXwiGiAYhUIwiSIYIBd8Ihd8IiEgFIVCKIkiFCAefCAFfCIeICCFQjCJIiAgIXwiISAiICOFQjCJIiIgJHwiIyAOhUIBiSIOIBx8IAt8IhwgGIVCIIkiGCAbfCIbIA6FQiiJIg4gHHwgEnwiHCAYhUIwiSIYIBcgFoVCAYkiFiAZfCABfCIXICKFQiCJIhkgFSAffCIVfCIfIBaFQiiJIhYgF3wgBnwiFyAZhUIwiSIZIB98Ih8gFoVCAYkiFiAVIA+FQgGJIg8gGnwgCHwiFSAdhUIgiSIaICN8Ih0gD4VCKIkiDyAVfCACfCIVfCANfCIihUIgiSIjfCIkIBaFQiiJIhYgInwgCXwiIiAjhUIwiSIjICR8IiQgFoVCAYkiFiAYIBt8IhggFSAahUIwiSIVICEgFIVCAYkiFCAXfCASfCIXhUIgiSIafCIbIBSFQiiJIhQgF3wgCHwiF3wgB3wiISAVIB18IhUgGSAYIA6FQgGJIg4gHnwgBnwiGIVCIIkiGXwiHSAOhUIoiSIOIBh8IAt8IhggGYVCMIkiGYVCIIkiHiAfICAgFSAPhUIBiSIPIBx8IAp8IhWFQiCJIhx8Ih8gD4VCKIkiDyAVfCAEfCIVIByFQjCJIhwgH3wiH3wiICAWhUIoiSIWICF8IAN8IiEgHoVCMIkiHiAgfCIgIBggFyAahUIwiSIXIBt8IhogFIVCAYkiFHwgBXwiGCAchUIgiSIbICR8IhwgFIVCKIkiFCAYfCABfCIYIBuFQjCJIhsgHyAPhUIBiSIPICJ8IAx8Ih8gF4VCIIkiFyAZIB18Ihl8Ih0gD4VCKIkiDyAffCATfCIfIBeFQjCJIhcgHXwiHSAPhUIBiSIPIBkgDoVCAYkiDiAVfCAQfCIVICOFQiCJIhkgGnwiGiAOhUIoiSIOIBV8IAJ8IhV8IBN8IiKFQiCJIiN8IiQgD4VCKIkiDyAifCASfCIiICOFQjCJIiMgJHwiJCAPhUIBiSIPIBsgHHwiGyAVIBmFQjCJIhUgICAWhUIBiSIWIB98IAt8IhmFQiCJIhx8Ih8gFoVCKIkiFiAZfCACfCIZfCAJfCIgIBUgGnwiFSAXIBsgFIVCAYkiFCAhfCAFfCIahUIgiSIXfCIbIBSFQiiJIhQgGnwgA3wiGiAXhUIwiSIXhUIgiSIhIB0gHiAVIA6FQgGJIg4gGHwgEHwiFYVCIIkiGHwiHSAOhUIoiSIOIBV8IAF8IhUgGIVCMIkiGCAdfCIdfCIeIA+FQiiJIg8gIHwgDXwiICAhhUIwiSIhIB58Ih4gGSAchUIwiSIZIB98IhwgFoVCAYkiFiAafCAIfCIaIBiFQiCJIhggJHwiHyAWhUIoiSIWIBp8IAp8IhogGIVCMIkiGCAdIA6FQgGJIg4gInwgBHwiHSAZhUIgiSIZIBcgG3wiF3wiGyAOhUIoiSIOIB18IAd8Ih0gGYVCMIkiGSAbfCIbIA6FQgGJIg4gFSAXIBSFQgGJIhR8IAx8IhUgI4VCIIkiFyAcfCIcIBSFQiiJIhQgFXwgBnwiFXwgEnwiIoVCIIkiI3wiJCAOhUIoiSIOICJ8IBN8IiIgGyAhIBUgF4VCMIkiFSAcfCIXIBSFQgGJIhQgGnwgBnwiGoVCIIkiHHwiGyAUhUIoiSIUIBp8IBB8IhogHIVCMIkiHCAbfCIbIBSFQgGJIhR8IA18IiEgGCAffCIYIBUgHiAPhUIBiSIPIB18IAJ8Ih2FQiCJIhV8Ih4gD4VCKIkiDyAdfCABfCIdIBWFQjCJIhWFQiCJIh8gFyAZIBggFoVCAYkiFiAgfCADfCIYhUIgiSIZfCIXIBaFQiiJIhYgGHwgBHwiGCAZhUIwiSIZIBd8Ihd8IiAgFIVCKIkiFCAhfCAIfCIhIB+FQjCJIh8gIHwiICAiICOFQjCJIiIgJHwiIyAOhUIBiSIOIB18IAd8Ih0gGYVCIIkiGSAbfCIbIA6FQiiJIg4gHXwgDHwiHSAZhUIwiSIZIBcgFoVCAYkiFiAafCALfCIXICKFQiCJIhogFSAefCIVfCIeIBaFQiiJIhYgF3wgCXwiFyAahUIwiSIaIB58Ih4gFoVCAYkiFiAVIA+FQgGJIg8gGHwgBXwiFSAchUIgiSIYICN8IhwgD4VCKIkiDyAVfCAKfCIVfCACfCIChUIgiSIifCIjIBaFQiiJIhYgAnwgC3wiAiAihUIwiSILICN8IiIgFoVCAYkiFiAZIBt8IhkgFSAYhUIwiSIVICAgFIVCAYkiFCAXfCANfCINhUIgiSIXfCIYIBSFQiiJIhQgDXwgBXwiBXwgEHwiECAVIBx8Ig0gGiAZIA6FQgGJIg4gIXwgDHwiDIVCIIkiFXwiGSAOhUIoiSIOIAx8IBJ8IhIgFYVCMIkiDIVCIIkiFSAeIB8gDSAPhUIBiSINIB18IAl8IgmFQiCJIg98IhogDYVCKIkiDSAJfCAIfCIJIA+FQjCJIgggGnwiD3wiGiAWhUIoiSIWIBB8IAd8IhAgEYUgDCAZfCIHIA6FQgGJIgwgCXwgCnwiCiALhUIgiSILIAUgF4VCMIkiBSAYfCIJfCIOIAyFQiiJIgwgCnwgE3wiEyALhUIwiSIKIA58IguFNwOAiQFBACADIAYgDyANhUIBiSINIAJ8fCICIAWFQiCJIgUgB3wiBiANhUIoiSIHIAJ8fCICQQApA4iJAYUgBCABIBIgCSAUhUIBiSIDfHwiASAIhUIgiSISICJ8IgkgA4VCKIkiAyABfHwiASAShUIwiSIEIAl8IhKFNwOIiQFBACATQQApA5CJAYUgECAVhUIwiSIQIBp8IhOFNwOQiQFBACABQQApA5iJAYUgAiAFhUIwiSICIAZ8IgGFNwOYiQFBACASIAOFQgGJQQApA6CJAYUgAoU3A6CJAUEAIBMgFoVCAYlBACkDqIkBhSAKhTcDqIkBQQAgASAHhUIBiUEAKQOwiQGFIASFNwOwiQFBACALIAyFQgGJQQApA7iJAYUgEIU3A7iJAQvdAgUBfwF+AX8BfgJ/IwBBwABrIgAkAAJAQQApA9CJAUIAUg0AQQBBACkDwIkBIgFBACgC4IoBIgKsfCIDNwPAiQFBAEEAKQPIiQEgAyABVK18NwPIiQECQEEALQDoigFFDQBBAEJ/NwPYiQELQQBCfzcD0IkBAkAgAkH/AEoNAEEAIQQDQCACIARqQeCJAWpBADoAACAEQQFqIgRBgAFBACgC4IoBIgJrSA0ACwtB4IkBEAIgAEEAKQOAiQE3AwAgAEEAKQOIiQE3AwggAEEAKQOQiQE3AxAgAEEAKQOYiQE3AxggAEEAKQOgiQE3AyAgAEEAKQOoiQE3AyggAEEAKQOwiQE3AzAgAEEAKQO4iQE3AzhBACgC5IoBIgVBAUgNAEEAIQRBACECA0AgBEGACWogACAEai0AADoAACAEQQFqIQQgBSACQQFqIgJB/wFxSg0ACwsgAEHAAGokAAv9AwMBfwF+AX8jAEGAAWsiAiQAQQBBgQI7AfKKAUEAIAE6APGKAUEAIAA6APCKAUGQfiEAA0AgAEGAiwFqQgA3AAAgAEH4igFqQgA3AAAgAEHwigFqQgA3AAAgAEEYaiIADQALQQAhAEEAQQApA/CKASIDQoiS853/zPmE6gCFNwOAiQFBAEEAKQP4igFCu86qptjQ67O7f4U3A4iJAUEAQQApA4CLAUKr8NP0r+68tzyFNwOQiQFBAEEAKQOIiwFC8e30+KWn/aelf4U3A5iJAUEAQQApA5CLAULRhZrv+s+Uh9EAhTcDoIkBQQBBACkDmIsBQp/Y+dnCkdqCm3+FNwOoiQFBAEEAKQOgiwFC6/qG2r+19sEfhTcDsIkBQQBBACkDqIsBQvnC+JuRo7Pw2wCFNwO4iQFBACADp0H/AXE2AuSKAQJAIAFBAUgNACACQgA3A3ggAkIANwNwIAJCADcDaCACQgA3A2AgAkIANwNYIAJCADcDUCACQgA3A0ggAkIANwNAIAJCADcDOCACQgA3AzAgAkIANwMoIAJCADcDICACQgA3AxggAkIANwMQIAJCADcDCCACQgA3AwBBACEEA0AgAiAAaiAAQYAJai0AADoAACAAQQFqIQAgBEEBaiIEQf8BcSABSA0ACyACQYABEAELIAJBgAFqJAALEgAgAEEDdkH/P3EgAEEQdhAECwkAQYAJIAAQAQsGAEGAiQELGwAgAUEDdkH/P3EgAUEQdhAEQYAJIAAQARADCwsLAQBBgAgLBPAAAAA=",zr="c6f286e6",Vr={name:Or,data:Yr,hash:zr},Ol=new nt;function zo(c){return!Number.isInteger(c)||c<8||c>512||c%8!==0?new Error("Invalid variant! Valid values: 8, 16, ..., 512"):null}function $r(c,a){return c|a<<16}function En(c=512,a=null){if(zo(c))return Promise.reject(zo(c));let t=null,e=c;if(a!==null){if(t=Xt(a),t.length>64)return Promise.reject(new Error("Max key length is 64 bytes"));e=$r(c,t.length)}let i=c/8;return Xo(Vr,i).then(s=>{e>512&&s.writeMemory(t),s.init(e);let n={init:e>512?()=>(s.writeMemory(t),s.init(e),n):()=>(s.init(e),n),update:o=>(s.update(o),n),digest:o=>s.digest(o),save:()=>s.save(),load:o=>(s.load(o),n),blockSize:128,digestSize:i};return n})}function Wr(c,a,t){let e=[`m=${a.memorySize}`,`t=${a.iterations}`,`p=${a.parallelism}`].join(",");return`$argon2${a.hashType}$v=19$${e}$${Yo(c,!1)}$${Yo(t,!1)}`}var Vo=new DataView(new ArrayBuffer(4));function Wt(c){return Vo.setInt32(0,c,!0),new Uint8Array(Vo.buffer)}function mn(c,a,t){return Ne(this,void 0,void 0,function*(){if(t<=64){let r=yield En(t*8);return r.update(Wt(t)),r.update(a),r.digest("binary")}let e=Math.ceil(t/32)-2,i=new Uint8Array(t);c.init(),c.update(Wt(t)),c.update(a);let s=c.digest("binary");i.set(s.subarray(0,32),0);for(let r=1;r<e;r++)c.init(),c.update(s),s=c.digest("binary"),i.set(s.subarray(0,32),r*32);let n=t-32*e,o;return n===64?(o=c,o.init()):o=yield En(n*8),o.update(s),s=o.digest("binary"),i.set(s.subarray(0,n),e*32),i})}function Xr(c){switch(c){case"d":return 0;case"i":return 1;default:return 2}}function Zr(c){return Ne(this,void 0,void 0,function*(){var a;let{parallelism:t,iterations:e,hashLength:i}=c,s=Xt(c.password),n=Xt(c.salt),o=19,r=Xr(c.hashType),{memorySize:A}=c,l=Xt((a=c.secret)!==null&&a!==void 0?a:""),[d,p]=yield Promise.all([Xo(Kr,1024),En(512)]);d.setMemorySize(A*1024+1024);let g=new Uint8Array(24),h=new DataView(g.buffer);h.setInt32(0,t,!0),h.setInt32(4,i,!0),h.setInt32(8,A,!0),h.setInt32(12,e,!0),h.setInt32(16,o,!0),h.setInt32(20,r,!0),d.writeMemory(g,A*1024),p.init(),p.update(g),p.update(Wt(s.length)),p.update(s),p.update(Wt(n.length)),p.update(n),p.update(Wt(l.length)),p.update(l),p.update(Wt(0));let u=Math.floor(A/(t*4))*4,f=new Uint8Array(72),C=p.digest("binary");f.set(C);for(let y=0;y<t;y++){f.set(Wt(0),64),f.set(Wt(y),68);let Q=y*u,E=yield mn(p,f,1024);d.writeMemory(E,Q*1024),Q+=1,f.set(Wt(1),64),E=yield mn(p,f,1024),d.writeMemory(E,Q*1024)}let B=new Uint8Array(1024);Wo(B,d.calculate(new Uint8Array([]),A));let m=yield mn(p,B,i);if(c.outputType==="hex"){let y=new Uint8Array(i*2);return yn(y,m,i)}return c.outputType==="encoded"?Wr(n,c,m):m})}var jr=c=>{var a;if(!c||typeof c!="object")throw new Error("Invalid options parameter. It requires an object.");if(!c.password)throw new Error("Password must be specified");if(c.password=Xt(c.password),c.password.length<1)throw new Error("Password must be specified");if(!c.salt)throw new Error("Salt must be specified");if(c.salt=Xt(c.salt),c.salt.length<8)throw new Error("Salt should be at least 8 bytes long");if(c.secret=Xt((a=c.secret)!==null&&a!==void 0?a:""),!Number.isInteger(c.iterations)||c.iterations<1)throw new Error("Iterations should be a positive number");if(!Number.isInteger(c.parallelism)||c.parallelism<1)throw new Error("Parallelism should be a positive number");if(!Number.isInteger(c.hashLength)||c.hashLength<4)throw new Error("Hash length should be at least 4 bytes.");if(!Number.isInteger(c.memorySize))throw new Error("Memory size should be specified.");if(c.memorySize<8*c.parallelism)throw new Error("Memory size should be at least 8 * parallelism.");if(c.outputType===void 0&&(c.outputType="hex"),!["hex","binary","encoded"].includes(c.outputType))throw new Error(`Insupported output type ${c.outputType}. Valid values: ['hex', 'binary', 'encoded']`)};function wn(c){return Ne(this,void 0,void 0,function*(){return jr(c),Zr(Object.assign(Object.assign({},c),{hashType:"id"}))})}var Yl=new nt;var zl=new nt;var Vl=new nt;var $l=new nt;var Wl=new Uint8Array(8);var Xl=new nt;var Zl=new nt;var jl=new nt;var _l=new nt;var tc=new nt;var ec=new nt;var ic=new nt;var sc=new nt;var nc=new nt;var oc=new nt;var ac=new nt;var rc=new Uint8Array(8);var Ac=new nt;var lc=new Uint8Array(8);var cc=new nt;var dc=new Uint8Array(8);var hc=new nt;var pc=new nt;var gc=new nt;Ft();var Pt=new Uint8Array([83,84,65,83,72,69,78,67]),kn=2,Sn=1,Dn=2,_o=3,_r=32,Je=12,vn=32,tA=6e5,eA=47104,iA=3,sA=1,dt=c=>c;function Ut(c){if(c.length<Pt.length+1)return!1;for(let a=0;a<Pt.length;a++)if(c[a]!==Pt[a])return!1;return!0}function Zo(c,a,t){c[a]=t>>>24&255,c[a+1]=t>>>16&255,c[a+2]=t>>>8&255,c[a+3]=t&255}function jo(c,a){return c[a]*16777216+(c[a+1]<<16)+(c[a+2]<<8)+c[a+3]}async function Fn(c,a,t){if(t.id===Dn)return await wn({password:c,salt:a,parallelism:t.c,iterations:t.b,memorySize:t.a,hashLength:vn,outputType:"binary"});if(t.id===Sn){let e=await crypto.subtle.importKey("raw",dt(new TextEncoder().encode(c)),"PBKDF2",!1,["deriveBits"]),i=await crypto.subtle.deriveBits({name:"PBKDF2",salt:dt(a),iterations:t.a,hash:"SHA-256"},e,vn*8);return new Uint8Array(i)}throw new Error(`Unsupported KDF id (${t.id}).`)}async function ss(c){return crypto.subtle.importKey("raw",dt(c),{name:"AES-GCM"},!1,["encrypt","decrypt"])}var ta={argon2id:{label:"Argon2id",strong:!0},pbkdf2:{label:"PBKDF2 (fallback)",strong:!1}};async function Ke(c,a){let t=crypto.getRandomValues(new Uint8Array(_r)),e=crypto.getRandomValues(new Uint8Array(Je)),i,s,n;try{i={id:Dn,a:eA,b:iA,c:sA},n=await Fn(a,t,i),s="argon2id"}catch(d){console.warn("[Stashpad] Argon2id unavailable \u2014 encrypting with PBKDF2 fallback.",d),i={id:Sn,a:tA,b:0,c:0},n=await Fn(a,t,i),s="pbkdf2"}let o=ea(i,t,e),r=await ss(n),A=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:dt(e),additionalData:dt(o)},r,dt(c))),l=new Uint8Array(o.length+A.length);return l.set(o,0),l.set(A,o.length),{data:l,kdf:s}}var wi=null;async function ns(){if(wi!==null)return wi;try{await wn({password:"x",salt:new Uint8Array(16),parallelism:1,iterations:1,memorySize:8,hashLength:16,outputType:"binary"}),wi=!0}catch{wi=!1}return wi}function ea(c,a,t){let e=new Uint8Array(Pt.length+1+1+4+4+1+1+a.length+t.length),i=0;return e.set(Pt,i),i+=Pt.length,e[i++]=kn,e[i++]=c.id,Zo(e,i,c.a),i+=4,Zo(e,i,c.b),i+=4,e[i++]=c.c,e[i++]=a.length,e.set(a,i),i+=a.length,e.set(t,i),i+=t.length,e}async function Zt(c,a){if(!Ut(c))throw new Error("Not an encrypted Stashpad file.");let t=c[Pt.length];if(t===1)return nA(c,a);if(t!==kn)throw new Error(`Unsupported encrypted .stash version (${t}).`);let e=Pt.length+1,i={id:c[e++],a:0,b:0,c:0};if(i.a=jo(c,e),e+=4,i.b=jo(c,e),e+=4,i.c=c[e++],i.id===Dn){if(i.a>2097152||i.b>64||i.c<1||i.c>8)throw new Error("Unsupported KDF parameters (file may be corrupted or malicious).")}else if(i.id===Sn&&i.a>1e7)throw new Error("Unsupported KDF parameters (file may be corrupted or malicious).");let s=c[e++];if(s<8||s>64)throw new Error("Unsupported KDF parameters (file may be corrupted or malicious).");let n=c.slice(e,e+s);e+=s;let o=c.slice(e,e+Je);e+=Je;let r=c.slice(0,e),A=c.slice(e),l=await Fn(a,n,i),d=await ss(l),p=await crypto.subtle.decrypt({name:"AES-GCM",iv:dt(o),additionalData:dt(r)},d,dt(A));return new Uint8Array(p)}async function nA(c,a){let t=Pt.length+1,e=c.slice(t,t+16);t+=16;let i=c.slice(t,t+12);t+=12;let s=c.slice(t),n=await crypto.subtle.importKey("raw",dt(new TextEncoder().encode(a)),"PBKDF2",!1,["deriveKey"]),o=await crypto.subtle.deriveKey({name:"PBKDF2",salt:dt(e),iterations:21e4,hash:"SHA-256"},n,{name:"AES-GCM",length:256},!1,["decrypt"]),r=await crypto.subtle.decrypt({name:"AES-GCM",iv:dt(i)},o,dt(s));return new Uint8Array(r)}async function vi(c,a){if(a.length!==vn)throw new Error("Encryption key must be 32 bytes.");let t=crypto.getRandomValues(new Uint8Array(Je)),i=ea({id:_o,a:0,b:0,c:0},new Uint8Array(0),t),s=await ss(a),n=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:dt(t),additionalData:dt(i)},s,dt(c))),o=new Uint8Array(i.length+n.length);return o.set(i,0),o.set(n,i.length),o}async function ce(c,a){if(!Ut(c))throw new Error("Not an encrypted Stashpad file.");let t=c[Pt.length];if(t!==kn)throw new Error(`Unsupported encrypted version (${t}).`);let e=Pt.length+1;if(c[e++]!==_o)throw new Error("Not a raw-key (.stashenc) envelope.");e+=9;let s=c[e++];e+=s;let n=c.slice(e,e+Je);e+=Je;let o=c.slice(0,e),r=c.slice(e),A=await ss(a),l=await crypto.subtle.decrypt({name:"AES-GCM",iv:dt(n),additionalData:dt(o)},A,dt(r));return new Uint8Array(l)}async function Oe(c,a,t={}){if(!Ut(a))return a;if(t.secretId){let i=c.secretStorage,s=null;try{s=i?.getSecret(t.secretId)??null}catch{s=null}if(s)try{return await Zt(a,s)}catch{}}let e;for(;;){let i=await new Promise(s=>{new hi(c,e,!!t.allowLater,s).open()});if(i.kind==="cancel")return null;if(i.kind==="later")return t.onLater?.(),null;try{return await Zt(a,i.value)}catch{e="Wrong password or corrupted file. Try again."}}}Tt();var os={name:"ECDH",namedCurve:"P-256"},oA="stashpad-vault-dek-wrap",aA=new TextEncoder;function bn(c){let a="";for(let t=0;t<c.length;t++)a+=String.fromCharCode(c[t]);return btoa(a)}function Nn(c){let a=atob(c),t=new Uint8Array(a.length);for(let e=0;e<a.length;e++)t[e]=a.charCodeAt(e);return t}async function ia(){let c=await crypto.subtle.generateKey(os,!0,["deriveBits"]);return{pubKeySpki:new Uint8Array(await crypto.subtle.exportKey("spki",c.publicKey)),privKeyPkcs8:new Uint8Array(await crypto.subtle.exportKey("pkcs8",c.privateKey))}}function sa(c){return crypto.subtle.importKey("spki",c,os,!1,[])}function rA(c){return crypto.subtle.importKey("pkcs8",c,os,!1,["deriveBits"])}async function na(c,a){let t=await crypto.subtle.deriveBits({name:"ECDH",public:a},c,256),e=await crypto.subtle.importKey("raw",t,"HKDF",!1,["deriveKey"]);return crypto.subtle.deriveKey({name:"HKDF",hash:"SHA-256",salt:new Uint8Array(0),info:aA.encode(oA)},e,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}async function as(c,a,t){let e=await crypto.subtle.generateKey(os,!0,["deriveBits"]),i=await na(e.privateKey,await sa(a)),s=crypto.getRandomValues(new Uint8Array(12)),n=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:s},i,c)),o=new Uint8Array(await crypto.subtle.exportKey("spki",e.publicKey));return{recipientId:t,ephPub:bn(o),iv:bn(s),ct:bn(n)}}async function oa(c,a){let t=await na(await rA(a),await sa(Nn(c.ephPub)));return new Uint8Array(await crypto.subtle.decrypt({name:"AES-GCM",iv:Nn(c.iv)},t,Nn(c.ct)))}var aa=".stashpad/keys.json",AA=".stashpad",Fi="_keys";function xn(c){return{v:2,keyId:c,identities:[],slots:[],joinRequests:[]}}var rs=class{constructor(a){this.app=a}get a(){return this.app.vault.adapter}validate(a){let t=a;return!!t&&t.v===2&&typeof t.keyId=="string"&&Array.isArray(t.identities)&&Array.isArray(t.slots)&&Array.isArray(t.joinRequests)}async readValid(a){try{if(!await this.a.exists(a))return null;let t=JSON.parse(await this.a.read(a));return this.validate(t)?t:null}catch{return null}}async load(){let a=await this.readValid(aa);if(a)return a;try{let e=((await this.a.list(Fi)).files||[]).filter(i=>/\/keys-\d+\.json$/.test(i)).sort();for(let i of e.reverse()){let s=await this.readValid(i);if(s)return s}}catch{}return null}async exists(){return await this.load()!==null}async ensureDir(a){try{await this.a.exists(a)||await this.a.mkdir(a)}catch{}}async save(a){let t=JSON.stringify(a,null,2);await this.ensureDir(AA),await this.a.write(aa,t),await this.ensureDir(Fi);for(let e=4;e>=1;e--){let i=`${Fi}/keys-${e}.json`,s=`${Fi}/keys-${e+1}.json`;try{await this.a.exists(i)&&await this.a.write(s,await this.a.read(i))}catch{}}try{await this.a.write(`${Fi}/keys-1.json`,t)}catch{}}};var As="stashpad-vault-encryption";function ki(){return{wrappedKey:null,kdf:null,identityId:null,identityLabel:null,identityPub:null,identityPrivWrapped:null,identityPrivKdf:null}}function ls(c){let a="";for(let t=0;t<c.length;t++)a+=String.fromCharCode(c[t]);return btoa(a)}function jt(c){let a=atob(c),t=new Uint8Array(a.length);for(let e=0;e<a.length;e++)t[e]=a.charCodeAt(e);return t}var lA=32,cs=class{constructor(a,t,e,i=()=>0){this.app=a;this.load=t;this.save=e;this.idleMinutes=i;this.sessionKey=null;this.idleTimer=null;this.kf=null;this.keyfiles=new rs(a)}argonProbe(){return ns()}async init(){await this.refresh()}async refresh(){this.kf=await this.keyfiles.load()}secretStore(){return this.app.secretStorage??null}keychainAvailable(){return!!this.secretStore()}keychainId(){let a=this.app.appId||"default";return`${As}-${a}`}isRemembered(){try{return!!this.secretStore()?.getSecret(this.keychainId())}catch{return!1}}async remember(a){try{await this.secretStore()?.setSecret(this.keychainId(),a)}catch(t){console.warn("[Stashpad] couldn't save password to keychain",t)}}async forgetKeychain(){let a=this.secretStore();if(a)try{a.removeSecret?await a.removeSecret(this.keychainId()):await a.setSecret(this.keychainId(),"")}catch(t){console.warn("[Stashpad] couldn't clear keychain",t)}}async tryAutoUnlock(){if(!this.isConfigured()||this.isUnlocked())return this.isUnlocked();if(this.accessState()!=="member"&&!this.hasSharedPassword())return!1;let a=this.secretStore(),t=null;try{t=a?.getSecret(this.keychainId())??null}catch{t=null}if(t)return this.unlock(t);let e=null;try{e=a?.getSecret(As)??null}catch{e=null}if(!e)return!1;let i=await this.unlock(e);if(i){await this.remember(e);try{a?.removeSecret?await a.removeSecret(As):await a?.setSecret(As,"")}catch{}}return i}isConfigured(){return!!this.kf||!!this.load().wrappedKey}isUnlocked(){return this.sessionKey!==null}kdf(){return this.load().identityPrivKdf??this.load().kdf}hasIdentity(){return!!this.load().identityPrivWrapped&&!!this.load().identityId}mySlot(){let a=this.load().identityId;return a?this.kf?.slots.find(t=>t.recipientId===a)??null:null}accessState(){let a=this.load();return!this.kf&&a.wrappedKey?"member":this.kf?this.hasIdentity()&&this.mySlot()?"member":a.identityId&&this.kf.joinRequests.some(t=>t.id===a.identityId)?"pending":"outsider":"none"}amIMember(){return this.accessState()==="member"}async setup(a,t=!1,e){if(await this.refresh(),this.isConfigured())throw new Error("Encryption is already set up in this vault.");if(!a)throw new Error("Password required.");let i=crypto.getRandomValues(new Uint8Array(lA)),s=await this.mintIdentity(a,e),n=xn(tt(8));n.identities.push(this.identityRecord(s)),n.slots.push(await as(i,jt(s.pub),s.id)),await this.keyfiles.save(n),this.kf=n,this.sessionKey=i,t?await this.remember(a):await this.forgetKeychain(),this.armIdle()}async unlock(a,t=!1){await this.refresh();let e=this.load();if(!this.kf&&e.wrappedKey){let s;try{s=await Zt(jt(e.wrappedKey),a)}catch{return!1}let n=await this.mintIdentity(a,e.identityLabel??void 0),o=xn(tt(8));return o.identities.push(this.identityRecord(n)),o.slots.push(await as(s,jt(n.pub),n.id)),await this.keyfiles.save(o),this.kf=o,this.sessionKey=s,t&&await this.remember(a),this.armIdle(),!0}let i=this.hasIdentity()?this.mySlot():null;if(i)try{let s=await Zt(jt(e.identityPrivWrapped),a);try{let n=await oa(i,s);return s.fill(0),this.sessionKey=n,t&&await this.remember(a),this.armIdle(),!0}catch{s.fill(0)}}catch{}for(let s of this.kf?.passwordSlots??[])try{let n=await Zt(jt(s.wrapped),a);return this.sessionKey=n,t&&await this.remember(a),this.armIdle(),!0}catch{}return!1}hasSharedPassword(){return(this.kf?.passwordSlots?.length??0)>0}async setSharedPassword(a){if(!this.sessionKey)throw new Error("Unlock encryption first.");if(!a)throw new Error("Password required.");if(await this.refresh(),!this.kf)throw new Error("Encryption is not set up.");let t=await Ke(this.sessionKey,a);this.kf.passwordSlots=[{id:tt(8),label:"Shared password",wrapped:ls(t.data),kdf:t.kdf,createdAt:new Date().toISOString()}],await this.keyfiles.save(this.kf)}async removeSharedPassword(){await this.refresh(),!(!this.kf||!this.kf.passwordSlots?.length)&&(this.kf.passwordSlots=[],await this.keyfiles.save(this.kf))}async verifyPassword(a){let t=this.load();try{if(t.identityPrivWrapped)return(await Zt(jt(t.identityPrivWrapped),a)).fill(0),!0;if(t.wrappedKey)return(await Zt(jt(t.wrappedKey),a)).fill(0),!0}catch{}return!1}async changePassword(a,t,e=!1){let i=this.load();if(!t)throw new Error("New password required.");if(!i.identityPrivWrapped&&!await this.unlock(a,!1))return!1;let s=this.load(),n;try{n=await Zt(jt(s.identityPrivWrapped),a)}catch{return!1}let o=await Ke(n,t);return n.fill(0),await this.save({...s,identityPrivWrapped:ls(o.data),identityPrivKdf:o.kdf}),e?await this.remember(t):await this.forgetKeychain(),this.armIdle(),!0}async requestAccess(a,t,e=!1){if(await this.refresh(),!this.kf)throw new Error("This vault has no encryption set up yet.");if(this.amIMember())return;if(!t)throw new Error("Password required.");let i=this.hasIdentity()?{id:this.load().identityId,label:this.load().identityLabel??a,pub:this.load().identityPub}:await this.mintIdentity(t,a);a&&i.label!==a&&(await this.save({...this.load(),identityLabel:a}),i.label=a);let s={id:i.id,label:i.label,pubKey:i.pub,requestedAt:new Date().toISOString()};this.kf.joinRequests=[...this.kf.joinRequests.filter(n=>n.id!==i.id),s],await this.keyfiles.save(this.kf),e?await this.remember(t):await this.forgetKeychain()}pendingJoinRequests(){return this.kf?.joinRequests??[]}members(){return this.kf?.identities??[]}myIdentityId(){return this.load().identityId}async approveJoinRequest(a,t){if(!this.sessionKey)throw new Error("Unlock encryption first.");if(await this.refresh(),!this.kf)return!1;let e=this.kf.joinRequests.find(i=>i.id===a);return e?(this.kf.slots=[...this.kf.slots.filter(i=>i.recipientId!==e.id),await as(this.sessionKey,jt(e.pubKey),e.id)],this.kf.identities=[...this.kf.identities.filter(i=>i.id!==e.id),{id:e.id,label:t??e.label,pubKey:e.pubKey,addedAt:new Date().toISOString()}],this.kf.joinRequests=this.kf.joinRequests.filter(i=>i.id!==a),await this.keyfiles.save(this.kf),!0):!1}async removeMember(a){await this.refresh(),this.kf&&(this.kf.slots=this.kf.slots.filter(t=>t.recipientId!==a),this.kf.identities=this.kf.identities.filter(t=>t.id!==a),this.kf.joinRequests=this.kf.joinRequests.filter(t=>t.id!==a),await this.keyfiles.save(this.kf))}async denyJoinRequest(a){await this.refresh(),this.kf&&(this.kf.joinRequests=this.kf.joinRequests.filter(t=>t.id!==a),await this.keyfiles.save(this.kf))}lock(){this.sessionKey&&this.sessionKey.fill(0),this.sessionKey=null,this.clearIdle()}async clear(){this.lock(),await this.forgetKeychain();try{let a=this.app.vault.adapter;for(let t of[".stashpad/keys.json"])try{await a.exists(t)&&await a.remove(t)}catch{}try{let t=await a.list("_keys");for(let e of t.files||[])if(/\/keys-\d+\.json$/.test(e))try{await a.remove(e)}catch{}}catch{}}catch{}this.kf=null,await this.save(ki())}getSessionKey(){return this.sessionKey&&this.armIdle(),this.sessionKey?this.sessionKey.slice():null}async mintIdentity(a,t){let e=await ia(),i=await Ke(e.privKeyPkcs8,a);e.privKeyPkcs8.fill(0);let s=this.load(),n=s.identityId??tt(8),o=t??s.identityLabel??"This device",r=ls(e.pubKeySpki);return await this.save({...s,identityId:n,identityLabel:o,identityPub:r,identityPrivWrapped:ls(i.data),identityPrivKdf:i.kdf}),{id:n,label:o,pub:r}}identityRecord(a){return{id:a.id,label:a.label,pubKey:a.pub,addedAt:new Date().toISOString()}}armIdle(){this.clearIdle();let a=this.idleMinutes();a>0&&(this.idleTimer=window.setTimeout(()=>this.lock(),a*6e4))}clearIdle(){this.idleTimer!=null&&(window.clearTimeout(this.idleTimer),this.idleTimer=null)}dispose(){this.lock()}};var us=require("obsidian");Is();Tt();rt();var ee="stash",Fa=1;function wa(c){let t=(c.split(/[\\/]/).pop()??"").trim();return!t||t==="."||t===".."||t.includes("/")||t.includes("\\")||t.includes("..")?"":t}var zn=/!\[\[([^\]\|]+)(?:\|[^\]]+)?\]\]/g;async function he(c,a){let t=[],e=NA([...a.rootNotes,...a.allDescendants]),i=new Map,s=[];for(let o of e){let r=await c.vault.read(o.file),A=r,l=ka(r);for(let d of l){let p=c.metadataCache.getFirstLinkpathDest(d,o.file.path);if(!p){s.push(`Missing attachment "${d}" in ${o.file.path}`);continue}let g=p.name;i.has(g)||i.set(g,await c.vault.readBinary(p)),A=xA(A,d,g)}A=HA(A,c,o.file.path),t.push({name:`notes/${o.file.name}`,data:A})}for(let[o,r]of i)t.push({name:`attachments/${o}`,data:r});let n={stashSchema:Fa,exportedAt:new Date().toISOString(),sourceFolder:a.sourceFolder,noteCount:e.length,rootIds:a.rootNotes.map(o=>o.id)};return t.push({name:"manifest.json",data:JSON.stringify(n,null,2)}),s.length&&t.push({name:"warnings.txt",data:s.join(` +`)}),xi(t,6)}async function Yt(c,a,t,e,i={}){let s=await Mi(a),n=s["manifest.json"];if(!n)throw new Error("Not a valid .stash package: missing manifest.json");let o=JSON.parse(gs(n));if(typeof o.stashSchema!="number"||o.stashSchema>Fa)throw new Error(`Unsupported .stash schema: v${o.stashSchema}`);await va(c,t);let r=Object.entries(s).filter(([E])=>E.startsWith("notes/")&&E.endsWith(".md")),A=[];for(let[E,v]of r){let w=gs(v),{fm:D,body:N}=lt(w),P=wa(E.slice(6))||`${D.id||"imported-"+tt(4)}.md`;A.push({originalName:P,fm:D,body:N})}let l=new Map,d=0;for(let E of A){let v=E.fm.id;v&&(i.forceNewIds?l.set(v,tt(6)):e.has(v)||l.has(v)?(l.set(v,`${v}-${tt(4)}-Imported`),d++):l.set(v,v))}let p=new Date().toISOString(),g=[],h=`${t}/_attachments`,I=0,u=Object.entries(s).filter(([E])=>E.startsWith("attachments/")),f=new Map,C=null;if(i.dedupeExisting){C=new Map;for(let E of c.vault.getFiles())C.has(E.name)||C.set(E.name,E.path)}let B=(E,v)=>{if(E.length!==v.length)return!1;for(let w=0;w<E.length;w++)if(E[w]!==v[w])return!1;return!0},m=!1;for(let[E,v]of u){let w=wa(E.slice(12));if(!w)continue;let D=v,N=[],P=C?.get(w);P&&N.push(P);let H=`${h}/${w}`;await c.vault.adapter.exists(H)&&N.push(H);let b=null;for(let M of N)try{if(B(new Uint8Array(await c.vault.adapter.readBinary(M)),D)){b=M;break}}catch{}if(b){f.set(w,b);continue}let S=H;for(let M=1;await c.vault.adapter.exists(S);M++)S=`${h}/${MA(w,M)}`;f.set(w,S),m||(await va(c,h),m=!0),await c.vault.createBinary(S,D.buffer),I++}let y=0;for(let E of A){let v=E.fm.id;if(!v){g.push(`Skipped ${E.originalName} \u2014 no id in frontmatter`);continue}let w=l.get(v),D=E.fm.parent??null,N=D;!D||D===F?N=i.reparentRootsTo??D??F:l.has(D)?N=l.get(D):N=e.has(D)?D:i.reparentRootsTo??F;let P=TA(E.body,f,h),H={...E.fm,id:w,parent:N,import_date:p};Array.isArray(H.attachments)&&(H.attachments=H.attachments.map(U=>{let L=Sa(Ee(U));return qt(f.get(L)??`${h}/${L}`)}));let b=pe(H,P),S=w===v?E.originalName:UA(E.originalName,v,w),M=`${t}/${S}`;await c.vault.adapter.exists(M)&&(S=`${S.replace(/\.md$/,"")}-${tt(4)}.md`,M=`${t}/${S}`),await c.vault.create(M,b),y++}let Q;if(o.colorAliases&&typeof o.colorAliases=="object"){let E={};for(let[v,w]of Object.entries(o.colorAliases)){let D=String(v).trim().toLowerCase(),N=String(w??"").trim();/^#([0-9a-f]{6})$/.test(D)&&N&&(E[D]=N.slice(0,60))}Object.keys(E).length&&(Q=E)}return{notesWritten:y,attachmentsWritten:I,collisionsRenamed:d,warnings:g,colorAliases:Q,idRemap:Object.fromEntries(l)}}function NA(c){let a=new Set,t=[];for(let e of c)a.has(e.id)||(a.add(e.id),t.push(e));return t}function ka(c){let a=new Set,t;for(zn.lastIndex=0;(t=zn.exec(c))!==null;)a.add(t[1]);return[...a]}async function fs(c,a){let t=await c.vault.read(a),e=[],i=new Set;for(let s of ka(t)){let n=c.metadataCache.getFirstLinkpathDest(s,a.path);n&&!i.has(n.path)&&(i.add(n.path),e.push(n))}return e}function xA(c,a,t){return c.replace(new RegExp(`!\\[\\[${PA(a)}(\\|[^\\]]+)?\\]\\]`,"g"),(e,i)=>`![[${t}${i??""}]]`)}function MA(c,a){let t=c.lastIndexOf(".");return t>0?`${c.slice(0,t)}-${a}${c.slice(t)}`:`${c}-${a}`}function TA(c,a,t){return c.replace(zn,(e,i,s)=>{if(i.includes("/"))return e;let n=a.get(i)??`${t}/${i}`;return e.replace(i,n)})}function HA(c,a,t){let e=lt(c);if(!e.fm.attachments||!Array.isArray(e.fm.attachments))return c;let i=e.fm.attachments.map(n=>{let o=a.metadataCache.getFirstLinkpathDest(n,t);return o?o.name:Sa(n)}),s={...e.fm,attachments:i};return pe(s,e.body)}function PA(c){return c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Sa(c){let a=c.lastIndexOf("/");return a<0?c:c.slice(a+1)}function UA(c,a,t){return c.includes(a)?c.replace(a,t):c.replace(/\.md$/,`-${t}.md`)}function lt(c){if(!c.startsWith("---"))return{fm:{},body:c};let a=c.indexOf(` +---`,3);if(a<0)return{fm:{},body:c};let t=c.slice(3,a).replace(/^\n/,""),e=c.slice(a+4),i={};try{i=(0,us.parseYaml)(t)??{}}catch{i={}}let s=e.startsWith(` +`)?e.slice(1):e;return{fm:i,body:s}}function pe(c,a){return`--- +${(0,us.stringifyYaml)(c).trimEnd()} --- -${a}`}async function pa(c,a){if(!(!a||await c.vault.adapter.exists(a)))try{await c.vault.createFolder(a)}catch(e){let i=e?.message??"";if(!/already exists/i.test(i))throw e}}As();var ce="stashenc",EA="stashmeta";function de(c){return c.replace(/\.stashenc$/,`.${EA}`)}async function Ca(c,a){try{return JSON.parse(await c.vault.adapter.read(de(a)))}catch{return null}}async function he(c,a,t){let e=a.replace(/\/+$/,""),i=[];for(let l of c.vault.getMarkdownFiles()){if((l.parent?.path?.replace(/\/+$/,"")??"")!==e)continue;let d;try{d=lt(await c.vault.read(l)).fm}catch{continue}typeof d.id=="string"&&i.push({id:d.id,file:l,parent:typeof d.parent=="string"?d.parent:null,created:typeof d.created=="string"?d.created:""})}let s=i.find(l=>l.id===t);if(!s)return null;let n=new Map;for(let l of i){if(!l.parent)continue;let d=n.get(l.parent)??[];d.push(l),n.set(l.parent,d)}let o=[],r=new Set([t]),A=[t];for(;A.length;){let l=[];for(let d of A)for(let g of n.get(d)??[])r.has(g.id)||(r.add(g.id),o.push(g),l.push(g.id));A=l}return{rootNote:s,descendants:o,parentId:s.parent}}function Ln(c){if(!c)return null;let a=c.replace(/\/+$/,"");return!a||a.startsWith("/")||a.includes("\\")||/^[a-zA-Z]:/.test(a)||a.split("/").some(t=>t===".."||t===".")?null:a}async function qn(c,a,t){await c.vault.adapter.writeBinary(a,t);let e;try{e=new Uint8Array(await c.vault.adapter.readBinary(a))}catch(s){throw new Error(`Couldn't read back the encrypted file to verify it (${s.message}). Nothing was deleted.`)}let i=e.length===t.length;if(i){for(let s=0;s<t.length;s++)if(e[s]!==t[s]){i=!1;break}}if(!i){try{await c.vault.adapter.remove(a)}catch{}throw new Error("The encrypted file on disk doesn't match what was written (bad write?). Nothing was deleted.")}}function ds(c){return c.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||c.basename}function Le(c){return(c.replace(/[\\/:*?"<>|]+/g," ").replace(/\s+/g," ").trim()||"locked").slice(0,60)}async function Ba(c,a,t){let e=new Set(a.map(r=>r.file.path)),i=new Map;for(let r of a)for(let A of await cs(c,r.file))i.set(A.path,A);let s=new Set,n=c.metadataCache.resolvedLinks??{};for(let r of Object.keys(n))if(!e.has(r))for(let A of Object.keys(n[r]??{}))i.has(A)&&s.add(A);let o=[];for(let r of a){let A=t?.get(r.file.path);if(A!=null)try{let l=await c.vault.adapter.stat(r.file.path);if(l&&l.mtime!==A){console.warn("[Stashpad] note changed since it was bundled \u2014 keeping plaintext",r.file.path),o.push(r.file.path);continue}}catch{}try{await c.vault.delete(r.file)}catch(l){console.warn("[Stashpad] couldn't delete plaintext note",r.file.path,l),o.push(r.file.path)}}for(let[r,A]of i)if(!s.has(r))try{await c.vault.delete(A)}catch(l){console.warn("[Stashpad] couldn't delete exclusive attachment",r,l),o.push(r)}return{unpurged:o}}async function ma(c,a,t,e,i=null,s=!1,n){let o=await he(c,a,t);if(!o)throw new Error("Couldn't find that note to lock.");let{rootNote:r,descendants:A,parentId:l}=o,d=[r,...A],g=new Map;for(let Q of d)try{let E=await c.vault.adapter.stat(Q.file.path);E&&g.set(Q.file.path,E.mtime)}catch{}let p=await Ae(c,{rootNotes:[{id:r.id,file:r.file}],allDescendants:A.map(Q=>({id:Q.id,file:Q.file})),sourceFolder:a}),h=await Qi(p,e),I=await ae(h,e);if(I.length!==p.length)throw new Error("Encryption self-check failed (size mismatch).");for(let Q=0;Q<p.length;Q++)if(I[Q]!==p[Q])throw new Error("Encryption self-check failed (content mismatch).");let u=(n??a).replace(/\/+$/,"");n&&!await c.vault.adapter.exists(u)&&await c.vault.adapter.mkdir(u);let f=Le(s?t:ds(r.file)),C=`${u}/${f}.${ce}`;for(let Q=1;await c.vault.adapter.exists(C);Q++)C=`${u}/${f} (${Q}).${ce}`;await qn(c,C,h);let B=d,m={v:1,parentId:l,title:s?"":ds(r.file),count:B.length,created:r.created,rootId:t,prevSibling:i};try{await c.vault.adapter.write(de(C),JSON.stringify(m))}catch(Q){console.warn("[Stashpad] couldn't write lock sidecar",Q)}let{unpurged:w}=await Ba(c,B,g);return{blobPath:C,noteCount:B.length,rootId:t,parentId:l,title:m.title,created:r.created,unpurged:w}}async function Qa(c,a,t,e,i){let s=new Uint8Array(await c.vault.adapter.readBinary(a));if(!Ht(s))throw new Error("Not an encrypted bundle.");let n=await ae(s,t),o=Ln(i)??a.replace(/\/[^/]*$/,""),r=await Kt(c,n,o,e,{dedupeExisting:!0});await c.vault.adapter.remove(a);try{await c.vault.adapter.remove(de(a))}catch{}return{notesWritten:r.notesWritten,restoredTo:o}}var Dt="_deleted";function wA(c){let a="";for(let t=0;t<c.length;t++)a+=String.fromCharCode(c[t]);return btoa(a)}function vA(c){let a=atob(c),t=new Uint8Array(a.length);for(let e=0;e<a.length;e++)t[e]=a.charCodeAt(e);return t}async function Jn(c,a,t,e){let i=Ln(t?.originalFolder);if(!i&&t?.originalFolderEnc&&e)try{i=Ln(new TextDecoder().decode(await ae(vA(t.originalFolderEnc),e)))}catch{i=null}if(i)return await c.vault.adapter.exists(i)||await c.vault.adapter.mkdir(i),i;let s=a.replace(/\/[^/]*$/,"");if(s===Dt||s.startsWith(`${Dt}/`))throw new Error("This deleted note's origin folder is unknown (missing or tampered sidecar) \u2014 can't restore it safely. The encrypted copy was kept.");return s}async function Kn(c){let a=[""];for(;a.length;){let t=a.shift(),e;try{e=await c.vault.adapter.list(t||"/")}catch{continue}if(e.files.some(i=>i.endsWith(`.${ce}`)))return!0;for(let i of e.folders)i===".obsidian"||i.endsWith("/.obsidian")||a.push(i)}return!1}async function ya(c,a,t,e,i,s=!1){let n=await he(c,a,t);if(!n)throw new Error("Couldn't find that note to delete.");let{rootNote:o,descendants:r,parentId:A}=n,l=[o,...r],d=new Map;for(let Q of l)try{let E=await c.vault.adapter.stat(Q.file.path);E&&d.set(Q.file.path,E.mtime)}catch{}let g=await Ae(c,{rootNotes:[{id:o.id,file:o.file}],allDescendants:r.map(Q=>({id:Q.id,file:Q.file})),sourceFolder:a}),p=await Qi(g,e),h=await ae(p,e);if(h.length!==g.length)throw new Error("Encryption self-check failed (size).");for(let Q=0;Q<g.length;Q++)if(h[Q]!==g[Q])throw new Error("Encryption self-check failed (content).");await c.vault.adapter.exists(Dt)||await c.vault.adapter.mkdir(Dt);let I=a.replace(/\/+$/,""),u=I.split("/").pop()||"vault",f=Le(s?t:`${u} ${ds(o.file)}`),C=`${Dt}/${f}.${ce}`;for(let Q=1;await c.vault.adapter.exists(C);Q++)C=`${Dt}/${f} (${Q}).${ce}`;await qn(c,C,p);let B=l,m={v:1,kind:"deleted",originalFolder:s?"":I,...s?{originalFolderEnc:wA(await Qi(new TextEncoder().encode(I),e))}:{},parentId:A,title:s?"":ds(o.file),count:B.length,created:o.created,rootId:t,deletedAt:i};try{await c.vault.adapter.write(de(C),JSON.stringify(m))}catch(Q){console.warn("[Stashpad] couldn't write deleted sidecar",Q)}let{unpurged:w}=await Ba(c,B,d);return{blobPath:C,noteCount:B.length,rootId:t,originalFolder:I,title:m.title,unpurged:w}}async function Ea(c,a,t,e){let i=new Uint8Array(await c.vault.adapter.readBinary(a));if(!Ht(i))throw new Error("Not an encrypted bundle.");let s=await hs(c,a),n=await Jn(c,a,s,t),o=await ae(i,t),r=await Kt(c,o,n,e,{dedupeExisting:!0});await c.vault.adapter.remove(a);try{await c.vault.adapter.remove(de(a))}catch{}return{notesWritten:r.notesWritten,restoredTo:n}}async function hs(c,a){try{return JSON.parse(await c.vault.adapter.read(de(a)))}catch{return null}}var Ut=".trash";async function FA(c,a){let t=[],e=[a];for(;e.length;){let i=e.shift(),s;try{s=await c.vault.adapter.list(i)}catch{continue}t.push(...s.files),e.push(...s.folders)}return t}function kA(c){let a=c.split("/").filter(Boolean);if(a.length===0)return null;for(let t of a)if(t===".."||t==="."||t.includes("\\")||/^[a-zA-Z]:/.test(t))return null;return a.join("/")}async function wa(c,a,t,e=!1){if(!await c.vault.adapter.exists(Ut))return null;let i=await FA(c,Ut);if(i.length===0)return null;let s=[],n=new Map;for(let h of i){let I=h.slice(Ut.length+1);s.push({name:`files/${I}`,data:await c.vault.adapter.readBinary(h)});try{let u=await c.vault.adapter.stat(h);u&&n.set(h,u.mtime)}catch{}}let o=await Si(s),r=await Qi(o,a),A=await ae(r,a);if(A.length!==o.length)throw new Error("Encryption self-check failed (size).");for(let h=0;h<o.length;h++)if(A[h]!==o[h])throw new Error("Encryption self-check failed (content).");await c.vault.adapter.exists(Dt)||await c.vault.adapter.mkdir(Dt);let l=Le(e?`trash-${t.replace(/[^0-9]/g,"").slice(0,14)}`:"Obsidian trash backfill"),d=`${Dt}/${l}.${ce}`;for(let h=1;await c.vault.adapter.exists(d);h++)d=`${Dt}/${l} (${h}).${ce}`;await qn(c,d,r);let g={v:1,kind:"rawtrash",originalFolder:Ut,parentId:null,title:e?"":"Obsidian trash (backfill)",count:i.length,created:t,rootId:"",deletedAt:t};try{await c.vault.adapter.write(de(d),JSON.stringify(g))}catch(h){console.warn("[Stashpad] couldn't write backfill sidecar",h)}let p=[];for(let h of i){let I=n.get(h);try{if(I!=null){let u=await c.vault.adapter.stat(h);if(u&&u.mtime!==I){p.push(h);continue}}await c.vault.adapter.remove(h)}catch(u){console.warn("[Stashpad] couldn't delete trash file",h,u),p.push(h)}}return{blobPath:d,fileCount:i.length,unpurged:p}}async function va(c,a,t){let e=new Uint8Array(await c.vault.adapter.readBinary(a));if(!Ht(e))throw new Error("Not an encrypted bundle.");let i=await ae(e,t),s=await Di(i),n=0;for(let[o,r]of Object.entries(s)){if(!o.startsWith("files/"))continue;let A=kA(o.slice(6));if(!A){console.warn("[Stashpad] skipped unsafe trash entry",o);continue}let l=`${Ut}/${A}`.split("/").slice(0,-1).join("/"),d="";for(let p of l.split("/"))d=d?`${d}/${p}`:p,await c.vault.adapter.exists(d)||await c.vault.adapter.mkdir(d);let g=`${Ut}/${A}`;for(let p=1;await c.vault.adapter.exists(g);p++)g=`${Ut}/${A.replace(/(\.[^./]*)?$/,` (${p})$1`)}`;await c.vault.adapter.writeBinary(g,r.buffer),n++}await c.vault.adapter.remove(a);try{await c.vault.adapter.remove(de(a))}catch{}return{filesWritten:n}}async function Fa(c){if(!await c.vault.adapter.exists(Dt))return[];try{return(await c.vault.adapter.list(Dt)).files.filter(t=>t.endsWith(`.${ce}`))}catch{return[]}}var bi=null,gs=new Set;function ps(c){if(bi!==c){bi=c;for(let a of gs)a()}}function _t(){return bi}function ka(c){if(bi===c){bi=null;for(let a of gs)a()}}function Sa(c){return gs.add(c),()=>gs.delete(c)}function SA(){return x.Platform.isMacOS?"Finder":x.Platform.isWin?"File Explorer":"file manager"}var qe=[{id:"move",label:"Move (picker)",desc:"Open a fuzzy picker to choose the new parent.",defaultPrimary:"M"},{id:"pickMove",label:"Move (in-list)",desc:"Highlight a note in the list with arrows; Enter sets it as parent.",defaultPrimary:"O"},{id:"merge",label:"Merge",desc:"Concatenate selected notes into the oldest one.",defaultPrimary:"&"},{id:"copy",label:"Copy",desc:"Copy selected note bodies to clipboard.",defaultPrimary:"C"},{id:"copyTree",label:"Copy tree",desc:"Copy the focused note + all descendants, indented.",defaultPrimary:"Y"},{id:"openEditor",label:"Open in editor",desc:"Open the cursor row (or focused note) in a regular Obsidian markdown tab.",defaultPrimary:"E"},{id:"openTab",label:"Open in new Stashpad tab",desc:"Open the cursor row (or focused note) in a new Stashpad tab focused on it.",defaultPrimary:"T"},{id:"split",label:"Split note",desc:"Split the cursor row (or focused note) into two notes at a chosen line.",defaultPrimary:"S"},{id:"copyOutline",label:"Copy as outline",desc:"Copy selection (or cursor row) as a nested ![[embed]] outline.",defaultPrimary:"L"},{id:"toggleSplit",label:"Toggle split-on-newlines",desc:"Default: Mod+/",defaultPrimary:"Mod+/"},{id:"pickDestination",label:"Pick destination",desc:"Default: Mod+D",defaultPrimary:"Mod+D"},{id:"search",label:"Search notes",desc:"Default: Mod+F",defaultPrimary:"Mod+F"},{id:"searchInParent",label:"Search in current parent",desc:"Default: Mod+Alt+F (Mod+Shift+F is taken by Obsidian's global search).",defaultPrimary:"Mod+Alt+F"},{id:"delete",label:"Delete selection",desc:"Default: Mod+Backspace",defaultPrimary:"Mod+Backspace"},{id:"undo",label:"Undo",desc:"Default: Mod+Z (Stashpad-only \u2014 won't fire while typing in the composer).",defaultPrimary:"Mod+Z"},{id:"redo",label:"Redo",desc:"Default: Mod+Shift+Z",defaultPrimary:"Mod+Shift+Z"},{id:"toggleComplete",label:"Toggle complete (strikethrough)",desc:"Default: Mod+Enter or X \u2014 marks selected/focused notes as complete (both chords active).",defaultPrimary:"Mod+Enter",defaultSecondary:"X",defaultUseBoth:!0},{id:"moveUp",label:"Move note up",desc:"Default: Mod+ArrowUp",defaultPrimary:"Mod+ArrowUp"},{id:"moveDown",label:"Move note down",desc:"Default: Mod+ArrowDown",defaultPrimary:"Mod+ArrowDown"},{id:"moveToTop",label:"Move note to top",desc:"Default: Mod+Shift+ArrowUp",defaultPrimary:"Mod+Shift+ArrowUp"},{id:"moveToBottom",label:"Move note to bottom",desc:"Default: Mod+Shift+ArrowDown",defaultPrimary:"Mod+Shift+ArrowDown"},{id:"outdent",label:"Outdent (move to grandparent)",desc:"Default: Mod+[ \u2014 re-parents the selection one level up.",defaultPrimary:"Mod+["},{id:"setColor",label:"Set note color",desc:"Default: Shift+: or ; \u2014 open the color picker for the selection (both chords active).",defaultPrimary:"Shift+:",defaultSecondary:";",defaultUseBoth:!0},{id:"clone",label:"Clone (duplicate / copy) selection",desc:"Default: Mod+Shift+D \u2014 clone selected notes (with their subtrees) as siblings.",defaultPrimary:"Mod+Shift+D"},{id:"insertTemplate",label:"Insert template (clone an existing note)",desc:"Pick any note in this Stashpad; clone it (with subtree + attachments) into the current view, retimestamped.",defaultPrimary:""},{id:"toggleExpand",label:"Show more / show less (expand toggle)",desc:"Default: Shift+? \u2014 toggle the clamp on the cursor row (or every selected row).",defaultPrimary:"Shift+?"},{id:"exportStash",label:"Export selection to .stash",desc:"Export the selected subtree(s) as a .stash bundle (notes + attachments).",defaultPrimary:""},{id:"importStash",label:"Import .stash file",desc:"Open the .stash bundle picker and import its notes into this Stashpad.",defaultPrimary:""},{id:"pickFolder",label:"Open / switch / create Stashpad folder",desc:"Default: Mod+S \u2014 opens the unified folder picker (reveal, switch, create, convert).",defaultPrimary:"Mod+S"},{id:"cloneStashpadTab",label:"Clone (duplicate / copy) this Stashpad tab",desc:'Open a second tab on the same folder + focus, mirroring the "copy" button in the focused-header actions.',defaultPrimary:""},{id:"selectAll",label:"Select all notes in view",desc:"Default: Mod+A \u2014 adds every visible row to the selection.",defaultPrimary:"Mod+A"},{id:"copyCodeBlock",label:"Copy code from codeblock",desc:"Default: { \u2014 copy the contents of the cursor row's first codeblock (or pick one when multiple exist).",defaultPrimary:"{"},{id:"swapWithParent",label:"Swap with parent (ouroboros)",desc:"Promote the cursor row above its current parent; the parent slides under it (carrying its other children). No default \u2014 bind in this tab.",defaultPrimary:""},{id:"togglePin",label:"Pin / unpin selected note",desc:"Default: P \u2014 toggle the sidebar pin state of the cursor row (or focused note).",defaultPrimary:"P"},{id:"toggleTask",label:"Toggle task (todo)",desc:"Default: H \u2014 mark the selection (or cursor row) as a task / todo, or clear it. Tasks appear in the Tasks panel.",defaultPrimary:"H"},{id:"setDue",label:"Set due date\u2026",desc:"Default: D \u2014 open a date+time picker to set (or clear) the due date on the selection. Setting a due date also marks the note as a task.",defaultPrimary:"D"},{id:"jumpToTop",label:"Jump to top of list",desc:"Default: Home \u2014 move the cursor to the first note in the current list.",defaultPrimary:"Home"},{id:"jumpToBottom",label:"Jump to bottom of list",desc:"Default: End \u2014 move the cursor to the last note in the current list.",defaultPrimary:"End"},{id:"commandPalette",label:"Command palette (Stashpad only)",desc:"Default: Mod+K \u2014 open a command palette listing only Stashpad's commands, with Sift search.",defaultPrimary:"Mod+K"},{id:"lockSelection",label:"Encrypt (lock) selection",desc:"Encrypt the selected note(s) + their children into a locked .stashenc bundle in place (prompts to unlock first if needed). No default chord.",defaultPrimary:""},{id:"unlockAll",label:"Decrypt (unlock) locked notes in view",desc:"Decrypt every locked stash shown in the current view back into place, skipping any that can't be read. No default chord.",defaultPrimary:""},{id:"moveToArchive",label:"Move selection to archive (encrypt)",desc:"Move the selected note(s) to the default archive folder, encrypted on arrival. Undoable. No default chord.",defaultPrimary:""},{id:"encryptDelete",label:"Encrypt & delete selection",desc:"Send the selected note(s) to the encrypted trash (recoverable with your password, Ctrl/Cmd+Z undoable). No default chord.",defaultPrimary:""},{id:"copyNotes",label:"Copy notes (note clipboard)",desc:"Copy the selected note(s) as NOTES: paste in the list to duplicate them (new ids), or anywhere else to paste their text. Skipped when text is highlighted (normal copy wins).",defaultPrimary:"Mod+C"},{id:"cutNotes",label:"Cut notes",desc:"Cut the selected note(s): paste in the list to MOVE them, or in the composer to extract their text and delete the originals (undoable).",defaultPrimary:"Mod+X"},{id:"pasteNotes",label:"Paste notes",desc:"Paste previously copied/cut notes at the cursor row (after it, same parent). Does nothing if the note clipboard is empty.",defaultPrimary:"Mod+V"}];function zn(){let c={};for(let a of qe)c[a.id]={primary:a.defaultPrimary,secondary:a.defaultSecondary??"",preferRight:!1,useBoth:!!a.defaultUseBoth};return c}var ge={folder:"Stashpad",importDropFolder:"",exportFolder:"_exports",autoImport:!1,inheritObsidianExclusions:!0,folderPanelPinnedFraction:.5,folderPanelPinned:[],folderPanelDownranked:[],folderPanelHidden:[],folderPanelPinnedGrouping:"pin-order",enablePerfProfiling:!1,writeRecoveryLinks:!0,useTemplatesFormat:!1,prefixTimestampsOnCopy:!0,splitOnLines:!1,splitMode:"lines",confirmCrossParentDrag:!0,confirmBulkDelete:!0,confirmAttachmentDelete:!0,autofocusComposerAfterSend:!0,popoutDuplicates:!0,encryption:Ei(),encryptTrash:!1,encryptTrashFilenames:!1,encryptionIdleLockMinutes:0,hideLockedTitles:!1,archiveFolders:[],lockedSubtrees:[],searchOpensInNewTab:!0,pinnedNotes:[],hideMobileToolbarInStashpad:!0,slugStopWords:[],searchIncludedFolders:[],searchExcludedFolders:[],shortcuts:{move:"M",pickMove:"O",merge:"&",copy:"C",copyTree:"Y",openEditor:"E",openTab:"T",split:"S",copyOutline:"L"},mod:{toggleSplit:"Mod+/",pickDestination:"Mod+D",search:"Mod+F",delete:"Mod+Backspace",undo:"Mod+Z",redo:"Mod+Shift+Z",toggleComplete:"Mod+Enter",moveUp:"Mod+ArrowUp",moveDown:"Mod+ArrowDown",moveToTop:"Mod+Shift+ArrowUp",moveToBottom:"Mod+Shift+ArrowDown",outdent:"Mod+[",setColor:"Shift+:"},customPalette:[],colorAliases:{},noteTemplates:{},authorName:"",authorId:"",authorRole:"",authorDepartment:"",showAuthor:!0,showContributors:!0,showLastEdit:!0,viewModes:{},includeAttachmentsInEverything:{},hideChildlessNotes:{},hideCompletedNotes:{},attachmentsOnlyNotes:{},mutedNotificationCategories:[],notificationHistoryLimit:5e3,notifiedDueKeys:[],autoNavOnMoveIn:!1,autoNavOnMoveOut:!1,autoExpandCursorRow:!1,autoOpenDetailPanel:!1,doubleClickToFocus:!0,dateDisplayFormat:"locale",dateDisplayTimezone:"",jdIndexScope:"vault",jdIndexScopeFolder:"",jdIndexStashpadFolder:"",jdIndexFile:"Index",jdIndexIncludeStashpadFolders:!1,jdIndexSort:"natural",jdIndexHasBuilt:!1,okfEnabled:!1,okfTemplatePath:"",drafts:{},lastSubmitted:{},bindings:zn()},Da=JSON.parse(JSON.stringify(ge)),Yn=new Set;function j(){return Da}function $n(c){Da=c;for(let a of Yn)a()}function ba(c){return Yn.add(c),()=>Yn.delete(c)}function fs(c){try{let a=c.internalPlugins?.plugins?.templates;if(!a?.enabled)return null;let t=a.instance?.options??{};return{dateFormat:t.dateFormat||"YYYY-MM-DD",timeFormat:t.timeFormat||"HH:mm"}}catch{return null}}var Is=[{id:"general",label:"General"},{id:"encryption",label:"Encryption"},{id:"diagnostics",label:"Diagnostics"},{id:"authorship",label:"Authorship"},{id:"templates",label:"Templates"},{id:"jdindex",label:"JD Index"},{id:"okf",label:"Open Knowledge Format (OKF)"},{id:"hotkeys",label:"Hotkeys"}],On=null;function DA(c,a){return On||(On=class extends x.SettingPage{constructor(t,e){super(),this.title=t,this._renderFn=e}display(){this.containerEl.empty(),this._renderFn(this.containerEl)}}),new On(c,a)}var us=class extends x.PluginSettingTab{constructor(t,e){super(t,e);this.plugin=e}display(){if(x.SettingPage){super.display();return}let{containerEl:t}=this;t.empty();for(let e of Is){new x.Setting(t).setName(e.label).setHeading();let i=this.itemsForTab(e.id);if(i)for(let s of i){let n=new x.Setting(t);typeof s.render=="function"?s.render(n):(s.name&&n.setName(s.name),s.desc&&n.setDesc(s.desc))}else this.renderTabContent(t,e.id)}}getSettingDefinitions(){return Is.map(t=>{let e=this.itemsForTab(t.id);return e?{type:"page",name:t.label,items:e}:{type:"page",name:t.label,page:()=>DA(t.label,i=>this.renderTabContent(i,t.id))}})}itemsForTab(t){switch(t){case"hotkeys":return this.hotkeyItems();case"diagnostics":return this.diagnosticsItems();case"general":return this.generalItems();case"encryption":return this.encryptionItems();case"authorship":return this.authorshipItems();case"templates":return this.templatesItems();case"jdindex":return this.jdIndexItems();case"okf":return this.okfItems();default:return null}}renderTabContent(t,e){switch(e){case"authorship":this.renderAuthorshipSection(t);break;case"templates":this.renderTemplatesTab(t);break;case"jdindex":this.renderJdIndexSection(t);break}}diagnosticsItems(){let t=new Set(this.plugin.settings.mutedNotificationCategories??[]),e=Object.keys(An);return[this.renderDef("Write recovery navigation links","Maintain the redundant parentLink/children frontmatter so you can walk the hierarchy from raw Markdown if the index ever breaks. On a slow / network drive this is a big per-move cost (several round-trips each); turn it off there for snappier moves \u2014 Rebootstrap rebuilds the fields on demand, and your notes' canonical structure (id/parent) is unaffected either way.",i=>i.addToggle(s=>s.setValue(this.plugin.settings.writeRecoveryLinks).onChange(async n=>{this.plugin.settings.writeRecoveryLinks=n,await this.plugin.saveSettings()})),["recovery","parentlink","children","frontmatter"]),this.renderDef("Performance profiling","Record timing for list rendering, body reads, and file writes. Turn on, use Stashpad normally (especially the slow operations), then run \u201CDump performance profile\u201D from the command palette and share the result. Off = zero overhead.",i=>i.addToggle(s=>s.setValue(this.plugin.settings.enablePerfProfiling).onChange(async n=>{this.plugin.settings.enablePerfProfiling=n,await this.plugin.saveSettings()})),["perf","profiling","timing","slow"]),this.renderDef("Open log file","Append-only history of creates, deletes, parent changes, renames. Stored alongside the plugin's other private files.",i=>i.addButton(s=>s.setButtonText("Open log").onClick(async()=>{let n=this.app.vault.adapter,o=this.plugin.pluginPrivatePath("log.jsonl");if(!await n.exists(o)){new x.Notice("No log yet \u2014 make some changes first.");return}let r=await n.read(o);new xe(this.app,r,o).open()})),["log","history","diagnostics"]),this.renderDef("Notification history limit","Maximum number of notifications kept in the persistent history. Set to 0 for unlimited (the file size grows with usage; expect a few hundred KB per ~5000 entries). Default: 5000.",i=>i.addText(s=>s.setValue(String(this.plugin.settings.notificationHistoryLimit??5e3)).setPlaceholder("5000").onChange(async n=>{let o=parseInt(n,10);Number.isFinite(o)&&(this.plugin.settings.notificationHistoryLimit=o,this.plugin.notifications.setHistoryLimit(o),await this.plugin.saveSettings())})),["notification","history","limit"]),{type:"group",heading:"Mute notification categories",items:e.map(i=>{let s=An[i];return this.renderDef(s.label,s.desc,n=>n.addToggle(o=>o.setValue(!t.has(i)).onChange(async r=>{let A=!r;A?t.add(i):t.delete(i),this.plugin.settings.mutedNotificationCategories=Array.from(t),this.plugin.notifications.setMuted(i,A),await this.plugin.saveSettings()})),["notification","mute","toast","category"])})},this.renderDef("Notification history","Browse the last 200 toasts. Filter by category. Live-updates as new notifications arrive. Muted categories still appear here so you can review what was suppressed.",i=>i.addButton(s=>s.setButtonText("View notification history").onClick(()=>{new ci(this.app,this.plugin.notifications,async n=>{let o=this.app.vault.adapter,r=this.plugin.pluginPrivatePath("log.jsonl");if(!await o.exists(r)){new x.Notice("No log yet \u2014 make some changes first.");return}let A=await o.read(r);new xe(this.app,A,r).open()},this.plugin.settings.authorId||null,n=>this.plugin.lookupNoteAuthorIds(n)).open()})),["notification","history","panel"])]}renderTemplatesTab(t){this.renderColorAliasesSection(t),this.renderNoteTemplatesSection(t)}renderDef(t,e,i,s){return{name:t,desc:e,aliases:s,render:n=>{n.setName(t).setDesc(e),i(n)}}}sectionDef(t,e,i,s){return{name:t,desc:e,aliases:s,render:n=>{let o=n.settingEl;o.empty(),o.removeClass("setting-item"),o.addClass("stashpad-settings-section"),i(o)}}}generalItems(){let t=async()=>this.plugin.saveSettings(),e=(s,n,o,r,A)=>this.renderDef(s,n,l=>l.addToggle(d=>d.setValue(o()).onChange(async g=>{r(g),await t()})),A),i=[];i.push(this.renderDef("Stashpad notes folder","Vault-relative folder where Stashpad stores its notes and attachments. Created on demand.",s=>{s.addText(n=>{new Pe(this.app,n.inputEl),n.setValue(this.plugin.settings.folder).setPlaceholder("Stashpad").onChange(async o=>{let r=(o||"").trim().replace(/^\/+|\/+$/g,"")||ge.folder,A=r.split("/").filter(Boolean).pop()??"";if(new Set([this.plugin.settings.importDropFolder,this.plugin.settings.exportFolder,"_attachments","_processed"].map(d=>(d??"").trim().replace(/^\/+|\/+$/g,"")).filter(Boolean)).has(A)){new x.Notice(`"${r}" uses a reserved Stashpad subfolder name. Pick something else.`);return}this.plugin.settings.folder=r,await t()})})},["folder","path","location","notes"])),i.push(e("Auto-import dropped files","When on, any file you drop directly into a Stashpad folder is imported automatically: markdown becomes a note (the original is archived to .archive); other files move to _attachments with a note that links to them. Large drops ask for confirmation first.",()=>this.plugin.settings.autoImport,s=>{this.plugin.settings.autoImport=s},["import","drop","auto"])),i.push(e("Inherit Obsidian's excluded files","Also hide files matching Obsidian's \u201CExcluded files\u201D list (Settings \u2192 Files & Links) from Stashpad's link autocomplete and file surfaces \u2014 so you manage exclusions in one place. Plugin-internal formats like .edtz are always excluded regardless.",()=>this.plugin.settings.inheritObsidianExclusions,s=>{this.plugin.settings.inheritObsidianExclusions=s},["excluded","ignore","files"])),i.push(this.renderDef("Dedicated import subfolder (optional)","Optional. A subfolder (relative to each Stashpad folder) where dropped .stash files auto-import. Leave blank to just drop files into the Stashpad folder itself (recommended). Suggested name: _imports.",s=>s.addText(n=>n.setValue(this.plugin.settings.importDropFolder).setPlaceholder("_imports (leave blank to use the folder root)").onChange(async o=>{this.plugin.settings.importDropFolder=(o||"").trim().replace(/^\/+|\/+$/g,""),await t()})),["import","subfolder"])),i.push(this.renderDef("Stash export subfolder","Subfolder name (relative to each Stashpad folder) where exports land. Must differ from the import subfolder above.",s=>s.addText(n=>n.setValue(this.plugin.settings.exportFolder).setPlaceholder("_exports").onChange(async o=>{this.plugin.settings.exportFolder=(o||"").trim().replace(/^\/+|\/+$/g,"")||ge.exportFolder,await t()})),["export","stash","subfolder"])),i.push(this.renderDef("Rebootstrap existing Stashpad folders","Walk every folder that has a home note: ensure infrastructure (_imports, _exports, drafts file), backfill the redundant parentLink + children frontmatter fields, AND rename any note whose filename slug no longer matches its body's first line. Safe to run anytime; skip-if-equal means already-synced notes are no-op writes.",s=>s.addButton(n=>n.setButtonText("Rebootstrap now").onClick(async()=>{n.setDisabled(!0).setButtonText("Working\u2026");try{let{touched:o,fmChecked:r,fmWritten:A,slugsRenamed:l,authors:d,imported:g,attachmentsLinked:p}=await this.plugin.rebootstrapAllFolders(),h=[];h.push(`rebootstrapped ${o.length} folder${o.length===1?"":"s"}`),g>0&&h.push(`imported ${g} loose file${g===1?"":"s"}`),p>0&&h.push(`linked attachments on ${p} note${p===1?"":"s"}`),A>0?h.push(`updated frontmatter on ${A} of ${r} notes`):r>0&&h.push(`frontmatter already in sync (${r} notes checked)`),l>0&&h.push(`renamed ${l} note${l===1?"":"s"} to match body`),d>0&&h.push(`rebuilt author registry (${d} author${d===1?"":"s"})`),new x.Notice(`Stashpad: ${h.join("; ")}.`)}catch(o){new x.Notice(`Stashpad: rebootstrap failed (${o.message})`)}finally{n.setDisabled(!1).setButtonText("Rebootstrap now")}})),["rebootstrap","rebuild","repair","backfill","slug"])),i.push(this.renderDef("Use Templates plugin date/time formats","When on, timestamps use the formats configured in the core Templates plugin. Off: YYYY.MM.DD + HH:mm A.",s=>{s.addToggle(o=>o.setValue(this.plugin.settings.useTemplatesFormat).onChange(async r=>{this.plugin.settings.useTemplatesFormat=r,await t()}));let n=fs(this.app);s.descEl.createDiv({cls:"stashpad-settings-note"}).setText(n?`Templates plugin: date = "${n.dateFormat}", time = "${n.timeFormat}"`:"Templates plugin not enabled.")},["templates","date","time","format"]));{let s=null,n=()=>{s&&s.setText(`Sample: ${Yt(Date.now(),this.plugin.settings)}`)};i.push(this.renderDef("Date display format","How due dates and created/modified times are shown in the Tasks and detail panels.",o=>{o.addDropdown(r=>{r.addOption("locale","Locale, short (Mar 5, 9:00 AM)"),r.addOption("long","Locale, long (Thursday, March 5\u2026)"),r.addOption("iso","ISO (2026-03-05 09:00)"),r.addOption("us","US (3/5/2026, 9:00 AM)"),r.addOption("eu","EU (5/3/2026, 09:00)"),r.setValue(this.plugin.settings.dateDisplayFormat??"locale"),r.onChange(async A=>{this.plugin.settings.dateDisplayFormat=A,await t(),n()})})},["date","format","display"])),i.push(this.renderDef("Display timezone","IANA timezone name (e.g. America/New_York, Europe/London, Asia/Kolkata). Leave blank to use your system timezone.",o=>{o.addText(r=>{r.setPlaceholder("(system timezone)"),r.setValue(this.plugin.settings.dateDisplayTimezone??""),r.onChange(async A=>{this.plugin.settings.dateDisplayTimezone=(A||"").trim(),await t(),n()})})},["timezone","tz","date","iana"])),i.push({name:"Date sample",searchable:!1,render:o=>{let r=o.settingEl;r.empty(),r.removeClass("setting-item"),s=r.createDiv({cls:"setting-item-description stashpad-settings-note"}),n()}})}return i.push(e("Navigate into parent after moving a note IN","When you move a note onto another note via the in-list move picker (drag-onto-sibling), automatically drill into the new parent so you can see the moved note in its new home. Off = stay focused where you were.",()=>this.plugin.settings.autoNavOnMoveIn,s=>{this.plugin.settings.autoNavOnMoveIn=s},["navigate","move","in"])),i.push(e("Navigate to destination after moving a note OUT","When you outdent a note, move it via the cross-parent picker, or send it to Home, automatically drill into the destination parent. Off = stay focused where you were.",()=>this.plugin.settings.autoNavOnMoveOut,s=>{this.plugin.settings.autoNavOnMoveOut=s},["navigate","move","out"])),i.push(e("Double-click a note to open it","Double-click (or double-tap on mobile) a note in the list to focus/open it \u2014 the same as pressing \u2192 or clicking the enter arrow. Single click still just selects. On by default.",()=>this.plugin.settings.doubleClickToFocus,s=>{this.plugin.settings.doubleClickToFocus=s},["double","click","open","focus"])),i.push(e("Auto-open the detail panel","Open the right-sidebar Stashpad detail panel automatically whenever a Stashpad view becomes active. The panel shows the cursored note's body, metadata, and children. Off = open manually via ribbon or command palette.",()=>this.plugin.settings.autoOpenDetailPanel,s=>{this.plugin.settings.autoOpenDetailPanel=s},["detail","panel","sidebar"])),i.push(e("Expand the cursor row's body automatically","As you arrow-key through the list, the row under the cursor temporarily un-clamps to show its full body. Moving away re-collapses it. Doesn't affect the persistent 'Show more' state \u2014 this is a transient view-only effect.",()=>this.plugin.settings.autoExpandCursorRow,s=>{this.plugin.settings.autoExpandCursorRow=s},["expand","cursor","body"])),i.push(e("Confirm cross-parent drag-and-drop","When dragging notes onto a note that has a different parent, ask before re-parenting (turn off to allow direct moves).",()=>this.plugin.settings.confirmCrossParentDrag,s=>{this.plugin.settings.confirmCrossParentDrag=s},["confirm","drag","drop","reparent"])),i.push(e("Confirm bulk deletes","Warn before deletes that affect more than one note \u2014 multi-selection delete OR deleting a note that has descendants. A single childless note with no attachments never prompts. Off = those deletes apply immediately (undo still recovers everything).",()=>this.plugin.settings.confirmBulkDelete,s=>{this.plugin.settings.confirmBulkDelete=s},["confirm","delete","bulk"])),i.push(e("Offer to delete attachments with note",`When a note references attachments, the delete modal includes an "Also delete attachments" checkbox so orphaned files don't pile up in your vault. Attachments are detected from both ![[\u2026]] embeds in the body and the frontmatter attachments: list. Off = attachments are always preserved on delete (no checkbox shown), and a single childless note with attachments deletes silently.`,()=>this.plugin.settings.confirmAttachmentDelete,s=>{this.plugin.settings.confirmAttachmentDelete=s},["delete","attachment","orphan"])),i.push(this.renderDef("Slug stop-words","Words removed from auto-generated note titles (filenames). One per line.",s=>{let n=null,o=(this.plugin.settings.slugStopWords?.length?this.plugin.settings.slugStopWords:Lt).join(` -`);s.addTextArea(r=>{r.setValue(o),n=r.inputEl,n.rows=6,n.setCssStyles({fontFamily:"var(--font-monospace)"}),r.onChange(async A=>{this.plugin.settings.slugStopWords=(A||"").split(/\r?\n/).map(l=>l.trim().toLowerCase()).filter(Boolean),await t()})}).addExtraButton(r=>r.setIcon("rotate-ccw").setTooltip("Reset to defaults").onClick(async()=>{this.plugin.settings.slugStopWords=[...Lt],n&&(n.value=Lt.join(` -`)),await t()}))},["slug","stopwords","filename","title"])),i.push(this.sectionDef("Cross-Stashpad search scope","Toggle each Stashpad's pill to choose whether its notes contribute to cross-folder search. Excluded folders are still valid move destinations. Also: create a new Stashpad.",s=>{let n=this.plugin.discoverStashpadFolders();if(new x.Setting(s).setName("Cross-Stashpad search scope").setDesc("Toggle each Stashpad's pill to choose whether its notes contribute to cross-folder search. Excluded folders are still valid move destinations \u2014 their notes just don't appear in search results from elsewhere."),n.length===0)s.createEl("p",{cls:"setting-item-description"}).setText('No Stashpads found in this vault yet. A Stashpad is just a folder that contains a Stashpad-shaped note (frontmatter has both `id` and `parent`). Easiest way: open Stashpad (ribbon icon or command "Reveal or open Stashpad") \u2014 it auto-creates the default folder on first use. Or create one below.');else{let r=s.createDiv({cls:"stashpad-folder-list"});for(let A of n)this.renderFolderScopeRow(r,A)}let o=null;new x.Setting(s).setName("Create a new Stashpad").setDesc("Type a vault-relative folder path. The folder is created (with intermediates) and seeded with a Home note so Stashpad recognizes it.").addText(r=>{r.setPlaceholder("my-stashpad"),o=r.inputEl}).addButton(r=>r.setButtonText("Create").setCta().onClick(async()=>{let A=(o?.value??"").trim().replace(/^\/+|\/+$/g,"");if(!A){new x.Notice("Enter a folder name first.");return}try{await this.plugin.createNewStashpad(A),new x.Notice(`Created Stashpad "${A}".`),o&&(o.value=""),await this.plugin.waitForStashpadFolder(A,2e3),this.update?.()}catch(l){new x.Notice(`Couldn't create: ${l.message}`)}}))},["search","scope","exclude","include","create","new","stashpad","folder"])),i.push(this.sectionDef("Folder panel placement","Pin, downrank, or hide folders in the Stashpad folder panel. Restore hidden folders here or from the panel's \u201CHidden\u201D section.",s=>{new x.Setting(s).setName("Folder panel placement").setDesc("Folders you've pinned, downranked, or hidden in the Stashpad folder panel. Pin/downrank from a folder's right-click menu in the panel; restore here or from the panel's \u201CHidden\u201D section."),this.renderFolderPlacementList(s)},["folder","panel","pin","pinned","downrank","hide","hidden","restore","placement"])),i.push(e("Autofocus composer after sending","After Enter-submitting a note, return focus to the composer so you can keep typing. Off keeps focus in the list \u2014 useful if you want arrow keys to work without an extra click.",()=>this.plugin.settings.autofocusComposerAfterSend,s=>{this.plugin.settings.autofocusComposerAfterSend=s},["composer","focus","send"])),i.push(e("Open in new window \u2014 duplicate tab","ON: the new-window button (in the time-filter row) duplicates the current Stashpad tab \u2014 original stays open in the main window. OFF: the leaf is MOVED to the new window, closing the original tab.",()=>this.plugin.settings.popoutDuplicates,s=>{this.plugin.settings.popoutDuplicates=s},["popout","window","duplicate"])),i.push(e("Search results open in a new tab","When you pick a result in the Search modal, open it in a new Stashpad tab instead of navigating the current tab. Applies to same-folder and cross-Stashpad results alike. On by default.",()=>this.plugin.settings.searchOpensInNewTab,s=>{this.plugin.settings.searchOpensInNewTab=s},["search","new tab","results","open"])),i.push(e("Prefix timestamps when copying","Include each note's timestamp before its body when copying with C or Y.",()=>this.plugin.settings.prefixTimestampsOnCopy,s=>{this.plugin.settings.prefixTimestampsOnCopy=s},["copy","timestamp","prefix"])),i}encryptionItems(){let t=this.plugin.encryption,e=[];return e.push(this.sectionDef("Vault encryption","Set one password to encrypt content in this vault. Stored only on this device \u2014 there is no recovery if you lose it.",i=>{i.addClass("stashpad-encryption-section");let s=i.createDiv({cls:"stashpad-beta-row"});s.createEl("span",{cls:"stashpad-beta-badge",text:"BETA"}),s.createEl("span",{cls:"stashpad-beta-note",text:"Encryption is in beta \u2014 keep your own backups of anything important."}),i.createEl("div",{cls:"stashpad-ai-disclaimer"}).setText("\u26A0\uFE0F AI-built, NOT human-audited. This encryption was written by an AI assistant \u2014 not designed, reviewed, or security-audited by a human, and not tested by any security professional. It may carry real security, privacy, and DATA-LOSS risks. Treat it as a best-effort nice-to-have that might buy a little time against a casual snoop \u2014 nothing is guaranteed. Do NOT rely on it for anything sensitive, and always keep your own unencrypted backups of anything important."),i.createEl("p",{cls:"setting-item-description"}).setText("\u26A0\uFE0F Encryption protects what you lock in this vault. Each device unlocks with its own password (which never leaves the device); the vault key is shared with collaborators by approving their device \u2014 no shared password. If everyone with access loses their password, anything encrypted is gone for good. While encrypting, avoid a sync/cloud service writing the vault mid-operation \u2014 it can corrupt files.");let n=()=>t.argonProbe(),o=()=>this.plugin.settings.authorName?.trim()||"This device",r=t.accessState();t.refresh().then(()=>{t.accessState()!==r&&this.update?.()});let A=r;if(A==="none"){new x.Setting(i).setName("Encryption").setDesc("Not set up yet in this vault.").addButton(p=>p.setButtonText("Set up password\u2026").setCta().onClick(()=>{new yt(this.app,{mode:"setup",offerKeychain:!0,kdfProbe:n,onSubmit:async({next:h,remember:I})=>{if(!h)return"Enter a password.";try{await t.setup(h,I,o())}catch(u){return u.message}return new x.Notice("Encryption set up \u2014 unlocked for this session."),this.update?.(),null}}).open()}));return}if(A==="outsider"&&!t.isUnlocked()){t.hasSharedPassword()&&new x.Setting(i).setName("This vault is encrypted").setDesc("Enter the shared password (ask whoever set it up \u2014 they'll send it via a password manager or secure message).").addButton(p=>p.setButtonText("Unlock with shared password\u2026").setCta().onClick(()=>{new yt(this.app,{mode:"unlock",offerKeychain:!0,onSubmit:async({current:h,remember:I})=>await t.unlock(h,I)?(new x.Notice("Encryption unlocked."),this.update?.(),null):"Wrong password (or the keyfile hasn't synced here yet)."}).open()})),new x.Setting(i).setName(t.hasSharedPassword()?"Or request device approval":"This vault is encrypted by a collaborator").setDesc("Request access \u2014 pick a password for THIS device, then ask an existing member to approve it. Once approved (and the keyfile syncs to you), you'll unlock with that password. No shared secret.").addButton(p=>p.setButtonText("Request access\u2026").onClick(()=>{new yt(this.app,{mode:"setup",offerKeychain:!0,kdfProbe:n,onSubmit:async({next:h,remember:I})=>{if(!h)return"Choose a password for this device.";try{await t.requestAccess(o(),h,I)}catch(u){return u.message}return new x.Notice("Access requested. An existing member can now approve this device."),this.update?.(),null}}).open()}));return}if(A==="pending"){new x.Setting(i).setName("Access requested \u2014 waiting for approval").setDesc("An existing member needs to approve this device. After they do and the keyfile syncs here, reopen this page to unlock with the password you chose.").addButton(p=>p.setButtonText("Try unlock now").setCta().onClick(()=>{new yt(this.app,{mode:"unlock",offerKeychain:!0,onSubmit:async({current:h,remember:I})=>await t.unlock(h,I)?(new x.Notice("Encryption unlocked."),this.update?.(),null):"Not approved yet (or wrong password). Ask a member to approve this device, then try again."}).open()})).addButton(p=>p.setButtonText("Cancel request").onClick(async()=>{let h=t.myIdentityId();h&&await t.denyJoinRequest(h),new x.Notice("Access request cancelled."),this.update?.()}));return}let l=t.kdf()==="argon2id"?"Argon2id":t.kdf()==="pbkdf2"?"PBKDF2 (fallback)":"",d=t.isRemembered()?" \xB7 remembered on this device":"";if(new x.Setting(i).setName("Status").setDesc(`${t.isUnlocked()?"Set up \xB7 unlocked this session":"Set up \xB7 locked"}${l?` \xB7 ${l}`:""}${d}`),t.isUnlocked()?new x.Setting(i).setName("Lock now").setDesc("Forget the password from memory until you re-enter it.").addButton(p=>p.setButtonText("Lock now").onClick(()=>{t.lock(),new x.Notice("Encryption locked."),this.update?.()})):new x.Setting(i).setName("Unlock").setDesc("Enter your password to use encryption this session.").addButton(p=>p.setButtonText("Unlock\u2026").setCta().onClick(()=>{new yt(this.app,{mode:"unlock",offerKeychain:!0,onSubmit:async({current:h,remember:I})=>await t.unlock(h,I)?(new x.Notice("Encryption unlocked."),this.update?.(),null):"Wrong password. Try again."}).open()})),t.keychainAvailable()&&t.isRemembered()&&new x.Setting(i).setName("Forget password on this device").setDesc("Drops ONLY the copy saved in this device's keychain \u2014 your encryption stays set up and nothing is decrypted or deleted. You'll just re-type the password next session. (To turn encryption off entirely, use \u201CRemove encryption\u201D below.)").addButton(p=>p.setButtonText("Forget on this device").onClick(async()=>{await t.forgetKeychain(),new x.Notice("Removed from this device's keychain \u2014 encryption still set up."),this.update?.()})),t.amIMember()&&new x.Setting(i).setName("Change this device's password").setDesc("Re-wraps THIS device's key under a new password \u2014 doesn't re-encrypt files or affect other people.").addButton(p=>p.setButtonText("Change\u2026").onClick(()=>{new yt(this.app,{mode:"change",offerKeychain:!0,kdfProbe:n,onSubmit:async({current:h,next:I,remember:u})=>await t.changePassword(h,I,u)?(new x.Notice("Password changed."),this.update?.(),null):"Wrong current password. Try again."}).open()})),t.amIMember()&&new x.Setting(i).setName("Remove encryption").setDesc("Erases the key from this vault. Refused while any locked notes exist \u2014 decrypt everything first (locked notes have NO plaintext copy; losing the key loses them forever).").addButton(p=>{p.setButtonText("Remove\u2026").onClick(async()=>{if(await Kn(this.app)){new x.Notice(`Can't remove encryption: locked/encrypted-deleted notes still exist and would be lost forever. Run "Decrypt (unlock) ALL locked notes in the vault" and empty the encrypted trash first.`,1e4);return}new ri(this.app,{title:"Remove encryption?",body:"This erases the encryption key for this vault. Nothing is currently encrypted (locked notes are checked), so no content is lost \u2014 but you'll need to set a new password to encrypt later, and anything you had exported encrypted with this key stays locked to its passphrase.",phrase:"REMOVE ENCRYPTION",confirmText:"Remove encryption",requirePassword:h=>t.verifyPassword(h),onConfirm:async()=>{if(await Kn(this.app)){new x.Notice("Locked notes appeared while this dialog was open \u2014 removal cancelled. Decrypt everything first.",1e4);return}await t.clear(),new x.Notice("Encryption removed."),this.update?.()}}).open()}),p.setDestructive()}),new x.Setting(i).setName("Sharing").setHeading(),t.isUnlocked()?t.hasSharedPassword()?new x.Setting(i).setName("Shared password").setDesc("ON \u2014 anyone who knows it can unlock this vault (no approval). Share it via a password manager or secure message; don't send it in the clear.").addButton(p=>p.setButtonText("Change\u2026").onClick(()=>{new yt(this.app,{mode:"setup",offerKeychain:!1,kdfProbe:n,title:"Change shared password",intro:"Everyone who unlocks with the shared password will need the new one. Re-share it securely after changing.",onSubmit:async({next:h})=>{if(!h)return"Enter a password.";try{await t.setSharedPassword(h)}catch(I){return I.message}return new x.Notice("Shared password updated."),this.update?.(),null}}).open()})).addButton(p=>{p.setButtonText("Turn off").onClick(async()=>{await t.removeSharedPassword(),new x.Notice("Shared password turned off."),this.update?.()}),p.setDestructive()}):new x.Setting(i).setName("Shared password").setDesc("OFF \u2014 set one passphrase that everyone types to unlock (the simplest way to share). Anyone who knows it can unlock; turning it off later doesn't claw back copies already synced elsewhere.").addButton(p=>p.setButtonText("Set shared password\u2026").onClick(()=>{new yt(this.app,{mode:"setup",offerKeychain:!1,kdfProbe:n,title:"Set shared password",intro:"One passphrase everyone types to unlock this vault. Anyone who knows it gets in \u2014 share it ONLY through a password manager or secure message, never in the clear. You can turn it off later.",onSubmit:async({next:h})=>{if(!h)return"Enter a password.";try{await t.setSharedPassword(h)}catch(I){return I.message}return new x.Notice("Shared password set \u2014 share it securely with your collaborators."),this.update?.(),null}}).open()})):i.createEl("p",{cls:"setting-item-description"}).setText("Unlock encryption above to manage how this vault is shared."),new x.Setting(i).setName("Collaborators (device approval)").setHeading(),i.createEl("p",{cls:"setting-item-description"}).setText("Everyone who can unlock this vault, and devices waiting for access. Approving a request shares the vault key with that device \u2014 it never sees a password. Removing a member revokes future access (existing synced copies they already hold aren't clawed back \u2014 rotate the key for that, a future feature)."),new x.Setting(i).setName("Synced from the vault keyfile").addButton(p=>p.setButtonText("Refresh").onClick(async()=>{await t.refresh(),this.update?.()})),!t.isUnlocked())i.createEl("p",{cls:"setting-item-description"}).setText("Unlock encryption above to approve or remove collaborators.");else{let p=t.myIdentityId();for(let I of t.members()){let u=I.id===p,f=new x.Setting(i).setName(`${I.label}${u?" \u2014 this device":""}`).setDesc(u?"You":"Member");u||f.addButton(C=>{C.setButtonText("Remove").onClick(async()=>{await t.removeMember(I.id),new x.Notice(`Removed ${I.label}. (Not full revocation without rotating the key.)`),this.update?.()}),C.setDestructive()})}let h=t.pendingJoinRequests();if(h.length===0)i.createEl("p",{cls:"setting-item-description"}).setText("No pending access requests.");else for(let I of h)new x.Setting(i).setName(I.label).setDesc("Wants access to this vault").addButton(u=>u.setButtonText("Approve").setCta().onClick(async()=>{try{await t.approveJoinRequest(I.id)}catch(f){new x.Notice(f.message);return}new x.Notice(`Approved ${I.label} \u2014 they can unlock once the keyfile syncs to them.`),this.update?.()})).addButton(u=>u.setButtonText("Deny").onClick(async()=>{await t.denyJoinRequest(I.id),new x.Notice("Request denied."),this.update?.()}))}},["encryption","encrypt","password","passphrase","lock","unlock","key","security","private","collaborator","share","team","member","approve"])),e.push(this.renderDef("Encrypt items sent to trash","When ON, deleting a note sends it to Stashpad's encrypted trash (recoverable with your password) instead of a plaintext trash. Default OFF.",i=>i.addToggle(s=>s.setValue(this.plugin.settings.encryptTrash).onChange(async n=>{this.plugin.settings.encryptTrash=n,await this.plugin.saveSettings()})),["trash","delete","encrypt"])),e.push(this.renderDef("Encrypt trash filenames","Hide the filename + origin folder of encrypted-trashed items (opaque names on disk; shown under \u201CHidden\u201D in the trash tab). Default OFF so you can still tell what to restore when working outside the app.",i=>i.addToggle(s=>s.setValue(this.plugin.settings.encryptTrashFilenames).onChange(async n=>{this.plugin.settings.encryptTrashFilenames=n,await this.plugin.saveSettings()})),["trash","filename","encrypt"])),e.push(this.renderDef("Follow Obsidian's trash setting instead","OFF (recommended): encrypted-deleted notes go to Stashpad's own \u201C_deleted/\u201D store \u2014 the only trash location Stashpad fully controls, so it can encrypt, list, and restore them. ON: deletes follow Obsidian's \u201CDeleted files\u201D setting instead (system/OS trash or permanent). \u26A0\uFE0F Stashpad CANNOT encrypt or recover notes that go to the system trash \u2014 so the encrypted trash + recoverable trash view won't apply. Only turn this on if you specifically want Obsidian's native trash behavior.",i=>i.addToggle(s=>s.setValue(this.plugin.settings.encryptTrashFollowObsidian??!1).onChange(async n=>{this.plugin.settings.encryptTrashFollowObsidian=n||void 0,await this.plugin.saveSettings()})),["trash","obsidian","system","delete","encrypt"])),e.push(this.renderDef("Auto-lock after idle minutes","Forget the password from memory after this many idle minutes (0 = never). Re-prompts on the next encryption action.",i=>i.addText(s=>s.setValue(String(this.plugin.settings.encryptionIdleLockMinutes??0)).onChange(async n=>{let o=Math.max(0,Math.floor(Number(n)||0));this.plugin.settings.encryptionIdleLockMinutes=o,await this.plugin.saveSettings()})),["auto-lock","idle","timeout","lock"])),e.push(this.renderDef("Hide titles of locked notes","Show a generic label on \u{1F512} locked placeholders instead of the note's title, so a glance at the vault doesn't reveal what's locked. Default OFF.",i=>i.addToggle(s=>s.setValue(this.plugin.settings.hideLockedTitles??!1).onChange(async n=>{this.plugin.settings.hideLockedTitles=n,await this.plugin.saveSettings(),this.plugin.refreshAllStashpadViews?.()})),["title","hide","private","lock","placeholder","visibility"])),e.push(this.renderDef("Default archive folder",`Where the "Move selection to archive" command sends notes (they're auto-encrypted on arrival). Leaving this blank is fine \u2014 the command will just show you a list of your archive folders to pick from each time (or use the only one if you have a single archive). Mark a folder as an archive via the folder panel \u2192 right-click \u2192 "Mark as archive".`,i=>{let s=this.plugin.settings.archiveFolders??[];i.addDropdown(n=>{n.addOption("",s.length?"\u2014 pick from list each time \u2014":"\u2014 no archive folders yet \u2014");for(let r of s)n.addOption(r,r);let o=this.plugin.settings.defaultArchiveFolder??"";n.setValue(s.includes(o)?o:""),n.onChange(async r=>{this.plugin.settings.defaultArchiveFolder=r||void 0,await this.plugin.saveSettings()})})},["archive","default","move","encrypt","folder"])),e}hotkeyItems(){let t={name:"Hotkeys",desc:"Each command has up to two slots. Click a slot and press a key (or chord) to bind it; press Backspace (delete on Mac) to cancel without binding; or click \u2715 to clear an existing binding. A \u21BA icon appears on any slot that differs from its shipped default \u2014 click it to revert that slot. When both slots are set, the pill on the right decides which one is active.",searchable:!1},e=qe.map(i=>({name:i.label,desc:i.desc,aliases:["hotkey","shortcut","keybind","binding","key"],render:s=>this.renderBindingRow(s,i)}));return[t,...e]}renderJdIndexSection(t){let e=new x.Setting(t).setName("JD Index Builder").setHeading();e.settingEl.id="stashpad-jd-index-section";let i=t.createEl("p",{cls:"setting-item-description"});i.innerHTML="Builds a Johnny-Decimal-style index inside a designated Stashpad folder. Two commands:<br/><strong>Preview</strong> overwrites the designated folder’s HOME note body with the would-be hierarchy + everything that didn’t match. Frontmatter is preserved; everything below it is replaced.<br/><strong>Build</strong> creates an actual hierarchy of Stashpad notes (one per prefix), with child\u2192parent relationships matching the dotted segments.<br/>Matches strict prefixes only: all-digits (<code>10 Life</code>) or alphanumeric-with-dots (<code>1.2 Family</code>, <code>animal.duck.yellow Eggs</code>). Mixed schemes sort numbers first, then alphabetically.";let s=this.plugin.discoverStashpadFolders();new x.Setting(t).setName("Scope").setDesc("Scan the whole vault, or restrict to a single folder + its descendants.").addDropdown(A=>{A.addOption("vault","Entire vault"),A.addOption("folder","Single folder"),A.setValue(this.plugin.settings.jdIndexScope??"vault"),A.onChange(async l=>{this.plugin.settings.jdIndexScope=l==="folder"?"folder":"vault",await this.plugin.saveSettings(),this.display()})}),(this.plugin.settings.jdIndexScope??"vault")==="folder"&&new x.Setting(t).setName("Scope folder").setDesc("Vault-relative path. Leave empty to fall back to the entire vault.").addText(A=>{new Pe(this.app,A.inputEl),A.setPlaceholder("Path/To/Folder"),A.setValue(this.plugin.settings.jdIndexScopeFolder??""),A.onChange(async l=>{this.plugin.settings.jdIndexScopeFolder=(l||"").trim().replace(/^\/+|\/+$/g,""),await this.plugin.saveSettings()})}),new x.Setting(t).setName("Include Stashpad folders in scan").setDesc("By default, notes inside any known Stashpad folder are excluded \u2014 the index destination shouldn't index itself, and other Stashpad folders are usually already organized. Toggle on if you want them included anyway.").addToggle(A=>{A.setValue(this.plugin.settings.jdIndexIncludeStashpadFolders===!0),A.onChange(async l=>{this.plugin.settings.jdIndexIncludeStashpadFolders=l,await this.plugin.saveSettings(),this.display()})}),new x.Setting(t).setName("Designated Stashpad folder for Index").setDesc("Required. Must be a Stashpad folder. The index hierarchy is built here. New notes are created; nothing is deleted.").addText(A=>{new Pe(this.app,A.inputEl),A.setPlaceholder(s[0]??"(pick a Stashpad folder)"),A.setValue(this.plugin.settings.jdIndexStashpadFolder??""),A.onChange(async l=>{this.plugin.settings.jdIndexStashpadFolder=(l||"").trim().replace(/^\/+|\/+$/g,""),await this.plugin.saveSettings()})}),new x.Setting(t).setName("Sort").setDesc("Order of entries within the same depth. Natural: numbers first then alphabetical (recommended). Created: by source file's creation time \u2014 handy when prefixes are word-only and don't carry ordering.").addDropdown(A=>{A.addOption("natural","Natural (numeric \u2192 alphabetical)"),A.addOption("created","By creation time"),A.setValue(this.plugin.settings.jdIndexSort??"natural"),A.onChange(async l=>{this.plugin.settings.jdIndexSort=l==="created"?"created":"natural",await this.plugin.saveSettings()})});let n=He(this.app,this.plugin,this.plugin.settings),o=t.createEl("p",{cls:"setting-item-description"}),r=n.skippedStashpadNotes.length>0?` (${n.skippedStashpadNotes.length} Stashpad-folder note${n.skippedStashpadNotes.length===1?"":"s"} excluded by default)`:"";o.setText(`Preview: ${n.indexed.length} note${n.indexed.length===1?"":"s"} would be indexed, ${n.nonIndex.length} would NOT be indexed${r}.`),new x.Setting(t).setName("Actions").setDesc("Preview aggressively overwrites the designated folder's HOME note body (frontmatter preserved). Build creates Stashpad notes (existing notes with the same jdPrefix are updated, not duplicated).").addButton(A=>{A.setButtonText("Preview"),A.setTooltip("Overwrites the designated Stashpad folder's HOME note body with the preview."),A.onClick(async()=>{try{let l=await Ki(this.app,this.plugin,this.plugin.settings);if(l.error==="no-dest"){new x.Notice("Set a Designated Stashpad folder for Index first.",5e3);return}if(l.error==="no-home"){new x.Notice(`"${this.plugin.settings.jdIndexStashpadFolder}" doesn't have a Stashpad home note. Open the folder in Stashpad first (it creates one automatically).`,7e3);return}Oi(this.app,l),this.display()}catch(l){console.error("[stashpad] preview failed",l),new x.Notice(`Preview failed: ${l?.message??l}`,8e3)}})}).addButton(A=>{A.setButtonText("Build Stashpad notes"),A.setCta(),A.setTooltip("Create the Stashpad-note hierarchy. Existing notes with matching jdPrefix are updated."),A.onClick(()=>{if(!(this.plugin.settings.jdIndexStashpadFolder??"").trim().replace(/^\/+|\/+$/g,"")){new x.Notice("Set a Designated Stashpad folder for Index first.",5e3);return}new Ii(this.app,this.plugin,this.plugin.settings,n.indexed.length,async()=>{try{let g=await an(this.app,this.plugin,this.plugin.settings);if(g.error==="no-dest"){new x.Notice("Set a Designated Stashpad folder for Index first.",5e3);return}if(g.error==="dest-not-stashpad"){new x.Notice(`"${g.destFolder}" isn't a known Stashpad folder. Pick a real Stashpad folder (or create one first).`,7e3);return}this.plugin.settings.jdIndexHasBuilt=!0,await this.plugin.saveSettings(),new x.Notice(`Built: ${g.created} created, ${g.updated} updated, ${g.skipped} skipped \u2192 ${g.destFolder}`,6e3),this.display()}catch(g){console.error("[stashpad] build failed",g),new x.Notice(`Build failed: ${g?.message??g}`,8e3)}}).open()})}).addButton(A=>{A.setButtonText(`Reveal in ${SA()}`),A.setTooltip("Open the designated Stashpad folder in your OS file browser."),A.onClick(async()=>{let l=(this.plugin.settings.jdIndexStashpadFolder??"").trim().replace(/^\/+|\/+$/g,"");if(!l){new x.Notice("Set a Designated Stashpad folder for Index first.",5e3);return}if(!this.app.vault.getAbstractFileByPath(l)){new x.Notice(`Folder "${l}" doesn't exist yet.`,5e3);return}try{let g=this.app.vault.adapter.basePath;if(g){let{shell:p}=window.require?.("electron")??{},h=`${g}/${l}`;p?.openPath?.(h)}else new x.Notice("Reveal in file system not supported on this platform.",4e3)}catch(g){new x.Notice(`Couldn't open folder: ${g?.message??g}`,5e3)}})})}renderColorAliasesSection(t){let e=this.plugin.discoverStashpadFolders();if(e.length===0){new x.Setting(t).setName("Color aliases per Stashpad").setDesc("No Stashpads discovered yet \u2014 create one above first.");return}let i=(()=>{let o=_t()?.noteFolder;return o&&e.includes(o)?o:e[0]})();new x.Setting(t).setName("Color aliases per Stashpad").setDesc("Which Stashpad's colors to label.").addDropdown(o=>{for(let r of e)o.addOption(r,r);o.setValue(i),o.onChange(r=>{i=r,n()})}),t.createEl("p",{cls:"setting-item-description",text:"Give each per-note color a friendly name. Filters and pickers display the alias instead of the hex code; the underlying color stays the same. The same hex in two Stashpads can have different aliases."});let s=t.createDiv({cls:"stashpad-color-aliases-list"}),n=()=>{s.empty();let o=this.plugin.collectColorsInFolder(i),r=new Map(o.map(g=>[g.hex,g.count])),A=this.plugin.settings.colorAliases?.[i.replace(/\/+$/,"")]??{},l=new Set([...r.keys(),...Object.keys(A)]);if(l.size===0){s.createEl("p",{cls:"setting-item-description",text:`No colors used or aliased in "${i}" yet. Set a per-note color (Shift+: or right-click \u2192 Set color) and it'll appear here.`});return}let d=[...l].map(g=>({hex:g,count:r.get(g)??0}));d.sort((g,p)=>p.count-g.count||g.hex.localeCompare(p.hex));for(let g of d)this.renderColorAliasRow(s,i,g.hex,g.count,n)};n()}authorshipItems(){let t=[];t.push(this.renderDef("Author name","Your display name. Used in the note footer + as the author/contributor link target. Leave blank to opt out (notes won't be stamped).",i=>i.addText(s=>s.setValue(this.plugin.settings.authorName).onChange(async n=>{this.plugin.settings.authorName=n.trim(),this.plugin.settings.authorName&&!this.plugin.settings.authorId&&(this.plugin.settings.authorId=tt()),await this.plugin.saveSettings(),await this.plugin.syncAuthorFilesToName()})),["author","name","identity","stamp"])),t.push(this.renderDef("Author id (auto-assigned)","Stable id appended to your name on links so coworkers with the same name don't collide. Generated once and shouldn't change. To reset it, clear and retype your author name.",i=>i.addText(s=>s.setValue(this.plugin.settings.authorId).setDisabled(!0)),["author","id"])),t.push(this.renderDef("Title / role",'Optional. Shown on your author page (e.g. "Engineer", "PM", "Designer").',i=>i.addText(s=>s.setValue(this.plugin.settings.authorRole).onChange(async n=>{this.plugin.settings.authorRole=n.trim(),await this.plugin.saveSettings(),await this.plugin.syncAuthorFilesToName()})),["role","title","job"])),t.push(this.renderDef("Department / team",'Optional. Shown on your author page (e.g. "Engineering", "Growth").',i=>i.addText(s=>s.setValue(this.plugin.settings.authorDepartment).onChange(async n=>{this.plugin.settings.authorDepartment=n.trim(),await this.plugin.saveSettings(),await this.plugin.syncAuthorFilesToName()})),["department","team"]));let e=(i,s,n,o)=>this.renderDef(i,"",r=>r.addToggle(A=>A.setValue(s()).onChange(async l=>{n(l),await this.plugin.saveSettings()})),o);return t.push(e("Show author in note footer",()=>this.plugin.settings.showAuthor,i=>{this.plugin.settings.showAuthor=i},["author","footer","show"])),t.push(e("Show contributors in note footer",()=>this.plugin.settings.showContributors,i=>{this.plugin.settings.showContributors=i},["contributors","footer","show"])),t.push(e("Show last edit time in note footer",()=>this.plugin.settings.showLastEdit,i=>{this.plugin.settings.showLastEdit=i},["last edit","modified","footer","time"])),t.push(this.sectionDef("Folders you've worked in","Folders where you've authored or contributed notes. Click one to open it.",i=>this.renderAuthoredFolders(i),["folders","authored","contributed","worked"])),t.push(this.sectionDef("Known authors","Everyone the plugin has seen, with role/department + rename history; rebuild/restore the registry.",i=>this.renderKnownAuthorsSection(i),["authors","registry","rename","known","rebuild"])),t}renderAuthoredFolders(t){let e=this.plugin.collectAuthoredFolders();if(e.length===0){t.createEl("p",{cls:"setting-item-description",text:"No authored or contributed folders yet."});return}let i=t.createDiv({cls:"stashpad-authored-folders-list"});for(let s of e){let n=i.createDiv({cls:"stashpad-authored-folder-row"}),o=n.createEl("a",{cls:"stashpad-authored-folder-link",text:s.folder});o.onclick=A=>{A.preventDefault(),this.plugin.activateViewForFolder(s.folder)};let r=[];s.authored>0&&r.push(`authored ${s.authored}`),s.contributed>0&&r.push(`contributed to ${s.contributed}`),n.createSpan({cls:"stashpad-authored-folder-counts",text:` \xB7 ${r.join(", ")}`})}}templatesItems(){return[this.sectionDef("Color aliases","Give your note colors friendly names, per Stashpad folder.",t=>this.renderColorAliasesSection(t),["color","colour","alias","name","swatch","palette","label"]),this.sectionDef("Note templates","Per-Stashpad note templates \u2014 content stamped into new notes.",t=>this.renderNoteTemplatesSection(t),["template","note","default","boilerplate","snippet"])]}jdIndexItems(){return[this.sectionDef("JD Index (Johnny Decimal)","Build a Johnny-Decimal-style index from dotted-prefix note titles \u2014 set the scope, preview, then build.",t=>this.renderJdIndexSection(t),["jd","johnny","decimal","index","scope","build","preview","hierarchy","folder"])]}okfItems(){return[this.sectionDef("Open Knowledge Format (OKF)","Turn a Stashpad folder into a browsable OKF bundle \u2014 markdown concept files with OKF frontmatter, a generated index.md, and relative-markdown cross-links \u2014 that LLMs/agents can read. Complements (never replaces) Stashpad's own frontmatter and links.",t=>this.renderOkfSection(t),["okf","open knowledge format","knowledge","catalog","index","export","bundle","tarball","agent","google"])]}appendCode(t,e){e.split(/`([^`]+)`/g).forEach((i,s)=>{s%2===1?t.createEl("code",{text:i}):i&&t.appendText(i)})}codeDesc(t){let e=document.createDocumentFragment();return this.appendCode(e,t),e}renderOkfSection(t){if(t.createDiv({cls:"stashpad-beta-row"}).createEl("span",{cls:"stashpad-beta-badge",text:"BETA"}),new x.Setting(t).setName("Enable OKF").setDesc(this.codeDesc("Master switch. When on, you choose which folders use OKF by assigning the OKF template to them in Settings \u2192 Templates (all / some / none \u2014 your call). Those folders then get OKF frontmatter and a maintained `index.md`. Turning this off leaves existing OKF files in place; it just stops maintaining them.")).addToggle(i=>i.setValue(this.plugin.settings.okfEnabled).onChange(async s=>{if(this.plugin.settings.okfEnabled=s,await this.plugin.saveSettings(),s)try{await this.plugin.ensureOkfTemplate()}catch(n){console.warn("[Stashpad] OKF template create failed",n)}new x.Notice(s?`OKF on. Next: assign the template "${this.plugin.okfTemplatePathOrDefault()}" to a folder \u2014 use \u201CCreate template + open Templates\u201D below. Heads-up: OKF frontmatter + index.md refresh automatically but NOT instantly (a few seconds after changes); hit Rebuild for an immediate pass.`:"OKF disabled.",s?0:4e3),this.update?.()})),this.plugin.settings.okfEnabled){let i=this.plugin.okfTemplatePathOrDefault(),s=this.plugin.okfActiveFolders().length,n=t.createEl("div",{cls:"setting-item-description stashpad-okf-howto"});n.createEl("p",{text:"How to use OKF in a folder:"});let o=n.createEl("ol");if(this.appendCode(o.createEl("li"),`Open Templates and set a folder's template to \`${i}\` (archive folders are skipped).`),this.appendCode(o.createEl("li"),"Hit Rebuild below to write OKF frontmatter (`okfParent`/`okfChildren` + `okfType`/`okfTitle`/`okfTimestamp`) and generate that folder's `index.md`."),this.appendCode(o.createEl("li"),"Right-click a note (or a selection) \u2192 \u201CExport as OKF\u2026\u201D to save a `.zip` / `.tar.gz` bundle (or `.stash`)."),n.createEl("p",{cls:"stashpad-okf-soon",text:"OKF frontmatter + index.md refresh automatically a few seconds after you add, move, or delete notes \u2014 NOT instantly. Use Rebuild for an immediate pass."}),s===0){let r=t.createEl("p",{cls:"stashpad-okf-cta"});this.appendCode(r,"\u{1F449} No folder is using OKF yet. Click \u201CCreate template + open Templates\u201D below, then set a folder's template to `"+i+"`.")}else n.createEl("p",{cls:"stashpad-okf-soon",text:`Currently ${s} folder${s===1?"":"s"} actively using OKF.`});new x.Setting(t).setName("Assign OKF to folders").setDesc(this.codeDesc(`Creates the OKF template if needed (never duplicates it), then opens Templates \u2014 set a folder's template to \`${i}\` there.`)).addButton(r=>{r.setButtonText("Create template + open Templates").setCta(),r.onClick(async()=>{let A;try{A=await this.plugin.ensureOkfTemplate()}catch(l){new x.Notice(`Couldn't create the OKF template: ${l.message}`);return}new x.Notice(`OKF template ready at "${A}" \u2014 set a folder's template to that path.`),this.update?.(),this.openSettingsPage("Templates")})}),new x.Setting(t).setName("Rebuild OKF frontmatter").setDesc(this.codeDesc("Write/refresh OKF fields for every folder using the OKF template \u2014 `okfParent`/`okfChildren` relative links (managed) plus `okfType`/`okfTitle`/`okfTimestamp` defaults (yours to edit after). Heads-up: adding, moving, or deleting notes already auto-refreshes the folder, but NOT instantly \u2014 it waits ~a few seconds after you stop. Use this button for an immediate rebuild (e.g. right after first assigning the template). Complements Stashpad's own links; nothing is removed.")).addButton(r=>r.setButtonText("Rebuild now").onClick(async()=>{let A=await this.plugin.rebuildAllOkf();new x.Notice(A.folders===0?"No folders use the OKF template yet \u2014 assign it in Templates first.":`OKF: updated ${A.written} of ${A.checked} notes across ${A.folders} folder${A.folders===1?"":"s"}.`),this.update?.()}))}let e=new x.Setting(t).setName("Learn about OKF").setDesc("Google's open, vendor-neutral spec for sharing curated knowledge with agents.");e.addButton(i=>i.setButtonText("Spec / repo").onClick(()=>window.open("https://github.com/GoogleCloudPlatform/knowledge-catalog/tree/main/okf"))),e.addButton(i=>i.setButtonText("Announcement").onClick(()=>window.open("https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing/")))}openSettingsPage(t){let e=()=>new x.Notice(`Open Settings \u2192 Stashpad \u2192 ${t}.`);try{let i=this.app.setting;if(!i?.openTabById){e();return}i.openTabById("stashpad"),window.setTimeout(()=>{let s=i.modalEl?.querySelector(".vertical-tab-content");if(!s){e();return}let o=Array.from(s.querySelectorAll("*")).find(r=>r.childElementCount===0&&r.textContent?.trim()===t&&!r.closest(".vertical-tab-header"))?.closest("[class*='nav'], .setting-item, button, a");o&&!o.closest(".vertical-tab-header")?o.click():e()},60)}catch{e()}}renderAuthorshipSection(t){new x.Setting(t).setName("Authorship").setHeading(),t.createEl("p",{cls:"setting-item-description",text:"Stamp each new note with your name. If the vault is later shared (e.g. a coworker opens it with --config pointing at their own settings folder), every modification automatically tracks contributors on top of the original author. Names link to per-user pages in <stashpad>/_authors/."}),new x.Setting(t).setName("Author name").setDesc("Your display name. Used in the note footer + as the author/contributor link target. Leave blank to opt out (notes won't be stamped).").addText(i=>{i.setValue(this.plugin.settings.authorName).onChange(async s=>{this.plugin.settings.authorName=s.trim(),this.plugin.settings.authorName&&!this.plugin.settings.authorId&&(this.plugin.settings.authorId=tt()),await this.plugin.saveSettings(),await this.plugin.syncAuthorFilesToName()})}),new x.Setting(t).setName("Author id (auto-assigned)").setDesc("Stable id appended to your name on links so coworkers with the same name don't collide. Generated once and shouldn't change. If you really need to reset it, clear and retype your author name above.").addText(i=>{i.setValue(this.plugin.settings.authorId).setDisabled(!0)}),new x.Setting(t).setName("Title / role").setDesc('Optional. Shown on your author page (e.g. "Engineer", "PM", "Designer").').addText(i=>{i.setValue(this.plugin.settings.authorRole).onChange(async s=>{this.plugin.settings.authorRole=s.trim(),await this.plugin.saveSettings(),await this.plugin.syncAuthorFilesToName()})}),new x.Setting(t).setName("Department / team").setDesc('Optional. Shown on your author page (e.g. "Engineering", "Growth").').addText(i=>{i.setValue(this.plugin.settings.authorDepartment).onChange(async s=>{this.plugin.settings.authorDepartment=s.trim(),await this.plugin.saveSettings(),await this.plugin.syncAuthorFilesToName()})}),new x.Setting(t).setName("Show author in note footer").addToggle(i=>i.setValue(this.plugin.settings.showAuthor).onChange(async s=>{this.plugin.settings.showAuthor=s,await this.plugin.saveSettings()})),new x.Setting(t).setName("Show contributors in note footer").addToggle(i=>i.setValue(this.plugin.settings.showContributors).onChange(async s=>{this.plugin.settings.showContributors=s,await this.plugin.saveSettings()})),new x.Setting(t).setName("Show last edit time in note footer").addToggle(i=>i.setValue(this.plugin.settings.showLastEdit).onChange(async s=>{this.plugin.settings.showLastEdit=s,await this.plugin.saveSettings()}));let e=this.plugin.collectAuthoredFolders();if(e.length>0){new x.Setting(t).setName("Folders you've worked in").setHeading();let i=t.createDiv({cls:"stashpad-authored-folders-list"});for(let s of e){let n=i.createDiv({cls:"stashpad-authored-folder-row"}),o=n.createEl("a",{cls:"stashpad-authored-folder-link",text:s.folder});o.onclick=A=>{A.preventDefault(),this.plugin.activateViewForFolder(s.folder)};let r=[];s.authored>0&&r.push(`authored ${s.authored}`),s.contributed>0&&r.push(`contributed to ${s.contributed}`),n.createSpan({cls:"stashpad-authored-folder-counts",text:` \xB7 ${r.join(", ")}`})}}this.renderKnownAuthorsSection(t)}renderKnownAuthorsSection(t){new x.Setting(t).setName("Known authors (registry)").setHeading(),t.createEl("div",{cls:"setting-item-description",text:"A rebuildable cache of every author Stashpad has seen, with rename history. Not a source of truth \u2014 the author id stored in each note is authoritative. Use it to recover deleted author pages or audit name changes."}),new x.Setting(t).setName("Registry maintenance").setDesc("Rebuild scans the whole vault to reconstruct the list. Restore regenerates any deleted author pages across every Stashpad folder.").addButton(s=>s.setButtonText("Rebuild").onClick(async()=>{s.setDisabled(!0).setButtonText("Rebuilding\u2026");try{let n=await this.plugin.rebuildAuthorRegistry();new x.Notice(`Author registry rebuilt: ${n.total} author(s).`)}catch(n){new x.Notice(`Rebuild failed: ${n.message}`)}s.setDisabled(!1).setButtonText("Rebuild"),this.display()})).addButton(s=>s.setButtonText("Restore missing pages").onClick(async()=>{s.setDisabled(!0).setButtonText("Restoring\u2026");try{let n=await this.plugin.restoreMissingAuthorStubs();new x.Notice(n.created>0?`Restored ${n.created} author page(s).`:"No missing author pages.")}catch(n){new x.Notice(`Restore failed: ${n.message}`)}s.setDisabled(!1).setButtonText("Restore missing pages")}));let e=this.plugin.authorRegistry.all();if(e.length===0){t.createEl("div",{cls:"setting-item-description",text:"No authors recorded yet. Rebuild to scan the vault."});return}let i=t.createDiv({cls:"stashpad-known-authors-list"});for(let s of e){let n=i.createDiv({cls:"stashpad-known-author-row"}),o=n.createDiv({cls:"stashpad-known-author-main"});o.createSpan({cls:"stashpad-known-author-name",text:s.name||"(unnamed)"});let r=[];if(s.role&&r.push(s.role),s.department&&r.push(s.department),r.push(`id ${s.id}`),o.createSpan({cls:"stashpad-known-author-meta",text:` \xB7 ${r.join(" \xB7 ")}`}),s.renames&&s.renames.length>0){let A=n.createDiv({cls:"stashpad-known-author-history"}),l=s.renames.map(d=>`${d.from} \u2192 ${d.to}`).join(", ");A.setText(`Renamed: ${l}`)}}}renderNoteTemplatesSection(t){let e=this.plugin.discoverStashpadFolders();if(e.length===0)return;if(new x.Setting(t).setName("Note templates per Stashpad").setDesc("Pick a markdown file to use as the default template for new notes in each Stashpad. The template's frontmatter becomes the new note's frontmatter (id/parent/created/attachments are always set by Stashpad). If the body contains {{body}}, that's where the user-typed body goes; otherwise the user body is followed by the template body."),this.plugin.settings.okfEnabled){let n=this.plugin.okfTemplatePathOrDefault();this.appendCode(t.createEl("p",{cls:"setting-item-description"}),`\u{1F4A1} OKF tip: type \`${n}\` into a folder's template field below to turn that folder into an OKF bundle (OKF frontmatter + a maintained \`index.md\`). Assign it to all, some, or none of your folders \u2014 it's per-folder. Manage OKF itself in Settings \u2192 OKF.`)}let i=t.createDiv({cls:"stashpad-note-templates-list"}),s=n=>{let o=n.replace(/\/+$/,""),r=i.createDiv({cls:"stashpad-note-template-row"});r.createSpan({cls:"stashpad-note-template-folder"}).setText(n);let l=r.createDiv({cls:"stashpad-note-template-input-wrap"}),d=l.createEl("input",{type:"text",cls:"stashpad-note-template-input",attr:{placeholder:"path/to/template.md (leave blank to disable)"}});d.value=(this.plugin.settings.noteTemplates??{})[o]??"";let g=l.createDiv({cls:"stashpad-note-template-suggest"});g.setCssStyles({display:"none"});let p=[],h=[],I=-1,u=()=>g.style.display!=="none"&&p.length>0,f=y=>{I=y,h.forEach((b,N)=>b.toggleClass("is-active",N===y)),y>=0&&h[y]&&h[y].scrollIntoView({block:"nearest"})},C=()=>{g.setCssStyles({display:"none"}),I=-1},B=async y=>{d.value=y,await E(),C()},m=r.createDiv({cls:"stashpad-note-template-warn"});m.setCssStyles({display:"none"});let w=()=>this.app.vault.getMarkdownFiles().map(y=>y.path).filter(y=>!/\/(_imports|_exports|_attachments|\.stashpad)\//.test(y)).sort(),Q=()=>{g.empty(),h=[];let y=d.value.trim().toLowerCase().split(/\s+/).filter(Boolean),b=N=>{let P=N.toLowerCase();return y.every(H=>P.includes(H))};if(p=w().filter(N=>b(N)).slice(0,12),p.length===0){C();return}g.setCssStyles({display:""}),p.forEach((N,P)=>{let H=g.createDiv({cls:"stashpad-note-template-suggest-item",text:N});h.push(H),H.addEventListener("mousemove",()=>f(P)),H.addEventListener("mousedown",async D=>{D.preventDefault(),await B(N)})}),I=I>=0&&I<p.length?I:-1,I>=0&&f(I)},E=async()=>{let y=d.value.trim(),b={...this.plugin.settings.noteTemplates??{}};y?b[o]=y:delete b[o],this.plugin.settings.noteTemplates=b,await this.plugin.saveSettings(),v()},v=()=>{m.empty(),m.setCssStyles({display:"none"});let y=d.value.trim();if(!y)return;let b=this.app.vault.getAbstractFileByPath(y);if(!b||b.extension!=="md"){m.setCssStyles({display:""}),m.setText(`\u26A0 "${y}" is not a markdown file in this vault.`);return}let N=this.app.metadataCache.getFileCache(b)?.frontmatter??{},H=se.filter(D=>{let S=N[D];return!(S==null||typeof S=="string"&&S.trim()===""||Array.isArray(S)&&S.length===0)});H.length!==0&&(m.setCssStyles({display:""}),m.setText(`\u26A0 Template defines ${H.join(", ")} \u2014 Stashpad always sets ${H.length===1?"this":"these"} on new notes, so the template value${H.length===1?"":"s"} will be ignored.`))};d.addEventListener("focus",Q),d.addEventListener("input",()=>{I=-1,Q()}),d.addEventListener("blur",()=>{setTimeout(C,150)}),d.addEventListener("change",()=>{E()}),d.addEventListener("keydown",y=>{if(y.key==="ArrowDown")y.preventDefault(),u()?f((I+1)%p.length):(Q(),p.length&&f(0));else if(y.key==="ArrowUp"){if(!u())return;y.preventDefault(),f((I-1+p.length)%p.length)}else if(y.key==="Enter")u()&&I>=0&&(y.preventDefault(),B(p[I]));else if(y.key==="Escape")u()&&(y.preventDefault(),C());else if(y.key==="Tab"&&!y.shiftKey){if(!u())return;let b=p[I>=0?I:0],N=d.value,P;if(b.toLowerCase().startsWith(N.toLowerCase())){let H=b.indexOf("/",N.length);P=H>=0?b.slice(0,H+1):b}else P=b;P&&P!==N&&(y.preventDefault(),d.value=P,I=-1,Q(),p.length===1&&f(0))}}),v()};for(let n of e)s(n)}renderColorAliasRow(t,e,i,s,n){let o=t.createDiv({cls:"stashpad-color-alias-row"});s===0&&o.addClass("is-unused");let r=o.createSpan({cls:"stashpad-color-alias-swatch"});r.setCssStyles({background:i}),r.title="Click to bulk-recolor every note of this color in this Stashpad",r.onclick=()=>{let g=this.plugin.settings.customPalette??[];new Ee(this.app,i,g,async p=>{if((p??null)===null&&s===0){await this.plugin.setColorAlias(e,i,""),n();return}if(p&&p.toLowerCase()===i){n();return}let h=await this.plugin.recolorAllInFolder(e,i,p??null);if(h>0)new x.Notice(`Recolored ${h} note${h===1?"":"s"}.`);else if(s===0){let I=this.plugin.getColorAlias(e,i);I&&(await this.plugin.setColorAlias(e,i,""),p&&await this.plugin.setColorAlias(e,p,I))}n()},async p=>{let h=(this.plugin.settings.customPalette??[]).filter(I=>I.toLowerCase()!==p.toLowerCase());return this.plugin.settings.customPalette=h,await this.plugin.saveSettings(),h}).open()};let A=o.createDiv({cls:"stashpad-color-alias-meta"});A.createSpan({cls:"stashpad-color-alias-hex",text:i}),A.createSpan({cls:"stashpad-color-alias-count",text:s===0?"\xB7 unused":`\xB7 ${s} note${s===1?"":"s"}`});let l=o.createEl("input",{type:"text",cls:"stashpad-color-alias-input",attr:{placeholder:"Alias (optional)"}});l.value=this.plugin.getColorAlias(e,i)??"",l.onchange=async()=>{await this.plugin.setColorAlias(e,i,l.value),!l.value.trim()&&s===0&&n()};let d=o.createEl("button",{cls:"stashpad-color-alias-del",text:"\xD7",attr:{title:"Delete alias"}});l.value||d.setCssStyles({visibility:"hidden"}),d.onclick=async()=>{await this.plugin.setColorAlias(e,i,""),s===0?n():(l.value="",d.setCssStyles({visibility:"hidden"}))}}renderFolderScopeRow(t,e){let i=t.createDiv({cls:"stashpad-folder-row"});i.createSpan({cls:"stashpad-folder-row-label",text:e});let s=i.createSpan({cls:"stashpad-folder-row-state"}),n=i.createDiv({cls:"stashpad-binding-pill"});n.setAttribute("role","switch"),n.setAttribute("tabindex","0");let o=n.createDiv({cls:"stashpad-binding-pill-knob"}),r=()=>(this.plugin.settings.searchExcludedFolders??[]).includes(e),A=()=>{let d=r();n.toggleClass("is-right",d),n.setAttribute("aria-checked",String(d)),o.setText(d?"X":"\u2713"),s.setText(d?"Excluded":"Included"),s.toggleClass("is-excluded",d),n.title=d?"Excluded \u2014 notes here won't appear in cross-Stashpad search. Click to include.":"Included \u2014 notes here appear in cross-Stashpad search. Click to exclude."},l=async()=>{let d=new Set(this.plugin.settings.searchExcludedFolders??[]);d.has(e)?d.delete(e):d.add(e),this.plugin.settings.searchExcludedFolders=[...d].sort(),A(),await this.plugin.saveSettings()};n.onclick=()=>void l(),n.onkeydown=d=>{(d.key===" "||d.key==="Enter")&&(d.preventDefault(),l())},A()}renderFolderPlacementList(t){let e=this.plugin.settings,i=[{key:"folderPanelPinned",label:"Pinned",action:"Unpin"},{key:"folderPanelDownranked",label:"Downranked",action:"Reset"},{key:"folderPanelHidden",label:"Hidden",action:"Unhide"}];if(!i.some(o=>(e[o.key]??[]).length>0)){t.createEl("p",{cls:"setting-item-description"}).setText("No folders customized yet. Right-click a folder in the Stashpad folder panel to pin, downrank, or hide it.");return}let n=async o=>{e.folderPanelPinned=(e.folderPanelPinned??[]).filter(r=>r!==o),e.folderPanelDownranked=(e.folderPanelDownranked??[]).filter(r=>r!==o),e.folderPanelHidden=(e.folderPanelHidden??[]).filter(r=>r!==o),await this.plugin.saveSettings(),this.update?.()};for(let o of i){let r=[...e[o.key]??[]].sort();if(r.length===0)continue;t.createEl("div",{cls:"stashpad-folder-placement-group",text:`${o.label} (${r.length})`});let A=t.createDiv({cls:"stashpad-folder-list"});for(let l of r){let d=A.createDiv({cls:"stashpad-folder-row"});d.createSpan({cls:"stashpad-folder-row-label",text:l});let g=d.createEl("button",{text:o.action});g.onclick=()=>void n(l)}}}renderBindingRow(t,e){t.setName(e.label).setDesc(e.desc);let i=()=>this.plugin.settings.bindings[e.id],s,n,o=()=>{},r=h=>{let I=t.controlEl.createDiv({cls:"stashpad-binding-slot"}),u=I.createEl("input",{type:"text"});u.readOnly=!0,u.placeholder="Click & press a key",u.value=fi(i()[h]),u.classList.add("stashpad-binding-input");let f=()=>{u.size=Math.max(3,u.value.length||u.placeholder.length)};f();let C=h==="primary"?e.defaultPrimary:e.defaultSecondary??"";u.onclick=()=>{No(u,async Q=>{this.plugin.settings.bindings[e.id][h]=Q,u.value=fi(Q),f(),await this.plugin.saveSettings(),o(),w()})};let B=I.createEl("button",{cls:"stashpad-binding-clear",text:"\xD7"});B.title="Clear this slot",B.onclick=async()=>{this.plugin.settings.bindings[e.id][h]="",u.value="",f(),await this.plugin.saveSettings(),o(),w()};let m=I.createEl("button",{cls:"stashpad-binding-revert"});(0,x.setIcon)(m,"rotate-ccw");let w=()=>{let E=i()[h]!==C;m.toggleClass("is-hidden",!E),m.title=C?`Revert to default (${fi(C)})`:"Revert to default (no binding)"};return m.onclick=async()=>{this.plugin.settings.bindings[e.id][h]=C,u.value=fi(C),f(),await this.plugin.saveSettings(),o(),w()},w(),u};s=r("primary"),n=r("secondary");let A=t.controlEl.createDiv({cls:"stashpad-binding-pill"});A.setAttribute("role","switch"),A.setAttribute("tabindex","0");let l=A.createDiv({cls:"stashpad-binding-pill-knob"}),d=t.controlEl.createDiv({cls:"stashpad-binding-useboth"}),g=d.createEl("input",{type:"checkbox"});g.title="Use both bindings simultaneously (overrides the L/R toggle)",d.createSpan({text:"Use both"}),g.onchange=async()=>{this.plugin.settings.bindings[e.id].useBoth=g.checked,await this.plugin.saveSettings(),o()},o=()=>{let h=i(),I=!!(h.primary&&h.secondary);g.checked=!!h.useBoth,g.disabled=!I,d.toggleClass("is-disabled",!I);let u=!!h.useBoth&&I;A.toggleClass("is-disabled",!I||u),A.toggleClass("is-right",h.preferRight),A.setAttribute("aria-checked",String(h.preferRight)),A.setAttribute("aria-disabled",String(!I||u)),l.setText(h.preferRight?"R":"L"),A.title=I?u?'Overridden by "Use both"':h.preferRight?"Right slot active \u2014 click for left":"Left slot active \u2014 click for right":"Set both slots to enable the toggle"};let p=async()=>{let h=i();!h.primary||!h.secondary||(this.plugin.settings.bindings[e.id].preferRight=!h.preferRight,o(),await this.plugin.saveSettings())};A.onclick=()=>void p(),A.onkeydown=h=>{(h.key===" "||h.key==="Enter")&&(h.preventDefault(),p())},o()}};var Je=class{constructor(a,t){this.app=a;this.ta=t;this.popupEl=null;this.items=[];this.activeIdx=0;this.state=null;this.fileIndex=[];this.tagIndex=[];this.indexBuilt=!1;this.vaultListeners=[];this.scope=null;this.onInput=()=>{let a=this.detectTrigger();if(!a){this.close();return}this.openFor(a)};this.onBlur=()=>{setTimeout(()=>this.close(),120)};this.onDocEscape=a=>{a.key==="Escape"&&(!this.state||!this.items.length||(a.preventDefault(),a.stopPropagation(),a.stopImmediatePropagation(),this.close()))};this.onKeyDown=a=>{!this.state||!this.items.length||(a.key==="ArrowDown"?(a.preventDefault(),this.activeIdx=(this.activeIdx+1)%this.items.length,this.refreshActive()):a.key==="ArrowUp"?(a.preventDefault(),this.activeIdx=(this.activeIdx-1+this.items.length)%this.items.length,this.refreshActive()):a.key==="Enter"||a.key==="Tab"?(a.preventDefault(),a.stopPropagation(),this.commit()):a.key==="Escape"&&(a.preventDefault(),a.stopPropagation(),a.stopImmediatePropagation(),this.close()))}}attach(){this.ta.addEventListener("input",this.onInput),this.ta.addEventListener("keydown",this.onKeyDown,!0),this.ta.addEventListener("blur",this.onBlur);let a=this.ta.ownerDocument??document;a.addEventListener("keydown",this.onDocEscape,!0),this.vaultListeners.push(()=>a.removeEventListener("keydown",this.onDocEscape,!0)),this.buildIndex();let t=()=>{this.indexBuilt=!1},e=this.app.vault;e.on("create",t),e.on("delete",t),e.on("rename",t),this.vaultListeners.push(()=>e.off("create",t),()=>e.off("delete",t),()=>e.off("rename",t))}isOpen(){return!!this.state&&this.items.length>0}detach(){this.close(),this.ta.removeEventListener("input",this.onInput),this.ta.removeEventListener("keydown",this.onKeyDown,!0),this.ta.removeEventListener("blur",this.onBlur);for(let a of this.vaultListeners)a();this.vaultListeners=[]}buildIndex(){if(this.indexBuilt)return;let a=j().inheritObsidianExclusions,t=a?this.app.vault.getConfig?.("userIgnoreFilters"):void 0;this.fileIndex=this.app.vault.getFiles().filter(i=>!lo(i.path)&&!co(i.path)&&!(a&&ho(i.path,t))).map(i=>{let s=i.extension==="md",n=s?i.basename:i.name,o=s?i.basename:i.name;return{label:n,lower:n.toLowerCase(),insertText:o,file:i}});let e=this.app.metadataCache.getTags?.()??{};this.tagIndex=Object.keys(e).sort((i,s)=>(e[s]||0)-(e[i]||0)),this.indexBuilt=!0}detectTrigger(){let a=this.ta.value,t=this.ta.selectionStart;if(t==null)return null;let e=a.slice(0,t),i=e.match(/\[\[([^\]\[\n]*)$/);if(i){let n=i[1];return{kind:"link",query:n,replaceStart:t-n.length-2,replaceEnd:t}}let s=e.match(/(^|\s)#([A-Za-z0-9_/\-]+)$/);if(s){let n=s[2];return{kind:"tag",query:n,replaceStart:t-n.length-1,replaceEnd:t}}return null}buildItems(a){this.buildIndex();let t=a.query.toLowerCase().trim(),e=t?t.split(/\s+/).filter(Boolean):[],i=s=>{if(!e.length)return!0;for(let n of e)if(!s.includes(n))return!1;return!0};return a.kind==="link"?this.fileIndex.filter(n=>i(n.lower)).slice(0,50).map(n=>({label:n.label,insert:`[[${n.insertText}]]`,subtitle:n.file.path})):this.tagIndex.filter(n=>i(n.toLowerCase())).slice(0,30).map(n=>({label:n,insert:n,subtitle:""}))}openFor(a){if(this.state=a,this.items=this.buildItems(a),this.activeIdx=0,!this.items.length){this.close();return}this.renderPopup(),this.pushScope()}pushScope(){if(this.scope)return;let a=new Na.Scope(this.app.scope);a.register([],"Escape",t=>(t.preventDefault(),this.close(),!1)),this.scope=a,this.app.keymap?.pushScope(a)}popScope(){if(this.scope){try{this.app.keymap?.popScope(this.scope)}catch{}this.scope=null}}renderPopup(){if(!this.popupEl){let t=this.ta.ownerDocument??document;this.popupEl=t.body.createDiv({cls:"stashpad-composer-suggest"}),this.popupEl.tabIndex=-1,this.popupEl.addEventListener("mousedown",e=>e.preventDefault())}let a=this.popupEl;a.empty();for(let t=0;t<this.items.length;t++){let e=this.items[t],i=a.createDiv({cls:"stashpad-composer-suggest-row"});t===this.activeIdx&&i.addClass("is-active"),i.createSpan({cls:"stashpad-composer-suggest-label",text:e.label}),e.subtitle&&i.createSpan({cls:"stashpad-composer-suggest-sub",text:e.subtitle}),i.onmousedown=s=>{s.preventDefault(),this.activeIdx=t,this.commit()}}this.position()}refreshActive(){if(!this.popupEl)return;let a=this.popupEl.children;for(let e=0;e<a.length;e++)a[e].toggleClass("is-active",e===this.activeIdx);let t=a[this.activeIdx];t&&t.scrollIntoView({block:"nearest"})}position(){if(!this.popupEl)return;let a=this.ta.getBoundingClientRect(),t=this.popupEl.offsetHeight||200,e=a.top-t-4,i=a.left;this.popupEl.style.left=`${Math.max(8,i)}px`,this.popupEl.style.top=`${Math.max(8,e)}px`,this.popupEl.style.minWidth=`${Math.min(360,a.width)}px`}commit(){if(!this.state||!this.items.length)return;let a=this.items[this.activeIdx];if(!a)return;let t=this.ta.value.slice(0,this.state.replaceStart),e=this.ta.value.slice(this.state.replaceEnd),i=a.insert;this.ta.value=t+i+e;let s=t.length+i.length;this.ta.setSelectionRange(s,s),this.ta.dispatchEvent(new Event("input",{bubbles:!0})),this.close(),this.ta.focus()}close(){this.popupEl&&(this.popupEl.remove(),this.popupEl=null),this.state=null,this.items=[],this.activeIdx=0,this.popScope()}};rt();var Cs=class extends mt.ItemView{constructor(t,e){super(t);this.plugin=e;this.displayedPath=null;this.unsubscribeSelection=null;this.renderTimer=null;this.expanded=new Set;this.composerAutocomplete=null;this.composerInputEl=null;this.composerDraft="";this.composerDraftForId=null;this.displayedId=null;this.unsubscribeContent=null}getViewType(){return Ce}getDisplayText(){return"Stashpad detail"}getIcon(){return"panel-right"}async onOpen(){this.render(),this.unsubscribeSelection=this.plugin.onStashpadSelectionChange(()=>{this.displayedId=null,this.scheduleRender()}),this.unsubscribeContent=this.plugin.onStashpadContentChange(()=>this.scheduleRender()),this.registerEvent(this.app.workspace.on("active-leaf-change",t=>{!t||t===this.leaf||t.view?.getViewType?.()===J&&this.scheduleRender()})),this.registerEvent(this.app.vault.on("modify",t=>{this.displayedPath&&t.path===this.displayedPath&&this.scheduleRender()})),this.registerEvent(this.app.metadataCache.on("changed",t=>{this.displayedPath&&t.path===this.displayedPath&&this.scheduleRender()}))}async onClose(){this.unsubscribeSelection?.(),this.unsubscribeSelection=null,this.unsubscribeContent?.(),this.unsubscribeContent=null,this.composerAutocomplete?.detach(),this.composerAutocomplete=null,this.composerInputEl=null,this.renderTimer!=null&&(window.clearTimeout(this.renderTimer),this.renderTimer=null)}scheduleRender(){this.renderTimer==null&&(this.renderTimer=window.setTimeout(()=>{this.renderTimer=null,this.containerEl.isConnected&&this.render()},60))}resolveDisplayed(){if(this.displayedId){let e=this.plugin.lastActiveStashpadLeaf?.view;if(e?.getViewType?.()===J&&e.tree?.get){let i=e.tree.get(this.displayedId);if(i?.file)return{folder:e.noteFolder,id:this.displayedId,file:i.file}}this.displayedId=null}let t=this.plugin.getActiveStashpadSelection();return t&&(this.displayedId=t.id),t}async render(){let t=this.contentEl,e=!!this.composerInputEl&&document.activeElement===this.composerInputEl,i=this.composerInputEl?.selectionStart??null;this.composerAutocomplete?.detach(),this.composerAutocomplete=null,this.composerInputEl=null,t.empty(),t.addClass("stashpad-detail-root");let s=this.resolveDisplayed();if(!s){this.displayedPath=null;let I=t.createDiv({cls:"stashpad-detail-empty"});(0,mt.setIcon)(I.createSpan({cls:"stashpad-detail-empty-icon"}),"panel-right"),I.createSpan({cls:"stashpad-detail-empty-text",text:"No Stashpad note selected. Cursor or click a note in a Stashpad list to inspect it here."});return}let n=s.file;this.displayedPath=n.path;let o=this.app.metadataCache.getFileCache(n)?.frontmatter??{},r=t.createDiv({cls:"stashpad-detail-scroll"}),A=r.createDiv({cls:"stashpad-detail-header"}),l=A.createDiv({cls:"stashpad-detail-titlerow"});l.createDiv({cls:"stashpad-detail-title",text:this.titleFor(n)});let d=l.createEl("button",{cls:"stashpad-detail-open-btn",attr:{"aria-label":"Open in Stashpad tab"}});(0,mt.setIcon)(d,"arrow-up-right"),d.title="Open this note in a new Stashpad tab",d.onclick=()=>{this.openInStashpad(s.folder,s.id)};let g=A.createDiv({cls:"stashpad-detail-metarow"});if(s.folder&&g.createSpan({cls:"stashpad-detail-meta-chip",text:s.folder.split("/").pop()||s.folder}),typeof o.color=="string"&&o.color){let I=g.createSpan({cls:"stashpad-detail-meta-color"});I.style.background=o.color,I.title=o.color}if(o.completed===!0&&g.createSpan({cls:"stashpad-detail-meta-chip is-completed",text:"\u2713 completed"}),typeof o.due=="string"||typeof o.due=="number"){let I=Date.parse(String(o.due)),u=Number.isNaN(I)?String(o.due):Yt(I,this.plugin.settings);g.createSpan({cls:"stashpad-detail-meta-chip is-due",text:`due ${u}`})}if(Array.isArray(o.tags))for(let I of o.tags.filter(u=>typeof u=="string"))g.createSpan({cls:"stashpad-detail-meta-tag",text:`#${I.replace(/^#/,"")}`});let p=r.createDiv({cls:"stashpad-detail-body"});try{let I=await this.app.vault.cachedRead(n),u=this.stripFrontmatter(I);await mt.MarkdownRenderer.render(this.app,u,p,n.path,this)}catch(I){p.createDiv({cls:"stashpad-detail-error",text:`Couldn't read \`${n.path}\`: ${I.message}`})}this.renderFooterMeta(r,n,o,s),this.renderChildren(r,s.folder,s.id),this.renderComposer(t,s);let h=this.composerInputEl;if(e&&h&&(h.focus(),i!=null)){let I=Math.min(i,h.value.length);try{h.setSelectionRange(I,I)}catch{}}}renderComposer(t,e){let i=t.createDiv({cls:"stashpad-detail-composer"}),s=i.createEl("textarea",{cls:"stashpad-detail-composer-input",attr:{placeholder:"Add a child note\u2026",rows:"2"}});this.composerInputEl=s,this.composerDraftForId===e.id?s.value=this.composerDraft:(this.composerDraft="",this.composerDraftForId=e.id),s.addEventListener("input",()=>{this.composerDraft=s.value,this.composerDraftForId=e.id}),s.addEventListener("keydown",o=>{if(o.key==="Enter"&&!o.shiftKey&&!o.isComposing){if(this.composerAutocomplete?.isOpen?.())return;o.preventDefault(),this.submitComposer(e)}});let n=i.createEl("button",{cls:"stashpad-detail-composer-send",attr:{"aria-label":"Add child note"}});(0,mt.setIcon)(n.createSpan({cls:"stashpad-detail-composer-send-icon"}),"plus"),n.createSpan({cls:"stashpad-detail-composer-send-text",text:"Add child note"}),n.title="Add child note (Enter)",n.onclick=()=>void this.submitComposer(e),this.composerAutocomplete=new Je(this.app,s),this.composerAutocomplete.attach()}async submitComposer(t){let e=(this.composerInputEl?.value??"").trim();if(!e)return;let i=this.plugin.lastActiveStashpadLeaf?.view;if(!i||i.getViewType?.()!==J||typeof i.createNoteUnder!="function"){new mt.Notice("Open a Stashpad view to add notes.");return}try{await i.createNoteUnder(e,t.id)}catch(s){new mt.Notice(`Couldn't add note: ${s.message}`);return}this.composerDraft="",this.composerDraftForId=t.id,this.composerInputEl&&(this.composerInputEl.value=""),await this.render(),setTimeout(()=>this.composerInputEl?.focus(),0)}renderChildren(t,e,i){let s=this.plugin.lastActiveStashpadLeaf?.view;if(!s||s.getViewType?.()!==J)return;let n=s.tree;if(!n?.getChildren)return;let o=n.getChildren(i);if(!o||o.length===0)return;let r=t.createDiv({cls:"stashpad-detail-children"});r.createDiv({cls:"stashpad-detail-children-header",text:`Children (${o.length})`});let A=r.createDiv({cls:"stashpad-detail-children-list"});for(let l of o)l.file&&this.renderDetailChildRow(A,s,n,e,l,0)}renderDetailChildRow(t,e,i,s,n,o){if(!n.file)return;let r=this.app.metadataCache.getFileCache(n.file)?.frontmatter??{},A=typeof r.color=="string"?r.color:null,l=r.completed===!0,d=i.getChildren(n.id),g=d.length>0,p=`${s}|${n.id}`,h=this.expanded.has(p),I=t.createDiv({cls:"stashpad-detail-child-row"});l&&I.addClass("is-completed"),o>0&&(I.style.paddingLeft=`${o*16}px`),I.draggable=!0,I.dataset.id=n.id,I.addEventListener("dragstart",m=>{m.dataTransfer?.setData("text/plain",n.id),m.dataTransfer&&(m.dataTransfer.effectAllowed="move"),I.addClass("is-dragging")}),I.addEventListener("dragend",()=>I.removeClass("is-dragging")),I.addEventListener("dragover",m=>{m.preventDefault(),m.dataTransfer&&(m.dataTransfer.dropEffect="move");let w=I.getBoundingClientRect(),Q=m.clientY-w.top<w.height/2;I.toggleClass("drop-before",Q),I.toggleClass("drop-after",!Q)}),I.addEventListener("dragleave",()=>{I.removeClass("drop-before"),I.removeClass("drop-after")}),I.addEventListener("drop",m=>{m.preventDefault(),I.removeClass("drop-before"),I.removeClass("drop-after");let w=m.dataTransfer?.getData("text/plain");if(!w||w===n.id)return;let Q=I.getBoundingClientRect(),E=m.clientY-Q.top<Q.height/2;typeof e.reorderToTarget=="function"&&e.reorderToTarget([w],n.id,E?"before":"after")}),I.oncontextmenu=m=>{m.preventDefault();let w=i.get(n.id);w&&typeof e.openNoteMenu=="function"&&e.openNoteMenu(m,w)};let u=I.createSpan({cls:"stashpad-detail-child-toggle"});if(g&&(we(u,d.length,h),u.onclick=m=>{m.stopPropagation(),this.expanded.has(p)?this.expanded.delete(p):this.expanded.add(p),this.render()}),be(r,"task")||r.task===!0||r.completed!==void 0){let m=I.createSpan({cls:"stashpad-detail-child-checkbox"});(0,mt.setIcon)(m,l?"check-square":"square"),m.title=l?"Mark not done":"Mark done",m.addEventListener("mousedown",w=>w.stopPropagation()),m.addEventListener("dblclick",w=>{w.preventDefault(),w.stopPropagation()}),m.onclick=w=>{w.preventDefault(),w.stopPropagation();let Q=i.get(n.id);Q&&typeof e.toggleCompletedForNode=="function"&&e.toggleCompletedForNode(Q)}}let C=I.createSpan({cls:"stashpad-detail-child-icon"});(0,mt.setIcon)(C,g?"folder-tree":"file-text"),A&&(C.style.color=A);let B=I.createSpan({cls:"stashpad-detail-child-title",text:this.titleFor(n.file)});if(B.onclick=()=>{e?.navigateTo&&e.navigateTo(n.id)},g&&h)for(let m of d)this.renderDetailChildRow(t,e,i,s,m,o+1)}renderFooterMeta(t,e,i,s){let n=t.createDiv({cls:"stashpad-detail-footer-meta"}),o=[];if(typeof i.author=="string"&&i.author&&o.push({label:"Author",value:this.stripWikiLink(i.author)}),Array.isArray(i.contributors)){let r=i.contributors.filter(A=>typeof A=="string").map(A=>this.stripWikiLink(A));r.length>0&&o.push({label:"Contributors",value:r.join(", ")})}if(typeof i.modified=="string"&&o.push({label:"Modified",value:this.formatTime(i.modified)}),typeof i.created=="string"&&o.push({label:"Created",value:this.formatTime(i.created)}),o.push({label:"Path",value:e.path}),o.push({label:"ID",value:s.id}),o.length===0){n.remove();return}for(let r of o){let A=n.createDiv({cls:"stashpad-detail-meta-line"});A.createSpan({cls:"stashpad-detail-meta-key",text:r.label}),A.createSpan({cls:"stashpad-detail-meta-val",text:r.value})}}titleFor(t){return t.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ")}stripFrontmatter(t){if(!t.startsWith("---"))return t;let e=t.indexOf(` ----`,3);return e<0?t:t.slice(e+4).replace(/^\n+/,"")}stripWikiLink(t){let e=t.match(/^\[\[(.+?)(?:\|(.+))?\]\]$/);return e?e[2]??(e[1].split("/").pop()??e[1]).replace(/\.md$/,""):t}formatTime(t){let e=Date.parse(t);return Number.isFinite(e)?Yt(e,this.plugin.settings):t}async openInStashpad(t,e){try{let i=await this.plugin.activateViewForFolder(t);e!==F&&this.plugin.navigateLeafTo(i,t,e)}catch(i){new mt.Notice(`Couldn't open: ${i.message}`)}}};async function Bs(c){let a=c.workspace.getLeavesOfType(Ce);if(a.length>0){c.workspace.revealLeaf(a[0]);return}let t=c.workspace.getRightLeaf(!1);if(!t){new mt.Notice("Stashpad: couldn't open the detail panel.");return}await t.setViewState({type:Ce,active:!0}),c.workspace.revealLeaf(t)}var k=require("obsidian");rt();var pe=require("obsidian");rt();function bA(c,a){let t=c.vault.getAbstractFileByPath(a);if(!(t instanceof pe.TFolder))return[];let e=[],i=[t];for(;i.length;){let s=i.pop();for(let n of s.children)n instanceof pe.TFile?n.extension==="md"&&e.push(n):n instanceof pe.TFolder&&(Ze.has(n.name)||i.push(n))}return e}var ms=class{constructor(a){this.app=a;this.nodes=new Map;this.byPath=new Map;this.listeners=new Set;this.orderProvider=null;this.synthetic=new Map;this.coalesceTimer=null;this.nodes.set(F,{id:F,parent:null,children:[],file:null,created:""})}setOrderProvider(a){this.orderProvider=a}onChange(a){return this.listeners.add(a),()=>this.listeners.delete(a)}emit(){for(let a of this.listeners)a()}rebuild(a){a!==void 0&&(this.currentFolder=a);let t=this.currentFolder,e=this.byPath,i=this.nodes;this.nodes=new Map,this.byPath=new Map,this.nodes.set(F,{id:F,parent:null,children:[],file:null,created:""});let s=t?bA(this.app,t):this.app.vault.getMarkdownFiles();for(let n of s){let o=this.app.metadataCache.getFileCache(n)?.frontmatter,r=o?.id;if(!r){let l=e.get(n.path),d=l?i.get(l):void 0,g=this.synthetic.get(n.path),p=d??g;p&&(this.nodes.set(p.id,{...p,children:[],file:n}),this.byPath.set(n.path,p.id));continue}if(this.synthetic.delete(n.path),r===F){let l=this.nodes.get(F);l.file=n,l.created=o?.created??"",this.byPath.set(n.path,F);continue}let A=o?.parent??null;A===r&&(A=null),this.nodes.set(r,{id:r,parent:A??F,children:[],file:n,created:o?.created??""}),this.byPath.set(n.path,r)}for(let n of this.nodes.values()){if(n.id===F)continue;let o=n.parent??F;(this.nodes.get(o)??this.nodes.get(F)).children.push(n.id)}for(let n of this.nodes.values())if(n.children.sort((o,r)=>{let A=this.nodes.get(o),l=this.nodes.get(r);return(A.created||"").localeCompare(l.created||"")}),this.orderProvider){let o=this.orderProvider(n.id);if(o.length>0){let r=new Map;o.forEach((A,l)=>r.set(A,l)),n.children.sort((A,l)=>{let d=r.has(A)?r.get(A):1/0,g=r.has(l)?r.get(l):1/0;return d===g?0:d-g})}}this.emit()}insertSynthetic(a){if(!a.file)return;let t=a.file.path;this.synthetic.set(t,a),this.nodes.set(a.id,a),this.byPath.set(t,a.id);let e=a.parent??F,i=this.nodes.get(e);i&&!i.children.includes(a.id)&&i.children.push(a.id),this.emit()}get(a){return this.nodes.get(a)}getRoot(){return this.nodes.get(F)}getChildren(a){let t=this.nodes.get(a);return t?t.children.map(e=>this.nodes.get(e)).filter(e=>!!e):[]}fileBackedCount(){let a=0;for(let t of this.nodes.values())t.file&&a++;return a}pathTo(a){let t=[],e=new Set,i=this.nodes.get(a);for(;i&&i.id!==F&&!e.has(i.id);)e.add(i.id),t.unshift(i),i=i.parent?this.nodes.get(i.parent):void 0;return t}idForPath(a){return this.byPath.get(a)}snapshot(){let a={};for(let t of this.nodes.values())t.id===F||!t.file||(a[t.id]={parent:t.parent===F?null:t.parent,path:t.file.path});return a}hookMetadataCache(a){let t=A=>{let l=this.currentFolder;return l?typeof A!="string"?!1:A===l||A.startsWith(l+"/"):!0},e=!1,i=()=>{e=!0,this.coalesceTimer==null&&(this.coalesceTimer=window.setTimeout(()=>{this.coalesceTimer=null,e&&(e=!1,this.emit(),a())},16))},s=A=>{A instanceof pe.TFile&&t(A.path)&&A.extension==="md"&&(this.applyChange(A),i())},n=A=>{A instanceof pe.TFile&&t(A.path)&&A.extension==="md"&&this.applyChange(A)&&i()},o=A=>{let l=A?.path;typeof l=="string"&&t(l)&&this.applyDelete(l)&&i()},r=(A,l)=>{if(!(A instanceof pe.TFile))return;let d=typeof l=="string"?l:null;!t(A.path)&&!t(d)||this.applyRename(A,d??"")&&i()};return this.app.metadataCache.on("changed",s),this.app.vault.on("create",n),this.app.vault.on("delete",o),this.app.vault.on("rename",r),()=>{this.app.metadataCache.off("changed",s),this.app.vault.off("create",n),this.app.vault.off("delete",o),this.app.vault.off("rename",r),this.coalesceTimer!=null&&(window.clearTimeout(this.coalesceTimer),this.coalesceTimer=null)}}applyChange(a){if(Ne(a.path))return this.byPath.has(a.path)?this.applyDelete(a.path):!1;let t=this.app.metadataCache.getFileCache(a)?.frontmatter,e=t?.id,i=this.byPath.get(a.path);if(!e){if(i){let l=this.nodes.get(i);if(l&&l.file!==a)return l.file=a,!0}return!1}if(this.synthetic.delete(a.path),e===F){let l=this.nodes.get(F),d=t?.created??"",g=!1;return l.file!==a&&(l.file=a,g=!0),l.created!==d&&(l.created=d,g=!0),this.byPath.get(a.path)!==F&&(this.byPath.set(a.path,F),g=!0),g}let s=t?.parent??F,n=t?.created??"";if(!(s===F||this.nodes.has(s)))return this.rebuild(),!0;if(i&&i!==e)return this.rebuild(),!0;let r=this.nodes.get(e);if(!r){let l={id:e,parent:s,children:[],file:a,created:n};return this.nodes.set(e,l),this.byPath.set(a.path,e),this.attachToParent(l),this.resortChildrenOf(s),!0}let A=!1;if(r.file!==a&&(r.file=a,A=!0),r.created!==n&&(r.created=n,this.resortChildrenOf(r.parent??F),A=!0),r.parent!==s){let l=r.parent??F;this.detachFromParent(r),r.parent=s,this.attachToParent(r),this.resortChildrenOf(l),this.resortChildrenOf(s),A=!0}return A}applyDelete(a){let t=this.byPath.get(a);if(!t)return!1;let e=this.nodes.get(t);if(!e)return this.byPath.delete(a),this.synthetic.delete(a),!0;this.detachFromParent(e);let i=this.nodes.get(F);for(let s of e.children){let n=this.nodes.get(s);n&&(n.parent=F,i.children.includes(s)||i.children.push(s))}return e.children.length>0&&this.resortChildrenOf(F),this.nodes.delete(t),this.byPath.delete(a),this.synthetic.delete(a),!0}applyRename(a,t){let e=this.currentFolder,i=!e||t===e||t.startsWith(e+"/"),s=!e||a.path===e||a.path.startsWith(e+"/");if(!i&&!s)return!1;if(i&&!s)return this.applyDelete(t);if(!i&&s)return this.applyChange(a);if(Ne(a.path))return this.byPath.has(t)?this.applyDelete(t):!1;let n=this.byPath.get(t);if(!n)return this.applyChange(a);this.byPath.delete(t),this.byPath.set(a.path,n);let o=this.nodes.get(n);return o&&(o.file=a),!0}detachFromParent(a){let t=this.nodes.get(a.parent??F);if(!t)return;let e=t.children.indexOf(a.id);e>=0&&t.children.splice(e,1)}attachToParent(a){let t=this.nodes.get(a.parent??F);t||(t=this.nodes.get(F)),t.children.includes(a.id)||t.children.push(a.id)}resortChildrenOf(a){let t=this.nodes.get(a);if(t&&(t.children.sort((e,i)=>{let s=this.nodes.get(e),n=this.nodes.get(i);return(s.created||"").localeCompare(n.created||"")}),this.orderProvider)){let e=this.orderProvider(a);if(e.length>0){let i=new Map;e.forEach((s,n)=>i.set(s,n)),t.children.sort((s,n)=>{let o=i.has(s)?i.get(s):1/0,r=i.has(n)?i.get(n):1/0;return o===r?0:o-r})}}}};var Vn=class{constructor(){this.enabled=!1;this.buckets=new Map}record(a,t){if(!this.enabled)return;let e=this.buckets.get(a);e||(e={count:0,total:0,max:0},this.buckets.set(a,e)),e.count+=1,e.total+=t,t>e.max&&(e.max=t)}time(a,t){if(!this.enabled)return t();let e=performance.now();try{return t()}finally{this.record(a,performance.now()-e)}}async timeAsync(a,t){if(!this.enabled)return t();let e=performance.now();try{return await t()}finally{this.record(a,performance.now()-e)}}reset(){this.buckets.clear()}hasData(){return this.buckets.size>0}report(){let a=[...this.buckets.entries()].map(([e,i])=>({label:e,...i,avg:i.total/i.count})).sort((e,i)=>i.total-e.total);if(a.length===0)return"Stashpad perf: no samples (enable profiling, then use the app).";let t=["**Stashpad performance profile**","","| label | count | total (ms) | avg (ms) | max (ms) |","| --- | ---: | ---: | ---: | ---: |"];for(let e of a)t.push(`| \`${e.label}\` | ${e.count} | ${e.total.toFixed(0)} | ${e.avg.toFixed(1)} | ${e.max.toFixed(0)} |`);return t.join(` -`)}},Qt=new Vn;var xa=".stashpad-order.json",Ke=class{constructor(a){this.app=a;this.cache=new Map;this.pendingTimers=new Map;this.writeInFlight=new Map}async load(a){if(this.cache.has(a))return this.cache.get(a);let t=`${a}/${xa}`,e=this.app.vault.adapter,i={};try{if(await e.exists(t)){let s=await e.read(t),n=JSON.parse(s);if(n&&typeof n=="object"&&!Array.isArray(n))for(let[o,r]of Object.entries(n))Array.isArray(r)&&r.every(A=>typeof A=="string")&&(i[o]=r)}}catch(s){console.warn("Stashpad: order load failed",s)}return this.cache.set(a,i),i}async save(a){this.scheduleWrite(a)}async flush(a){let t=this.pendingTimers.get(a);t!=null&&(window.clearTimeout(t),this.pendingTimers.delete(a)),await this.writeNow(a)}scheduleWrite(a){let t=this.pendingTimers.get(a);t!=null&&window.clearTimeout(t);let e=window.setTimeout(()=>{this.pendingTimers.delete(a),this.writeNow(a)},150);this.pendingTimers.set(a,e)}async writeNow(a){let e=(this.writeInFlight.get(a)??Promise.resolve()).then(()=>this.doWrite(a));this.writeInFlight.set(a,e);try{await e}finally{this.writeInFlight.get(a)===e&&this.writeInFlight.delete(a)}}async doWrite(a){let t=this.cache.get(a)??{},e={};for(let[n,o]of Object.entries(t))o.length>0&&(e[n]=o);this.cache.set(a,e);let i=`${a}/${xa}`,s=this.app.vault.adapter;try{if(Object.keys(e).length===0)try{await s.remove(i)}catch{}else await s.write(i,JSON.stringify(e,null,2))}catch(n){console.warn("Stashpad: order save failed",n)}}getOrder(a,t){return this.cache.get(a)?.[t]?.slice()??[]}setOrder(a,t,e){let i=this.cache.get(a)??{};i[t]=e.slice(),this.cache.set(a,i)}appendChild(a,t,e){let i=this.cache.get(a)??{},s=i[t]??[];s.includes(e)||s.push(e),i[t]=s,this.cache.set(a,i)}removeChild(a,t){let e=this.cache.get(a);if(e)for(let i of Object.values(e)){let s=i.indexOf(t);s>=0&&i.splice(s,1)}}invalidate(a){this.cache.delete(a)}};var Ni={manual:"Manual","created-asc":"Created \u2014 oldest first","created-desc":"Created \u2014 newest first","modified-asc":"Modified \u2014 oldest first","modified-desc":"Modified \u2014 newest first","title-az":"Title \u2014 A\u2192Z","title-za":"Title \u2014 Z\u2192A"},Wn=["manual","created-asc","created-desc","modified-asc","modified-desc","title-az","title-za"],NA=new Set(Wn),Ma=".stashpad-sort.json",Qs=class{constructor(a){this.app=a;this.cache=new Map;this.pendingTimers=new Map;this.writeInFlight=new Map}async load(a){if(this.cache.has(a))return this.cache.get(a);let t=`${a}/${Ma}`,e=this.app.vault.adapter,i={};try{if(await e.exists(t)){let s=JSON.parse(await e.read(t));if(s&&typeof s=="object"&&!Array.isArray(s))for(let[n,o]of Object.entries(s))typeof o=="string"&&NA.has(o)&&(i[n]=o)}}catch(s){console.warn("Stashpad: sort load failed",s)}return this.cache.set(a,i),i}async save(a){this.scheduleWrite(a)}async flush(a){let t=this.pendingTimers.get(a);t!=null&&(window.clearTimeout(t),this.pendingTimers.delete(a)),await this.writeNow(a)}scheduleWrite(a){let t=this.pendingTimers.get(a);t!=null&&window.clearTimeout(t);let e=window.setTimeout(()=>{this.pendingTimers.delete(a),this.writeNow(a)},150);this.pendingTimers.set(a,e)}async writeNow(a){let e=(this.writeInFlight.get(a)??Promise.resolve()).then(()=>this.doWrite(a));this.writeInFlight.set(a,e);try{await e}finally{this.writeInFlight.get(a)===e&&this.writeInFlight.delete(a)}}async doWrite(a){let t=this.cache.get(a)??{},e=`${a}/${Ma}`,i=this.app.vault.adapter;try{if(Object.keys(t).length===0)try{await i.remove(e)}catch{}else await i.write(e,JSON.stringify(t,null,2))}catch(s){console.warn("Stashpad: sort save failed",s)}}getMode(a,t){return this.cache.get(a)?.[t]??"manual"}setMode(a,t,e){let i=this.cache.get(a)??{};e==="manual"?delete i[t]:i[t]=e,this.cache.set(a,i)}removeParent(a,t){let e=this.cache.get(a);e&&delete e[t]}invalidate(a){this.cache.delete(a)}};rt();var Ie="parentLink",Oe="children";var ws=class ws{constructor(a,t){this.app=a;this.getTree=t;this.pending=new Set;this.timer=null;this.activityListeners=new Set;this.errorListeners=new Set}onActivity(a){return this.activityListeners.add(a),()=>this.activityListeners.delete(a)}emitActivity(){let a=this.pending.size;for(let t of this.activityListeners)try{t(a)}catch(e){console.warn("[Stashpad] fmSync activity listener failed",e)}}schedule(a){if(!a||!j().writeRecoveryLinks)return;let t=this.pending.size;this.pending.add(a),this.pending.size!==t&&this.emitActivity(),this.kick()}scheduleParentChange(a,t,e){this.schedule(a),t&&this.schedule(t),this.schedule(e)}scheduleSubtree(a){let t=this.getTree(),e=i=>{this.schedule(i);for(let s of t.getChildren(i))e(s.id)};e(a)}scheduleParentOfDeleted(a){a&&this.schedule(a)}async flush(){for(this.timer!=null&&(window.clearTimeout(this.timer),this.timer=null);this.pending.size>0;){let a=this.pending.values().next().value;if(a===void 0)break;this.pending.delete(a),this.emitActivity(),await this.syncOne(a)}}pendingCount(){return this.pending.size}onError(a){return this.errorListeners.add(a),()=>this.errorListeners.delete(a)}emitError(a,t){for(let e of this.errorListeners)try{e(a,t)}catch(i){console.warn("[Stashpad] fmSync error listener failed",i)}}reset(){this.timer!=null&&(window.clearTimeout(this.timer),this.timer=null),this.pending.clear()}kick(){this.timer!=null||this.pending.size===0||(this.timer=window.setTimeout(()=>this.tick(),ws.PACING_MS))}async tick(){this.timer=null;let a=this.pending.values().next().value;if(a!==void 0){this.pending.delete(a),this.emitActivity();try{await this.syncOne(a)}catch(t){console.warn("[Stashpad] frontmatter sync tick failed",t)}this.pending.size>0&&this.kick()}}wouldWrite(a){let e=this.getTree().get(a);if(!e||!e.file)return!1;let i=this.computeParentLink(e),s=this.computeChildrenLinks(e),n=this.app.metadataCache.getFileCache(e.file)?.frontmatter,o=n&&typeof n[Ie]=="string"?n[Ie]:null,r=n?.[Oe],A=Array.isArray(r)?r.filter(l=>typeof l=="string"):[];if((o??null)!==(i??null)||A.length!==s.length)return!0;for(let l=0;l<A.length;l++)if(A[l]!==s[l])return!0;return!1}async syncOne(a){let e=this.getTree().get(a);if(!e||!e.file||!this.wouldWrite(a))return;let i=this.computeParentLink(e),s=this.computeChildrenLinks(e);try{await Qt.timeAsync("write.fmSync",()=>this.app.fileManager.processFrontMatter(e.file,n=>{i?n[Ie]=i:delete n[Ie],s.length>0?n[Oe]=s:delete n[Oe]}))}catch(n){console.warn("[Stashpad] frontmatter sync failed",e.file?.path,n),this.emitError(e.file.path,n)}}computeParentLink(a){if(a.id===F)return null;let t=this.getTree();if(!a.parent||a.parent===F){let i=t.getRoot();return i&&i.id!==a.id&&i.file?ys(i.file.path):null}let e=t.get(a.parent);return e?.file?ys(e.file.path):null}computeChildrenLinks(a){return this.getTree().getChildren(a.id).filter(e=>!!e.file).map(e=>ys(e.file.path))}};ws.PACING_MS=100;var Es=ws;async function Ye(c,a){let t=a.endsWith("/")?a:a+"/",e=new Map,i=new Map;for(let l of c.vault.getMarkdownFiles()){if(l.path!==a&&!l.path.startsWith(t))continue;let d=c.metadataCache.getFileCache(l)?.frontmatter,g=typeof d?.id=="string"?d.id:null;if(!g)continue;let p=typeof d?.parent=="string"?d.parent:F;e.set(g,{file:l,id:g,parent:p});let h=i.get(p)??[];h.push(g),i.set(p,h)}let s=l=>ys(l.file.path),n=l=>{if(l.id===F)return null;if(l.parent===F||!l.parent){let g=e.get(F);return g?s(g):null}let d=e.get(l.parent);return d?s(d):null},o=l=>{let d=i.get(l.id)??[],g=[];for(let p of d){let h=e.get(p);h&&g.push(s(h))}return g},r=0,A=0;for(let l of e.values()){r+=1;let d=n(l),g=o(l),p=c.metadataCache.getFileCache(l.file)?.frontmatter,h=p&&typeof p[Ie]=="string"?p[Ie]:null,I=p?.[Oe],u=Array.isArray(I)?I.filter(B=>typeof B=="string"):[],f=(h??null)===(d??null),C=u.length===g.length&&u.every((B,m)=>B===g[m]);if(!(f&&C))try{await c.fileManager.processFrontMatter(l.file,B=>{d?B[Ie]=d:delete B[Ie],g.length>0?B[Oe]=g:delete B[Oe]}),A+=1,await new Promise(B=>setTimeout(B,50))}catch(B){console.warn("[Stashpad] rebootstrap fm sync failed",l.file.path,B)}}return{checked:r,written:A}}function ys(c){return`[[${c.replace(/\.md$/i,"")}]]`}xt();Te();var vs=class{constructor(a,t){this.tree=a;this.log=t}async sweep(a){let t=await this.log.readState(),e=this.tree.snapshot(),i=n=>{if(!a)return!0;let o=a.replace(/\/+$/,"");return n===o||n.startsWith(o+"/")};for(let[n,o]of Object.entries(e)){let r=t[n];r?r.parent!==o.parent?await this.log.append({type:"parent_change",id:n,payload:{from:r.parent,to:o.parent}}):r.path!==o.path&&await this.log.append({type:"rename",id:n,payload:{from:r.path,to:o.path}}):await this.log.append({type:"create",id:n,payload:{path:o.path,parent:o.parent}})}for(let[n,o]of Object.entries(t))!e[n]&&i(o.path)&&await this.log.append({type:"missing",id:n,payload:{lastPath:o.path}});let s={};for(let[n,o]of Object.entries(t))i(o.path)||(s[n]=o);for(let[n,o]of Object.entries(e))s[n]=o;await this.log.writeState(s)}};var ht=require("obsidian");rt();_s();var ft=ht.moment;function Xn(c){let a=c.trim().toLowerCase();if(!a)return null;let t=Date.now(),e=I=>ft(I).startOf("day").valueOf(),i=/\b(\d{1,2})(?::(\d{2}))?\s*(am|pm)?\b/,s=0,n=!1,o=a,r=i.exec(a);if(r&&(r[3]||r[2])){let I=parseInt(r[1],10),u=r[2]?parseInt(r[2],10):0,f=r[3];f==="pm"&&I<12&&(I+=12),f==="am"&&I===12&&(I=0),I>=0&&I<24&&u>=0&&u<60&&(s=(I*3600+u*60)*1e3,n=!0,o=a.replace(r[0]," ").replace(/\s+/g," ").trim())}let A=I=>n?I+s:I;if(o===""||o==="today")return A(e(t));if(o==="yesterday")return A(e(t)-864e5);if(o==="tomorrow")return A(e(t)+864e5);let l=["sunday","monday","tuesday","wednesday","thursday","friday","saturday"],d=["sun","mon","tue","wed","thu","fri","sat"],g=l.indexOf(o)>=0?l.indexOf(o):d.indexOf(o);if(g>=0){let I=ft().startOf("day"),f=(I.day()-g+7)%7;return A(I.subtract(f,"days").valueOf())}let p=/^(\d+)\s*([dwmy])$/.exec(o);if(p){let I=parseInt(p[1],10),u={d:"days",w:"weeks",m:"months",y:"years"}[p[2]];return A(ft().subtract(I,u).startOf("day").valueOf())}let h=ft(o,["YYYY-MM-DD","YYYY/MM/DD","MM-DD-YYYY","MM/DD/YYYY","M-D-YYYY","M/D/YYYY"],!0);return h.isValid()?A(h.startOf("day").valueOf()):null}function Ta(c){let a={text:[],filters:{}},t=(c||"").trim();if(!t)return a;let e=/\b(in|before|after|on):\s*(?:\[([^\]]*)\]|([^]*?)(?=\s+(?:in|before|after|on):|$))/gi,i=t,s;for(;(s=e.exec(t))!=null;){let n=s[1].toLowerCase(),o=(s[2]!==void 0?s[2]:s[3]??"").trim();if(o){if(n==="in")a.filters.in=o.toLowerCase();else if(n==="before"){let r=Xn(o);r!=null&&(a.filters.before=r)}else if(n==="after"){let r=Xn(o);r!=null&&(a.filters.after=r)}else if(n==="on"){let r=Xn(o);if(r!=null)if(/\b\d{1,2}:\d{2}\b|\b\d{1,2}\s*(?:am|pm)\b/i.test(o))a.filters.on={start:r-6e4,end:r+6e4};else{let l=ft(r).startOf("day").valueOf();a.filters.on={start:l,end:l+864e5}}}i=i.replace(s[0]," ")}}for(let n of i.split(/\s+/))n&&a.text.push(n.toLowerCase());return a}var te=class c extends ht.SuggestModal{constructor(t,e,i,s){super(t);this.tree=e;this.titleFn=i;this.opts=s;this.notes=[];this.includeExcluded=!1;this.pendingCleanups=[];this.crossFolderIndex=null;this.whenBuilderEl=null;this.whenMode="on";this.whenSingleText="";this.whenBetweenEndText="";this.setPlaceholder(s.placeholder??(s.mode==="search"?"Search notes\u2026":"Pick a note\u2026")),this.loadAll()}onClose(){for(;this.pendingCleanups.length>0;){let t=this.pendingCleanups.pop();try{t&&t()}catch{}}try{this.opts.onClose?.()}catch{}}loadAll(){let t=this.tree.getRoot(),e=t.file?.parent?.name?.trim()??"",i=e?`Home \u2014 ${e}`:"Home",s=(n,o)=>{let r=this.tree.get(n);r?.file&&n!==F?this.notes.push({node:r,title:`${" ".repeat(o)}${this.titleFn(r)}`,body:""}):r?.file&&n===F&&this.notes.push({node:r,title:i,body:""});for(let A of this.tree.getChildren(n))s(A.id,o+1)};t.file&&this.notes.push({node:t,title:i,body:""});for(let n of this.tree.getChildren(F))s(n.id,1);for(let n of this.notes)n.node?.file&&this.app.vault.cachedRead(n.node.file).then(o=>{n.body=this.stripFm(o)});if(this.opts.crossFolderNotes){let n=this.opts.crossFolderNotes();for(let o of n)this.notes.push({node:null,title:o.title,body:o.body,cross:o});for(let o of this.notes)!o.cross||o.body||o.cross.file&&this.app.vault.cachedRead(o.cross.file).then(r=>{o.body=this.stripFm(r)})}}createdMsFor(t){if(t.node?.created){let e=Date.parse(t.node.created);if(!Number.isNaN(e))return e}return t.cross?.file?.stat?.ctime!=null?t.cross.file.stat.ctime:null}stripFm(t){if(!t.startsWith("---"))return t;let e=t.indexOf(` ----`,3);return e===-1?t:t.slice(e+4).replace(/^\r?\n/,"")}getSuggestions(t){let e=t.trim().toLowerCase(),i=Ta(t),s=i.text;console.log("[Stashpad] search query parsed",{query:t,text:i.text,filters:i.filters});let n=C=>{if(!s.length)return!0;for(let B of s)if(!C.includes(B))return!1;return!0},o=null,r=null;if(i.filters.in){let C=i.filters.in.split(/\s+/).filter(Boolean);o=new Set,r=new Map;let B=Q=>C.every(E=>Q.toLowerCase().includes(E)),m=Q=>{if(!o.has(Q)){o.add(Q);for(let E of this.tree.getChildren(Q))m(E.id)}};for(let Q of this.notes)!Q.node||Q.cross||B(Q.title)&&m(Q.node.id);let w=new Map;for(let Q of this.notes){if(!Q.cross)continue;let E=w.get(Q.cross.folder)??[];E.push(Q),w.set(Q.cross.folder,E)}for(let[Q,E]of w){let v=new Map;for(let N of E){let P=N.cross?.parentId??null;if(!P)continue;let H=v.get(P)??[];H.push(N.cross.id),v.set(P,H)}let y=new Set;r.set(Q,y);let b=N=>{if(!y.has(N)){y.add(N);for(let P of v.get(N)??[])b(P)}};for(let N of E)B(N.title)&&b(N.cross.id)}}let A=C=>{let B=i.filters;if(o||r)if(C.cross){let m=r?.get(C.cross.folder);if(!m||!m.has(C.cross.id))return!1}else if(C.node){if(!o||!o.has(C.node.id))return!1}else return!1;if(B.before||B.after||B.on){let m=this.createdMsFor(C);if(m==null||B.before!=null&&m>=B.before||B.after!=null&&m<=B.after||B.on&&(m<B.on.start||m>=B.on.end))return!1}return!0},l=C=>n(C.toLowerCase()),d=this.notes.filter(C=>!C.cross),g=this.notes.filter(C=>C.cross),p=(C,B)=>({id:C.cross?`cross:${C.cross.folder}:${C.cross.id}`:C.node.id,label:C.title,node:C.node,kind:"note",bodyPreview:this.previewFromBody(C.body,B),matchLine:B,crossFolder:C.cross?.folder,crossFile:C.cross?.file,crossId:C.cross?.id}),h=C=>{let B=[];for(let m of C)if(A(m))if(this.opts.mode==="search"){if(!e){B.push(p(m,-1));continue}let w=n(m.title.toLowerCase()),Q=m.body.split(/\r?\n/),E=[];for(let y=0;y<Q.length;y++)l(Q[y])&&E.push(y);let v=E.length>0||n(m.body.toLowerCase());if(!w&&!v)continue;if(E.length===0)B.push(p(m,-1));else{let y=[],b=-100;for(let P of E)P-b>5&&y.push(P),b=P;let N=5;for(let P of y.slice(0,N))B.push(p(m,P))}}else{if(e&&!n(m.title.toLowerCase())&&!n(m.body.toLowerCase()))continue;B.push(p(m,-1))}return B},I=h(d),u=[...I];if(this.opts.mode==="search"?e?!0:I.length<10:!!e){let C=h(g);this.opts.mode==="search"&&!e&&(u.length=Math.min(u.length,50)),u.push(...C)}if(this.opts.folderResults){let C=this.opts.folderResults(),B={id:"__folder_picker__",label:"Open folder in a new tab\u2026",node:null,kind:"folder-open"};C.length>0&&(e?C.some(m=>{let w=m.split("/").pop()??m;return n(`${m.toLowerCase()} ${w.toLowerCase()}`)})&&u.push(B):u.unshift(B))}if(this.opts.allowCreate&&e&&!u.some(C=>C.label.trim().toLowerCase()===e)&&u.push({id:"__create__",label:`Create new: "${t}"`,node:null,kind:"create"}),i.text.join("").length>=3){let C=m=>m.kind==="note"&&(m.id===F||m.crossId===F)&&n(m.label.toLowerCase()),B=u.filter(C);if(B.length>0){let m=u.filter(w=>!C(w));u.splice(0,u.length,...B,...m)}}return this.opts.excludedFolderNotes&&!this.includeExcluded&&u.push({id:"__search_excluded__",label:"Search excluded Stashpad folders",node:null,kind:"search-excluded"}),u}loadExcludedNotes(){if(this.includeExcluded||!this.opts.excludedFolderNotes)return;this.includeExcluded=!0;for(let e of this.opts.excludedFolderNotes())this.notes.push({node:null,title:e.title,body:e.body,cross:e});for(let e of this.notes)!e.cross||e.body||!e.cross.file||this.app.vault.cachedRead(e.cross.file).then(i=>{e.body=this.stripFm(i)});let t=this.inputEl;t&&(t.dispatchEvent(new Event("input",{bubbles:!0})),setTimeout(()=>t.dispatchEvent(new Event("input",{bubbles:!0})),250))}previewFromBody(t,e){let i=t.split(/\r?\n/);if(e<0)return i.filter(r=>r.trim().length>0).slice(0,3).join(` +${a}`}async function va(c,a){if(!(!a||await c.vault.adapter.exists(a)))try{await c.vault.createFolder(a)}catch(e){let i=e?.message??"";if(!/already exists/i.test(i))throw e}}Is();var ge="stashenc",GA="stashmeta";function Ie(c){return c.replace(/\.stashenc$/,`.${GA}`)}async function Da(c,a){try{return JSON.parse(await c.vault.adapter.read(Ie(a)))}catch{return null}}async function ue(c,a,t){let e=a.replace(/\/+$/,""),i=[];for(let l of c.vault.getMarkdownFiles()){if((l.parent?.path?.replace(/\/+$/,"")??"")!==e)continue;let d;try{d=lt(await c.vault.read(l)).fm}catch{continue}typeof d.id=="string"&&i.push({id:d.id,file:l,parent:typeof d.parent=="string"?d.parent:null,created:typeof d.created=="string"?d.created:""})}let s=i.find(l=>l.id===t);if(!s)return null;let n=new Map;for(let l of i){if(!l.parent)continue;let d=n.get(l.parent)??[];d.push(l),n.set(l.parent,d)}let o=[],r=new Set([t]),A=[t];for(;A.length;){let l=[];for(let d of A)for(let p of n.get(d)??[])r.has(p.id)||(r.add(p.id),o.push(p),l.push(p.id));A=l}return{rootNote:s,descendants:o,parentId:s.parent}}function Vn(c){if(!c)return null;let a=c.replace(/\/+$/,"");return!a||a.startsWith("/")||a.includes("\\")||/^[a-zA-Z]:/.test(a)||a.split("/").some(t=>t===".."||t===".")?null:a}async function $n(c,a,t){await c.vault.adapter.writeBinary(a,t);let e;try{e=new Uint8Array(await c.vault.adapter.readBinary(a))}catch(s){throw new Error(`Couldn't read back the encrypted file to verify it (${s.message}). Nothing was deleted.`)}let i=e.length===t.length;if(i){for(let s=0;s<t.length;s++)if(e[s]!==t[s]){i=!1;break}}if(!i){try{await c.vault.adapter.remove(a)}catch{}throw new Error("The encrypted file on disk doesn't match what was written (bad write?). Nothing was deleted.")}}function Cs(c){return c.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||c.basename}function Ye(c){return(c.replace(/[\\/:*?"<>|]+/g," ").replace(/\s+/g," ").trim()||"locked").slice(0,60)}async function ba(c,a,t){let e=new Set(a.map(r=>r.file.path)),i=new Map;for(let r of a)for(let A of await fs(c,r.file))i.set(A.path,A);let s=new Set,n=c.metadataCache.resolvedLinks??{};for(let r of Object.keys(n))if(!e.has(r))for(let A of Object.keys(n[r]??{}))i.has(A)&&s.add(A);let o=[];for(let r of a){let A=t?.get(r.file.path);if(A!=null)try{let l=await c.vault.adapter.stat(r.file.path);if(l&&l.mtime!==A){console.warn("[Stashpad] note changed since it was bundled \u2014 keeping plaintext",r.file.path),o.push(r.file.path);continue}}catch{}try{await c.vault.delete(r.file)}catch(l){console.warn("[Stashpad] couldn't delete plaintext note",r.file.path,l),o.push(r.file.path)}}for(let[r,A]of i)if(!s.has(r))try{await c.vault.delete(A)}catch(l){console.warn("[Stashpad] couldn't delete exclusive attachment",r,l),o.push(r)}return{unpurged:o}}async function Na(c,a,t,e,i=null,s=!1,n){let o=await ue(c,a,t);if(!o)throw new Error("Couldn't find that note to lock.");let{rootNote:r,descendants:A,parentId:l}=o,d=[r,...A],p=new Map;for(let Q of d)try{let E=await c.vault.adapter.stat(Q.file.path);E&&p.set(Q.file.path,E.mtime)}catch{}let g=await he(c,{rootNotes:[{id:r.id,file:r.file}],allDescendants:A.map(Q=>({id:Q.id,file:Q.file})),sourceFolder:a}),h=await vi(g,e),I=await ce(h,e);if(I.length!==g.length)throw new Error("Encryption self-check failed (size mismatch).");for(let Q=0;Q<g.length;Q++)if(I[Q]!==g[Q])throw new Error("Encryption self-check failed (content mismatch).");let u=(n??a).replace(/\/+$/,"");n&&!await c.vault.adapter.exists(u)&&await c.vault.adapter.mkdir(u);let f=Ye(s?t:Cs(r.file)),C=`${u}/${f}.${ge}`;for(let Q=1;await c.vault.adapter.exists(C);Q++)C=`${u}/${f} (${Q}).${ge}`;await $n(c,C,h);let B=d,m={v:1,parentId:l,title:s?"":Cs(r.file),count:B.length,created:r.created,rootId:t,prevSibling:i};try{await c.vault.adapter.write(Ie(C),JSON.stringify(m))}catch(Q){console.warn("[Stashpad] couldn't write lock sidecar",Q)}let{unpurged:y}=await ba(c,B,p);return{blobPath:C,noteCount:B.length,rootId:t,parentId:l,title:m.title,created:r.created,unpurged:y}}async function xa(c,a,t,e,i){let s=new Uint8Array(await c.vault.adapter.readBinary(a));if(!Ut(s))throw new Error("Not an encrypted bundle.");let n=await ce(s,t),o=Vn(i)??a.replace(/\/[^/]*$/,""),r=await Yt(c,n,o,e,{dedupeExisting:!0});await c.vault.adapter.remove(a);try{await c.vault.adapter.remove(Ie(a))}catch{}return{notesWritten:r.notesWritten,restoredTo:o}}var bt="_deleted";function RA(c){let a="";for(let t=0;t<c.length;t++)a+=String.fromCharCode(c[t]);return btoa(a)}function LA(c){let a=atob(c),t=new Uint8Array(a.length);for(let e=0;e<a.length;e++)t[e]=a.charCodeAt(e);return t}async function Wn(c,a,t,e){let i=Vn(t?.originalFolder);if(!i&&t?.originalFolderEnc&&e)try{i=Vn(new TextDecoder().decode(await ce(LA(t.originalFolderEnc),e)))}catch{i=null}if(i)return await c.vault.adapter.exists(i)||await c.vault.adapter.mkdir(i),i;let s=a.replace(/\/[^/]*$/,"");if(s===bt||s.startsWith(`${bt}/`))throw new Error("This deleted note's origin folder is unknown (missing or tampered sidecar) \u2014 can't restore it safely. The encrypted copy was kept.");return s}async function Xn(c){let a=[""];for(;a.length;){let t=a.shift(),e;try{e=await c.vault.adapter.list(t||"/")}catch{continue}if(e.files.some(i=>i.endsWith(`.${ge}`)))return!0;for(let i of e.folders)i===".obsidian"||i.endsWith("/.obsidian")||a.push(i)}return!1}async function Ma(c,a,t,e,i,s=!1){let n=await ue(c,a,t);if(!n)throw new Error("Couldn't find that note to delete.");let{rootNote:o,descendants:r,parentId:A}=n,l=[o,...r],d=new Map;for(let Q of l)try{let E=await c.vault.adapter.stat(Q.file.path);E&&d.set(Q.file.path,E.mtime)}catch{}let p=await he(c,{rootNotes:[{id:o.id,file:o.file}],allDescendants:r.map(Q=>({id:Q.id,file:Q.file})),sourceFolder:a}),g=await vi(p,e),h=await ce(g,e);if(h.length!==p.length)throw new Error("Encryption self-check failed (size).");for(let Q=0;Q<p.length;Q++)if(h[Q]!==p[Q])throw new Error("Encryption self-check failed (content).");await c.vault.adapter.exists(bt)||await c.vault.adapter.mkdir(bt);let I=a.replace(/\/+$/,""),u=I.split("/").pop()||"vault",f=Ye(s?t:`${u} ${Cs(o.file)}`),C=`${bt}/${f}.${ge}`;for(let Q=1;await c.vault.adapter.exists(C);Q++)C=`${bt}/${f} (${Q}).${ge}`;await $n(c,C,g);let B=l,m={v:1,kind:"deleted",originalFolder:s?"":I,...s?{originalFolderEnc:RA(await vi(new TextEncoder().encode(I),e))}:{},parentId:A,title:s?"":Cs(o.file),count:B.length,created:o.created,rootId:t,deletedAt:i};try{await c.vault.adapter.write(Ie(C),JSON.stringify(m))}catch(Q){console.warn("[Stashpad] couldn't write deleted sidecar",Q)}let{unpurged:y}=await ba(c,B,d);return{blobPath:C,noteCount:B.length,rootId:t,originalFolder:I,title:m.title,unpurged:y}}async function Ta(c,a,t,e){let i=new Uint8Array(await c.vault.adapter.readBinary(a));if(!Ut(i))throw new Error("Not an encrypted bundle.");let s=await Bs(c,a),n=await Wn(c,a,s,t),o=await ce(i,t),r=await Yt(c,o,n,e,{dedupeExisting:!0});await c.vault.adapter.remove(a);try{await c.vault.adapter.remove(Ie(a))}catch{}return{notesWritten:r.notesWritten,restoredTo:n}}async function Bs(c,a){try{return JSON.parse(await c.vault.adapter.read(Ie(a)))}catch{return null}}var Rt=".trash";async function qA(c,a){let t=[],e=[a];for(;e.length;){let i=e.shift(),s;try{s=await c.vault.adapter.list(i)}catch{continue}t.push(...s.files),e.push(...s.folders)}return t}function JA(c){let a=c.split("/").filter(Boolean);if(a.length===0)return null;for(let t of a)if(t===".."||t==="."||t.includes("\\")||/^[a-zA-Z]:/.test(t))return null;return a.join("/")}async function Ha(c,a,t,e=!1){if(!await c.vault.adapter.exists(Rt))return null;let i=await qA(c,Rt);if(i.length===0)return null;let s=[],n=new Map;for(let h of i){let I=h.slice(Rt.length+1);s.push({name:`files/${I}`,data:await c.vault.adapter.readBinary(h)});try{let u=await c.vault.adapter.stat(h);u&&n.set(h,u.mtime)}catch{}}let o=await xi(s),r=await vi(o,a),A=await ce(r,a);if(A.length!==o.length)throw new Error("Encryption self-check failed (size).");for(let h=0;h<o.length;h++)if(A[h]!==o[h])throw new Error("Encryption self-check failed (content).");await c.vault.adapter.exists(bt)||await c.vault.adapter.mkdir(bt);let l=Ye(e?`trash-${t.replace(/[^0-9]/g,"").slice(0,14)}`:"Obsidian trash backfill"),d=`${bt}/${l}.${ge}`;for(let h=1;await c.vault.adapter.exists(d);h++)d=`${bt}/${l} (${h}).${ge}`;await $n(c,d,r);let p={v:1,kind:"rawtrash",originalFolder:Rt,parentId:null,title:e?"":"Obsidian trash (backfill)",count:i.length,created:t,rootId:"",deletedAt:t};try{await c.vault.adapter.write(Ie(d),JSON.stringify(p))}catch(h){console.warn("[Stashpad] couldn't write backfill sidecar",h)}let g=[];for(let h of i){let I=n.get(h);try{if(I!=null){let u=await c.vault.adapter.stat(h);if(u&&u.mtime!==I){g.push(h);continue}}await c.vault.adapter.remove(h)}catch(u){console.warn("[Stashpad] couldn't delete trash file",h,u),g.push(h)}}return{blobPath:d,fileCount:i.length,unpurged:g}}async function Pa(c,a,t){let e=new Uint8Array(await c.vault.adapter.readBinary(a));if(!Ut(e))throw new Error("Not an encrypted bundle.");let i=await ce(e,t),s=await Mi(i),n=0;for(let[o,r]of Object.entries(s)){if(!o.startsWith("files/"))continue;let A=JA(o.slice(6));if(!A){console.warn("[Stashpad] skipped unsafe trash entry",o);continue}let l=`${Rt}/${A}`.split("/").slice(0,-1).join("/"),d="";for(let g of l.split("/"))d=d?`${d}/${g}`:g,await c.vault.adapter.exists(d)||await c.vault.adapter.mkdir(d);let p=`${Rt}/${A}`;for(let g=1;await c.vault.adapter.exists(p);g++)p=`${Rt}/${A.replace(/(\.[^./]*)?$/,` (${g})$1`)}`;await c.vault.adapter.writeBinary(p,r.buffer),n++}await c.vault.adapter.remove(a);try{await c.vault.adapter.remove(Ie(a))}catch{}return{filesWritten:n}}async function Ua(c){if(!await c.vault.adapter.exists(bt))return[];try{return(await c.vault.adapter.list(bt)).files.filter(t=>t.endsWith(`.${ge}`))}catch{return[]}}var Ti=null,ms=new Set;function Qs(c){if(Ti!==c){Ti=c;for(let a of ms)a()}}function ie(){return Ti}function Ga(c){if(Ti===c){Ti=null;for(let a of ms)a()}}function Ra(c){return ms.add(c),()=>ms.delete(c)}function KA(){return x.Platform.isMacOS?"Finder":x.Platform.isWin?"File Explorer":"file manager"}var ze=[{id:"move",label:"Move (picker)",desc:"Open a fuzzy picker to choose the new parent.",defaultPrimary:"M"},{id:"pickMove",label:"Move (in-list)",desc:"Highlight a note in the list with arrows; Enter sets it as parent.",defaultPrimary:"O"},{id:"merge",label:"Merge",desc:"Concatenate selected notes into the oldest one.",defaultPrimary:"&"},{id:"copy",label:"Copy",desc:"Copy selected note bodies to clipboard.",defaultPrimary:"C"},{id:"copyTree",label:"Copy tree",desc:"Copy the focused note + all descendants, indented.",defaultPrimary:"Y"},{id:"openEditor",label:"Open in editor",desc:"Open the cursor row (or focused note) in a regular Obsidian markdown tab.",defaultPrimary:"E"},{id:"openTab",label:"Open in new Stashpad tab",desc:"Open the cursor row (or focused note) in a new Stashpad tab focused on it.",defaultPrimary:"T"},{id:"split",label:"Split note",desc:"Split the cursor row (or focused note) into two notes at a chosen line.",defaultPrimary:"S"},{id:"copyOutline",label:"Copy as outline",desc:"Copy selection (or cursor row) as a nested ![[embed]] outline.",defaultPrimary:"L"},{id:"toggleSplit",label:"Toggle split-on-newlines",desc:"Default: Mod+/",defaultPrimary:"Mod+/"},{id:"pickDestination",label:"Pick destination",desc:"Default: Mod+D",defaultPrimary:"Mod+D"},{id:"search",label:"Search notes",desc:"Default: Mod+F",defaultPrimary:"Mod+F"},{id:"searchInParent",label:"Search in current parent",desc:"Default: Mod+Alt+F (Mod+Shift+F is taken by Obsidian's global search).",defaultPrimary:"Mod+Alt+F"},{id:"delete",label:"Delete selection",desc:"Default: Mod+Backspace",defaultPrimary:"Mod+Backspace"},{id:"undo",label:"Undo",desc:"Default: Mod+Z (Stashpad-only \u2014 won't fire while typing in the composer).",defaultPrimary:"Mod+Z"},{id:"redo",label:"Redo",desc:"Default: Mod+Shift+Z",defaultPrimary:"Mod+Shift+Z"},{id:"toggleComplete",label:"Toggle complete (strikethrough)",desc:"Default: Mod+Enter or X \u2014 marks selected/focused notes as complete (both chords active).",defaultPrimary:"Mod+Enter",defaultSecondary:"X",defaultUseBoth:!0},{id:"moveUp",label:"Move note up",desc:"Default: Mod+ArrowUp",defaultPrimary:"Mod+ArrowUp"},{id:"moveDown",label:"Move note down",desc:"Default: Mod+ArrowDown",defaultPrimary:"Mod+ArrowDown"},{id:"moveToTop",label:"Move note to top",desc:"Default: Mod+Shift+ArrowUp",defaultPrimary:"Mod+Shift+ArrowUp"},{id:"moveToBottom",label:"Move note to bottom",desc:"Default: Mod+Shift+ArrowDown",defaultPrimary:"Mod+Shift+ArrowDown"},{id:"outdent",label:"Outdent (move to grandparent)",desc:"Default: Mod+[ \u2014 re-parents the selection one level up.",defaultPrimary:"Mod+["},{id:"setColor",label:"Set note color",desc:"Default: Shift+: or ; \u2014 open the color picker for the selection (both chords active).",defaultPrimary:"Shift+:",defaultSecondary:";",defaultUseBoth:!0},{id:"clone",label:"Clone (duplicate / copy) selection",desc:"Default: Mod+Shift+D \u2014 clone selected notes (with their subtrees) as siblings.",defaultPrimary:"Mod+Shift+D"},{id:"forkNote",label:"Fork note (copy under a chosen parent)",desc:"Duplicate the cursor row (with its subtree) as a variant and pick which parent it nests under. No default chord.",defaultPrimary:""},{id:"insertTemplate",label:"Insert template (clone an existing note)",desc:"Pick any note in this Stashpad; clone it (with subtree + attachments) into the current view, retimestamped.",defaultPrimary:""},{id:"toggleExpand",label:"Show more / show less (expand toggle)",desc:"Default: Shift+? \u2014 toggle the clamp on the cursor row (or every selected row).",defaultPrimary:"Shift+?"},{id:"expandAll",label:"Expand all (show every note's full body)",desc:"Un-clamp every note in the current list at once.",defaultPrimary:""},{id:"collapseAll",label:"Collapse all (clamp every note's body)",desc:"Re-clamp every note in the current list at once.",defaultPrimary:""},{id:"exportStash",label:"Export selection to .stash",desc:"Export the selected subtree(s) as a .stash bundle (notes + attachments).",defaultPrimary:""},{id:"importStash",label:"Import .stash file",desc:"Open the .stash bundle picker and import its notes into this Stashpad.",defaultPrimary:""},{id:"pickFolder",label:"Open / switch / create Stashpad folder",desc:"Default: Mod+S \u2014 opens the unified folder picker (reveal, switch, create, convert).",defaultPrimary:"Mod+S"},{id:"cloneStashpadTab",label:"Clone (duplicate / copy) this Stashpad tab",desc:'Open a second tab on the same folder + focus, mirroring the "copy" button in the focused-header actions.',defaultPrimary:""},{id:"selectAll",label:"Select all notes in view",desc:"Default: Mod+A \u2014 adds every visible row to the selection.",defaultPrimary:"Mod+A"},{id:"copyCodeBlock",label:"Copy code from codeblock",desc:"Default: { \u2014 copy the contents of the cursor row's first codeblock (or pick one when multiple exist).",defaultPrimary:"{"},{id:"swapWithParent",label:"Swap with parent (ouroboros)",desc:"Promote the cursor row above its current parent; the parent slides under it (carrying its other children). No default \u2014 bind in this tab.",defaultPrimary:""},{id:"togglePin",label:"Pin / unpin selected note",desc:"Default: P \u2014 toggle the sidebar pin state of the cursor row (or focused note).",defaultPrimary:"P"},{id:"listPin",label:"Pin / unpin to top of list",desc:"Float the cursor row (or selection) to the TOP of its list \u2014 distinct from the sidebar pin. No default chord.",defaultPrimary:""},{id:"toggleTask",label:"Toggle task (todo)",desc:"Default: H \u2014 mark the selection (or cursor row) as a task / todo, or clear it. Tasks appear in the Tasks panel.",defaultPrimary:"H"},{id:"setDue",label:"Set due date\u2026",desc:"Default: D \u2014 open a date+time picker to set (or clear) the due date on the selection. Setting a due date also marks the note as a task.",defaultPrimary:"D"},{id:"jumpToTop",label:"Jump to top of list",desc:"Default: Home \u2014 move the cursor to the first note in the current list.",defaultPrimary:"Home"},{id:"jumpToBottom",label:"Jump to bottom of list",desc:"Default: End \u2014 move the cursor to the last note in the current list.",defaultPrimary:"End"},{id:"commandPalette",label:"Command palette (Stashpad only)",desc:"Default: Mod+K \u2014 open a command palette listing only Stashpad's commands, with Sift search.",defaultPrimary:"Mod+K"},{id:"lockSelection",label:"Encrypt (lock) selection",desc:"Encrypt the selected note(s) + their children into a locked .stashenc bundle in place (prompts to unlock first if needed). No default chord.",defaultPrimary:""},{id:"unlockAll",label:"Decrypt (unlock) locked notes in view",desc:"Decrypt every locked stash shown in the current view back into place, skipping any that can't be read. No default chord.",defaultPrimary:""},{id:"moveToArchive",label:"Move selection to archive (encrypt)",desc:"Move the selected note(s) to the default archive folder, encrypted on arrival. Undoable. No default chord.",defaultPrimary:""},{id:"encryptDelete",label:"Encrypt & delete selection",desc:"Send the selected note(s) to the encrypted trash (recoverable with your password, Ctrl/Cmd+Z undoable). No default chord.",defaultPrimary:""},{id:"copyNotes",label:"Copy notes (note clipboard)",desc:"Copy the selected note(s) as NOTES: paste in the list to duplicate them (new ids), or anywhere else to paste their text. Skipped when text is highlighted (normal copy wins).",defaultPrimary:"Mod+C"},{id:"cutNotes",label:"Cut notes",desc:"Cut the selected note(s): paste in the list to MOVE them, or in the composer to extract their text and delete the originals (undoable).",defaultPrimary:"Mod+X"},{id:"pasteNotes",label:"Paste notes",desc:"Paste previously copied/cut notes at the cursor row (after it, same parent). Does nothing if the note clipboard is empty.",defaultPrimary:"Mod+V"}];function _n(){let c={};for(let a of ze)c[a.id]={primary:a.defaultPrimary,secondary:a.defaultSecondary??"",preferRight:!1,useBoth:!!a.defaultUseBoth};return c}var fe={folder:"Stashpad",importDropFolder:"",exportFolder:"_exports",autoImport:!1,inheritObsidianExclusions:!0,folderPanelPinnedFraction:.5,folderPanelPinned:[],folderPanelDownranked:[],folderPanelHidden:[],folderPanelPinnedGrouping:"pin-order",enablePerfProfiling:!1,writeRecoveryLinks:!0,useTemplatesFormat:!1,prefixTimestampsOnCopy:!0,splitOnLines:!1,splitMode:"lines",confirmCrossParentDrag:!0,confirmBulkDelete:!0,confirmAttachmentDelete:!0,autofocusComposerAfterSend:!0,popoutDuplicates:!0,encryption:ki(),encryptTrash:!1,encryptTrashFilenames:!1,encryptionIdleLockMinutes:0,hideLockedTitles:!1,archiveFolders:[],lockedSubtrees:[],searchOpensInNewTab:!0,pinnedNotes:[],hideMobileToolbarInStashpad:!0,slugStopWords:[],searchIncludedFolders:[],searchExcludedFolders:[],shortcuts:{move:"M",pickMove:"O",merge:"&",copy:"C",copyTree:"Y",openEditor:"E",openTab:"T",split:"S",copyOutline:"L"},mod:{toggleSplit:"Mod+/",pickDestination:"Mod+D",search:"Mod+F",delete:"Mod+Backspace",undo:"Mod+Z",redo:"Mod+Shift+Z",toggleComplete:"Mod+Enter",moveUp:"Mod+ArrowUp",moveDown:"Mod+ArrowDown",moveToTop:"Mod+Shift+ArrowUp",moveToBottom:"Mod+Shift+ArrowDown",outdent:"Mod+[",setColor:"Shift+:"},customPalette:[],colorAliases:{},noteTemplates:{},authorName:"",authorId:"",authorRole:"",authorDepartment:"",showAuthor:!0,showContributors:!0,showLastEdit:!0,viewModes:{},includeAttachmentsInEverything:{},hideChildlessNotes:{},hideCompletedNotes:{},attachmentsOnlyNotes:{},mutedNotificationCategories:[],notificationHistoryLimit:5e3,notifiedDueKeys:[],autoNavOnMoveIn:!1,autoNavOnMoveOut:!1,autoExpandCursorRow:!1,expandBodiesByDefault:!1,autoOpenDetailPanel:!1,doubleClickToFocus:!0,enableSheetVersions:!1,dateDisplayFormat:"locale",dateDisplayTimezone:"",jdIndexScope:"vault",jdIndexScopeFolder:"",jdIndexStashpadFolder:"",jdIndexFile:"Index",jdIndexIncludeStashpadFolders:!1,jdIndexSort:"natural",jdIndexHasBuilt:!1,okfEnabled:!1,okfTemplatePath:"",drafts:{},lastSubmitted:{},bindings:_n()},La=JSON.parse(JSON.stringify(fe)),jn=new Set;function j(){return La}function to(c){La=c;for(let a of jn)a()}function qa(c){return jn.add(c),()=>jn.delete(c)}function ws(c){try{let a=c.internalPlugins?.plugins?.templates;if(!a?.enabled)return null;let t=a.instance?.options??{};return{dateFormat:t.dateFormat||"YYYY-MM-DD",timeFormat:t.timeFormat||"HH:mm"}}catch{return null}}var ys=[{id:"general",label:"General"},{id:"encryption",label:"Encryption"},{id:"diagnostics",label:"Diagnostics"},{id:"authorship",label:"Authorship"},{id:"templates",label:"Templates"},{id:"jdindex",label:"JD Index"},{id:"okf",label:"Open Knowledge Format (OKF)"},{id:"hotkeys",label:"Hotkeys"}],Zn=null;function OA(c,a){return Zn||(Zn=class extends x.SettingPage{constructor(t,e){super(),this.title=t,this._renderFn=e}display(){this.containerEl.empty(),this._renderFn(this.containerEl)}}),new Zn(c,a)}var Es=class extends x.PluginSettingTab{constructor(t,e){super(t,e);this.plugin=e}display(){if(x.SettingPage){super.display();return}let{containerEl:t}=this;t.empty();for(let e of ys){new x.Setting(t).setName(e.label).setHeading();let i=this.itemsForTab(e.id);if(i)for(let s of i){let n=new x.Setting(t);typeof s.render=="function"?s.render(n):(s.name&&n.setName(s.name),s.desc&&n.setDesc(s.desc))}else this.renderTabContent(t,e.id)}}getSettingDefinitions(){return ys.map(t=>{let e=this.itemsForTab(t.id);return e?{type:"page",name:t.label,items:e}:{type:"page",name:t.label,page:()=>OA(t.label,i=>this.renderTabContent(i,t.id))}})}itemsForTab(t){switch(t){case"hotkeys":return this.hotkeyItems();case"diagnostics":return this.diagnosticsItems();case"general":return this.generalItems();case"encryption":return this.encryptionItems();case"authorship":return this.authorshipItems();case"templates":return this.templatesItems();case"jdindex":return this.jdIndexItems();case"okf":return this.okfItems();default:return null}}renderTabContent(t,e){switch(e){case"authorship":this.renderAuthorshipSection(t);break;case"templates":this.renderTemplatesTab(t);break;case"jdindex":this.renderJdIndexSection(t);break}}diagnosticsItems(){let t=new Set(this.plugin.settings.mutedNotificationCategories??[]),e=Object.keys(In);return[this.renderDef("Write recovery navigation links","Maintain the redundant parentLink/children frontmatter so you can walk the hierarchy from raw Markdown if the index ever breaks. On a slow / network drive this is a big per-move cost (several round-trips each); turn it off there for snappier moves \u2014 Rebootstrap rebuilds the fields on demand, and your notes' canonical structure (id/parent) is unaffected either way.",i=>i.addToggle(s=>s.setValue(this.plugin.settings.writeRecoveryLinks).onChange(async n=>{this.plugin.settings.writeRecoveryLinks=n,await this.plugin.saveSettings()})),["recovery","parentlink","children","frontmatter"]),this.renderDef("Performance profiling","Record timing for list rendering, body reads, and file writes. Turn on, use Stashpad normally (especially the slow operations), then run \u201CDump performance profile\u201D from the command palette and share the result. Off = zero overhead.",i=>i.addToggle(s=>s.setValue(this.plugin.settings.enablePerfProfiling).onChange(async n=>{this.plugin.settings.enablePerfProfiling=n,await this.plugin.saveSettings()})),["perf","profiling","timing","slow"]),this.renderDef("Open log file","Append-only history of creates, deletes, parent changes, renames. Stored alongside the plugin's other private files.",i=>i.addButton(s=>s.setButtonText("Open log").onClick(async()=>{let n=this.app.vault.adapter,o=this.plugin.pluginPrivatePath("log.jsonl");if(!await n.exists(o)){new x.Notice("No log yet \u2014 make some changes first.");return}let r=await n.read(o);new Pe(this.app,r,o).open()})),["log","history","diagnostics"]),this.renderDef("Notification history limit","Maximum number of notifications kept in the persistent history. Set to 0 for unlimited (the file size grows with usage; expect a few hundred KB per ~5000 entries). Default: 5000.",i=>i.addText(s=>s.setValue(String(this.plugin.settings.notificationHistoryLimit??5e3)).setPlaceholder("5000").onChange(async n=>{let o=parseInt(n,10);Number.isFinite(o)&&(this.plugin.settings.notificationHistoryLimit=o,this.plugin.notifications.setHistoryLimit(o),await this.plugin.saveSettings())})),["notification","history","limit"]),{type:"group",heading:"Mute notification categories",items:e.map(i=>{let s=In[i];return this.renderDef(s.label,s.desc,n=>n.addToggle(o=>o.setValue(!t.has(i)).onChange(async r=>{let A=!r;A?t.add(i):t.delete(i),this.plugin.settings.mutedNotificationCategories=Array.from(t),this.plugin.notifications.setMuted(i,A),await this.plugin.saveSettings()})),["notification","mute","toast","category"])})},this.renderDef("Notification history","Browse the last 200 toasts. Filter by category. Live-updates as new notifications arrive. Muted categories still appear here so you can review what was suppressed.",i=>i.addButton(s=>s.setButtonText("View notification history").onClick(()=>{new gi(this.app,this.plugin.notifications,async n=>{let o=this.app.vault.adapter,r=this.plugin.pluginPrivatePath("log.jsonl");if(!await o.exists(r)){new x.Notice("No log yet \u2014 make some changes first.");return}let A=await o.read(r);new Pe(this.app,A,r).open()},this.plugin.settings.authorId||null,n=>this.plugin.lookupNoteAuthorIds(n)).open()})),["notification","history","panel"])]}renderTemplatesTab(t){this.renderColorAliasesSection(t),this.renderNoteTemplatesSection(t)}renderDef(t,e,i,s){return{name:t,desc:e,aliases:s,render:n=>{n.setName(t).setDesc(e),i(n)}}}sectionDef(t,e,i,s){return{name:t,desc:e,aliases:s,render:n=>{let o=n.settingEl;o.empty(),o.removeClass("setting-item"),o.addClass("stashpad-settings-section"),i(o)}}}generalItems(){let t=async()=>this.plugin.saveSettings(),e=(s,n,o,r,A)=>this.renderDef(s,n,l=>l.addToggle(d=>d.setValue(o()).onChange(async p=>{r(p),await t()})),A),i=[];i.push(this.renderDef("Stashpad notes folder","Vault-relative folder where Stashpad stores its notes and attachments. Created on demand.",s=>{s.addText(n=>{new qe(this.app,n.inputEl),n.setValue(this.plugin.settings.folder).setPlaceholder("Stashpad").onChange(async o=>{let r=(o||"").trim().replace(/^\/+|\/+$/g,"")||fe.folder,A=r.split("/").filter(Boolean).pop()??"";if(new Set([this.plugin.settings.importDropFolder,this.plugin.settings.exportFolder,"_attachments","_processed"].map(d=>(d??"").trim().replace(/^\/+|\/+$/g,"")).filter(Boolean)).has(A)){new x.Notice(`"${r}" uses a reserved Stashpad subfolder name. Pick something else.`);return}this.plugin.settings.folder=r,await t()})})},["folder","path","location","notes"])),i.push(e("Auto-import dropped files","When on, any file you drop directly into a Stashpad folder is imported automatically: markdown becomes a note (the original is archived to .archive); other files move to _attachments with a note that links to them. Large drops ask for confirmation first.",()=>this.plugin.settings.autoImport,s=>{this.plugin.settings.autoImport=s},["import","drop","auto"])),i.push(e("Inherit Obsidian's excluded files","Also hide files matching Obsidian's \u201CExcluded files\u201D list (Settings \u2192 Files & Links) from Stashpad's link autocomplete and file surfaces \u2014 so you manage exclusions in one place. Plugin-internal formats like .edtz are always excluded regardless.",()=>this.plugin.settings.inheritObsidianExclusions,s=>{this.plugin.settings.inheritObsidianExclusions=s},["excluded","ignore","files"])),i.push(this.renderDef("Dedicated import subfolder (optional)","Optional. A subfolder (relative to each Stashpad folder) where dropped .stash files auto-import. Leave blank to just drop files into the Stashpad folder itself (recommended). Suggested name: _imports.",s=>s.addText(n=>n.setValue(this.plugin.settings.importDropFolder).setPlaceholder("_imports (leave blank to use the folder root)").onChange(async o=>{this.plugin.settings.importDropFolder=(o||"").trim().replace(/^\/+|\/+$/g,""),await t()})),["import","subfolder"])),i.push(this.renderDef("Stash export subfolder","Subfolder name (relative to each Stashpad folder) where exports land. Must differ from the import subfolder above.",s=>s.addText(n=>n.setValue(this.plugin.settings.exportFolder).setPlaceholder("_exports").onChange(async o=>{this.plugin.settings.exportFolder=(o||"").trim().replace(/^\/+|\/+$/g,"")||fe.exportFolder,await t()})),["export","stash","subfolder"])),i.push(this.renderDef("Rebootstrap existing Stashpad folders","Walk every folder that has a home note: ensure infrastructure (_imports, _exports, drafts file), backfill the redundant parentLink + children frontmatter fields, AND rename any note whose filename slug no longer matches its body's first line. Safe to run anytime; skip-if-equal means already-synced notes are no-op writes.",s=>s.addButton(n=>n.setButtonText("Rebootstrap now").onClick(async()=>{n.setDisabled(!0).setButtonText("Working\u2026");try{let{touched:o,fmChecked:r,fmWritten:A,slugsRenamed:l,authors:d,imported:p,attachmentsLinked:g}=await this.plugin.rebootstrapAllFolders(),h=[];h.push(`rebootstrapped ${o.length} folder${o.length===1?"":"s"}`),p>0&&h.push(`imported ${p} loose file${p===1?"":"s"}`),g>0&&h.push(`linked attachments on ${g} note${g===1?"":"s"}`),A>0?h.push(`updated frontmatter on ${A} of ${r} notes`):r>0&&h.push(`frontmatter already in sync (${r} notes checked)`),l>0&&h.push(`renamed ${l} note${l===1?"":"s"} to match body`),d>0&&h.push(`rebuilt author registry (${d} author${d===1?"":"s"})`),new x.Notice(`Stashpad: ${h.join("; ")}.`)}catch(o){new x.Notice(`Stashpad: rebootstrap failed (${o.message})`)}finally{n.setDisabled(!1).setButtonText("Rebootstrap now")}})),["rebootstrap","rebuild","repair","backfill","slug"])),i.push(this.renderDef("Use Templates plugin date/time formats","When on, timestamps use the formats configured in the core Templates plugin. Off: YYYY.MM.DD + HH:mm A.",s=>{s.addToggle(o=>o.setValue(this.plugin.settings.useTemplatesFormat).onChange(async r=>{this.plugin.settings.useTemplatesFormat=r,await t()}));let n=ws(this.app);s.descEl.createDiv({cls:"stashpad-settings-note"}).setText(n?`Templates plugin: date = "${n.dateFormat}", time = "${n.timeFormat}"`:"Templates plugin not enabled.")},["templates","date","time","format"]));{let s=null,n=()=>{s&&s.setText(`Sample: ${$t(Date.now(),this.plugin.settings)}`)};i.push(this.renderDef("Date display format","How due dates and created/modified times are shown in the Tasks and detail panels.",o=>{o.addDropdown(r=>{r.addOption("locale","Locale, short (Mar 5, 9:00 AM)"),r.addOption("long","Locale, long (Thursday, March 5\u2026)"),r.addOption("iso","ISO (2026-03-05 09:00)"),r.addOption("us","US (3/5/2026, 9:00 AM)"),r.addOption("eu","EU (5/3/2026, 09:00)"),r.setValue(this.plugin.settings.dateDisplayFormat??"locale"),r.onChange(async A=>{this.plugin.settings.dateDisplayFormat=A,await t(),n()})})},["date","format","display"])),i.push(this.renderDef("Display timezone","IANA timezone name (e.g. America/New_York, Europe/London, Asia/Kolkata). Leave blank to use your system timezone.",o=>{o.addText(r=>{r.setPlaceholder("(system timezone)"),r.setValue(this.plugin.settings.dateDisplayTimezone??""),r.onChange(async A=>{this.plugin.settings.dateDisplayTimezone=(A||"").trim(),await t(),n()})})},["timezone","tz","date","iana"])),i.push({name:"Date sample",searchable:!1,render:o=>{let r=o.settingEl;r.empty(),r.removeClass("setting-item"),s=r.createDiv({cls:"setting-item-description stashpad-settings-note"}),n()}})}return i.push(e("Navigate into parent after moving a note IN","When you move a note onto another note via the in-list move picker (drag-onto-sibling), automatically drill into the new parent so you can see the moved note in its new home. Off = stay focused where you were.",()=>this.plugin.settings.autoNavOnMoveIn,s=>{this.plugin.settings.autoNavOnMoveIn=s},["navigate","move","in"])),i.push(e("Navigate to destination after moving a note OUT","When you outdent a note, move it via the cross-parent picker, or send it to Home, automatically drill into the destination parent. Off = stay focused where you were.",()=>this.plugin.settings.autoNavOnMoveOut,s=>{this.plugin.settings.autoNavOnMoveOut=s},["navigate","move","out"])),i.push(e("Double-click a note to open it","Double-click (or double-tap on mobile) a note in the list to focus/open it \u2014 the same as pressing \u2192 or clicking the enter arrow. Single click still just selects. On by default.",()=>this.plugin.settings.doubleClickToFocus,s=>{this.plugin.settings.doubleClickToFocus=s},["double","click","open","focus"])),i.push(e("Sheet versions (alternate drafts)",`Treat notes that share a 'sheet-group' frontmatter id as alternate versions of one item: only the active version shows as a row, and its siblings collapse into a tab bar at the bottom of that row. Use "Fork as version" on a note to start. Off by default \u2014 when off, no note is ever hidden by this feature and the commands do nothing.`,()=>this.plugin.settings.enableSheetVersions,s=>{this.plugin.settings.enableSheetVersions=s},["sheet","version","draft","alternate","fork"])),i.push(e("Auto-open the detail panel","Open the right-sidebar Stashpad detail panel automatically whenever a Stashpad view becomes active. The panel shows the cursored note's body, metadata, and children. Off = open manually via ribbon or command palette.",()=>this.plugin.settings.autoOpenDetailPanel,s=>{this.plugin.settings.autoOpenDetailPanel=s},["detail","panel","sidebar"])),i.push(e("Expand the cursor row's body automatically","As you arrow-key through the list, the row under the cursor temporarily un-clamps to show its full body. Moving away re-collapses it. Doesn't affect the persistent 'Show more' state \u2014 this is a transient view-only effect.",()=>this.plugin.settings.autoExpandCursorRow,s=>{this.plugin.settings.autoExpandCursorRow=s},["expand","cursor","body"])),i.push(e("Expand note bodies by default","Show every note's full body by default instead of clamping long notes. The per-note 'Show more / show less' toggle and the Expand-all / Collapse-all commands then work in reverse \u2014 they let you collapse individual notes back down. Off = bodies clamp by default (expand is opt-in).",()=>this.plugin.settings.expandBodiesByDefault,s=>{this.plugin.settings.expandBodiesByDefault=s},["expand","collapse","default","body","clamp"])),i.push(e("Confirm cross-parent drag-and-drop","When dragging notes onto a note that has a different parent, ask before re-parenting (turn off to allow direct moves).",()=>this.plugin.settings.confirmCrossParentDrag,s=>{this.plugin.settings.confirmCrossParentDrag=s},["confirm","drag","drop","reparent"])),i.push(e("Confirm bulk deletes","Warn before deletes that affect more than one note \u2014 multi-selection delete OR deleting a note that has descendants. A single childless note with no attachments never prompts. Off = those deletes apply immediately (undo still recovers everything).",()=>this.plugin.settings.confirmBulkDelete,s=>{this.plugin.settings.confirmBulkDelete=s},["confirm","delete","bulk"])),i.push(e("Offer to delete attachments with note",`When a note references attachments, the delete modal includes an "Also delete attachments" checkbox so orphaned files don't pile up in your vault. Attachments are detected from both ![[\u2026]] embeds in the body and the frontmatter attachments: list. Off = attachments are always preserved on delete (no checkbox shown), and a single childless note with attachments deletes silently.`,()=>this.plugin.settings.confirmAttachmentDelete,s=>{this.plugin.settings.confirmAttachmentDelete=s},["delete","attachment","orphan"])),i.push(this.renderDef("Slug stop-words","Words removed from auto-generated note titles (filenames). One per line.",s=>{let n=null,o=(this.plugin.settings.slugStopWords?.length?this.plugin.settings.slugStopWords:Jt).join(` +`);s.addTextArea(r=>{r.setValue(o),n=r.inputEl,n.rows=6,n.setCssStyles({fontFamily:"var(--font-monospace)"}),r.onChange(async A=>{this.plugin.settings.slugStopWords=(A||"").split(/\r?\n/).map(l=>l.trim().toLowerCase()).filter(Boolean),await t()})}).addExtraButton(r=>r.setIcon("rotate-ccw").setTooltip("Reset to defaults").onClick(async()=>{this.plugin.settings.slugStopWords=[...Jt],n&&(n.value=Jt.join(` +`)),await t()}))},["slug","stopwords","filename","title"])),i.push(this.sectionDef("Cross-Stashpad search scope","Toggle each Stashpad's pill to choose whether its notes contribute to cross-folder search. Excluded folders are still valid move destinations. Also: create a new Stashpad.",s=>{let n=this.plugin.discoverStashpadFolders();if(new x.Setting(s).setName("Cross-Stashpad search scope").setDesc("Toggle each Stashpad's pill to choose whether its notes contribute to cross-folder search. Excluded folders are still valid move destinations \u2014 their notes just don't appear in search results from elsewhere."),n.length===0)s.createEl("p",{cls:"setting-item-description"}).setText('No Stashpads found in this vault yet. A Stashpad is just a folder that contains a Stashpad-shaped note (frontmatter has both `id` and `parent`). Easiest way: open Stashpad (ribbon icon or command "Reveal or open Stashpad") \u2014 it auto-creates the default folder on first use. Or create one below.');else{let r=s.createDiv({cls:"stashpad-folder-list"});for(let A of n)this.renderFolderScopeRow(r,A)}let o=null;new x.Setting(s).setName("Create a new Stashpad").setDesc("Type a vault-relative folder path. The folder is created (with intermediates) and seeded with a Home note so Stashpad recognizes it.").addText(r=>{r.setPlaceholder("my-stashpad"),o=r.inputEl}).addButton(r=>r.setButtonText("Create").setCta().onClick(async()=>{let A=(o?.value??"").trim().replace(/^\/+|\/+$/g,"");if(!A){new x.Notice("Enter a folder name first.");return}try{await this.plugin.createNewStashpad(A),new x.Notice(`Created Stashpad "${A}".`),o&&(o.value=""),await this.plugin.waitForStashpadFolder(A,2e3),this.update?.()}catch(l){new x.Notice(`Couldn't create: ${l.message}`)}}))},["search","scope","exclude","include","create","new","stashpad","folder"])),i.push(this.sectionDef("Folder panel placement","Pin, downrank, or hide folders in the Stashpad folder panel. Restore hidden folders here or from the panel's \u201CHidden\u201D section.",s=>{new x.Setting(s).setName("Folder panel placement").setDesc("Folders you've pinned, downranked, or hidden in the Stashpad folder panel. Pin/downrank from a folder's right-click menu in the panel; restore here or from the panel's \u201CHidden\u201D section."),this.renderFolderPlacementList(s)},["folder","panel","pin","pinned","downrank","hide","hidden","restore","placement"])),i.push(e("Autofocus composer after sending","After Enter-submitting a note, return focus to the composer so you can keep typing. Off keeps focus in the list \u2014 useful if you want arrow keys to work without an extra click.",()=>this.plugin.settings.autofocusComposerAfterSend,s=>{this.plugin.settings.autofocusComposerAfterSend=s},["composer","focus","send"])),i.push(e("Open in new window \u2014 duplicate tab","ON: the new-window button (in the time-filter row) duplicates the current Stashpad tab \u2014 original stays open in the main window. OFF: the leaf is MOVED to the new window, closing the original tab.",()=>this.plugin.settings.popoutDuplicates,s=>{this.plugin.settings.popoutDuplicates=s},["popout","window","duplicate"])),i.push(e("Search results open in a new tab","When you pick a result in the Search modal, open it in a new Stashpad tab instead of navigating the current tab. Applies to same-folder and cross-Stashpad results alike. On by default.",()=>this.plugin.settings.searchOpensInNewTab,s=>{this.plugin.settings.searchOpensInNewTab=s},["search","new tab","results","open"])),i.push(e("Prefix timestamps when copying","Include each note's timestamp before its body when copying with C or Y.",()=>this.plugin.settings.prefixTimestampsOnCopy,s=>{this.plugin.settings.prefixTimestampsOnCopy=s},["copy","timestamp","prefix"])),i}encryptionItems(){let t=this.plugin.encryption,e=[];return e.push(this.sectionDef("Vault encryption","Set one password to encrypt content in this vault. Stored only on this device \u2014 there is no recovery if you lose it.",i=>{i.addClass("stashpad-encryption-section");let s=i.createDiv({cls:"stashpad-beta-row"});s.createEl("span",{cls:"stashpad-beta-badge",text:"BETA"}),s.createEl("span",{cls:"stashpad-beta-note",text:"Encryption is in beta \u2014 keep your own backups of anything important."}),i.createEl("div",{cls:"stashpad-ai-disclaimer"}).setText("\u26A0\uFE0F AI-built, NOT human-audited. This encryption was written by an AI assistant \u2014 not designed, reviewed, or security-audited by a human, and not tested by any security professional. It may carry real security, privacy, and DATA-LOSS risks. Treat it as a best-effort nice-to-have that might buy a little time against a casual snoop \u2014 nothing is guaranteed. Do NOT rely on it for anything sensitive, and always keep your own unencrypted backups of anything important."),i.createEl("p",{cls:"setting-item-description"}).setText("\u26A0\uFE0F Encryption protects what you lock in this vault. Each device unlocks with its own password (which never leaves the device); the vault key is shared with collaborators by approving their device \u2014 no shared password. If everyone with access loses their password, anything encrypted is gone for good. While encrypting, avoid a sync/cloud service writing the vault mid-operation \u2014 it can corrupt files.");let n=()=>t.argonProbe(),o=()=>this.plugin.settings.authorName?.trim()||"This device",r=t.accessState();t.refresh().then(()=>{t.accessState()!==r&&this.update?.()});let A=r;if(A==="none"){new x.Setting(i).setName("Encryption").setDesc("Not set up yet in this vault.").addButton(g=>g.setButtonText("Set up password\u2026").setCta().onClick(()=>{new vt(this.app,{mode:"setup",offerKeychain:!0,kdfProbe:n,onSubmit:async({next:h,remember:I})=>{if(!h)return"Enter a password.";try{await t.setup(h,I,o())}catch(u){return u.message}return new x.Notice("Encryption set up \u2014 unlocked for this session."),this.update?.(),null}}).open()}));return}if(A==="outsider"&&!t.isUnlocked()){t.hasSharedPassword()&&new x.Setting(i).setName("This vault is encrypted").setDesc("Enter the shared password (ask whoever set it up \u2014 they'll send it via a password manager or secure message).").addButton(g=>g.setButtonText("Unlock with shared password\u2026").setCta().onClick(()=>{new vt(this.app,{mode:"unlock",offerKeychain:!0,onSubmit:async({current:h,remember:I})=>await t.unlock(h,I)?(new x.Notice("Encryption unlocked."),this.update?.(),null):"Wrong password (or the keyfile hasn't synced here yet)."}).open()})),new x.Setting(i).setName(t.hasSharedPassword()?"Or request device approval":"This vault is encrypted by a collaborator").setDesc("Request access \u2014 pick a password for THIS device, then ask an existing member to approve it. Once approved (and the keyfile syncs to you), you'll unlock with that password. No shared secret.").addButton(g=>g.setButtonText("Request access\u2026").onClick(()=>{new vt(this.app,{mode:"setup",offerKeychain:!0,kdfProbe:n,onSubmit:async({next:h,remember:I})=>{if(!h)return"Choose a password for this device.";try{await t.requestAccess(o(),h,I)}catch(u){return u.message}return new x.Notice("Access requested. An existing member can now approve this device."),this.update?.(),null}}).open()}));return}if(A==="pending"){new x.Setting(i).setName("Access requested \u2014 waiting for approval").setDesc("An existing member needs to approve this device. After they do and the keyfile syncs here, reopen this page to unlock with the password you chose.").addButton(g=>g.setButtonText("Try unlock now").setCta().onClick(()=>{new vt(this.app,{mode:"unlock",offerKeychain:!0,onSubmit:async({current:h,remember:I})=>await t.unlock(h,I)?(new x.Notice("Encryption unlocked."),this.update?.(),null):"Not approved yet (or wrong password). Ask a member to approve this device, then try again."}).open()})).addButton(g=>g.setButtonText("Cancel request").onClick(async()=>{let h=t.myIdentityId();h&&await t.denyJoinRequest(h),new x.Notice("Access request cancelled."),this.update?.()}));return}let l=t.kdf()==="argon2id"?"Argon2id":t.kdf()==="pbkdf2"?"PBKDF2 (fallback)":"",d=t.isRemembered()?" \xB7 remembered on this device":"";if(new x.Setting(i).setName("Status").setDesc(`${t.isUnlocked()?"Set up \xB7 unlocked this session":"Set up \xB7 locked"}${l?` \xB7 ${l}`:""}${d}`),t.isUnlocked()?new x.Setting(i).setName("Lock now").setDesc("Forget the password from memory until you re-enter it.").addButton(g=>g.setButtonText("Lock now").onClick(()=>{t.lock(),new x.Notice("Encryption locked."),this.update?.()})):new x.Setting(i).setName("Unlock").setDesc("Enter your password to use encryption this session.").addButton(g=>g.setButtonText("Unlock\u2026").setCta().onClick(()=>{new vt(this.app,{mode:"unlock",offerKeychain:!0,onSubmit:async({current:h,remember:I})=>await t.unlock(h,I)?(new x.Notice("Encryption unlocked."),this.update?.(),null):"Wrong password. Try again."}).open()})),t.keychainAvailable()&&t.isRemembered()&&new x.Setting(i).setName("Forget password on this device").setDesc("Drops ONLY the copy saved in this device's keychain \u2014 your encryption stays set up and nothing is decrypted or deleted. You'll just re-type the password next session. (To turn encryption off entirely, use \u201CRemove encryption\u201D below.)").addButton(g=>g.setButtonText("Forget on this device").onClick(async()=>{await t.forgetKeychain(),new x.Notice("Removed from this device's keychain \u2014 encryption still set up."),this.update?.()})),t.amIMember()&&new x.Setting(i).setName("Change this device's password").setDesc("Re-wraps THIS device's key under a new password \u2014 doesn't re-encrypt files or affect other people.").addButton(g=>g.setButtonText("Change\u2026").onClick(()=>{new vt(this.app,{mode:"change",offerKeychain:!0,kdfProbe:n,onSubmit:async({current:h,next:I,remember:u})=>await t.changePassword(h,I,u)?(new x.Notice("Password changed."),this.update?.(),null):"Wrong current password. Try again."}).open()})),t.amIMember()&&new x.Setting(i).setName("Remove encryption").setDesc("Erases the key from this vault. Refused while any locked notes exist \u2014 decrypt everything first (locked notes have NO plaintext copy; losing the key loses them forever).").addButton(g=>{g.setButtonText("Remove\u2026").onClick(async()=>{if(await Xn(this.app)){new x.Notice(`Can't remove encryption: locked/encrypted-deleted notes still exist and would be lost forever. Run "Decrypt (unlock) ALL locked notes in the vault" and empty the encrypted trash first.`,1e4);return}new pi(this.app,{title:"Remove encryption?",body:"This erases the encryption key for this vault. Nothing is currently encrypted (locked notes are checked), so no content is lost \u2014 but you'll need to set a new password to encrypt later, and anything you had exported encrypted with this key stays locked to its passphrase.",phrase:"REMOVE ENCRYPTION",confirmText:"Remove encryption",requirePassword:h=>t.verifyPassword(h),onConfirm:async()=>{if(await Xn(this.app)){new x.Notice("Locked notes appeared while this dialog was open \u2014 removal cancelled. Decrypt everything first.",1e4);return}await t.clear(),new x.Notice("Encryption removed."),this.update?.()}}).open()}),g.setDestructive()}),new x.Setting(i).setName("Sharing").setHeading(),t.isUnlocked()?t.hasSharedPassword()?new x.Setting(i).setName("Shared password").setDesc("ON \u2014 anyone who knows it can unlock this vault (no approval). Share it via a password manager or secure message; don't send it in the clear.").addButton(g=>g.setButtonText("Change\u2026").onClick(()=>{new vt(this.app,{mode:"setup",offerKeychain:!1,kdfProbe:n,title:"Change shared password",intro:"Everyone who unlocks with the shared password will need the new one. Re-share it securely after changing.",onSubmit:async({next:h})=>{if(!h)return"Enter a password.";try{await t.setSharedPassword(h)}catch(I){return I.message}return new x.Notice("Shared password updated."),this.update?.(),null}}).open()})).addButton(g=>{g.setButtonText("Turn off").onClick(async()=>{await t.removeSharedPassword(),new x.Notice("Shared password turned off."),this.update?.()}),g.setDestructive()}):new x.Setting(i).setName("Shared password").setDesc("OFF \u2014 set one passphrase that everyone types to unlock (the simplest way to share). Anyone who knows it can unlock; turning it off later doesn't claw back copies already synced elsewhere.").addButton(g=>g.setButtonText("Set shared password\u2026").onClick(()=>{new vt(this.app,{mode:"setup",offerKeychain:!1,kdfProbe:n,title:"Set shared password",intro:"One passphrase everyone types to unlock this vault. Anyone who knows it gets in \u2014 share it ONLY through a password manager or secure message, never in the clear. You can turn it off later.",onSubmit:async({next:h})=>{if(!h)return"Enter a password.";try{await t.setSharedPassword(h)}catch(I){return I.message}return new x.Notice("Shared password set \u2014 share it securely with your collaborators."),this.update?.(),null}}).open()})):i.createEl("p",{cls:"setting-item-description"}).setText("Unlock encryption above to manage how this vault is shared."),new x.Setting(i).setName("Collaborators (device approval)").setHeading(),i.createEl("p",{cls:"setting-item-description"}).setText("Everyone who can unlock this vault, and devices waiting for access. Approving a request shares the vault key with that device \u2014 it never sees a password. Removing a member revokes future access (existing synced copies they already hold aren't clawed back \u2014 rotate the key for that, a future feature)."),new x.Setting(i).setName("Synced from the vault keyfile").addButton(g=>g.setButtonText("Refresh").onClick(async()=>{await t.refresh(),this.update?.()})),!t.isUnlocked())i.createEl("p",{cls:"setting-item-description"}).setText("Unlock encryption above to approve or remove collaborators.");else{let g=t.myIdentityId();for(let I of t.members()){let u=I.id===g,f=new x.Setting(i).setName(`${I.label}${u?" \u2014 this device":""}`).setDesc(u?"You":"Member");u||f.addButton(C=>{C.setButtonText("Remove").onClick(async()=>{await t.removeMember(I.id),new x.Notice(`Removed ${I.label}. (Not full revocation without rotating the key.)`),this.update?.()}),C.setDestructive()})}let h=t.pendingJoinRequests();if(h.length===0)i.createEl("p",{cls:"setting-item-description"}).setText("No pending access requests.");else for(let I of h)new x.Setting(i).setName(I.label).setDesc("Wants access to this vault").addButton(u=>u.setButtonText("Approve").setCta().onClick(async()=>{try{await t.approveJoinRequest(I.id)}catch(f){new x.Notice(f.message);return}new x.Notice(`Approved ${I.label} \u2014 they can unlock once the keyfile syncs to them.`),this.update?.()})).addButton(u=>u.setButtonText("Deny").onClick(async()=>{await t.denyJoinRequest(I.id),new x.Notice("Request denied."),this.update?.()}))}},["encryption","encrypt","password","passphrase","lock","unlock","key","security","private","collaborator","share","team","member","approve"])),e.push(this.renderDef("Encrypt items sent to trash","When ON, deleting a note sends it to Stashpad's encrypted trash (recoverable with your password) instead of a plaintext trash. Default OFF.",i=>i.addToggle(s=>s.setValue(this.plugin.settings.encryptTrash).onChange(async n=>{this.plugin.settings.encryptTrash=n,await this.plugin.saveSettings()})),["trash","delete","encrypt"])),e.push(this.renderDef("Encrypt trash filenames","Hide the filename + origin folder of encrypted-trashed items (opaque names on disk; shown under \u201CHidden\u201D in the trash tab). Default OFF so you can still tell what to restore when working outside the app.",i=>i.addToggle(s=>s.setValue(this.plugin.settings.encryptTrashFilenames).onChange(async n=>{this.plugin.settings.encryptTrashFilenames=n,await this.plugin.saveSettings()})),["trash","filename","encrypt"])),e.push(this.renderDef("Follow Obsidian's trash setting instead","OFF (recommended): encrypted-deleted notes go to Stashpad's own \u201C_deleted/\u201D store \u2014 the only trash location Stashpad fully controls, so it can encrypt, list, and restore them. ON: deletes follow Obsidian's \u201CDeleted files\u201D setting instead (system/OS trash or permanent). \u26A0\uFE0F Stashpad CANNOT encrypt or recover notes that go to the system trash \u2014 so the encrypted trash + recoverable trash view won't apply. Only turn this on if you specifically want Obsidian's native trash behavior.",i=>i.addToggle(s=>s.setValue(this.plugin.settings.encryptTrashFollowObsidian??!1).onChange(async n=>{this.plugin.settings.encryptTrashFollowObsidian=n||void 0,await this.plugin.saveSettings()})),["trash","obsidian","system","delete","encrypt"])),e.push(this.renderDef("Auto-lock after idle minutes","Forget the password from memory after this many idle minutes (0 = never). Re-prompts on the next encryption action.",i=>i.addText(s=>s.setValue(String(this.plugin.settings.encryptionIdleLockMinutes??0)).onChange(async n=>{let o=Math.max(0,Math.floor(Number(n)||0));this.plugin.settings.encryptionIdleLockMinutes=o,await this.plugin.saveSettings()})),["auto-lock","idle","timeout","lock"])),e.push(this.renderDef("Hide titles of locked notes","Show a generic label on \u{1F512} locked placeholders instead of the note's title, so a glance at the vault doesn't reveal what's locked. Default OFF.",i=>i.addToggle(s=>s.setValue(this.plugin.settings.hideLockedTitles??!1).onChange(async n=>{this.plugin.settings.hideLockedTitles=n,await this.plugin.saveSettings(),this.plugin.refreshAllStashpadViews?.()})),["title","hide","private","lock","placeholder","visibility"])),e.push(this.renderDef("Default archive folder",`Where the "Move selection to archive" command sends notes (they're auto-encrypted on arrival). Leaving this blank is fine \u2014 the command will just show you a list of your archive folders to pick from each time (or use the only one if you have a single archive). Mark a folder as an archive via the folder panel \u2192 right-click \u2192 "Mark as archive".`,i=>{let s=this.plugin.settings.archiveFolders??[];i.addDropdown(n=>{n.addOption("",s.length?"\u2014 pick from list each time \u2014":"\u2014 no archive folders yet \u2014");for(let r of s)n.addOption(r,r);let o=this.plugin.settings.defaultArchiveFolder??"";n.setValue(s.includes(o)?o:""),n.onChange(async r=>{this.plugin.settings.defaultArchiveFolder=r||void 0,await this.plugin.saveSettings()})})},["archive","default","move","encrypt","folder"])),e}hotkeyItems(){let t={name:"Hotkeys",desc:"Each command has up to two slots. Click a slot and press a key (or chord) to bind it; press Backspace (delete on Mac) to cancel without binding; or click \u2715 to clear an existing binding. A \u21BA icon appears on any slot that differs from its shipped default \u2014 click it to revert that slot. When both slots are set, the pill on the right decides which one is active.",searchable:!1},e=ze.map(i=>({name:i.label,desc:i.desc,aliases:["hotkey","shortcut","keybind","binding","key"],render:s=>this.renderBindingRow(s,i)}));return[t,...e]}renderJdIndexSection(t){let e=new x.Setting(t).setName("JD Index Builder").setHeading();e.settingEl.id="stashpad-jd-index-section";let i=t.createEl("p",{cls:"setting-item-description"});i.innerHTML="Builds a Johnny-Decimal-style index inside a designated Stashpad folder. Two commands:<br/><strong>Preview</strong> overwrites the designated folder’s HOME note body with the would-be hierarchy + everything that didn’t match. Frontmatter is preserved; everything below it is replaced.<br/><strong>Build</strong> creates an actual hierarchy of Stashpad notes (one per prefix), with child\u2192parent relationships matching the dotted segments.<br/>Matches strict prefixes only: all-digits (<code>10 Life</code>) or alphanumeric-with-dots (<code>1.2 Family</code>, <code>animal.duck.yellow Eggs</code>). Mixed schemes sort numbers first, then alphabetically.";let s=this.plugin.discoverStashpadFolders();new x.Setting(t).setName("Scope").setDesc("Scan the whole vault, or restrict to a single folder + its descendants.").addDropdown(A=>{A.addOption("vault","Entire vault"),A.addOption("folder","Single folder"),A.setValue(this.plugin.settings.jdIndexScope??"vault"),A.onChange(async l=>{this.plugin.settings.jdIndexScope=l==="folder"?"folder":"vault",await this.plugin.saveSettings(),this.display()})}),(this.plugin.settings.jdIndexScope??"vault")==="folder"&&new x.Setting(t).setName("Scope folder").setDesc("Vault-relative path. Leave empty to fall back to the entire vault.").addText(A=>{new qe(this.app,A.inputEl),A.setPlaceholder("Path/To/Folder"),A.setValue(this.plugin.settings.jdIndexScopeFolder??""),A.onChange(async l=>{this.plugin.settings.jdIndexScopeFolder=(l||"").trim().replace(/^\/+|\/+$/g,""),await this.plugin.saveSettings()})}),new x.Setting(t).setName("Include Stashpad folders in scan").setDesc("By default, notes inside any known Stashpad folder are excluded \u2014 the index destination shouldn't index itself, and other Stashpad folders are usually already organized. Toggle on if you want them included anyway.").addToggle(A=>{A.setValue(this.plugin.settings.jdIndexIncludeStashpadFolders===!0),A.onChange(async l=>{this.plugin.settings.jdIndexIncludeStashpadFolders=l,await this.plugin.saveSettings(),this.display()})}),new x.Setting(t).setName("Designated Stashpad folder for Index").setDesc("Required. Must be a Stashpad folder. The index hierarchy is built here. New notes are created; nothing is deleted.").addText(A=>{new qe(this.app,A.inputEl),A.setPlaceholder(s[0]??"(pick a Stashpad folder)"),A.setValue(this.plugin.settings.jdIndexStashpadFolder??""),A.onChange(async l=>{this.plugin.settings.jdIndexStashpadFolder=(l||"").trim().replace(/^\/+|\/+$/g,""),await this.plugin.saveSettings()})}),new x.Setting(t).setName("Sort").setDesc("Order of entries within the same depth. Natural: numbers first then alphabetical (recommended). Created: by source file's creation time \u2014 handy when prefixes are word-only and don't carry ordering.").addDropdown(A=>{A.addOption("natural","Natural (numeric \u2192 alphabetical)"),A.addOption("created","By creation time"),A.setValue(this.plugin.settings.jdIndexSort??"natural"),A.onChange(async l=>{this.plugin.settings.jdIndexSort=l==="created"?"created":"natural",await this.plugin.saveSettings()})});let n=Le(this.app,this.plugin,this.plugin.settings),o=t.createEl("p",{cls:"setting-item-description"}),r=n.skippedStashpadNotes.length>0?` (${n.skippedStashpadNotes.length} Stashpad-folder note${n.skippedStashpadNotes.length===1?"":"s"} excluded by default)`:"";o.setText(`Preview: ${n.indexed.length} note${n.indexed.length===1?"":"s"} would be indexed, ${n.nonIndex.length} would NOT be indexed${r}.`),new x.Setting(t).setName("Actions").setDesc("Preview aggressively overwrites the designated folder's HOME note body (frontmatter preserved). Build creates Stashpad notes (existing notes with the same jdPrefix are updated, not duplicated).").addButton(A=>{A.setButtonText("Preview"),A.setTooltip("Overwrites the designated Stashpad folder's HOME note body with the preview."),A.onClick(async()=>{try{let l=await Xi(this.app,this.plugin,this.plugin.settings);if(l.error==="no-dest"){new x.Notice("Set a Designated Stashpad folder for Index first.",5e3);return}if(l.error==="no-home"){new x.Notice(`"${this.plugin.settings.jdIndexStashpadFolder}" doesn't have a Stashpad home note. Open the folder in Stashpad first (it creates one automatically).`,7e3);return}Zi(this.app,l),this.display()}catch(l){console.error("[stashpad] preview failed",l),new x.Notice(`Preview failed: ${l?.message??l}`,8e3)}})}).addButton(A=>{A.setButtonText("Build Stashpad notes"),A.setCta(),A.setTooltip("Create the Stashpad-note hierarchy. Existing notes with matching jdPrefix are updated."),A.onClick(()=>{if(!(this.plugin.settings.jdIndexStashpadFolder??"").trim().replace(/^\/+|\/+$/g,"")){new x.Notice("Set a Designated Stashpad folder for Index first.",5e3);return}new Bi(this.app,this.plugin,this.plugin.settings,n.indexed.length,async()=>{try{let p=await pn(this.app,this.plugin,this.plugin.settings);if(p.error==="no-dest"){new x.Notice("Set a Designated Stashpad folder for Index first.",5e3);return}if(p.error==="dest-not-stashpad"){new x.Notice(`"${p.destFolder}" isn't a known Stashpad folder. Pick a real Stashpad folder (or create one first).`,7e3);return}this.plugin.settings.jdIndexHasBuilt=!0,await this.plugin.saveSettings(),new x.Notice(`Built: ${p.created} created, ${p.updated} updated, ${p.skipped} skipped \u2192 ${p.destFolder}`,6e3),this.display()}catch(p){console.error("[stashpad] build failed",p),new x.Notice(`Build failed: ${p?.message??p}`,8e3)}}).open()})}).addButton(A=>{A.setButtonText(`Reveal in ${KA()}`),A.setTooltip("Open the designated Stashpad folder in your OS file browser."),A.onClick(async()=>{let l=(this.plugin.settings.jdIndexStashpadFolder??"").trim().replace(/^\/+|\/+$/g,"");if(!l){new x.Notice("Set a Designated Stashpad folder for Index first.",5e3);return}if(!this.app.vault.getAbstractFileByPath(l)){new x.Notice(`Folder "${l}" doesn't exist yet.`,5e3);return}try{let p=this.app.vault.adapter.basePath;if(p){let{shell:g}=window.require?.("electron")??{},h=`${p}/${l}`;g?.openPath?.(h)}else new x.Notice("Reveal in file system not supported on this platform.",4e3)}catch(p){new x.Notice(`Couldn't open folder: ${p?.message??p}`,5e3)}})})}renderColorAliasesSection(t){let e=this.plugin.discoverStashpadFolders();if(e.length===0){new x.Setting(t).setName("Color aliases per Stashpad").setDesc("No Stashpads discovered yet \u2014 create one above first.");return}let i=(()=>{let o=ie()?.noteFolder;return o&&e.includes(o)?o:e[0]})();new x.Setting(t).setName("Color aliases per Stashpad").setDesc("Which Stashpad's colors to label.").addDropdown(o=>{for(let r of e)o.addOption(r,r);o.setValue(i),o.onChange(r=>{i=r,n()})}),t.createEl("p",{cls:"setting-item-description",text:"Give each per-note color a friendly name. Filters and pickers display the alias instead of the hex code; the underlying color stays the same. The same hex in two Stashpads can have different aliases."});let s=t.createDiv({cls:"stashpad-color-aliases-list"}),n=()=>{s.empty();let o=this.plugin.collectColorsInFolder(i),r=new Map(o.map(p=>[p.hex,p.count])),A=this.plugin.settings.colorAliases?.[i.replace(/\/+$/,"")]??{},l=new Set([...r.keys(),...Object.keys(A)]);if(l.size===0){s.createEl("p",{cls:"setting-item-description",text:`No colors used or aliased in "${i}" yet. Set a per-note color (Shift+: or right-click \u2192 Set color) and it'll appear here.`});return}let d=[...l].map(p=>({hex:p,count:r.get(p)??0}));d.sort((p,g)=>g.count-p.count||p.hex.localeCompare(g.hex));for(let p of d)this.renderColorAliasRow(s,i,p.hex,p.count,n)};n()}authorshipItems(){let t=[];t.push(this.renderDef("Author name","Your display name. Used in the note footer + as the author/contributor link target. Leave blank to opt out (notes won't be stamped).",i=>i.addText(s=>s.setValue(this.plugin.settings.authorName).onChange(async n=>{this.plugin.settings.authorName=n.trim(),this.plugin.settings.authorName&&!this.plugin.settings.authorId&&(this.plugin.settings.authorId=tt()),await this.plugin.saveSettings(),await this.plugin.syncAuthorFilesToName()})),["author","name","identity","stamp"])),t.push(this.renderDef("Author id (auto-assigned)","Stable id appended to your name on links so coworkers with the same name don't collide. Generated once and shouldn't change. To reset it, clear and retype your author name.",i=>i.addText(s=>s.setValue(this.plugin.settings.authorId).setDisabled(!0)),["author","id"])),t.push(this.renderDef("Title / role",'Optional. Shown on your author page (e.g. "Engineer", "PM", "Designer").',i=>i.addText(s=>s.setValue(this.plugin.settings.authorRole).onChange(async n=>{this.plugin.settings.authorRole=n.trim(),await this.plugin.saveSettings(),await this.plugin.syncAuthorFilesToName()})),["role","title","job"])),t.push(this.renderDef("Department / team",'Optional. Shown on your author page (e.g. "Engineering", "Growth").',i=>i.addText(s=>s.setValue(this.plugin.settings.authorDepartment).onChange(async n=>{this.plugin.settings.authorDepartment=n.trim(),await this.plugin.saveSettings(),await this.plugin.syncAuthorFilesToName()})),["department","team"]));let e=(i,s,n,o)=>this.renderDef(i,"",r=>r.addToggle(A=>A.setValue(s()).onChange(async l=>{n(l),await this.plugin.saveSettings()})),o);return t.push(e("Show author in note footer",()=>this.plugin.settings.showAuthor,i=>{this.plugin.settings.showAuthor=i},["author","footer","show"])),t.push(e("Show contributors in note footer",()=>this.plugin.settings.showContributors,i=>{this.plugin.settings.showContributors=i},["contributors","footer","show"])),t.push(e("Show last edit time in note footer",()=>this.plugin.settings.showLastEdit,i=>{this.plugin.settings.showLastEdit=i},["last edit","modified","footer","time"])),t.push(this.sectionDef("Folders you've worked in","Folders where you've authored or contributed notes. Click one to open it.",i=>this.renderAuthoredFolders(i),["folders","authored","contributed","worked"])),t.push(this.sectionDef("Known authors","Everyone the plugin has seen, with role/department + rename history; rebuild/restore the registry.",i=>this.renderKnownAuthorsSection(i),["authors","registry","rename","known","rebuild"])),t}renderAuthoredFolders(t){let e=this.plugin.collectAuthoredFolders();if(e.length===0){t.createEl("p",{cls:"setting-item-description",text:"No authored or contributed folders yet."});return}let i=t.createDiv({cls:"stashpad-authored-folders-list"});for(let s of e){let n=i.createDiv({cls:"stashpad-authored-folder-row"}),o=n.createEl("a",{cls:"stashpad-authored-folder-link",text:s.folder});o.onclick=A=>{A.preventDefault(),this.plugin.activateViewForFolder(s.folder)};let r=[];s.authored>0&&r.push(`authored ${s.authored}`),s.contributed>0&&r.push(`contributed to ${s.contributed}`),n.createSpan({cls:"stashpad-authored-folder-counts",text:` \xB7 ${r.join(", ")}`})}}templatesItems(){return[this.sectionDef("Color aliases","Give your note colors friendly names, per Stashpad folder.",t=>this.renderColorAliasesSection(t),["color","colour","alias","name","swatch","palette","label"]),this.sectionDef("Note templates","Per-Stashpad note templates \u2014 content stamped into new notes.",t=>this.renderNoteTemplatesSection(t),["template","note","default","boilerplate","snippet"])]}jdIndexItems(){return[this.sectionDef("JD Index (Johnny Decimal)","Build a Johnny-Decimal-style index from dotted-prefix note titles \u2014 set the scope, preview, then build.",t=>this.renderJdIndexSection(t),["jd","johnny","decimal","index","scope","build","preview","hierarchy","folder"])]}okfItems(){return[this.sectionDef("Open Knowledge Format (OKF)","Turn a Stashpad folder into a browsable OKF bundle \u2014 markdown concept files with OKF frontmatter, a generated index.md, and relative-markdown cross-links \u2014 that LLMs/agents can read. Complements (never replaces) Stashpad's own frontmatter and links.",t=>this.renderOkfSection(t),["okf","open knowledge format","knowledge","catalog","index","export","bundle","tarball","agent","google"])]}appendCode(t,e){e.split(/`([^`]+)`/g).forEach((i,s)=>{s%2===1?t.createEl("code",{text:i}):i&&t.appendText(i)})}codeDesc(t){let e=document.createDocumentFragment();return this.appendCode(e,t),e}renderOkfSection(t){if(t.createDiv({cls:"stashpad-beta-row"}).createEl("span",{cls:"stashpad-beta-badge",text:"BETA"}),new x.Setting(t).setName("Enable OKF").setDesc(this.codeDesc("Master switch. When on, you choose which folders use OKF by assigning the OKF template to them in Settings \u2192 Templates (all / some / none \u2014 your call). Those folders then get OKF frontmatter and a maintained `index.md`. Turning this off leaves existing OKF files in place; it just stops maintaining them.")).addToggle(i=>i.setValue(this.plugin.settings.okfEnabled).onChange(async s=>{if(this.plugin.settings.okfEnabled=s,await this.plugin.saveSettings(),s)try{await this.plugin.ensureOkfTemplate()}catch(n){console.warn("[Stashpad] OKF template create failed",n)}new x.Notice(s?`OKF on. Next: assign the template "${this.plugin.okfTemplatePathOrDefault()}" to a folder \u2014 use \u201CCreate template + open Templates\u201D below. Heads-up: OKF frontmatter + index.md refresh automatically but NOT instantly (a few seconds after changes); hit Rebuild for an immediate pass.`:"OKF disabled.",s?0:4e3),this.update?.()})),this.plugin.settings.okfEnabled){let i=this.plugin.okfTemplatePathOrDefault(),s=this.plugin.okfActiveFolders().length,n=t.createEl("div",{cls:"setting-item-description stashpad-okf-howto"});n.createEl("p",{text:"How to use OKF in a folder:"});let o=n.createEl("ol");if(this.appendCode(o.createEl("li"),`Open Templates and set a folder's template to \`${i}\` (archive folders are skipped).`),this.appendCode(o.createEl("li"),"Hit Rebuild below to write OKF frontmatter (`okfParent`/`okfChildren` + `okfType`/`okfTitle`/`okfTimestamp`) and generate that folder's `index.md`."),this.appendCode(o.createEl("li"),"Right-click a note (or a selection) \u2192 \u201CExport as OKF\u2026\u201D to save a `.zip` / `.tar.gz` bundle (or `.stash`)."),n.createEl("p",{cls:"stashpad-okf-soon",text:"OKF frontmatter + index.md refresh automatically a few seconds after you add, move, or delete notes \u2014 NOT instantly. Use Rebuild for an immediate pass."}),s===0){let r=t.createEl("p",{cls:"stashpad-okf-cta"});this.appendCode(r,"\u{1F449} No folder is using OKF yet. Click \u201CCreate template + open Templates\u201D below, then set a folder's template to `"+i+"`.")}else n.createEl("p",{cls:"stashpad-okf-soon",text:`Currently ${s} folder${s===1?"":"s"} actively using OKF.`});new x.Setting(t).setName("Assign OKF to folders").setDesc(this.codeDesc(`Creates the OKF template if needed (never duplicates it), then opens Templates \u2014 set a folder's template to \`${i}\` there.`)).addButton(r=>{r.setButtonText("Create template + open Templates").setCta(),r.onClick(async()=>{let A;try{A=await this.plugin.ensureOkfTemplate()}catch(l){new x.Notice(`Couldn't create the OKF template: ${l.message}`);return}new x.Notice(`OKF template ready at "${A}" \u2014 set a folder's template to that path.`),this.update?.(),this.openSettingsPage("Templates")})}),new x.Setting(t).setName("Rebuild OKF frontmatter").setDesc(this.codeDesc("Write/refresh OKF fields for every folder using the OKF template \u2014 `okfParent`/`okfChildren` relative links (managed) plus `okfType`/`okfTitle`/`okfTimestamp` defaults (yours to edit after). Heads-up: adding, moving, or deleting notes already auto-refreshes the folder, but NOT instantly \u2014 it waits ~a few seconds after you stop. Use this button for an immediate rebuild (e.g. right after first assigning the template). Complements Stashpad's own links; nothing is removed.")).addButton(r=>r.setButtonText("Rebuild now").onClick(async()=>{let A=await this.plugin.rebuildAllOkf();new x.Notice(A.folders===0?"No folders use the OKF template yet \u2014 assign it in Templates first.":`OKF: updated ${A.written} of ${A.checked} notes across ${A.folders} folder${A.folders===1?"":"s"}.`),this.update?.()}))}let e=new x.Setting(t).setName("Learn about OKF").setDesc("Google's open, vendor-neutral spec for sharing curated knowledge with agents.");e.addButton(i=>i.setButtonText("Spec / repo").onClick(()=>window.open("https://github.com/GoogleCloudPlatform/knowledge-catalog/tree/main/okf"))),e.addButton(i=>i.setButtonText("Announcement").onClick(()=>window.open("https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing/")))}openSettingsPage(t){let e=()=>new x.Notice(`Open Settings \u2192 Stashpad \u2192 ${t}.`);try{let i=this.app.setting;if(!i?.openTabById){e();return}i.openTabById("stashpad"),window.setTimeout(()=>{let s=i.modalEl?.querySelector(".vertical-tab-content");if(!s){e();return}let o=Array.from(s.querySelectorAll("*")).find(r=>r.childElementCount===0&&r.textContent?.trim()===t&&!r.closest(".vertical-tab-header"))?.closest("[class*='nav'], .setting-item, button, a");o&&!o.closest(".vertical-tab-header")?o.click():e()},60)}catch{e()}}renderAuthorshipSection(t){new x.Setting(t).setName("Authorship").setHeading(),t.createEl("p",{cls:"setting-item-description",text:"Stamp each new note with your name. If the vault is later shared (e.g. a coworker opens it with --config pointing at their own settings folder), every modification automatically tracks contributors on top of the original author. Names link to per-user pages in <stashpad>/_authors/."}),new x.Setting(t).setName("Author name").setDesc("Your display name. Used in the note footer + as the author/contributor link target. Leave blank to opt out (notes won't be stamped).").addText(i=>{i.setValue(this.plugin.settings.authorName).onChange(async s=>{this.plugin.settings.authorName=s.trim(),this.plugin.settings.authorName&&!this.plugin.settings.authorId&&(this.plugin.settings.authorId=tt()),await this.plugin.saveSettings(),await this.plugin.syncAuthorFilesToName()})}),new x.Setting(t).setName("Author id (auto-assigned)").setDesc("Stable id appended to your name on links so coworkers with the same name don't collide. Generated once and shouldn't change. If you really need to reset it, clear and retype your author name above.").addText(i=>{i.setValue(this.plugin.settings.authorId).setDisabled(!0)}),new x.Setting(t).setName("Title / role").setDesc('Optional. Shown on your author page (e.g. "Engineer", "PM", "Designer").').addText(i=>{i.setValue(this.plugin.settings.authorRole).onChange(async s=>{this.plugin.settings.authorRole=s.trim(),await this.plugin.saveSettings(),await this.plugin.syncAuthorFilesToName()})}),new x.Setting(t).setName("Department / team").setDesc('Optional. Shown on your author page (e.g. "Engineering", "Growth").').addText(i=>{i.setValue(this.plugin.settings.authorDepartment).onChange(async s=>{this.plugin.settings.authorDepartment=s.trim(),await this.plugin.saveSettings(),await this.plugin.syncAuthorFilesToName()})}),new x.Setting(t).setName("Show author in note footer").addToggle(i=>i.setValue(this.plugin.settings.showAuthor).onChange(async s=>{this.plugin.settings.showAuthor=s,await this.plugin.saveSettings()})),new x.Setting(t).setName("Show contributors in note footer").addToggle(i=>i.setValue(this.plugin.settings.showContributors).onChange(async s=>{this.plugin.settings.showContributors=s,await this.plugin.saveSettings()})),new x.Setting(t).setName("Show last edit time in note footer").addToggle(i=>i.setValue(this.plugin.settings.showLastEdit).onChange(async s=>{this.plugin.settings.showLastEdit=s,await this.plugin.saveSettings()}));let e=this.plugin.collectAuthoredFolders();if(e.length>0){new x.Setting(t).setName("Folders you've worked in").setHeading();let i=t.createDiv({cls:"stashpad-authored-folders-list"});for(let s of e){let n=i.createDiv({cls:"stashpad-authored-folder-row"}),o=n.createEl("a",{cls:"stashpad-authored-folder-link",text:s.folder});o.onclick=A=>{A.preventDefault(),this.plugin.activateViewForFolder(s.folder)};let r=[];s.authored>0&&r.push(`authored ${s.authored}`),s.contributed>0&&r.push(`contributed to ${s.contributed}`),n.createSpan({cls:"stashpad-authored-folder-counts",text:` \xB7 ${r.join(", ")}`})}}this.renderKnownAuthorsSection(t)}renderKnownAuthorsSection(t){new x.Setting(t).setName("Known authors (registry)").setHeading(),t.createEl("div",{cls:"setting-item-description",text:"A rebuildable cache of every author Stashpad has seen, with rename history. Not a source of truth \u2014 the author id stored in each note is authoritative. Use it to recover deleted author pages or audit name changes."}),new x.Setting(t).setName("Registry maintenance").setDesc("Rebuild scans the whole vault to reconstruct the list. Restore regenerates any deleted author pages across every Stashpad folder.").addButton(s=>s.setButtonText("Rebuild").onClick(async()=>{s.setDisabled(!0).setButtonText("Rebuilding\u2026");try{let n=await this.plugin.rebuildAuthorRegistry();new x.Notice(`Author registry rebuilt: ${n.total} author(s).`)}catch(n){new x.Notice(`Rebuild failed: ${n.message}`)}s.setDisabled(!1).setButtonText("Rebuild"),this.display()})).addButton(s=>s.setButtonText("Restore missing pages").onClick(async()=>{s.setDisabled(!0).setButtonText("Restoring\u2026");try{let n=await this.plugin.restoreMissingAuthorStubs();new x.Notice(n.created>0?`Restored ${n.created} author page(s).`:"No missing author pages.")}catch(n){new x.Notice(`Restore failed: ${n.message}`)}s.setDisabled(!1).setButtonText("Restore missing pages")}));let e=this.plugin.authorRegistry.all();if(e.length===0){t.createEl("div",{cls:"setting-item-description",text:"No authors recorded yet. Rebuild to scan the vault."});return}let i=t.createDiv({cls:"stashpad-known-authors-list"});for(let s of e){let n=i.createDiv({cls:"stashpad-known-author-row"}),o=n.createDiv({cls:"stashpad-known-author-main"});o.createSpan({cls:"stashpad-known-author-name",text:s.name||"(unnamed)"});let r=[];if(s.role&&r.push(s.role),s.department&&r.push(s.department),r.push(`id ${s.id}`),o.createSpan({cls:"stashpad-known-author-meta",text:` \xB7 ${r.join(" \xB7 ")}`}),s.renames&&s.renames.length>0){let A=n.createDiv({cls:"stashpad-known-author-history"}),l=s.renames.map(d=>`${d.from} \u2192 ${d.to}`).join(", ");A.setText(`Renamed: ${l}`)}}}renderNoteTemplatesSection(t){let e=this.plugin.discoverStashpadFolders();if(e.length===0)return;if(new x.Setting(t).setName("Note templates per Stashpad").setDesc("Pick a markdown file to use as the default template for new notes in each Stashpad. The template's frontmatter becomes the new note's frontmatter (id/parent/created/attachments are always set by Stashpad). If the body contains {{body}}, that's where the user-typed body goes; otherwise the user body is followed by the template body."),this.plugin.settings.okfEnabled){let n=this.plugin.okfTemplatePathOrDefault();this.appendCode(t.createEl("p",{cls:"setting-item-description"}),`\u{1F4A1} OKF tip: type \`${n}\` into a folder's template field below to turn that folder into an OKF bundle (OKF frontmatter + a maintained \`index.md\`). Assign it to all, some, or none of your folders \u2014 it's per-folder. Manage OKF itself in Settings \u2192 OKF.`)}let i=t.createDiv({cls:"stashpad-note-templates-list"}),s=n=>{let o=n.replace(/\/+$/,""),r=i.createDiv({cls:"stashpad-note-template-row"});r.createSpan({cls:"stashpad-note-template-folder"}).setText(n);let l=r.createDiv({cls:"stashpad-note-template-input-wrap"}),d=l.createEl("input",{type:"text",cls:"stashpad-note-template-input",attr:{placeholder:"path/to/template.md (leave blank to disable)"}});d.value=(this.plugin.settings.noteTemplates??{})[o]??"";let p=l.createDiv({cls:"stashpad-note-template-suggest"});p.setCssStyles({display:"none"});let g=[],h=[],I=-1,u=()=>p.style.display!=="none"&&g.length>0,f=w=>{I=w,h.forEach((D,N)=>D.toggleClass("is-active",N===w)),w>=0&&h[w]&&h[w].scrollIntoView({block:"nearest"})},C=()=>{p.setCssStyles({display:"none"}),I=-1},B=async w=>{d.value=w,await E(),C()},m=r.createDiv({cls:"stashpad-note-template-warn"});m.setCssStyles({display:"none"});let y=()=>this.app.vault.getMarkdownFiles().map(w=>w.path).filter(w=>!/\/(_imports|_exports|_attachments|\.stashpad)\//.test(w)).sort(),Q=()=>{p.empty(),h=[];let w=d.value.trim().toLowerCase().split(/\s+/).filter(Boolean),D=N=>{let P=N.toLowerCase();return w.every(H=>P.includes(H))};if(g=y().filter(N=>D(N)).slice(0,12),g.length===0){C();return}p.setCssStyles({display:""}),g.forEach((N,P)=>{let H=p.createDiv({cls:"stashpad-note-template-suggest-item",text:N});h.push(H),H.addEventListener("mousemove",()=>f(P)),H.addEventListener("mousedown",async b=>{b.preventDefault(),await B(N)})}),I=I>=0&&I<g.length?I:-1,I>=0&&f(I)},E=async()=>{let w=d.value.trim(),D={...this.plugin.settings.noteTemplates??{}};w?D[o]=w:delete D[o],this.plugin.settings.noteTemplates=D,await this.plugin.saveSettings(),v()},v=()=>{m.empty(),m.setCssStyles({display:"none"});let w=d.value.trim();if(!w)return;let D=this.app.vault.getAbstractFileByPath(w);if(!D||D.extension!=="md"){m.setCssStyles({display:""}),m.setText(`\u26A0 "${w}" is not a markdown file in this vault.`);return}let N=this.app.metadataCache.getFileCache(D)?.frontmatter??{},H=ae.filter(b=>{let S=N[b];return!(S==null||typeof S=="string"&&S.trim()===""||Array.isArray(S)&&S.length===0)});H.length!==0&&(m.setCssStyles({display:""}),m.setText(`\u26A0 Template defines ${H.join(", ")} \u2014 Stashpad always sets ${H.length===1?"this":"these"} on new notes, so the template value${H.length===1?"":"s"} will be ignored.`))};d.addEventListener("focus",Q),d.addEventListener("input",()=>{I=-1,Q()}),d.addEventListener("blur",()=>{setTimeout(C,150)}),d.addEventListener("change",()=>{E()}),d.addEventListener("keydown",w=>{if(w.key==="ArrowDown")w.preventDefault(),u()?f((I+1)%g.length):(Q(),g.length&&f(0));else if(w.key==="ArrowUp"){if(!u())return;w.preventDefault(),f((I-1+g.length)%g.length)}else if(w.key==="Enter")u()&&I>=0&&(w.preventDefault(),B(g[I]));else if(w.key==="Escape")u()&&(w.preventDefault(),C());else if(w.key==="Tab"&&!w.shiftKey){if(!u())return;let D=g[I>=0?I:0],N=d.value,P;if(D.toLowerCase().startsWith(N.toLowerCase())){let H=D.indexOf("/",N.length);P=H>=0?D.slice(0,H+1):D}else P=D;P&&P!==N&&(w.preventDefault(),d.value=P,I=-1,Q(),g.length===1&&f(0))}}),v()};for(let n of e)s(n)}renderColorAliasRow(t,e,i,s,n){let o=t.createDiv({cls:"stashpad-color-alias-row"});s===0&&o.addClass("is-unused");let r=o.createSpan({cls:"stashpad-color-alias-swatch"});r.setCssStyles({background:i}),r.title="Click to bulk-recolor every note of this color in this Stashpad",r.onclick=()=>{let p=this.plugin.settings.customPalette??[];new De(this.app,i,p,async g=>{if((g??null)===null&&s===0){await this.plugin.setColorAlias(e,i,""),n();return}if(g&&g.toLowerCase()===i){n();return}let h=await this.plugin.recolorAllInFolder(e,i,g??null);if(h>0)new x.Notice(`Recolored ${h} note${h===1?"":"s"}.`);else if(s===0){let I=this.plugin.getColorAlias(e,i);I&&(await this.plugin.setColorAlias(e,i,""),g&&await this.plugin.setColorAlias(e,g,I))}n()},async g=>{let h=(this.plugin.settings.customPalette??[]).filter(I=>I.toLowerCase()!==g.toLowerCase());return this.plugin.settings.customPalette=h,await this.plugin.saveSettings(),h}).open()};let A=o.createDiv({cls:"stashpad-color-alias-meta"});A.createSpan({cls:"stashpad-color-alias-hex",text:i}),A.createSpan({cls:"stashpad-color-alias-count",text:s===0?"\xB7 unused":`\xB7 ${s} note${s===1?"":"s"}`});let l=o.createEl("input",{type:"text",cls:"stashpad-color-alias-input",attr:{placeholder:"Alias (optional)"}});l.value=this.plugin.getColorAlias(e,i)??"",l.onchange=async()=>{await this.plugin.setColorAlias(e,i,l.value),!l.value.trim()&&s===0&&n()};let d=o.createEl("button",{cls:"stashpad-color-alias-del",text:"\xD7",attr:{title:"Delete alias"}});l.value||d.setCssStyles({visibility:"hidden"}),d.onclick=async()=>{await this.plugin.setColorAlias(e,i,""),s===0?n():(l.value="",d.setCssStyles({visibility:"hidden"}))}}renderFolderScopeRow(t,e){let i=t.createDiv({cls:"stashpad-folder-row"});i.createSpan({cls:"stashpad-folder-row-label",text:e});let s=i.createSpan({cls:"stashpad-folder-row-state"}),n=i.createDiv({cls:"stashpad-binding-pill"});n.setAttribute("role","switch"),n.setAttribute("tabindex","0");let o=n.createDiv({cls:"stashpad-binding-pill-knob"}),r=()=>(this.plugin.settings.searchExcludedFolders??[]).includes(e),A=()=>{let d=r();n.toggleClass("is-right",d),n.setAttribute("aria-checked",String(d)),o.setText(d?"X":"\u2713"),s.setText(d?"Excluded":"Included"),s.toggleClass("is-excluded",d),n.title=d?"Excluded \u2014 notes here won't appear in cross-Stashpad search. Click to include.":"Included \u2014 notes here appear in cross-Stashpad search. Click to exclude."},l=async()=>{let d=new Set(this.plugin.settings.searchExcludedFolders??[]);d.has(e)?d.delete(e):d.add(e),this.plugin.settings.searchExcludedFolders=[...d].sort(),A(),await this.plugin.saveSettings()};n.onclick=()=>void l(),n.onkeydown=d=>{(d.key===" "||d.key==="Enter")&&(d.preventDefault(),l())},A()}renderFolderPlacementList(t){let e=this.plugin.settings,i=[{key:"folderPanelPinned",label:"Pinned",action:"Unpin"},{key:"folderPanelDownranked",label:"Downranked",action:"Reset"},{key:"folderPanelHidden",label:"Hidden",action:"Unhide"}];if(!i.some(o=>(e[o.key]??[]).length>0)){t.createEl("p",{cls:"setting-item-description"}).setText("No folders customized yet. Right-click a folder in the Stashpad folder panel to pin, downrank, or hide it.");return}let n=async o=>{e.folderPanelPinned=(e.folderPanelPinned??[]).filter(r=>r!==o),e.folderPanelDownranked=(e.folderPanelDownranked??[]).filter(r=>r!==o),e.folderPanelHidden=(e.folderPanelHidden??[]).filter(r=>r!==o),await this.plugin.saveSettings(),this.update?.()};for(let o of i){let r=[...e[o.key]??[]].sort();if(r.length===0)continue;t.createEl("div",{cls:"stashpad-folder-placement-group",text:`${o.label} (${r.length})`});let A=t.createDiv({cls:"stashpad-folder-list"});for(let l of r){let d=A.createDiv({cls:"stashpad-folder-row"});d.createSpan({cls:"stashpad-folder-row-label",text:l});let p=d.createEl("button",{text:o.action});p.onclick=()=>void n(l)}}}renderBindingRow(t,e){t.setName(e.label).setDesc(e.desc);let i=()=>this.plugin.settings.bindings[e.id],s,n,o=()=>{},r=h=>{let I=t.controlEl.createDiv({cls:"stashpad-binding-slot"}),u=I.createEl("input",{type:"text"});u.readOnly=!0,u.placeholder="Click & press a key",u.value=Qi(i()[h]),u.classList.add("stashpad-binding-input");let f=()=>{u.size=Math.max(3,u.value.length||u.placeholder.length)};f();let C=h==="primary"?e.defaultPrimary:e.defaultSecondary??"";u.onclick=()=>{Jo(u,async Q=>{this.plugin.settings.bindings[e.id][h]=Q,u.value=Qi(Q),f(),await this.plugin.saveSettings(),o(),y()})};let B=I.createEl("button",{cls:"stashpad-binding-clear",text:"\xD7"});B.title="Clear this slot",B.onclick=async()=>{this.plugin.settings.bindings[e.id][h]="",u.value="",f(),await this.plugin.saveSettings(),o(),y()};let m=I.createEl("button",{cls:"stashpad-binding-revert"});(0,x.setIcon)(m,"rotate-ccw");let y=()=>{let E=i()[h]!==C;m.toggleClass("is-hidden",!E),m.title=C?`Revert to default (${Qi(C)})`:"Revert to default (no binding)"};return m.onclick=async()=>{this.plugin.settings.bindings[e.id][h]=C,u.value=Qi(C),f(),await this.plugin.saveSettings(),o(),y()},y(),u};s=r("primary"),n=r("secondary");let A=t.controlEl.createDiv({cls:"stashpad-binding-pill"});A.setAttribute("role","switch"),A.setAttribute("tabindex","0");let l=A.createDiv({cls:"stashpad-binding-pill-knob"}),d=t.controlEl.createDiv({cls:"stashpad-binding-useboth"}),p=d.createEl("input",{type:"checkbox"});p.title="Use both bindings simultaneously (overrides the L/R toggle)",d.createSpan({text:"Use both"}),p.onchange=async()=>{this.plugin.settings.bindings[e.id].useBoth=p.checked,await this.plugin.saveSettings(),o()},o=()=>{let h=i(),I=!!(h.primary&&h.secondary);p.checked=!!h.useBoth,p.disabled=!I,d.toggleClass("is-disabled",!I);let u=!!h.useBoth&&I;A.toggleClass("is-disabled",!I||u),A.toggleClass("is-right",h.preferRight),A.setAttribute("aria-checked",String(h.preferRight)),A.setAttribute("aria-disabled",String(!I||u)),l.setText(h.preferRight?"R":"L"),A.title=I?u?'Overridden by "Use both"':h.preferRight?"Right slot active \u2014 click for left":"Left slot active \u2014 click for right":"Set both slots to enable the toggle"};let g=async()=>{let h=i();!h.primary||!h.secondary||(this.plugin.settings.bindings[e.id].preferRight=!h.preferRight,o(),await this.plugin.saveSettings())};A.onclick=()=>void g(),A.onkeydown=h=>{(h.key===" "||h.key==="Enter")&&(h.preventDefault(),g())},o()}};var Ve=class{constructor(a,t){this.app=a;this.ta=t;this.popupEl=null;this.items=[];this.activeIdx=0;this.state=null;this.fileIndex=[];this.tagIndex=[];this.indexBuilt=!1;this.vaultListeners=[];this.scope=null;this.onInput=()=>{let a=this.detectTrigger();if(!a){this.close();return}this.openFor(a)};this.onBlur=()=>{setTimeout(()=>this.close(),120)};this.onDocEscape=a=>{a.key==="Escape"&&(!this.state||!this.items.length||(a.preventDefault(),a.stopPropagation(),a.stopImmediatePropagation(),this.close()))};this.onKeyDown=a=>{!this.state||!this.items.length||(a.key==="ArrowDown"?(a.preventDefault(),this.activeIdx=(this.activeIdx+1)%this.items.length,this.refreshActive()):a.key==="ArrowUp"?(a.preventDefault(),this.activeIdx=(this.activeIdx-1+this.items.length)%this.items.length,this.refreshActive()):a.key==="Enter"||a.key==="Tab"?(a.preventDefault(),a.stopPropagation(),this.commit()):a.key==="Escape"&&(a.preventDefault(),a.stopPropagation(),a.stopImmediatePropagation(),this.close()))}}attach(){this.ta.addEventListener("input",this.onInput),this.ta.addEventListener("keydown",this.onKeyDown,!0),this.ta.addEventListener("blur",this.onBlur);let a=this.ta.ownerDocument??document;a.addEventListener("keydown",this.onDocEscape,!0),this.vaultListeners.push(()=>a.removeEventListener("keydown",this.onDocEscape,!0)),this.buildIndex();let t=()=>{this.indexBuilt=!1},e=this.app.vault;e.on("create",t),e.on("delete",t),e.on("rename",t),this.vaultListeners.push(()=>e.off("create",t),()=>e.off("delete",t),()=>e.off("rename",t))}isOpen(){return!!this.state&&this.items.length>0}detach(){this.close(),this.ta.removeEventListener("input",this.onInput),this.ta.removeEventListener("keydown",this.onKeyDown,!0),this.ta.removeEventListener("blur",this.onBlur);for(let a of this.vaultListeners)a();this.vaultListeners=[]}buildIndex(){if(this.indexBuilt)return;let a=j().inheritObsidianExclusions,t=a?this.app.vault.getConfig?.("userIgnoreFilters"):void 0;this.fileIndex=this.app.vault.getFiles().filter(i=>!Bo(i.path)&&!mo(i.path)&&!(a&&Qo(i.path,t))).map(i=>{let s=i.extension==="md",n=s?i.basename:i.name,o=s?i.basename:i.name;return{label:n,lower:n.toLowerCase(),insertText:o,file:i}});let e=this.app.metadataCache.getTags?.()??{};this.tagIndex=Object.keys(e).sort((i,s)=>(e[s]||0)-(e[i]||0)),this.indexBuilt=!0}detectTrigger(){let a=this.ta.value,t=this.ta.selectionStart;if(t==null)return null;let e=a.slice(0,t),i=e.match(/\[\[([^\]\[\n]*)$/);if(i){let n=i[1];return{kind:"link",query:n,replaceStart:t-n.length-2,replaceEnd:t}}let s=e.match(/(^|\s)#([A-Za-z0-9_/\-]+)$/);if(s){let n=s[2];return{kind:"tag",query:n,replaceStart:t-n.length-1,replaceEnd:t}}return null}buildItems(a){this.buildIndex();let t=a.query.toLowerCase().trim(),e=t?t.split(/\s+/).filter(Boolean):[],i=s=>{if(!e.length)return!0;for(let n of e)if(!s.includes(n))return!1;return!0};return a.kind==="link"?this.fileIndex.filter(n=>i(n.lower)).slice(0,50).map(n=>({label:n.label,insert:`[[${n.insertText}]]`,subtitle:n.file.path})):this.tagIndex.filter(n=>i(n.toLowerCase())).slice(0,30).map(n=>({label:n,insert:n,subtitle:""}))}openFor(a){if(this.state=a,this.items=this.buildItems(a),this.activeIdx=0,!this.items.length){this.close();return}this.renderPopup(),this.pushScope()}pushScope(){if(this.scope)return;let a=new Ja.Scope(this.app.scope);a.register([],"Escape",t=>(t.preventDefault(),this.close(),!1)),this.scope=a,this.app.keymap?.pushScope(a)}popScope(){if(this.scope){try{this.app.keymap?.popScope(this.scope)}catch{}this.scope=null}}renderPopup(){if(!this.popupEl){let t=this.ta.ownerDocument??document;this.popupEl=t.body.createDiv({cls:"stashpad-composer-suggest"}),this.popupEl.tabIndex=-1,this.popupEl.addEventListener("mousedown",e=>e.preventDefault())}let a=this.popupEl;a.empty();for(let t=0;t<this.items.length;t++){let e=this.items[t],i=a.createDiv({cls:"stashpad-composer-suggest-row"});t===this.activeIdx&&i.addClass("is-active"),i.createSpan({cls:"stashpad-composer-suggest-label",text:e.label}),e.subtitle&&i.createSpan({cls:"stashpad-composer-suggest-sub",text:e.subtitle}),i.onmousedown=s=>{s.preventDefault(),this.activeIdx=t,this.commit()}}this.position()}refreshActive(){if(!this.popupEl)return;let a=this.popupEl.children;for(let e=0;e<a.length;e++)a[e].toggleClass("is-active",e===this.activeIdx);let t=a[this.activeIdx];t&&t.scrollIntoView({block:"nearest"})}position(){if(!this.popupEl)return;let a=this.ta.getBoundingClientRect(),t=this.popupEl.offsetHeight||200,e=a.top-t-4,i=a.left;this.popupEl.style.left=`${Math.max(8,i)}px`,this.popupEl.style.top=`${Math.max(8,e)}px`,this.popupEl.style.minWidth=`${Math.min(360,a.width)}px`}commit(){if(!this.state||!this.items.length)return;let a=this.items[this.activeIdx];if(!a)return;let t=this.ta.value.slice(0,this.state.replaceStart),e=this.ta.value.slice(this.state.replaceEnd),i=a.insert;this.ta.value=t+i+e;let s=t.length+i.length;this.ta.setSelectionRange(s,s),this.ta.dispatchEvent(new Event("input",{bubbles:!0})),this.close(),this.ta.focus()}close(){this.popupEl&&(this.popupEl.remove(),this.popupEl=null),this.state=null,this.items=[],this.activeIdx=0,this.popScope()}};rt();var vs=class extends Et.ItemView{constructor(t,e){super(t);this.plugin=e;this.displayedPath=null;this.unsubscribeSelection=null;this.renderTimer=null;this.expanded=new Set;this.composerAutocomplete=null;this.composerInputEl=null;this.composerDraft="";this.composerDraftForId=null;this.displayedId=null;this.unsubscribeContent=null}getViewType(){return ye}getDisplayText(){return"Stashpad detail"}getIcon(){return"panel-right"}async onOpen(){this.render(),this.unsubscribeSelection=this.plugin.onStashpadSelectionChange(()=>{this.displayedId=null,this.scheduleRender()}),this.unsubscribeContent=this.plugin.onStashpadContentChange(()=>this.scheduleRender()),this.registerEvent(this.app.workspace.on("active-leaf-change",t=>{!t||t===this.leaf||t.view?.getViewType?.()===J&&this.scheduleRender()})),this.registerEvent(this.app.vault.on("modify",t=>{this.displayedPath&&t.path===this.displayedPath&&this.scheduleRender()})),this.registerEvent(this.app.metadataCache.on("changed",t=>{this.displayedPath&&t.path===this.displayedPath&&this.scheduleRender()}))}async onClose(){this.unsubscribeSelection?.(),this.unsubscribeSelection=null,this.unsubscribeContent?.(),this.unsubscribeContent=null,this.composerAutocomplete?.detach(),this.composerAutocomplete=null,this.composerInputEl=null,this.renderTimer!=null&&(window.clearTimeout(this.renderTimer),this.renderTimer=null)}scheduleRender(){this.renderTimer==null&&(this.renderTimer=window.setTimeout(()=>{this.renderTimer=null,this.containerEl.isConnected&&this.render()},60))}resolveDisplayed(){if(this.displayedId){let e=this.plugin.lastActiveStashpadLeaf?.view;if(e?.getViewType?.()===J&&e.tree?.get){let i=e.tree.get(this.displayedId);if(i?.file)return{folder:e.noteFolder,id:this.displayedId,file:i.file}}this.displayedId=null}let t=this.plugin.getActiveStashpadSelection();return t&&(this.displayedId=t.id),t}async render(){let t=this.contentEl,e=!!this.composerInputEl&&document.activeElement===this.composerInputEl,i=this.composerInputEl?.selectionStart??null;this.composerAutocomplete?.detach(),this.composerAutocomplete=null,this.composerInputEl=null,t.empty(),t.addClass("stashpad-detail-root");let s=this.resolveDisplayed();if(!s){this.displayedPath=null;let I=t.createDiv({cls:"stashpad-detail-empty"});(0,Et.setIcon)(I.createSpan({cls:"stashpad-detail-empty-icon"}),"panel-right"),I.createSpan({cls:"stashpad-detail-empty-text",text:"No Stashpad note selected. Cursor or click a note in a Stashpad list to inspect it here."});return}let n=s.file;this.displayedPath=n.path;let o=this.app.metadataCache.getFileCache(n)?.frontmatter??{},r=t.createDiv({cls:"stashpad-detail-scroll"}),A=r.createDiv({cls:"stashpad-detail-header"}),l=A.createDiv({cls:"stashpad-detail-titlerow"});l.createDiv({cls:"stashpad-detail-title",text:this.titleFor(n)});let d=l.createEl("button",{cls:"stashpad-detail-open-btn",attr:{"aria-label":"Open in Stashpad tab"}});(0,Et.setIcon)(d,"arrow-up-right"),d.title="Open this note in a new Stashpad tab",d.onclick=()=>{this.openInStashpad(s.folder,s.id)};let p=A.createDiv({cls:"stashpad-detail-metarow"});if(s.folder&&p.createSpan({cls:"stashpad-detail-meta-chip",text:s.folder.split("/").pop()||s.folder}),typeof o.color=="string"&&o.color){let I=p.createSpan({cls:"stashpad-detail-meta-color"});I.style.background=o.color,I.title=o.color}if(o.completed===!0&&p.createSpan({cls:"stashpad-detail-meta-chip is-completed",text:"\u2713 completed"}),typeof o.due=="string"||typeof o.due=="number"){let I=Date.parse(String(o.due)),u=Number.isNaN(I)?String(o.due):$t(I,this.plugin.settings);p.createSpan({cls:"stashpad-detail-meta-chip is-due",text:`due ${u}`})}if(Array.isArray(o.tags))for(let I of o.tags.filter(u=>typeof u=="string"))p.createSpan({cls:"stashpad-detail-meta-tag",text:`#${I.replace(/^#/,"")}`});let g=r.createDiv({cls:"stashpad-detail-body"});try{let I=await this.app.vault.cachedRead(n),u=this.stripFrontmatter(I);await Et.MarkdownRenderer.render(this.app,u,g,n.path,this)}catch(I){g.createDiv({cls:"stashpad-detail-error",text:`Couldn't read \`${n.path}\`: ${I.message}`})}this.renderFooterMeta(r,n,o,s),this.renderChildren(r,s.folder,s.id),this.renderComposer(t,s);let h=this.composerInputEl;if(e&&h&&(h.focus(),i!=null)){let I=Math.min(i,h.value.length);try{h.setSelectionRange(I,I)}catch{}}}renderComposer(t,e){let i=t.createDiv({cls:"stashpad-detail-composer"}),s=i.createEl("textarea",{cls:"stashpad-detail-composer-input",attr:{placeholder:"Add a child note\u2026",rows:"2"}});this.composerInputEl=s,this.composerDraftForId===e.id?s.value=this.composerDraft:(this.composerDraft="",this.composerDraftForId=e.id),s.addEventListener("input",()=>{this.composerDraft=s.value,this.composerDraftForId=e.id}),s.addEventListener("keydown",o=>{if(o.key==="Enter"&&!o.shiftKey&&!o.isComposing){if(this.composerAutocomplete?.isOpen?.())return;o.preventDefault(),this.submitComposer(e)}});let n=i.createEl("button",{cls:"stashpad-detail-composer-send",attr:{"aria-label":"Add child note"}});(0,Et.setIcon)(n.createSpan({cls:"stashpad-detail-composer-send-icon"}),"plus"),n.createSpan({cls:"stashpad-detail-composer-send-text",text:"Add child note"}),n.title="Add child note (Enter)",n.onclick=()=>void this.submitComposer(e),this.composerAutocomplete=new Ve(this.app,s),this.composerAutocomplete.attach()}async submitComposer(t){let e=(this.composerInputEl?.value??"").trim();if(!e)return;let i=this.plugin.lastActiveStashpadLeaf?.view;if(!i||i.getViewType?.()!==J||typeof i.createNoteUnder!="function"){new Et.Notice("Open a Stashpad view to add notes.");return}try{await i.createNoteUnder(e,t.id)}catch(s){new Et.Notice(`Couldn't add note: ${s.message}`);return}this.composerDraft="",this.composerDraftForId=t.id,this.composerInputEl&&(this.composerInputEl.value=""),await this.render(),setTimeout(()=>this.composerInputEl?.focus(),0)}renderChildren(t,e,i){let s=this.plugin.lastActiveStashpadLeaf?.view;if(!s||s.getViewType?.()!==J)return;let n=s.tree;if(!n?.getChildren)return;let o=n.getChildren(i);if(!o||o.length===0)return;let r=t.createDiv({cls:"stashpad-detail-children"});r.createDiv({cls:"stashpad-detail-children-header",text:`Children (${o.length})`});let A=r.createDiv({cls:"stashpad-detail-children-list"});for(let l of o)l.file&&this.renderDetailChildRow(A,s,n,e,l,0)}renderDetailChildRow(t,e,i,s,n,o){if(!n.file)return;let r=this.app.metadataCache.getFileCache(n.file)?.frontmatter??{},A=typeof r.color=="string"?r.color:null,l=r.completed===!0,d=i.getChildren(n.id),p=d.length>0,g=`${s}|${n.id}`,h=this.expanded.has(g),I=t.createDiv({cls:"stashpad-detail-child-row"});l&&I.addClass("is-completed"),o>0&&(I.style.paddingLeft=`${o*16}px`),I.draggable=!0,I.dataset.id=n.id,I.addEventListener("dragstart",m=>{m.dataTransfer?.setData("text/plain",n.id),m.dataTransfer&&(m.dataTransfer.effectAllowed="move"),I.addClass("is-dragging")}),I.addEventListener("dragend",()=>I.removeClass("is-dragging")),I.addEventListener("dragover",m=>{m.preventDefault(),m.dataTransfer&&(m.dataTransfer.dropEffect="move");let y=I.getBoundingClientRect(),Q=m.clientY-y.top<y.height/2;I.toggleClass("drop-before",Q),I.toggleClass("drop-after",!Q)}),I.addEventListener("dragleave",()=>{I.removeClass("drop-before"),I.removeClass("drop-after")}),I.addEventListener("drop",m=>{m.preventDefault(),I.removeClass("drop-before"),I.removeClass("drop-after");let y=m.dataTransfer?.getData("text/plain");if(!y||y===n.id)return;let Q=I.getBoundingClientRect(),E=m.clientY-Q.top<Q.height/2;typeof e.reorderToTarget=="function"&&e.reorderToTarget([y],n.id,E?"before":"after")}),I.oncontextmenu=m=>{m.preventDefault();let y=i.get(n.id);y&&typeof e.openNoteMenu=="function"&&e.openNoteMenu(m,y)};let u=I.createSpan({cls:"stashpad-detail-child-toggle"});if(p&&(Ae(u,d.length,h),u.onclick=m=>{m.stopPropagation(),this.expanded.has(g)?this.expanded.delete(g):this.expanded.add(g),this.render()}),Te(r,"task")||r.task===!0||r.completed!==void 0){let m=I.createSpan({cls:"stashpad-detail-child-checkbox"});(0,Et.setIcon)(m,l?"check-square":"square"),m.title=l?"Mark not done":"Mark done",m.addEventListener("mousedown",y=>y.stopPropagation()),m.addEventListener("dblclick",y=>{y.preventDefault(),y.stopPropagation()}),m.onclick=y=>{y.preventDefault(),y.stopPropagation();let Q=i.get(n.id);Q&&typeof e.toggleCompletedForNode=="function"&&e.toggleCompletedForNode(Q)}}let C=I.createSpan({cls:"stashpad-detail-child-icon"});(0,Et.setIcon)(C,p?"folder-tree":"file-text"),A&&(C.style.color=A);let B=I.createSpan({cls:"stashpad-detail-child-title",text:this.titleFor(n.file)});if(B.onclick=()=>{e?.navigateTo&&e.navigateTo(n.id)},p&&h)for(let m of d)this.renderDetailChildRow(t,e,i,s,m,o+1)}renderFooterMeta(t,e,i,s){let n=t.createDiv({cls:"stashpad-detail-footer-meta"}),o=[];if(typeof i.author=="string"&&i.author&&o.push({label:"Author",value:this.stripWikiLink(i.author)}),Array.isArray(i.contributors)){let r=i.contributors.filter(A=>typeof A=="string").map(A=>this.stripWikiLink(A));r.length>0&&o.push({label:"Contributors",value:r.join(", ")})}if(typeof i.modified=="string"&&o.push({label:"Modified",value:this.formatTime(i.modified)}),typeof i.created=="string"&&o.push({label:"Created",value:this.formatTime(i.created)}),o.push({label:"Path",value:e.path}),o.push({label:"ID",value:s.id}),o.length===0){n.remove();return}for(let r of o){let A=n.createDiv({cls:"stashpad-detail-meta-line"});A.createSpan({cls:"stashpad-detail-meta-key",text:r.label}),A.createSpan({cls:"stashpad-detail-meta-val",text:r.value})}}titleFor(t){return t.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ")}stripFrontmatter(t){if(!t.startsWith("---"))return t;let e=t.indexOf(` +---`,3);return e<0?t:t.slice(e+4).replace(/^\n+/,"")}stripWikiLink(t){let e=t.match(/^\[\[(.+?)(?:\|(.+))?\]\]$/);return e?e[2]??(e[1].split("/").pop()??e[1]).replace(/\.md$/,""):t}formatTime(t){let e=Date.parse(t);return Number.isFinite(e)?$t(e,this.plugin.settings):t}async openInStashpad(t,e){try{let i=await this.plugin.activateViewForFolder(t);e!==F&&this.plugin.navigateLeafTo(i,t,e)}catch(i){new Et.Notice(`Couldn't open: ${i.message}`)}}};async function Fs(c){let a=c.workspace.getLeavesOfType(ye);if(a.length>0){c.workspace.revealLeaf(a[0]);return}let t=c.workspace.getRightLeaf(!1);if(!t){new Et.Notice("Stashpad: couldn't open the detail panel.");return}await t.setViewState({type:ye,active:!0}),c.workspace.revealLeaf(t)}var k=require("obsidian");rt();var Ce=require("obsidian");rt();function YA(c,a){let t=c.vault.getAbstractFileByPath(a);if(!(t instanceof Ce.TFolder))return[];let e=[],i=[t];for(;i.length;){let s=i.pop();for(let n of s.children)n instanceof Ce.TFile?n.extension==="md"&&e.push(n):n instanceof Ce.TFolder&&(si.has(n.name)||i.push(n))}return e}var ks=class{constructor(a){this.app=a;this.nodes=new Map;this.byPath=new Map;this.listeners=new Set;this.orderProvider=null;this.synthetic=new Map;this.coalesceTimer=null;this.nodes.set(F,{id:F,parent:null,children:[],file:null,created:""})}setOrderProvider(a){this.orderProvider=a}onChange(a){return this.listeners.add(a),()=>this.listeners.delete(a)}emit(){for(let a of this.listeners)a()}rebuild(a){a!==void 0&&(this.currentFolder=a);let t=this.currentFolder,e=this.byPath,i=this.nodes;this.nodes=new Map,this.byPath=new Map,this.nodes.set(F,{id:F,parent:null,children:[],file:null,created:""});let s=t?YA(this.app,t):this.app.vault.getMarkdownFiles();for(let n of s){let o=this.app.metadataCache.getFileCache(n)?.frontmatter,r=o?.id;if(!r){let l=e.get(n.path),d=l?i.get(l):void 0,p=this.synthetic.get(n.path),g=d??p;g&&(this.nodes.set(g.id,{...g,children:[],file:n}),this.byPath.set(n.path,g.id));continue}if(this.synthetic.delete(n.path),r===F){let l=this.nodes.get(F);l.file=n,l.created=o?.created??"",this.byPath.set(n.path,F);continue}let A=o?.parent??null;A===r&&(A=null),this.nodes.set(r,{id:r,parent:A??F,children:[],file:n,created:o?.created??""}),this.byPath.set(n.path,r)}for(let n of this.nodes.values()){if(n.id===F)continue;let o=n.parent??F;(this.nodes.get(o)??this.nodes.get(F)).children.push(n.id)}for(let n of this.nodes.values())if(n.children.sort((o,r)=>{let A=this.nodes.get(o),l=this.nodes.get(r);return(A.created||"").localeCompare(l.created||"")}),this.orderProvider){let o=this.orderProvider(n.id);if(o.length>0){let r=new Map;o.forEach((A,l)=>r.set(A,l)),n.children.sort((A,l)=>{let d=r.has(A)?r.get(A):1/0,p=r.has(l)?r.get(l):1/0;return d===p?0:d-p})}}this.emit()}insertSynthetic(a){if(!a.file)return;let t=a.file.path;this.synthetic.set(t,a),this.nodes.set(a.id,a),this.byPath.set(t,a.id);let e=a.parent??F,i=this.nodes.get(e);i&&!i.children.includes(a.id)&&i.children.push(a.id),this.emit()}get(a){return this.nodes.get(a)}getRoot(){return this.nodes.get(F)}getChildren(a){let t=this.nodes.get(a);return t?t.children.map(e=>this.nodes.get(e)).filter(e=>!!e):[]}fileBackedCount(){let a=0;for(let t of this.nodes.values())t.file&&a++;return a}pathTo(a){let t=[],e=new Set,i=this.nodes.get(a);for(;i&&i.id!==F&&!e.has(i.id);)e.add(i.id),t.unshift(i),i=i.parent?this.nodes.get(i.parent):void 0;return t}idForPath(a){return this.byPath.get(a)}snapshot(){let a={};for(let t of this.nodes.values())t.id===F||!t.file||(a[t.id]={parent:t.parent===F?null:t.parent,path:t.file.path});return a}hookMetadataCache(a){let t=A=>{let l=this.currentFolder;return l?typeof A!="string"?!1:A===l||A.startsWith(l+"/"):!0},e=!1,i=()=>{e=!0,this.coalesceTimer==null&&(this.coalesceTimer=window.setTimeout(()=>{this.coalesceTimer=null,e&&(e=!1,this.emit(),a())},16))},s=A=>{A instanceof Ce.TFile&&t(A.path)&&A.extension==="md"&&(this.applyChange(A),i())},n=A=>{A instanceof Ce.TFile&&t(A.path)&&A.extension==="md"&&this.applyChange(A)&&i()},o=A=>{let l=A?.path;typeof l=="string"&&t(l)&&this.applyDelete(l)&&i()},r=(A,l)=>{if(!(A instanceof Ce.TFile))return;let d=typeof l=="string"?l:null;!t(A.path)&&!t(d)||this.applyRename(A,d??"")&&i()};return this.app.metadataCache.on("changed",s),this.app.vault.on("create",n),this.app.vault.on("delete",o),this.app.vault.on("rename",r),()=>{this.app.metadataCache.off("changed",s),this.app.vault.off("create",n),this.app.vault.off("delete",o),this.app.vault.off("rename",r),this.coalesceTimer!=null&&(window.clearTimeout(this.coalesceTimer),this.coalesceTimer=null)}}applyChange(a){if(He(a.path))return this.byPath.has(a.path)?this.applyDelete(a.path):!1;let t=this.app.metadataCache.getFileCache(a)?.frontmatter,e=t?.id,i=this.byPath.get(a.path);if(!e){if(i){let l=this.nodes.get(i);if(l&&l.file!==a)return l.file=a,!0}return!1}if(this.synthetic.delete(a.path),e===F){let l=this.nodes.get(F),d=t?.created??"",p=!1;return l.file!==a&&(l.file=a,p=!0),l.created!==d&&(l.created=d,p=!0),this.byPath.get(a.path)!==F&&(this.byPath.set(a.path,F),p=!0),p}let s=t?.parent??F,n=t?.created??"";if(!(s===F||this.nodes.has(s)))return this.rebuild(),!0;if(i&&i!==e)return this.rebuild(),!0;let r=this.nodes.get(e);if(!r){let l={id:e,parent:s,children:[],file:a,created:n};return this.nodes.set(e,l),this.byPath.set(a.path,e),this.attachToParent(l),this.resortChildrenOf(s),!0}let A=!1;if(r.file!==a&&(r.file=a,A=!0),r.created!==n&&(r.created=n,this.resortChildrenOf(r.parent??F),A=!0),r.parent!==s){let l=r.parent??F;this.detachFromParent(r),r.parent=s,this.attachToParent(r),this.resortChildrenOf(l),this.resortChildrenOf(s),A=!0}return A}applyDelete(a){let t=this.byPath.get(a);if(!t)return!1;let e=this.nodes.get(t);if(!e)return this.byPath.delete(a),this.synthetic.delete(a),!0;this.detachFromParent(e);let i=this.nodes.get(F);for(let s of e.children){let n=this.nodes.get(s);n&&(n.parent=F,i.children.includes(s)||i.children.push(s))}return e.children.length>0&&this.resortChildrenOf(F),this.nodes.delete(t),this.byPath.delete(a),this.synthetic.delete(a),!0}applyRename(a,t){let e=this.currentFolder,i=!e||t===e||t.startsWith(e+"/"),s=!e||a.path===e||a.path.startsWith(e+"/");if(!i&&!s)return!1;if(i&&!s)return this.applyDelete(t);if(!i&&s)return this.applyChange(a);if(He(a.path))return this.byPath.has(t)?this.applyDelete(t):!1;let n=this.byPath.get(t);if(!n)return this.applyChange(a);this.byPath.delete(t),this.byPath.set(a.path,n);let o=this.nodes.get(n);return o&&(o.file=a),!0}detachFromParent(a){let t=this.nodes.get(a.parent??F);if(!t)return;let e=t.children.indexOf(a.id);e>=0&&t.children.splice(e,1)}attachToParent(a){let t=this.nodes.get(a.parent??F);t||(t=this.nodes.get(F)),t.children.includes(a.id)||t.children.push(a.id)}resortChildrenOf(a){let t=this.nodes.get(a);if(t&&(t.children.sort((e,i)=>{let s=this.nodes.get(e),n=this.nodes.get(i);return(s.created||"").localeCompare(n.created||"")}),this.orderProvider)){let e=this.orderProvider(a);if(e.length>0){let i=new Map;e.forEach((s,n)=>i.set(s,n)),t.children.sort((s,n)=>{let o=i.has(s)?i.get(s):1/0,r=i.has(n)?i.get(n):1/0;return o===r?0:o-r})}}}};var eo=class{constructor(){this.enabled=!1;this.buckets=new Map}record(a,t){if(!this.enabled)return;let e=this.buckets.get(a);e||(e={count:0,total:0,max:0},this.buckets.set(a,e)),e.count+=1,e.total+=t,t>e.max&&(e.max=t)}time(a,t){if(!this.enabled)return t();let e=performance.now();try{return t()}finally{this.record(a,performance.now()-e)}}async timeAsync(a,t){if(!this.enabled)return t();let e=performance.now();try{return await t()}finally{this.record(a,performance.now()-e)}}reset(){this.buckets.clear()}hasData(){return this.buckets.size>0}report(){let a=[...this.buckets.entries()].map(([e,i])=>({label:e,...i,avg:i.total/i.count})).sort((e,i)=>i.total-e.total);if(a.length===0)return"Stashpad perf: no samples (enable profiling, then use the app).";let t=["**Stashpad performance profile**","","| label | count | total (ms) | avg (ms) | max (ms) |","| --- | ---: | ---: | ---: | ---: |"];for(let e of a)t.push(`| \`${e.label}\` | ${e.count} | ${e.total.toFixed(0)} | ${e.avg.toFixed(1)} | ${e.max.toFixed(0)} |`);return t.join(` +`)}},wt=new eo;var Ka=".stashpad-order.json",$e=class{constructor(a){this.app=a;this.cache=new Map;this.pendingTimers=new Map;this.writeInFlight=new Map}async load(a){if(this.cache.has(a))return this.cache.get(a);let t=`${a}/${Ka}`,e=this.app.vault.adapter,i={};try{if(await e.exists(t)){let s=await e.read(t),n=JSON.parse(s);if(n&&typeof n=="object"&&!Array.isArray(n))for(let[o,r]of Object.entries(n))Array.isArray(r)&&r.every(A=>typeof A=="string")&&(i[o]=r)}}catch(s){console.warn("Stashpad: order load failed",s)}return this.cache.set(a,i),i}async save(a){this.scheduleWrite(a)}async flush(a){let t=this.pendingTimers.get(a);t!=null&&(window.clearTimeout(t),this.pendingTimers.delete(a)),await this.writeNow(a)}scheduleWrite(a){let t=this.pendingTimers.get(a);t!=null&&window.clearTimeout(t);let e=window.setTimeout(()=>{this.pendingTimers.delete(a),this.writeNow(a)},150);this.pendingTimers.set(a,e)}async writeNow(a){let e=(this.writeInFlight.get(a)??Promise.resolve()).then(()=>this.doWrite(a));this.writeInFlight.set(a,e);try{await e}finally{this.writeInFlight.get(a)===e&&this.writeInFlight.delete(a)}}async doWrite(a){let t=this.cache.get(a)??{},e={};for(let[n,o]of Object.entries(t))o.length>0&&(e[n]=o);this.cache.set(a,e);let i=`${a}/${Ka}`,s=this.app.vault.adapter;try{if(Object.keys(e).length===0)try{await s.remove(i)}catch{}else await s.write(i,JSON.stringify(e,null,2))}catch(n){console.warn("Stashpad: order save failed",n)}}getOrder(a,t){return this.cache.get(a)?.[t]?.slice()??[]}setOrder(a,t,e){let i=this.cache.get(a)??{};i[t]=e.slice(),this.cache.set(a,i)}appendChild(a,t,e){let i=this.cache.get(a)??{},s=i[t]??[];s.includes(e)||s.push(e),i[t]=s,this.cache.set(a,i)}removeChild(a,t){let e=this.cache.get(a);if(e)for(let i of Object.values(e)){let s=i.indexOf(t);s>=0&&i.splice(s,1)}}invalidate(a){this.cache.delete(a)}};var Hi={manual:"Manual","created-asc":"Created \u2014 oldest first","created-desc":"Created \u2014 newest first","modified-asc":"Modified \u2014 oldest first","modified-desc":"Modified \u2014 newest first","title-az":"Title \u2014 A\u2192Z","title-za":"Title \u2014 Z\u2192A"},io=["manual","created-asc","created-desc","modified-asc","modified-desc","title-az","title-za"],zA=new Set(io),Oa=".stashpad-sort.json",Ss=class{constructor(a){this.app=a;this.cache=new Map;this.pendingTimers=new Map;this.writeInFlight=new Map}async load(a){if(this.cache.has(a))return this.cache.get(a);let t=`${a}/${Oa}`,e=this.app.vault.adapter,i={};try{if(await e.exists(t)){let s=JSON.parse(await e.read(t));if(s&&typeof s=="object"&&!Array.isArray(s))for(let[n,o]of Object.entries(s))typeof o=="string"&&zA.has(o)&&(i[n]=o)}}catch(s){console.warn("Stashpad: sort load failed",s)}return this.cache.set(a,i),i}async save(a){this.scheduleWrite(a)}async flush(a){let t=this.pendingTimers.get(a);t!=null&&(window.clearTimeout(t),this.pendingTimers.delete(a)),await this.writeNow(a)}scheduleWrite(a){let t=this.pendingTimers.get(a);t!=null&&window.clearTimeout(t);let e=window.setTimeout(()=>{this.pendingTimers.delete(a),this.writeNow(a)},150);this.pendingTimers.set(a,e)}async writeNow(a){let e=(this.writeInFlight.get(a)??Promise.resolve()).then(()=>this.doWrite(a));this.writeInFlight.set(a,e);try{await e}finally{this.writeInFlight.get(a)===e&&this.writeInFlight.delete(a)}}async doWrite(a){let t=this.cache.get(a)??{},e=`${a}/${Oa}`,i=this.app.vault.adapter;try{if(Object.keys(t).length===0)try{await i.remove(e)}catch{}else await i.write(e,JSON.stringify(t,null,2))}catch(s){console.warn("Stashpad: sort save failed",s)}}getMode(a,t){return this.cache.get(a)?.[t]??"manual"}setMode(a,t,e){let i=this.cache.get(a)??{};e==="manual"?delete i[t]:i[t]=e,this.cache.set(a,i)}removeParent(a,t){let e=this.cache.get(a);e&&delete e[t]}invalidate(a){this.cache.delete(a)}};rt();var Be="parentLink",We="children";var Ns=class Ns{constructor(a,t){this.app=a;this.getTree=t;this.pending=new Set;this.timer=null;this.activityListeners=new Set;this.errorListeners=new Set}onActivity(a){return this.activityListeners.add(a),()=>this.activityListeners.delete(a)}emitActivity(){let a=this.pending.size;for(let t of this.activityListeners)try{t(a)}catch(e){console.warn("[Stashpad] fmSync activity listener failed",e)}}schedule(a){if(!a||!j().writeRecoveryLinks)return;let t=this.pending.size;this.pending.add(a),this.pending.size!==t&&this.emitActivity(),this.kick()}scheduleParentChange(a,t,e){this.schedule(a),t&&this.schedule(t),this.schedule(e)}scheduleSubtree(a){let t=this.getTree(),e=i=>{this.schedule(i);for(let s of t.getChildren(i))e(s.id)};e(a)}scheduleParentOfDeleted(a){a&&this.schedule(a)}async flush(){for(this.timer!=null&&(window.clearTimeout(this.timer),this.timer=null);this.pending.size>0;){let a=this.pending.values().next().value;if(a===void 0)break;this.pending.delete(a),this.emitActivity(),await this.syncOne(a)}}pendingCount(){return this.pending.size}onError(a){return this.errorListeners.add(a),()=>this.errorListeners.delete(a)}emitError(a,t){for(let e of this.errorListeners)try{e(a,t)}catch(i){console.warn("[Stashpad] fmSync error listener failed",i)}}reset(){this.timer!=null&&(window.clearTimeout(this.timer),this.timer=null),this.pending.clear()}kick(){this.timer!=null||this.pending.size===0||(this.timer=window.setTimeout(()=>this.tick(),Ns.PACING_MS))}async tick(){this.timer=null;let a=this.pending.values().next().value;if(a!==void 0){this.pending.delete(a),this.emitActivity();try{await this.syncOne(a)}catch(t){console.warn("[Stashpad] frontmatter sync tick failed",t)}this.pending.size>0&&this.kick()}}wouldWrite(a){let e=this.getTree().get(a);if(!e||!e.file)return!1;let i=this.computeParentLink(e),s=this.computeChildrenLinks(e),n=this.app.metadataCache.getFileCache(e.file)?.frontmatter,o=n&&typeof n[Be]=="string"?n[Be]:null,r=n?.[We],A=Array.isArray(r)?r.filter(l=>typeof l=="string"):[];if((o??null)!==(i??null)||A.length!==s.length)return!0;for(let l=0;l<A.length;l++)if(A[l]!==s[l])return!0;return!1}async syncOne(a){let e=this.getTree().get(a);if(!e||!e.file||!this.wouldWrite(a))return;let i=this.computeParentLink(e),s=this.computeChildrenLinks(e);try{await wt.timeAsync("write.fmSync",()=>this.app.fileManager.processFrontMatter(e.file,n=>{i?n[Be]=i:delete n[Be],s.length>0?n[We]=s:delete n[We]}))}catch(n){console.warn("[Stashpad] frontmatter sync failed",e.file?.path,n),this.emitError(e.file.path,n)}}computeParentLink(a){if(a.id===F)return null;let t=this.getTree();if(!a.parent||a.parent===F){let i=t.getRoot();return i&&i.id!==a.id&&i.file?Ds(i.file.path):null}let e=t.get(a.parent);return e?.file?Ds(e.file.path):null}computeChildrenLinks(a){return this.getTree().getChildren(a.id).filter(e=>!!e.file).map(e=>Ds(e.file.path))}};Ns.PACING_MS=100;var bs=Ns;async function Xe(c,a){let t=a.endsWith("/")?a:a+"/",e=new Map,i=new Map;for(let l of c.vault.getMarkdownFiles()){if(l.path!==a&&!l.path.startsWith(t))continue;let d=c.metadataCache.getFileCache(l)?.frontmatter,p=typeof d?.id=="string"?d.id:null;if(!p)continue;let g=typeof d?.parent=="string"?d.parent:F;e.set(p,{file:l,id:p,parent:g});let h=i.get(g)??[];h.push(p),i.set(g,h)}let s=l=>Ds(l.file.path),n=l=>{if(l.id===F)return null;if(l.parent===F||!l.parent){let p=e.get(F);return p?s(p):null}let d=e.get(l.parent);return d?s(d):null},o=l=>{let d=i.get(l.id)??[],p=[];for(let g of d){let h=e.get(g);h&&p.push(s(h))}return p},r=0,A=0;for(let l of e.values()){r+=1;let d=n(l),p=o(l),g=c.metadataCache.getFileCache(l.file)?.frontmatter,h=g&&typeof g[Be]=="string"?g[Be]:null,I=g?.[We],u=Array.isArray(I)?I.filter(B=>typeof B=="string"):[],f=(h??null)===(d??null),C=u.length===p.length&&u.every((B,m)=>B===p[m]);if(!(f&&C))try{await c.fileManager.processFrontMatter(l.file,B=>{d?B[Be]=d:delete B[Be],p.length>0?B[We]=p:delete B[We]}),A+=1,await new Promise(B=>setTimeout(B,50))}catch(B){console.warn("[Stashpad] rebootstrap fm sync failed",l.file.path,B)}}return{checked:r,written:A}}function Ds(c){return`[[${c.replace(/\.md$/i,"")}]]`}Tt();Re();var xs=class{constructor(a,t){this.tree=a;this.log=t}async sweep(a){let t=await this.log.readState(),e=this.tree.snapshot(),i=n=>{if(!a)return!0;let o=a.replace(/\/+$/,"");return n===o||n.startsWith(o+"/")};for(let[n,o]of Object.entries(e)){let r=t[n];r?r.parent!==o.parent?await this.log.append({type:"parent_change",id:n,payload:{from:r.parent,to:o.parent}}):r.path!==o.path&&await this.log.append({type:"rename",id:n,payload:{from:r.path,to:o.path}}):await this.log.append({type:"create",id:n,payload:{path:o.path,parent:o.parent}})}for(let[n,o]of Object.entries(t))!e[n]&&i(o.path)&&await this.log.append({type:"missing",id:n,payload:{lastPath:o.path}});let s={};for(let[n,o]of Object.entries(t))i(o.path)||(s[n]=o);for(let[n,o]of Object.entries(e))s[n]=o;await this.log.writeState(s)}};var ht=require("obsidian");rt();An();var ft=ht.moment;function so(c){let a=c.trim().toLowerCase();if(!a)return null;let t=Date.now(),e=I=>ft(I).startOf("day").valueOf(),i=/\b(\d{1,2})(?::(\d{2}))?\s*(am|pm)?\b/,s=0,n=!1,o=a,r=i.exec(a);if(r&&(r[3]||r[2])){let I=parseInt(r[1],10),u=r[2]?parseInt(r[2],10):0,f=r[3];f==="pm"&&I<12&&(I+=12),f==="am"&&I===12&&(I=0),I>=0&&I<24&&u>=0&&u<60&&(s=(I*3600+u*60)*1e3,n=!0,o=a.replace(r[0]," ").replace(/\s+/g," ").trim())}let A=I=>n?I+s:I;if(o===""||o==="today")return A(e(t));if(o==="yesterday")return A(e(t)-864e5);if(o==="tomorrow")return A(e(t)+864e5);let l=["sunday","monday","tuesday","wednesday","thursday","friday","saturday"],d=["sun","mon","tue","wed","thu","fri","sat"],p=l.indexOf(o)>=0?l.indexOf(o):d.indexOf(o);if(p>=0){let I=ft().startOf("day"),f=(I.day()-p+7)%7;return A(I.subtract(f,"days").valueOf())}let g=/^(\d+)\s*([dwmy])$/.exec(o);if(g){let I=parseInt(g[1],10),u={d:"days",w:"weeks",m:"months",y:"years"}[g[2]];return A(ft().subtract(I,u).startOf("day").valueOf())}let h=ft(o,["YYYY-MM-DD","YYYY/MM/DD","MM-DD-YYYY","MM/DD/YYYY","M-D-YYYY","M/D/YYYY"],!0);return h.isValid()?A(h.startOf("day").valueOf()):null}function Ya(c){let a={text:[],filters:{}},t=(c||"").trim();if(!t)return a;let e=/\b(in|before|after|on):\s*(?:\[([^\]]*)\]|([^]*?)(?=\s+(?:in|before|after|on):|$))/gi,i=t,s;for(;(s=e.exec(t))!=null;){let n=s[1].toLowerCase(),o=(s[2]!==void 0?s[2]:s[3]??"").trim();if(o){if(n==="in")a.filters.in=o.toLowerCase();else if(n==="before"){let r=so(o);r!=null&&(a.filters.before=r)}else if(n==="after"){let r=so(o);r!=null&&(a.filters.after=r)}else if(n==="on"){let r=so(o);if(r!=null)if(/\b\d{1,2}:\d{2}\b|\b\d{1,2}\s*(?:am|pm)\b/i.test(o))a.filters.on={start:r-6e4,end:r+6e4};else{let l=ft(r).startOf("day").valueOf();a.filters.on={start:l,end:l+864e5}}}i=i.replace(s[0]," ")}}for(let n of i.split(/\s+/))n&&a.text.push(n.toLowerCase());return a}var zt=class c extends ht.SuggestModal{constructor(t,e,i,s){super(t);this.tree=e;this.titleFn=i;this.opts=s;this.notes=[];this.includeExcluded=!1;this.pendingCleanups=[];this.crossFolderIndex=null;this.whenBuilderEl=null;this.whenMode="on";this.whenSingleText="";this.whenBetweenEndText="";this.setPlaceholder(s.placeholder??(s.mode==="search"?"Search notes\u2026":"Pick a note\u2026")),this.loadAll()}onClose(){for(;this.pendingCleanups.length>0;){let t=this.pendingCleanups.pop();try{t&&t()}catch{}}try{this.opts.onClose?.()}catch{}}loadAll(){let t=this.tree.getRoot(),e=t.file?.parent?.name?.trim()??"",i=e?`Home \u2014 ${e}`:"Home",s=(n,o)=>{let r=this.tree.get(n);r?.file&&n!==F?this.notes.push({node:r,title:`${" ".repeat(o)}${this.titleFn(r)}`,body:""}):r?.file&&n===F&&this.notes.push({node:r,title:i,body:""});for(let A of this.tree.getChildren(n))s(A.id,o+1)};t.file&&this.notes.push({node:t,title:i,body:""});for(let n of this.tree.getChildren(F))s(n.id,1);for(let n of this.notes)n.node?.file&&this.app.vault.cachedRead(n.node.file).then(o=>{n.body=this.stripFm(o)});if(this.opts.crossFolderNotes){let n=this.opts.crossFolderNotes();for(let o of n)this.notes.push({node:null,title:o.title,body:o.body,cross:o});for(let o of this.notes)!o.cross||o.body||o.cross.file&&this.app.vault.cachedRead(o.cross.file).then(r=>{o.body=this.stripFm(r)})}}createdMsFor(t){if(t.node?.created){let e=Date.parse(t.node.created);if(!Number.isNaN(e))return e}return t.cross?.file?.stat?.ctime!=null?t.cross.file.stat.ctime:null}stripFm(t){if(!t.startsWith("---"))return t;let e=t.indexOf(` +---`,3);return e===-1?t:t.slice(e+4).replace(/^\r?\n/,"")}getSuggestions(t){let e=t.trim().toLowerCase(),i=Ya(t),s=i.text;console.log("[Stashpad] search query parsed",{query:t,text:i.text,filters:i.filters});let n=C=>{if(!s.length)return!0;for(let B of s)if(!C.includes(B))return!1;return!0},o=null,r=null;if(i.filters.in){let C=i.filters.in.split(/\s+/).filter(Boolean);o=new Set,r=new Map;let B=Q=>C.every(E=>Q.toLowerCase().includes(E)),m=Q=>{if(!o.has(Q)){o.add(Q);for(let E of this.tree.getChildren(Q))m(E.id)}};for(let Q of this.notes)!Q.node||Q.cross||B(Q.title)&&m(Q.node.id);let y=new Map;for(let Q of this.notes){if(!Q.cross)continue;let E=y.get(Q.cross.folder)??[];E.push(Q),y.set(Q.cross.folder,E)}for(let[Q,E]of y){let v=new Map;for(let N of E){let P=N.cross?.parentId??null;if(!P)continue;let H=v.get(P)??[];H.push(N.cross.id),v.set(P,H)}let w=new Set;r.set(Q,w);let D=N=>{if(!w.has(N)){w.add(N);for(let P of v.get(N)??[])D(P)}};for(let N of E)B(N.title)&&D(N.cross.id)}}let A=C=>{let B=i.filters;if(o||r)if(C.cross){let m=r?.get(C.cross.folder);if(!m||!m.has(C.cross.id))return!1}else if(C.node){if(!o||!o.has(C.node.id))return!1}else return!1;if(B.before||B.after||B.on){let m=this.createdMsFor(C);if(m==null||B.before!=null&&m>=B.before||B.after!=null&&m<=B.after||B.on&&(m<B.on.start||m>=B.on.end))return!1}return!0},l=C=>n(C.toLowerCase()),d=this.notes.filter(C=>!C.cross),p=this.notes.filter(C=>C.cross),g=(C,B)=>({id:C.cross?`cross:${C.cross.folder}:${C.cross.id}`:C.node.id,label:C.title,node:C.node,kind:"note",bodyPreview:this.previewFromBody(C.body,B),matchLine:B,crossFolder:C.cross?.folder,crossFile:C.cross?.file,crossId:C.cross?.id}),h=C=>{let B=[];for(let m of C)if(A(m))if(this.opts.mode==="search"){if(!e){B.push(g(m,-1));continue}let y=n(m.title.toLowerCase()),Q=m.body.split(/\r?\n/),E=[];for(let w=0;w<Q.length;w++)l(Q[w])&&E.push(w);let v=E.length>0||n(m.body.toLowerCase());if(!y&&!v)continue;if(E.length===0)B.push(g(m,-1));else{let w=[],D=-100;for(let P of E)P-D>5&&w.push(P),D=P;let N=5;for(let P of w.slice(0,N))B.push(g(m,P))}}else{if(e&&!n(m.title.toLowerCase())&&!n(m.body.toLowerCase()))continue;B.push(g(m,-1))}return B},I=h(d),u=[...I];if(this.opts.mode==="search"?e?!0:I.length<10:!!e){let C=h(p);this.opts.mode==="search"&&!e&&(u.length=Math.min(u.length,50)),u.push(...C)}if(this.opts.folderResults){let C=this.opts.folderResults(),B={id:"__folder_picker__",label:"Open folder in a new tab\u2026",node:null,kind:"folder-open"};C.length>0&&(e?C.some(m=>{let y=m.split("/").pop()??m;return n(`${m.toLowerCase()} ${y.toLowerCase()}`)})&&u.push(B):u.unshift(B))}if(this.opts.allowCreate&&e&&!u.some(C=>C.label.trim().toLowerCase()===e)&&u.push({id:"__create__",label:`Create new: "${t}"`,node:null,kind:"create"}),i.text.join("").length>=3){let C=m=>m.kind==="note"&&(m.id===F||m.crossId===F)&&n(m.label.toLowerCase()),B=u.filter(C);if(B.length>0){let m=u.filter(y=>!C(y));u.splice(0,u.length,...B,...m)}}return this.opts.excludedFolderNotes&&!this.includeExcluded&&u.push({id:"__search_excluded__",label:"Search excluded Stashpad folders",node:null,kind:"search-excluded"}),u}loadExcludedNotes(){if(this.includeExcluded||!this.opts.excludedFolderNotes)return;this.includeExcluded=!0;for(let e of this.opts.excludedFolderNotes())this.notes.push({node:null,title:e.title,body:e.body,cross:e});for(let e of this.notes)!e.cross||e.body||!e.cross.file||this.app.vault.cachedRead(e.cross.file).then(i=>{e.body=this.stripFm(i)});let t=this.inputEl;t&&(t.dispatchEvent(new Event("input",{bubbles:!0})),setTimeout(()=>t.dispatchEvent(new Event("input",{bubbles:!0})),250))}previewFromBody(t,e){let i=t.split(/\r?\n/);if(e<0)return i.filter(r=>r.trim().length>0).slice(0,3).join(` `);let s=Math.max(0,e-2),n=Math.min(i.length,e+3);return i.slice(s,n).filter(o=>o.trim().length>0).join(` -`)}renderSuggestion(t,e){if(e.addClass("stashpad-suggest-item"),t.kind==="create"){e.createDiv({cls:"stashpad-suggest-create",text:t.label});return}if(t.kind==="folder-open"){e.addClass("is-folder-open"),e.createDiv({cls:"stashpad-suggest-title",text:t.label}),t.folder?e.createDiv({cls:"stashpad-suggest-preview",text:t.folder}):e.createDiv({cls:"stashpad-suggest-preview",text:"Click to choose a folder\u2026"});return}if(t.kind==="search-excluded"){e.addClass("is-search-excluded");let h=e.createDiv({cls:"stashpad-suggest-title stashpad-search-excluded-row"}),I=h.createSpan({cls:"stashpad-search-excluded-icon"});(0,ht.setIcon)(I,"folder-search"),h.createSpan({text:t.label}),e.createDiv({cls:"stashpad-suggest-preview",text:"Include folders you've excluded from search (e.g. to move a note there)."});return}t.crossFolder&&e.addClass("is-cross-folder"),e.addClass("stashpad-suggest-row");let i=e.createDiv({cls:"stashpad-suggest-body"}),s=this.notes.find(h=>t.crossFolder?h.cross?.folder===t.crossFolder&&h.cross?.id===t.crossId:h.node?.id===t.id),n=Ta(this.inputEl?.value??"").text,o=this.firstLineOfBody(s?.body??"")||t.label.trim(),r=i.createDiv({cls:"stashpad-suggest-title"});this.highlightInto(r,o,n);let A=t.crossFolder??this.opts.localFolder??null;if(t.bodyPreview&&t.matchLine!=null&&t.matchLine>=0){let h=i.createDiv({cls:"stashpad-suggest-preview stashpad-suggest-snippet"});this.highlightInto(h,t.bodyPreview,n)}let l="";if(t.crossFolder?l=s?.cross?.parentBlurb??"":l=this.parentBlurbFor(t.node),l){let h=i.createDiv({cls:"stashpad-suggest-preview"});h.appendText("Parent: "),this.highlightInto(h,l,n)}let d=t.crossFolder?this.buildCrossBreadcrumb(t):this.buildLocalBreadcrumb(t.node),g=t.crossFolder??this.opts.localFolder??null;if(g||d){let h=i.createDiv({cls:"stashpad-suggest-breadcrumb"}),u=[g?g.split("/").pop()||g:"",d].filter(f=>f&&f.length>0).join(" \u203A ");u&&h.setText(u)}let p=s?this.createdMsFor(s):null;if(p!=null||A){let h=e.createDiv({cls:"stashpad-suggest-rail"});if(p!=null){let I=h.createDiv({cls:"stashpad-suggest-time"});I.setText(this.formatRelativeTime(p)),I.title=ft(p).format("YYYY-MM-DD HH:mm")}A&&h.createDiv({cls:"stashpad-suggest-folder-badge",text:A.split("/").pop()||A})}}formatRelativeTime(t){let e=ft(t),i=ft().startOf("day").diff(ft(t).startOf("day"),"days");return i===0?e.format("h:mm a"):i===1?"yesterday":i>1&&i<7?`${i}d ago`:i>=7&&i<30?`${Math.floor(i/7)}w ago`:i>=30&&i<365?e.format("MMM D"):e.format("MMM D, YYYY")}highlightInto(t,e,i){if(!e)return;let s=i.filter(l=>l&&l.length>0);if(!s.length){t.appendText(e);return}let n=e.toLowerCase(),o=[];for(let l of s){let d=0;for(;(d=n.indexOf(l,d))!==-1;)o.push([d,d+l.length]),d+=l.length}if(!o.length){t.appendText(e);return}o.sort((l,d)=>l[0]-d[0]);let r=[];for(let l of o){let d=r[r.length-1];d&&l[0]<=d[1]?d[1]=Math.max(d[1],l[1]):r.push([l[0],l[1]])}let A=0;for(let[l,d]of r)l>A&&t.appendText(e.slice(A,l)),t.createSpan({cls:"stashpad-suggest-match",text:e.slice(l,d)}),A=d;A<e.length&&t.appendText(e.slice(A))}buildLocalBreadcrumb(t){if(!t||!t.parent||t.parent===F)return"";let e=[],i=new Set([t.id]),s=this.tree.get(t.parent);for(;s&&s.id!==F&&!i.has(s.id);)i.add(s.id),e.unshift(this.titleFn(s)),s=s.parent&&s.parent!==F?this.tree.get(s.parent):void 0;return e.join(" \u203A ")}buildCrossBreadcrumb(t){if(!t.crossFolder)return"";if(!this.crossFolderIndex){this.crossFolderIndex=new Map;for(let A of this.notes){if(!A.cross)continue;let l=this.crossFolderIndex.get(A.cross.folder);l||(l=new Map,this.crossFolderIndex.set(A.cross.folder,l)),l.set(A.cross.id,A.cross)}}let e=this.crossFolderIndex.get(t.crossFolder);if(!e)return"";let i=t.crossId??t.id.replace(/^cross:/,""),s=e.get(i);if(!s)return"";let n=[],o=new Set([s.id]),r=s.parentId?e.get(s.parentId):null;for(;r&&!o.has(r.id);)o.add(r.id),n.unshift(r.title),r=r.parentId?e.get(r.parentId):null;return n.join(" \u203A ")}firstLineOfBody(t){if(!t)return"";let e=t.split(/\r?\n/);for(let i of e){let s=i.trim();if(s)return s}return""}parentBlurbFor(t){if(!t||!t.parent||t.parent===F)return"";let e=this.tree.get(t.parent);if(!e||!e.file)return"";let i=this.notes.find(s=>s.node?.id===e.id);return i?this.firstLineOfBody(i.body):""}onOpen(){if(super.onOpen(),this.opts.showFilterChips&&!ht.Platform.isMobile){let t=this.inputEl,e=this.resultContainerEl;if(!t||!e)return;this.mountFilterChipRow(t,e);return}if(ht.Platform.isMobile){let t=this.inputEl;t&&t.focus()}}mountFilterChipRow(t,e){t.addEventListener("keydown",l=>{if(l.key==="["){l.preventDefault();let d=t.selectionStart??t.value.length,g=t.selectionEnd??d,p=t.value.slice(0,d),h=t.value.slice(d,g),I=t.value.slice(g);t.value=`${p}[${h}]${I}`;let u=d+1+h.length;t.setSelectionRange(u,u),t.dispatchEvent(new Event("input",{bubbles:!0}));return}if(l.key==="]"){let d=t.selectionStart??-1;d>=0&&t.value[d]==="]"&&(l.preventDefault(),t.setSelectionRange(d+1,d+1));return}if(l.key==="Backspace"&&!l.metaKey&&!l.ctrlKey&&!l.altKey&&t.selectionStart===t.selectionEnd){let d=t.selectionStart??-1;if(d>0&&t.value[d-1]==="["&&t.value[d]==="]"){l.preventDefault();let g=t.value.slice(0,d-1),p=t.value.slice(d+1);t.value=`${g}${p}`,t.setSelectionRange(d-1,d-1),t.dispatchEvent(new Event("input",{bubbles:!0}))}}});let i=document.createElement("div");i.className="stashpad-search-filter-row";let s=document.createElement("span");s.className="stashpad-search-filter-label",s.textContent="Filters:",i.appendChild(s);let n=document.createElement("button");n.className="stashpad-search-filter-chip",n.type="button",n.textContent="in:[parent note]",n.title='Insert "in:" \u2014 filter by parent note.',n.addEventListener("mousedown",l=>{l.preventDefault()}),n.addEventListener("click",l=>{l.preventDefault(),this.appendFilterToInput(t,"in","")}),n.addEventListener("keydown",l=>{(l.key==="Enter"||l.key===" ")&&(l.preventDefault(),l.stopPropagation(),n.click())}),i.appendChild(n);let o=document.createElement("button");o.className="stashpad-search-filter-chip stashpad-search-filter-when",o.type="button",o.textContent="when:[date / day / timeframe]",o.title="Open the time-filter builder (Before / On / After / Between).",o.addEventListener("mousedown",l=>{l.preventDefault()}),o.addEventListener("click",l=>{l.preventDefault(),this.toggleWhenBuilder(t,i)}),o.addEventListener("keydown",l=>{(l.key==="Enter"||l.key===" ")&&(l.preventDefault(),l.stopPropagation(),o.click())}),i.appendChild(o),e.parentElement?.insertBefore(i,e);let r=new ht.Scope(this.scope),A=l=>{let d=document.activeElement;return d?.classList?.contains("stashpad-search-filter-chip")?(l.preventDefault(),d.click(),!1):l.key==="Enter"&&!l.isComposing?(l.preventDefault(),this.selectActiveSuggestion?.(l),!1):!0};r.register([],"Enter",A),r.register([]," ",A),r.register(["Mod"],"f",l=>{l.preventDefault();let d=this.inputEl;return d&&(d.focus(),d.select()),!1}),r.register([],"Tab",l=>{let d=this.modalEl,g=this.inputEl;if(!d)return!0;let p=Array.from(d.querySelectorAll('input, button, select, textarea, a[href], [tabindex]:not([tabindex="-1"])')).filter(u=>!u.hasAttribute("disabled")&&u.tabIndex!==-1&&u.offsetParent!==null);if(p.length===0)return!0;let h=document.activeElement,I=h?p.indexOf(h):-1;if(l.shiftKey){if(I<=0)return l.preventDefault(),p[p.length-1].focus(),!1}else if(I===p.length-1)return l.preventDefault(),(g??p[0]).focus(),!1;return!0}),this.app.keymap?.pushScope(r),this.pendingCleanups.push(()=>{try{this.app.keymap?.popScope(r)}catch{}})}appendFilterToInput(t,e,i){let s=t.value,o=`${s.length>0&&!/\s$/.test(s)?" ":""}${e}: [`,r="]",A=i;t.value=`${s}${o}${A}${r}`;let l=s.length+o.length+A.length;if(t.setSelectionRange(l,l+0),!A){let d=s.length+o.length;t.setSelectionRange(d,d)}t.focus(),t.dispatchEvent(new Event("input",{bubbles:!0}))}toggleWhenBuilder(t,e){let i=this.modalEl;if(this.whenBuilderEl){this.whenBuilderEl.remove(),this.whenBuilderEl=null,i?.removeClass("is-when-builder-open");return}i?.addClass("is-when-builder-open");let s=document.createElement("div");s.className="stashpad-when-builder";let n=document.createElement("div");n.className="stashpad-when-tabs";let o=[{id:"before",label:"Before"},{id:"on",label:"On"},{id:"after",label:"After"},{id:"between",label:"Between"}],r={};for(let u of o){let f=document.createElement("button");f.type="button",f.className="stashpad-when-tab",f.textContent=u.label,this.whenMode===u.id&&f.addClass("is-active"),f.addEventListener("mousedown",C=>C.preventDefault()),f.addEventListener("click",C=>{if(C.preventDefault(),this.whenMode===u.id)return;let B=this.whenMode;B!=="between"&&u.id==="between"?this.whenBetweenEndText="":B==="between"&&u.id!=="between"&&(!this.whenSingleText&&this.whenBetweenEndText&&(this.whenSingleText=this.whenBetweenEndText),this.whenBetweenEndText=""),this.whenMode=u.id;for(let m in r)r[m].toggleClass("is-active",m===u.id);I()}),r[u.id]=f,n.appendChild(f)}s.appendChild(n);let A=document.createElement("div");A.className="stashpad-when-body",s.appendChild(A);let l=(u,f,C="single")=>{let B=ft().format("YYYY-MM-DD"),m=!f||f===B;if(C==="betweenStart")return"00:00";if(C==="betweenEnd")return"23:59";switch(u){case"after":return"00:00";case"on":return m?ft().format("HH:mm"):"23:59";case"before":return m?ft().format("HH:mm"):"23:59";default:return"23:59"}},d=(u,f)=>{u.addEventListener("keydown",C=>{C.key==="Enter"?(C.preventDefault(),C.stopPropagation(),f()):C.key==="Escape"&&(C.preventDefault(),C.stopPropagation(),this.closeWhenBuilder())})},g=(u,f)=>{let C=u.selectionStart??u.value.length,B=u.selectionEnd??u.value.length,w=`${C>0&&!/\s$/.test(u.value.slice(0,C))?" ":""}${f}`,Q=u.value.slice(0,C)+w+u.value.slice(B);u.value=Q;let E=C+w.length;u.setSelectionRange(E,E),u.focus(),u.dispatchEvent(new Event("input",{bubbles:!0}))},p=(u,f)=>{let B=u.slice(0,f).match(/(\d{4}-\d{2}-\d{2})(?!.*\d{4}-\d{2}-\d{2})/);return B?B[1]:null},h=(u,f,C,B)=>{let m=A.createDiv({cls:"stashpad-when-input-wrap has-icons"}),w=m.createDiv({cls:"stashpad-when-icon-slot"}),Q=w.createEl("button",{cls:"stashpad-when-icon stashpad-when-icon-cal"});Q.type="button",Q.title="Pick date",(0,ht.setIcon)(Q,"calendar-days");let E=w.createEl("input",{cls:"stashpad-when-native",attr:{type:"date"}});E.tabIndex=-1;let v=m.createDiv({cls:"stashpad-when-icon-slot"}),y=v.createEl("button",{cls:"stashpad-when-icon stashpad-when-icon-clock"});y.type="button",y.title="Pick time",(0,ht.setIcon)(y,"clock");let b=m.createDiv({cls:"stashpad-when-icon-slot"}),N=b.createEl("button",{cls:"stashpad-when-icon stashpad-when-icon-day"});N.type="button",N.title="Pick day",(0,ht.setIcon)(N,"calendar");let P=m.createDiv({cls:"stashpad-when-icon-slot"}),H=P.createEl("button",{cls:"stashpad-when-icon stashpad-when-icon-tf"});H.type="button",H.title="Pick timeframe",(0,ht.setIcon)(H,"history");let D=m.createEl("input",{cls:"stashpad-when-input",attr:{type:"text",placeholder:u}});D.value=f(),D.addEventListener("input",()=>C(D.value));let S=m.createEl("button",{cls:"stashpad-when-clear"});S.type="button",S.textContent="\xD7",S.title="Clear";for(let Y of[Q,y,N,H,S])Y.addEventListener("mousedown",z=>z.preventDefault());let M=null,U=(Y,z)=>{M&&M();let G=Y.createDiv({cls:"stashpad-when-popover"}),V=new ht.Scope(this.scope),K=null,O=X=>{K=X},it=!1,at=X=>{!G.contains(X.target)&&X.target!==Y&&!Y.contains(X.target)&&_()},_=()=>{if(!it){it=!0,G.remove(),document.removeEventListener("mousedown",at,!0);try{this.app.keymap?.popScope(V)}catch{}M===_&&(M=null)}};M=_,V.register([],"Escape",X=>(X.preventDefault(),_(),!1)),V.register([],"Enter",X=>(X.preventDefault(),K&&K(),!1));try{z(G,_,O)}catch(X){console.error("[stashpad] popover fill threw:",X),G.remove(),M=null;return}this.app.keymap?.pushScope(V),this.pendingCleanups.push(_),setTimeout(()=>document.addEventListener("mousedown",at,!0),0)};H.addEventListener("click",Y=>{Y.preventDefault(),U(P,(z,G,V)=>{let K=this.whenMode==="on",O=(st,Bt)=>{if(!K)return`${st}${Bt}`;let ue={d:"days",w:"weeks",m:"months",y:"years"}[Bt];return ft().subtract(st,ue).format("YYYY-MM-DD")},it=z.createDiv({cls:"stashpad-when-pop-row"}),at=[{label:"Last 7d",n:7,unit:"d"},{label:"Last 30d",n:30,unit:"d"},{label:"This week",n:1,unit:"w"},{label:"This month",n:1,unit:"m"}];for(let st of at){let Bt=it.createEl("button",{cls:"stashpad-when-pop-chip",text:st.label});Bt.type="button",Bt.addEventListener("mousedown",ue=>ue.preventDefault()),Bt.addEventListener("click",ue=>{ue.preventDefault(),g(D,O(st.n,st.unit)),G()})}let _=z.createDiv({cls:"stashpad-when-pop-row stashpad-when-pop-builder"});_.createSpan({text:"Last",cls:"stashpad-when-pop-label"});let X=_.createEl("input",{cls:"stashpad-when-pop-number",attr:{type:"number",min:"1",max:"999",value:"7"}}),Ct=_.createEl("select",{cls:"stashpad-when-pop-unit"});for(let st of[{v:"d",label:"days"},{v:"w",label:"weeks"},{v:"m",label:"months"},{v:"y",label:"years"}]){let Bt=Ct.createEl("option",{text:st.label});Bt.value=st.v}let ct=_.createEl("button",{cls:"stashpad-when-pop-chip stashpad-when-pop-go",text:"Insert"});ct.type="button";let kt=()=>{let st=parseInt(X.value,10);!Number.isFinite(st)||st<1||(g(D,O(st,Ct.value)),G())};ct.addEventListener("mousedown",st=>st.preventDefault()),ct.addEventListener("click",st=>{st.preventDefault(),kt()}),V(kt),X.focus(),X.select()})});let R=(Y,z,G,V,K)=>{U(z,(O,it,at)=>{Ui(O,{seedH:G,seedM:V,seedPeriod:K,close:it,setOnEnter:at,onFinalize:_=>g(Y,Qo(_))})})};N.addEventListener("click",Y=>{Y.preventDefault(),U(b,(z,G,V)=>{let K=z.createDiv({cls:"stashpad-when-pop-row"});for(let X of["Today","Yesterday"]){let Ct=K.createEl("button",{cls:"stashpad-when-pop-chip",text:X});Ct.type="button",Ct.addEventListener("mousedown",ct=>ct.preventDefault()),Ct.addEventListener("click",ct=>{ct.preventDefault(),g(D,X),G()})}let O=z.createDiv({cls:"stashpad-when-pop-row stashpad-when-pop-days"}),it=["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],_=(ft().day()+6)%7;for(let X=0;X<it.length;X++){let Ct=it[X],ct=O.createEl("button",{cls:"stashpad-when-pop-chip",text:Ct.slice(0,3)});ct.type="button",ct.title=Ct,X===_&&ct.addClass("is-today"),ct.addEventListener("mousedown",kt=>kt.preventDefault()),ct.addEventListener("click",kt=>{if(kt.preventDefault(),B==="betweenEnd"){let st=X,Bt=ft().startOf("day"),ue=(Bt.day()+6)%7,$s=(st-ue+7)%7;$s===0&&($s=7);let ir=Bt.clone().add($s,"days").format("YYYY-MM-DD");g(D,ir)}else g(D,Ct);G()})}})});let W=(Y,z)=>{Y.value||(Y.value=z);let G=Y;if(typeof G.showPicker=="function")try{G.showPicker();return}catch{}Y.focus(),Y.click()};return Q.addEventListener("click",Y=>{Y.preventDefault(),W(E,ft().format("YYYY-MM-DD"))}),E.addEventListener("change",()=>{E.value&&g(D,E.value)}),y.addEventListener("click",Y=>{Y.preventDefault();let z=D.selectionStart??D.value.length,G=p(D.value,z),V=l(this.whenMode,G,B),[K,O]=V.split(":"),it=parseInt(K,10),at=parseInt(O,10),_=it%12;_===0&&(_=12);let X=it>=12?"pm":"am";R(D,v,_,at,X)}),S.addEventListener("click",Y=>{Y.preventDefault(),D.value="",C(""),D.focus()}),D},I=()=>{if(A.empty(),this.whenMode==="between"){let u=h("start (date / day / timeframe)",()=>this.whenSingleText,Q=>{this.whenSingleText=Q},"betweenStart"),f=h("end (date / day / timeframe)",()=>this.whenBetweenEndText,Q=>{this.whenBetweenEndText=Q},"betweenEnd"),C=A.createDiv({cls:"stashpad-when-actions"}),B=C.createEl("button",{cls:"stashpad-when-insert",text:"Insert"});B.type="button",B.addEventListener("mousedown",Q=>Q.preventDefault());let m=()=>{let Q=u.value.trim(),E=f.value.trim();Q&&this.appendFilterToInput(t,"after",Q),E&&this.appendFilterToInput(t,"before",E),this.closeWhenBuilder()};B.addEventListener("click",Q=>{Q.preventDefault(),m()});let w=C.createEl("button",{cls:"stashpad-when-cancel",text:"Cancel"});w.type="button",w.addEventListener("mousedown",Q=>Q.preventDefault()),w.addEventListener("click",Q=>{Q.preventDefault(),this.closeWhenBuilder()}),d(u,m),d(f,m),u.focus(),u.setSelectionRange(u.value.length,u.value.length)}else{let u=h("date / day / timeframe",()=>this.whenSingleText,w=>{this.whenSingleText=w},"single"),f=A.createDiv({cls:"stashpad-when-actions"}),C=f.createEl("button",{cls:"stashpad-when-insert",text:"Insert"});C.type="button",C.addEventListener("mousedown",w=>w.preventDefault());let B=()=>{let w=u.value.trim();w&&this.appendFilterToInput(t,this.whenMode,w),this.closeWhenBuilder()};C.addEventListener("click",w=>{w.preventDefault(),B()});let m=f.createEl("button",{cls:"stashpad-when-cancel",text:"Cancel"});m.type="button",m.addEventListener("mousedown",w=>w.preventDefault()),m.addEventListener("click",w=>{w.preventDefault(),this.closeWhenBuilder()}),d(u,B),u.focus(),u.setSelectionRange(u.value.length,u.value.length)}};I(),e.parentElement?.insertBefore(s,e.nextSibling),this.whenBuilderEl=s}closeWhenBuilder(){if(!this.whenBuilderEl)return;this.whenBuilderEl.remove(),this.whenBuilderEl=null,this.modalEl?.removeClass("is-when-builder-open")}selectSuggestion(t,e){if(t&&t.kind==="search-excluded"){this.loadExcludedNotes();return}super.selectSuggestion(t,e)}onChooseSuggestion(t){if(t.kind==="create"&&this.opts.onCreate){this.opts.onCreate(this.inputEl?.value??"");return}if(t.kind==="folder-open"&&t.id==="__folder_picker__"){let e=this.opts.folderResults?.()??[];if(!e.length)return;let i=this.inputEl?.value??"",s=!1,n=p=>{s=!0;let h=p.split("/").pop()??p;this.opts.onPick({id:`folder:${p}`,label:`Open folder \u201C${h}\u201D in a new tab`,node:null,kind:"folder-open",folder:p})},o=new Zn(this.app,e,n),r=o.onClose.bind(o),A=this.tree,l=this.titleFn,d=this.opts,g=this.app;o.onClose=()=>{if(r(),!s){let p=new c(g,A,l,d);p.open(),setTimeout(()=>{let h=p.inputEl;h&&(i&&(h.value=i,h.dispatchEvent(new Event("input",{bubbles:!0}))),h.focus(),h.setSelectionRange(h.value.length,h.value.length))},0)}},o.open();return}this.opts.onPick(t)}},Zn=class extends ht.FuzzySuggestModal{constructor(t,e,i){super(t);this.folders=e;this.onChosen=i;this.setPlaceholder("Open which folder?")}getItems(){return this.folders}getItemText(t){let e=t.split("/").pop()??t;return e===t?t:`${e} \u2014 ${t}`}onChooseItem(t){this.onChosen(t)}};var Ha=require("obsidian");rt();var Fs=class extends Ha.SuggestModal{constructor(a){super(a),this.setPlaceholder("Run a Stashpad command\u2026");let t=this.app.commands?.commands??{};this.commands=Object.keys(t).filter(e=>e.startsWith("stashpad:")).filter(e=>e!=="stashpad:stashpad-command-palette").map(e=>({id:e,name:xA(t[e]?.name??e)})).sort((e,i)=>e.name.localeCompare(i.name))}getSuggestions(a){return this.commands.filter(t=>Hi(a,t.name))}renderSuggestion(a,t){t.createDiv({text:a.name,cls:"stashpad-cmd-palette-name"})}onChooseSuggestion(a){this.app.commands?.executeCommandById?.(a.id)}};function xA(c){return c.replace(/^(?:\s*Stashpad:\s*)+/i,"").trim()||c}vt();var jn=require("obsidian");function MA(c,a){return!a||c.metaKey||c.ctrlKey||c.altKey?!1:c.key.toLowerCase()===a.toLowerCase()}function ze(c,a){return a?a.includes("+")?TA(c,a):MA(c,a):!1}function L(c,a){if(!a)return!1;let{primary:t,secondary:e,preferRight:i,useBoth:s}=a;return t&&e?s?ze(c,t)||ze(c,e):i?ze(c,e):ze(c,t):ze(c,t)||ze(c,e)}function xi(c){if(!c)return"";let a=jn.Platform.isMacOS;return c.split("+").map(t=>{let e=t.trim();return e?e.toLowerCase()==="mod"?a?"Cmd":"Ctrl":e.toLowerCase()==="alt"?a?"Opt":"Alt":e.length===1?e.toUpperCase():e:""}).filter(Boolean).join("+")}function TA(c,a){if(!a)return!1;let t=a.split("+").map(g=>g.trim()).filter(Boolean);if(t.length<2)return!1;let e=t[t.length-1].toLowerCase(),i=new Set(t.slice(0,-1).map(g=>g.toLowerCase())),s=i.has("mod"),n=i.has("ctrl")||i.has("control"),o=i.has("cmd")||i.has("meta")||i.has("command"),r=i.has("alt")||i.has("option"),A=i.has("shift"),d=jn.Platform.isMacOS?c.metaKey:c.ctrlKey;return s&&!d||n&&!c.ctrlKey||o&&!c.metaKey||r!==c.altKey||A!==c.shiftKey||!s&&(!n&&c.ctrlKey||!o&&c.metaKey)?!1:c.key.toLowerCase()===e}var Se=require("obsidian");vt();var bt=class bt{constructor(a){this.host=a;this.knownBodies=new Map;this.contribTimers=new Map;this.recentSelfWrites=new Map;this.lastExternalModify=new Map}dispose(){for(let a of this.contribTimers.values())clearTimeout(a);this.contribTimers.clear(),this.knownBodies.clear(),this.recentSelfWrites.clear(),this.lastExternalModify.clear()}currentAuthorLink(){let a=(this.host.plugin.settings.authorName??"").trim(),t=(this.host.plugin.settings.authorId??"").trim();if(!a||!t)return null;let e=a.replace(/[^\w\- ]+/g,"").trim().replace(/\s+/g,"-")||"author",i=`${this.host.noteFolder}/_authors/${e}-${t}.md`,s=a.replace(/[\[\]|]/g,"").trim()||e;return{link:`[[${i}|${s}]]`,path:i,name:a,id:t}}claimSelectedAsAuthor(){this.claimAuthorship({scope:"selection",contributorMode:!1})}claimFolderAsAuthor(){this.claimAuthorship({scope:"folder",contributorMode:!1})}claimSelectedWithContributor(){this.claimAuthorship({scope:"selection",contributorMode:!0})}claimFolderWithContributor(){this.claimAuthorship({scope:"folder",contributorMode:!0})}fileBackedNotesInFolder(){let a=this.host.noteFolder.replace(/\/+$/,"");return this.host.app.vault.getMarkdownFiles().filter(t=>{let e=t.parent?.path?.replace(/\/+$/,"")??"";if(e!==a&&!e.startsWith(a+"/")||t.path.includes("/_authors/"))return!1;let i=this.host.app.metadataCache.getFileCache(t)?.frontmatter;return typeof i?.id=="string"&&!!i.id})}async pacedFrontmatter(a,t){for(let s=0;s<a.length;s++){let n=this.host.app.vault.getAbstractFileByPath(a[s]);if(n instanceof Se.TFile){this.recentSelfWrites.set(n.path,Date.now());try{await this.host.app.fileManager.processFrontMatter(n,o=>t(o,a[s]))}catch(o){console.warn("[Stashpad] claim: frontmatter write failed",a[s],o)}}(s+1)%25===0&&await new Promise(o=>setTimeout(o,30))}}async claimAuthorship(a){let t=this.currentAuthorLink();if(!t){new Se.Notice("Set your author name in Stashpad settings first.");return}let e=`-${t.id}`,i=a.scope==="selection"?this.host.getActionTargets().map(p=>p.file).filter(p=>!!p):this.fileBackedNotesInFolder();if(i.length===0){new Se.Notice(a.scope==="selection"?"No notes selected.":"No notes in this folder.");return}let s=[],n=[];for(let p of i){let h=this.host.app.metadataCache.getFileCache(p)?.frontmatter,I=typeof h?.author=="string"?h.author:"";if(!I.trim()){s.push(p.path);continue}if(I.includes(e)||!a.contributorMode)continue;(Array.isArray(h?.contributors)?h.contributors.filter(f=>typeof f=="string"):[]).some(f=>f.includes(e))||n.push(p.path)}let o=s.length+n.length;if(o===0){new Se.Notice("Nothing to claim \u2014 those notes are already authored by you.");return}if(a.scope==="folder"){let p=[`Stamp yourself as author on ${s.length} unauthored note(s)`];if(n.length&&p.push(`and as a contributor on ${n.length} already-authored note(s)`),!await new Promise(I=>{new gt(this.host.app,"Claim authorship",`${p.join(" ")}? -Existing authors are never overwritten. This can be undone.`,"Claim",I).open()}))return}let r=this.host.noteFolder,A=t.link,l=new Set,d=async()=>{await this.pacedFrontmatter(s,(p,h)=>{typeof p.author=="string"&&p.author.trim()||(p.author=A),Array.isArray(p.contributors)&&p.contributors.some(I=>typeof I=="string"&&I.includes(e))&&(p.contributors=p.contributors.filter(I=>!(typeof I=="string"&&I.includes(e))),l.add(h))}),await this.pacedFrontmatter(n,p=>{let h=Array.isArray(p.contributors)?p.contributors.filter(I=>typeof I=="string"):[];h.some(I=>I.includes(e))||h.push(A),p.contributors=h})};this.ensureAuthorFile(t),await d(),this.host.plugin.getUndoStack(r).push({label:`Claim authorship (${o} note${o===1?"":"s"})`,undo:async()=>{await this.pacedFrontmatter(s,(p,h)=>{if(typeof p.author=="string"&&p.author.includes(e)&&delete p.author,l.has(h)){let I=Array.isArray(p.contributors)?p.contributors.filter(u=>typeof u=="string"):[];I.some(u=>u.includes(e))||I.push(A),p.contributors=I}}),await this.pacedFrontmatter(n,p=>{Array.isArray(p.contributors)&&(p.contributors=p.contributors.filter(h=>!(typeof h=="string"&&h.includes(e))))}),this.host.debouncedRender()},redo:async()=>{l.clear(),await d(),this.host.debouncedRender()}});let g=[];s.length&&g.push(`authored ${s.length}`),n.length&&g.push(`contributing to ${n.length}`),new Se.Notice(`Claimed authorship: ${g.join(", ")}. Undo available.`),this.host.debouncedRender()}async ensureAuthorFile(a){try{a.id&&this.host.plugin.authorRegistry.record({id:a.id,name:a.name});let t=`${this.host.noteFolder}/_authors`;if(await this.host.ensureFolder(t),await this.host.app.vault.adapter.exists(a.path))return;let e=a.id===(this.host.plugin.settings.authorId??"").trim(),i=this.host.plugin.buildAuthorStub({id:a.id,name:a.name,role:e?this.host.plugin.settings.authorRole:void 0,department:e?this.host.plugin.settings.authorDepartment:void 0},new Date().toISOString());await this.host.app.vault.create(a.path,i)}catch(t){console.warn("[Stashpad] ensureAuthorFile failed",t)}}collectAuthorIds(a){let t=new Set,e=i=>{if(typeof i!="string")return null;let s=i.match(/-([a-z0-9]{4,12})(?:\.md)?(?:\||\]\])/i);return s?s[1]:null};for(let i of a){if(!i.file)continue;let s=this.host.app.metadataCache.getFileCache(i.file)?.frontmatter;if(!s)continue;let n=e(s.author);if(n&&t.add(n),Array.isArray(s.contributors))for(let o of s.contributors){let r=e(o);r&&t.add(r)}}return Array.from(t)}pruneContribMaps(){let a=Date.now(),t=bt.EXTERNAL_WRITE_GRACE_MS*20,e=bt.EXTERNAL_QUIESCENCE_MS*12;for(let[i,s]of this.recentSelfWrites)a-s>t&&this.recentSelfWrites.delete(i);for(let[i,s]of this.lastExternalModify)a-s>e&&this.lastExternalModify.delete(i);if(this.knownBodies.size>64)for(let i of this.knownBodies.keys())this.host.tree.idForPath(i)||this.knownBodies.delete(i)}noteModify(a){let t=Date.now(),e=this.recentSelfWrites.get(a.path);e!==void 0&&t-e<bt.EXTERNAL_WRITE_GRACE_MS||this.lastExternalModify.set(a.path,t),this.scheduleContribution(a)}scheduleContribution(a){let t=this.contribTimers.get(a.path);t&&clearTimeout(t);let e=this.isFileActivelyEdited(a),i=bt.CONTRIB_DEBOUNCE_MS+(e?bt.CONTRIB_ACTIVE_EDITOR_BONUS_MS:0),s=setTimeout(()=>{if(this.contribTimers.delete(a.path),this.isFileActivelyEdited(a)){this.scheduleContribution(a);return}let n=this.lastExternalModify.get(a.path);if(n!==void 0&&Date.now()-n<bt.EXTERNAL_QUIESCENCE_MS){this.scheduleContribution(a);return}this.maybeRecordContribution(a)},i);this.contribTimers.set(a.path,s)}isFileActivelyEdited(a){try{let t=this.host.app.workspace.activeLeaf;if(!t)return!1;let e=t.view;if(!e||e.getViewType?.()!=="markdown"||e.file?.path!==a.path)return!1;let i=e.containerEl??null;return!!i&&i.contains(document.activeElement)}catch{return!1}}async maybeRecordContribution(a){let t="";try{t=await this.host.app.vault.cachedRead(a)}catch{return}let e=this.host.stripFrontmatter(t),i=this.knownBodies.get(a.path);if(this.knownBodies.set(a.path,e),i===void 0||i===e||this.host.plugin.rebootstrapInProgress)return;let s=this.currentAuthorLink();if(!s)return;this.ensureAuthorFile(s);let n=new Date().toISOString();this.recentSelfWrites.set(a.path,Date.now());try{await this.host.app.fileManager.processFrontMatter(a,o=>{o.modified=n;let r=typeof o.author=="string"?o.author:"",A=Array.isArray(o.contributors)?o.contributors.filter(p=>typeof p=="string"):[],l=`-${s.id}`,d=r.includes(l),g=A.some(p=>p.includes(l));!d&&!g&&A.push(s.link),o.contributors=A})}catch(o){console.warn("[Stashpad] maybeRecordContribution failed",o)}}};bt.CONTRIB_DEBOUNCE_MS=4e3,bt.CONTRIB_ACTIVE_EDITOR_BONUS_MS=2e3,bt.EXTERNAL_WRITE_GRACE_MS=1500,bt.EXTERNAL_QUIESCENCE_MS=5e3;var ks=bt;var Ss=class{constructor(a){this.host=a;this.dragSourceIds=null;this.dragPlaceholder=null;this.dragRowHeight=0}attachRowDnD(a,t,e){a.addEventListener("dragstart",i=>{let s=this.host.selection.has(t.id)&&this.host.selection.size>1?[...this.host.selection]:[t.id];if(this.dragSourceIds=s,this.dragRowHeight=a.offsetHeight,a.addClass("is-dragging"),this.host.listEl&&(this.dragPlaceholder=this.host.listEl.createDiv({cls:"stashpad-drop-placeholder"}),this.dragPlaceholder.setCssStyles({height:"0px"}),this.dragPlaceholder.addEventListener("dragover",n=>{this.dragSourceIds&&(n.preventDefault(),n.dataTransfer&&(n.dataTransfer.dropEffect="move"))}),this.dragPlaceholder.addEventListener("drop",n=>{if(!this.dragSourceIds||!this.dragPlaceholder)return;n.preventDefault(),n.stopPropagation();let o=this.dragSourceIds.slice();this.dragSourceIds=null;let r=this.dragPlaceholder.nextElementSibling,A=this.dragPlaceholder.previousElementSibling;this.removeDragPlaceholder();let l,d="before";r&&r.classList.contains("stashpad-note")?(l=r.dataset.id,d="before"):A&&A.classList.contains("stashpad-note")&&(l=A.dataset.id,d="after"),l&&this.host.reorderToTarget(o,l,d)}),this.dragPlaceholder.remove()),i.dataTransfer?.setData("text/plain",s.join(",")),i.dataTransfer){i.dataTransfer.effectAllowed="move";try{i.dataTransfer.setDragImage(a,12,12)}catch{}}}),a.addEventListener("dragend",()=>{a.removeClass("is-dragging"),this.clearDropIndicators(),this.removeDragPlaceholder(),this.dragSourceIds=null}),a.addEventListener("dragover",i=>{if(!this.dragSourceIds)return;i.preventDefault(),i.dataTransfer&&(i.dataTransfer.dropEffect="move");let s=this.dropZone(i,a);this.clearDropIndicators(),s==="drop-into"?(this.removeDragPlaceholder(),a.addClass("drop-into")):(a.removeClass("drop-into"),this.placePlaceholder(a,s==="drop-above"?"before":"after"))}),a.addEventListener("dragleave",i=>{let s=a.getBoundingClientRect();(i.clientX<s.left||i.clientX>s.right||i.clientY<s.top||i.clientY>s.bottom)&&a.removeClass("drop-into")}),a.addEventListener("drop",i=>{if(!this.dragSourceIds)return;i.preventDefault(),i.stopPropagation();let s=this.dragSourceIds.slice();this.dragSourceIds=null;let n=this.dropZone(i,a);this.clearDropIndicators(),this.removeDragPlaceholder(),a.removeClass("is-dragging"),n==="drop-into"?this.host.reorderToTarget(s,t.id,"into"):this.host.reorderToTarget(s,t.id,n==="drop-above"?"before":"after")})}attachListDnD(a){a.addEventListener("dragover",t=>{if(!this.dragSourceIds)return;let e=t.target;if(e&&e.closest&&e.closest(".stashpad-note"))return;t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="move");let i=Array.from(a.querySelectorAll(".stashpad-note"));if(i.length!==0){for(let s of i){let n=s.getBoundingClientRect();if(t.clientY<n.top+n.height/2){this.placePlaceholder(s,"before");return}}this.placePlaceholder(i[i.length-1],"after")}}),a.addEventListener("drop",t=>{if(!this.dragSourceIds)return;t.preventDefault();let e=this.dragSourceIds.slice();if(this.dragSourceIds=null,!this.dragPlaceholder)return;let i=this.dragPlaceholder.nextElementSibling,s=this.dragPlaceholder.previousElementSibling;if(this.removeDragPlaceholder(),i&&i.classList.contains("stashpad-note")){let n=i.dataset.id;n&&this.host.reorderToTarget(e,n,"before")}else if(s&&s.classList.contains("stashpad-note")){let n=s.dataset.id;n&&this.host.reorderToTarget(e,n,"after")}})}placePlaceholder(a,t){if(!this.dragPlaceholder||!this.host.listEl)return;let e=t==="before"?a:a.nextSibling;if(t==="before"&&this.dragPlaceholder.nextSibling===a||t==="after"&&this.dragPlaceholder.previousSibling===a)return;let i=!!this.dragPlaceholder.parentElement;this.host.listEl.insertBefore(this.dragPlaceholder,e),this.dragPlaceholder.setCssStyles({opacity:"1"}),i?this.dragPlaceholder.setCssStyles({height:`${this.dragRowHeight}px`}):(this.dragPlaceholder.setCssStyles({height:"0px"}),this.dragPlaceholder.offsetHeight,this.dragPlaceholder.setCssStyles({height:`${this.dragRowHeight}px`}))}removeDragPlaceholder(){if(!this.dragPlaceholder?.parentElement)return;let a=this.dragPlaceholder;a.setCssStyles({height:"0px",opacity:"0"}),setTimeout(()=>{a.parentElement&&a.remove()},150)}dropZone(a,t){let e=t.getBoundingClientRect(),i=a.clientY-e.top;return i<e.height*.3?"drop-above":i>e.height*.7?"drop-below":"drop-into"}clearDropIndicators(){if(this.host.listEl)for(let a of Array.from(this.host.listEl.querySelectorAll(".drop-into")))a.removeClass("drop-into")}};var Pa=require("obsidian");var Ds=class{constructor(a,t,e){this.host=a;this.component=t;this.bodyObserver=null;this.lazyBodies=new WeakMap;this.renderCache=e??new Map}async getOrComputeRender(a){let t=this.renderCache.get(a.path);if(t&&t.mtime===a.stat.mtime)return Qt.record("render.row.cacheHit",0),t;let e=await Qt.timeAsync("render.row.read",()=>this.host.app.vault.cachedRead(a)),i=this.host.stripFrontmatter(e),{text:s,attachments:n}=this.splitAttachments(i),o=createDiv({cls:"stashpad-note-text"});await Qt.timeAsync("render.row.markdown",()=>Pa.MarkdownRenderer.render(this.host.app,s,o,a.path,this.component));let r=o.innerHTML,A={mtime:a.stat.mtime,text:s,attachments:n,html:r};return this.renderCache.set(a.path,A),A}arm(){this.bodyObserver?.disconnect(),this.lazyBodies=new WeakMap,this.bodyObserver=new IntersectionObserver(a=>{for(let t of a){if(!t.isIntersecting)continue;let e=t.target,i=this.lazyBodies.get(e);this.bodyObserver?.unobserve(e),this.lazyBodies.delete(e),i&&i()}},{root:this.host.contentEl,rootMargin:"1400px 0px"})}dispose(){this.bodyObserver?.disconnect(),this.bodyObserver=null}isArmed(){return!!this.bodyObserver}hasFreshRenderCache(a){let t=this.renderCache.get(a.path);return!!t&&t.mtime===a.stat.mtime}defer(a,t){this.lazyBodies.set(a,t),this.bodyObserver?.observe(a)}splitAttachments(a){let t=[];return{text:a.replace(/!\[\[([^\]\|]+)(?:\|[^\]]+)?\]\]/g,(i,s)=>(t.push(s),"")).replace(/\n{3,}/g,` +`)}renderSuggestion(t,e){if(e.addClass("stashpad-suggest-item"),t.kind==="create"){e.createDiv({cls:"stashpad-suggest-create",text:t.label});return}if(t.kind==="folder-open"){e.addClass("is-folder-open"),e.createDiv({cls:"stashpad-suggest-title",text:t.label}),t.folder?e.createDiv({cls:"stashpad-suggest-preview",text:t.folder}):e.createDiv({cls:"stashpad-suggest-preview",text:"Click to choose a folder\u2026"});return}if(t.kind==="search-excluded"){e.addClass("is-search-excluded");let h=e.createDiv({cls:"stashpad-suggest-title stashpad-search-excluded-row"}),I=h.createSpan({cls:"stashpad-search-excluded-icon"});(0,ht.setIcon)(I,"folder-search"),h.createSpan({text:t.label}),e.createDiv({cls:"stashpad-suggest-preview",text:"Include folders you've excluded from search (e.g. to move a note there)."});return}t.crossFolder&&e.addClass("is-cross-folder"),e.addClass("stashpad-suggest-row");let i=e.createDiv({cls:"stashpad-suggest-body"}),s=this.notes.find(h=>t.crossFolder?h.cross?.folder===t.crossFolder&&h.cross?.id===t.crossId:h.node?.id===t.id),n=Ya(this.inputEl?.value??"").text,o=this.firstLineOfBody(s?.body??"")||t.label.trim(),r=i.createDiv({cls:"stashpad-suggest-title"});this.highlightInto(r,o,n);let A=t.crossFolder??this.opts.localFolder??null;if(t.bodyPreview&&t.matchLine!=null&&t.matchLine>=0){let h=i.createDiv({cls:"stashpad-suggest-preview stashpad-suggest-snippet"});this.highlightInto(h,t.bodyPreview,n)}let l="";if(t.crossFolder?l=s?.cross?.parentBlurb??"":l=this.parentBlurbFor(t.node),l){let h=i.createDiv({cls:"stashpad-suggest-preview"});h.appendText("Parent: "),this.highlightInto(h,l,n)}let d=t.crossFolder?this.buildCrossBreadcrumb(t):this.buildLocalBreadcrumb(t.node),p=t.crossFolder??this.opts.localFolder??null;if(p||d){let h=i.createDiv({cls:"stashpad-suggest-breadcrumb"}),u=[p?p.split("/").pop()||p:"",d].filter(f=>f&&f.length>0).join(" \u203A ");u&&h.setText(u)}let g=s?this.createdMsFor(s):null;if(g!=null||A){let h=e.createDiv({cls:"stashpad-suggest-rail"});if(g!=null){let I=h.createDiv({cls:"stashpad-suggest-time"});I.setText(this.formatRelativeTime(g)),I.title=ft(g).format("YYYY-MM-DD HH:mm")}A&&h.createDiv({cls:"stashpad-suggest-folder-badge",text:A.split("/").pop()||A})}}formatRelativeTime(t){let e=ft(t),i=ft().startOf("day").diff(ft(t).startOf("day"),"days");return i===0?e.format("h:mm a"):i===1?"yesterday":i>1&&i<7?`${i}d ago`:i>=7&&i<30?`${Math.floor(i/7)}w ago`:i>=30&&i<365?e.format("MMM D"):e.format("MMM D, YYYY")}highlightInto(t,e,i){if(!e)return;let s=i.filter(l=>l&&l.length>0);if(!s.length){t.appendText(e);return}let n=e.toLowerCase(),o=[];for(let l of s){let d=0;for(;(d=n.indexOf(l,d))!==-1;)o.push([d,d+l.length]),d+=l.length}if(!o.length){t.appendText(e);return}o.sort((l,d)=>l[0]-d[0]);let r=[];for(let l of o){let d=r[r.length-1];d&&l[0]<=d[1]?d[1]=Math.max(d[1],l[1]):r.push([l[0],l[1]])}let A=0;for(let[l,d]of r)l>A&&t.appendText(e.slice(A,l)),t.createSpan({cls:"stashpad-suggest-match",text:e.slice(l,d)}),A=d;A<e.length&&t.appendText(e.slice(A))}buildLocalBreadcrumb(t){if(!t||!t.parent||t.parent===F)return"";let e=[],i=new Set([t.id]),s=this.tree.get(t.parent);for(;s&&s.id!==F&&!i.has(s.id);)i.add(s.id),e.unshift(this.titleFn(s)),s=s.parent&&s.parent!==F?this.tree.get(s.parent):void 0;return e.join(" \u203A ")}buildCrossBreadcrumb(t){if(!t.crossFolder)return"";if(!this.crossFolderIndex){this.crossFolderIndex=new Map;for(let A of this.notes){if(!A.cross)continue;let l=this.crossFolderIndex.get(A.cross.folder);l||(l=new Map,this.crossFolderIndex.set(A.cross.folder,l)),l.set(A.cross.id,A.cross)}}let e=this.crossFolderIndex.get(t.crossFolder);if(!e)return"";let i=t.crossId??t.id.replace(/^cross:/,""),s=e.get(i);if(!s)return"";let n=[],o=new Set([s.id]),r=s.parentId?e.get(s.parentId):null;for(;r&&!o.has(r.id);)o.add(r.id),n.unshift(r.title),r=r.parentId?e.get(r.parentId):null;return n.join(" \u203A ")}firstLineOfBody(t){if(!t)return"";let e=t.split(/\r?\n/);for(let i of e){let s=i.trim();if(s)return s}return""}parentBlurbFor(t){if(!t||!t.parent||t.parent===F)return"";let e=this.tree.get(t.parent);if(!e||!e.file)return"";let i=this.notes.find(s=>s.node?.id===e.id);return i?this.firstLineOfBody(i.body):""}onOpen(){if(super.onOpen(),this.opts.showFilterChips&&!ht.Platform.isMobile){let t=this.inputEl,e=this.resultContainerEl;if(!t||!e)return;this.mountFilterChipRow(t,e);return}if(ht.Platform.isMobile){let t=this.inputEl;t&&t.focus()}}mountFilterChipRow(t,e){t.addEventListener("keydown",l=>{if(l.key==="["){l.preventDefault();let d=t.selectionStart??t.value.length,p=t.selectionEnd??d,g=t.value.slice(0,d),h=t.value.slice(d,p),I=t.value.slice(p);t.value=`${g}[${h}]${I}`;let u=d+1+h.length;t.setSelectionRange(u,u),t.dispatchEvent(new Event("input",{bubbles:!0}));return}if(l.key==="]"){let d=t.selectionStart??-1;d>=0&&t.value[d]==="]"&&(l.preventDefault(),t.setSelectionRange(d+1,d+1));return}if(l.key==="Backspace"&&!l.metaKey&&!l.ctrlKey&&!l.altKey&&t.selectionStart===t.selectionEnd){let d=t.selectionStart??-1;if(d>0&&t.value[d-1]==="["&&t.value[d]==="]"){l.preventDefault();let p=t.value.slice(0,d-1),g=t.value.slice(d+1);t.value=`${p}${g}`,t.setSelectionRange(d-1,d-1),t.dispatchEvent(new Event("input",{bubbles:!0}))}}});let i=document.createElement("div");i.className="stashpad-search-filter-row";let s=document.createElement("span");s.className="stashpad-search-filter-label",s.textContent="Filters:",i.appendChild(s);let n=document.createElement("button");n.className="stashpad-search-filter-chip",n.type="button",n.textContent="in:[parent note]",n.title='Insert "in:" \u2014 filter by parent note.',n.addEventListener("mousedown",l=>{l.preventDefault()}),n.addEventListener("click",l=>{l.preventDefault(),this.appendFilterToInput(t,"in","")}),n.addEventListener("keydown",l=>{(l.key==="Enter"||l.key===" ")&&(l.preventDefault(),l.stopPropagation(),n.click())}),i.appendChild(n);let o=document.createElement("button");o.className="stashpad-search-filter-chip stashpad-search-filter-when",o.type="button",o.textContent="when:[date / day / timeframe]",o.title="Open the time-filter builder (Before / On / After / Between).",o.addEventListener("mousedown",l=>{l.preventDefault()}),o.addEventListener("click",l=>{l.preventDefault(),this.toggleWhenBuilder(t,i)}),o.addEventListener("keydown",l=>{(l.key==="Enter"||l.key===" ")&&(l.preventDefault(),l.stopPropagation(),o.click())}),i.appendChild(o),e.parentElement?.insertBefore(i,e);let r=new ht.Scope(this.scope),A=l=>{let d=document.activeElement;return d?.classList?.contains("stashpad-search-filter-chip")?(l.preventDefault(),d.click(),!1):l.key==="Enter"&&!l.isComposing?(l.preventDefault(),this.selectActiveSuggestion?.(l),!1):!0};r.register([],"Enter",A),r.register([]," ",A),r.register(["Mod"],"f",l=>{l.preventDefault();let d=this.inputEl;return d&&(d.focus(),d.select()),!1}),r.register([],"Tab",l=>{let d=this.modalEl,p=this.inputEl;if(!d)return!0;let g=Array.from(d.querySelectorAll('input, button, select, textarea, a[href], [tabindex]:not([tabindex="-1"])')).filter(u=>!u.hasAttribute("disabled")&&u.tabIndex!==-1&&u.offsetParent!==null);if(g.length===0)return!0;let h=document.activeElement,I=h?g.indexOf(h):-1;if(l.shiftKey){if(I<=0)return l.preventDefault(),g[g.length-1].focus(),!1}else if(I===g.length-1)return l.preventDefault(),(p??g[0]).focus(),!1;return!0}),this.app.keymap?.pushScope(r),this.pendingCleanups.push(()=>{try{this.app.keymap?.popScope(r)}catch{}})}appendFilterToInput(t,e,i){let s=t.value,o=`${s.length>0&&!/\s$/.test(s)?" ":""}${e}: [`,r="]",A=i;t.value=`${s}${o}${A}${r}`;let l=s.length+o.length+A.length;if(t.setSelectionRange(l,l+0),!A){let d=s.length+o.length;t.setSelectionRange(d,d)}t.focus(),t.dispatchEvent(new Event("input",{bubbles:!0}))}toggleWhenBuilder(t,e){let i=this.modalEl;if(this.whenBuilderEl){this.whenBuilderEl.remove(),this.whenBuilderEl=null,i?.removeClass("is-when-builder-open");return}i?.addClass("is-when-builder-open");let s=document.createElement("div");s.className="stashpad-when-builder";let n=document.createElement("div");n.className="stashpad-when-tabs";let o=[{id:"before",label:"Before"},{id:"on",label:"On"},{id:"after",label:"After"},{id:"between",label:"Between"}],r={};for(let u of o){let f=document.createElement("button");f.type="button",f.className="stashpad-when-tab",f.textContent=u.label,this.whenMode===u.id&&f.addClass("is-active"),f.addEventListener("mousedown",C=>C.preventDefault()),f.addEventListener("click",C=>{if(C.preventDefault(),this.whenMode===u.id)return;let B=this.whenMode;B!=="between"&&u.id==="between"?this.whenBetweenEndText="":B==="between"&&u.id!=="between"&&(!this.whenSingleText&&this.whenBetweenEndText&&(this.whenSingleText=this.whenBetweenEndText),this.whenBetweenEndText=""),this.whenMode=u.id;for(let m in r)r[m].toggleClass("is-active",m===u.id);I()}),r[u.id]=f,n.appendChild(f)}s.appendChild(n);let A=document.createElement("div");A.className="stashpad-when-body",s.appendChild(A);let l=(u,f,C="single")=>{let B=ft().format("YYYY-MM-DD"),m=!f||f===B;if(C==="betweenStart")return"00:00";if(C==="betweenEnd")return"23:59";switch(u){case"after":return"00:00";case"on":return m?ft().format("HH:mm"):"23:59";case"before":return m?ft().format("HH:mm"):"23:59";default:return"23:59"}},d=(u,f)=>{u.addEventListener("keydown",C=>{C.key==="Enter"?(C.preventDefault(),C.stopPropagation(),f()):C.key==="Escape"&&(C.preventDefault(),C.stopPropagation(),this.closeWhenBuilder())})},p=(u,f)=>{let C=u.selectionStart??u.value.length,B=u.selectionEnd??u.value.length,y=`${C>0&&!/\s$/.test(u.value.slice(0,C))?" ":""}${f}`,Q=u.value.slice(0,C)+y+u.value.slice(B);u.value=Q;let E=C+y.length;u.setSelectionRange(E,E),u.focus(),u.dispatchEvent(new Event("input",{bubbles:!0}))},g=(u,f)=>{let B=u.slice(0,f).match(/(\d{4}-\d{2}-\d{2})(?!.*\d{4}-\d{2}-\d{2})/);return B?B[1]:null},h=(u,f,C,B)=>{let m=A.createDiv({cls:"stashpad-when-input-wrap has-icons"}),y=m.createDiv({cls:"stashpad-when-icon-slot"}),Q=y.createEl("button",{cls:"stashpad-when-icon stashpad-when-icon-cal"});Q.type="button",Q.title="Pick date",(0,ht.setIcon)(Q,"calendar-days");let E=y.createEl("input",{cls:"stashpad-when-native",attr:{type:"date"}});E.tabIndex=-1;let v=m.createDiv({cls:"stashpad-when-icon-slot"}),w=v.createEl("button",{cls:"stashpad-when-icon stashpad-when-icon-clock"});w.type="button",w.title="Pick time",(0,ht.setIcon)(w,"clock");let D=m.createDiv({cls:"stashpad-when-icon-slot"}),N=D.createEl("button",{cls:"stashpad-when-icon stashpad-when-icon-day"});N.type="button",N.title="Pick day",(0,ht.setIcon)(N,"calendar");let P=m.createDiv({cls:"stashpad-when-icon-slot"}),H=P.createEl("button",{cls:"stashpad-when-icon stashpad-when-icon-tf"});H.type="button",H.title="Pick timeframe",(0,ht.setIcon)(H,"history");let b=m.createEl("input",{cls:"stashpad-when-input",attr:{type:"text",placeholder:u}});b.value=f(),b.addEventListener("input",()=>C(b.value));let S=m.createEl("button",{cls:"stashpad-when-clear"});S.type="button",S.textContent="\xD7",S.title="Clear";for(let z of[Q,w,N,H,S])z.addEventListener("mousedown",V=>V.preventDefault());let M=null,U=(z,V)=>{M&&M();let R=z.createDiv({cls:"stashpad-when-popover"}),$=new ht.Scope(this.scope),K=null,O=X=>{K=X},it=!1,at=X=>{!R.contains(X.target)&&X.target!==z&&!z.contains(X.target)&&_()},_=()=>{if(!it){it=!0,R.remove(),document.removeEventListener("mousedown",at,!0);try{this.app.keymap?.popScope($)}catch{}M===_&&(M=null)}};M=_,$.register([],"Escape",X=>(X.preventDefault(),_(),!1)),$.register([],"Enter",X=>(X.preventDefault(),K&&K(),!1));try{V(R,_,O)}catch(X){console.error("[stashpad] popover fill threw:",X),R.remove(),M=null;return}this.app.keymap?.pushScope($),this.pendingCleanups.push(_),setTimeout(()=>document.addEventListener("mousedown",at,!0),0)};H.addEventListener("click",z=>{z.preventDefault(),U(P,(V,R,$)=>{let K=this.whenMode==="on",O=(st,mt)=>{if(!K)return`${st}${mt}`;let me={d:"days",w:"weeks",m:"months",y:"years"}[mt];return ft().subtract(st,me).format("YYYY-MM-DD")},it=V.createDiv({cls:"stashpad-when-pop-row"}),at=[{label:"Last 7d",n:7,unit:"d"},{label:"Last 30d",n:30,unit:"d"},{label:"This week",n:1,unit:"w"},{label:"This month",n:1,unit:"m"}];for(let st of at){let mt=it.createEl("button",{cls:"stashpad-when-pop-chip",text:st.label});mt.type="button",mt.addEventListener("mousedown",me=>me.preventDefault()),mt.addEventListener("click",me=>{me.preventDefault(),p(b,O(st.n,st.unit)),R()})}let _=V.createDiv({cls:"stashpad-when-pop-row stashpad-when-pop-builder"});_.createSpan({text:"Last",cls:"stashpad-when-pop-label"});let X=_.createEl("input",{cls:"stashpad-when-pop-number",attr:{type:"number",min:"1",max:"999",value:"7"}}),Bt=_.createEl("select",{cls:"stashpad-when-pop-unit"});for(let st of[{v:"d",label:"days"},{v:"w",label:"weeks"},{v:"m",label:"months"},{v:"y",label:"years"}]){let mt=Bt.createEl("option",{text:st.label});mt.value=st.v}let ct=_.createEl("button",{cls:"stashpad-when-pop-chip stashpad-when-pop-go",text:"Insert"});ct.type="button";let St=()=>{let st=parseInt(X.value,10);!Number.isFinite(st)||st<1||(p(b,O(st,Bt.value)),R())};ct.addEventListener("mousedown",st=>st.preventDefault()),ct.addEventListener("click",st=>{st.preventDefault(),St()}),$(St),X.focus(),X.select()})});let L=(z,V,R,$,K)=>{U(V,(O,it,at)=>{Oi(O,{seedH:R,seedM:$,seedPeriod:K,close:it,setOnEnter:at,onFinalize:_=>p(z,No(_))})})};N.addEventListener("click",z=>{z.preventDefault(),U(D,(V,R,$)=>{let K=V.createDiv({cls:"stashpad-when-pop-row"});for(let X of["Today","Yesterday"]){let Bt=K.createEl("button",{cls:"stashpad-when-pop-chip",text:X});Bt.type="button",Bt.addEventListener("mousedown",ct=>ct.preventDefault()),Bt.addEventListener("click",ct=>{ct.preventDefault(),p(b,X),R()})}let O=V.createDiv({cls:"stashpad-when-pop-row stashpad-when-pop-days"}),it=["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],_=(ft().day()+6)%7;for(let X=0;X<it.length;X++){let Bt=it[X],ct=O.createEl("button",{cls:"stashpad-when-pop-chip",text:Bt.slice(0,3)});ct.type="button",ct.title=Bt,X===_&&ct.addClass("is-today"),ct.addEventListener("mousedown",St=>St.preventDefault()),ct.addEventListener("click",St=>{if(St.preventDefault(),B==="betweenEnd"){let st=X,mt=ft().startOf("day"),me=(mt.day()+6)%7,en=(st-me+7)%7;en===0&&(en=7);let ur=mt.clone().add(en,"days").format("YYYY-MM-DD");p(b,ur)}else p(b,Bt);R()})}})});let W=(z,V)=>{z.value||(z.value=V);let R=z;if(typeof R.showPicker=="function")try{R.showPicker();return}catch{}z.focus(),z.click()};return Q.addEventListener("click",z=>{z.preventDefault(),W(E,ft().format("YYYY-MM-DD"))}),E.addEventListener("change",()=>{E.value&&p(b,E.value)}),w.addEventListener("click",z=>{z.preventDefault();let V=b.selectionStart??b.value.length,R=g(b.value,V),$=l(this.whenMode,R,B),[K,O]=$.split(":"),it=parseInt(K,10),at=parseInt(O,10),_=it%12;_===0&&(_=12);let X=it>=12?"pm":"am";L(b,v,_,at,X)}),S.addEventListener("click",z=>{z.preventDefault(),b.value="",C(""),b.focus()}),b},I=()=>{if(A.empty(),this.whenMode==="between"){let u=h("start (date / day / timeframe)",()=>this.whenSingleText,Q=>{this.whenSingleText=Q},"betweenStart"),f=h("end (date / day / timeframe)",()=>this.whenBetweenEndText,Q=>{this.whenBetweenEndText=Q},"betweenEnd"),C=A.createDiv({cls:"stashpad-when-actions"}),B=C.createEl("button",{cls:"stashpad-when-insert",text:"Insert"});B.type="button",B.addEventListener("mousedown",Q=>Q.preventDefault());let m=()=>{let Q=u.value.trim(),E=f.value.trim();Q&&this.appendFilterToInput(t,"after",Q),E&&this.appendFilterToInput(t,"before",E),this.closeWhenBuilder()};B.addEventListener("click",Q=>{Q.preventDefault(),m()});let y=C.createEl("button",{cls:"stashpad-when-cancel",text:"Cancel"});y.type="button",y.addEventListener("mousedown",Q=>Q.preventDefault()),y.addEventListener("click",Q=>{Q.preventDefault(),this.closeWhenBuilder()}),d(u,m),d(f,m),u.focus(),u.setSelectionRange(u.value.length,u.value.length)}else{let u=h("date / day / timeframe",()=>this.whenSingleText,y=>{this.whenSingleText=y},"single"),f=A.createDiv({cls:"stashpad-when-actions"}),C=f.createEl("button",{cls:"stashpad-when-insert",text:"Insert"});C.type="button",C.addEventListener("mousedown",y=>y.preventDefault());let B=()=>{let y=u.value.trim();y&&this.appendFilterToInput(t,this.whenMode,y),this.closeWhenBuilder()};C.addEventListener("click",y=>{y.preventDefault(),B()});let m=f.createEl("button",{cls:"stashpad-when-cancel",text:"Cancel"});m.type="button",m.addEventListener("mousedown",y=>y.preventDefault()),m.addEventListener("click",y=>{y.preventDefault(),this.closeWhenBuilder()}),d(u,B),u.focus(),u.setSelectionRange(u.value.length,u.value.length)}};I(),e.parentElement?.insertBefore(s,e.nextSibling),this.whenBuilderEl=s}closeWhenBuilder(){if(!this.whenBuilderEl)return;this.whenBuilderEl.remove(),this.whenBuilderEl=null,this.modalEl?.removeClass("is-when-builder-open")}selectSuggestion(t,e){if(t&&t.kind==="search-excluded"){this.loadExcludedNotes();return}super.selectSuggestion(t,e)}onChooseSuggestion(t){if(t.kind==="create"&&this.opts.onCreate){this.opts.onCreate(this.inputEl?.value??"");return}if(t.kind==="folder-open"&&t.id==="__folder_picker__"){let e=this.opts.folderResults?.()??[];if(!e.length)return;let i=this.inputEl?.value??"",s=!1,n=g=>{s=!0;let h=g.split("/").pop()??g;this.opts.onPick({id:`folder:${g}`,label:`Open folder \u201C${h}\u201D in a new tab`,node:null,kind:"folder-open",folder:g})},o=new no(this.app,e,n),r=o.onClose.bind(o),A=this.tree,l=this.titleFn,d=this.opts,p=this.app;o.onClose=()=>{if(r(),!s){let g=new c(p,A,l,d);g.open(),setTimeout(()=>{let h=g.inputEl;h&&(i&&(h.value=i,h.dispatchEvent(new Event("input",{bubbles:!0}))),h.focus(),h.setSelectionRange(h.value.length,h.value.length))},0)}},o.open();return}this.opts.onPick(t)}},no=class extends ht.FuzzySuggestModal{constructor(t,e,i){super(t);this.folders=e;this.onChosen=i;this.setPlaceholder("Open which folder?")}getItems(){return this.folders}getItemText(t){let e=t.split("/").pop()??t;return e===t?t:`${e} \u2014 ${t}`}onChooseItem(t){this.onChosen(t)}};var za=require("obsidian");rt();var Ms=class extends za.SuggestModal{constructor(a){super(a),this.setPlaceholder("Run a Stashpad command\u2026");let t=this.app.commands?.commands??{};this.commands=Object.keys(t).filter(e=>e.startsWith("stashpad:")).filter(e=>e!=="stashpad:stashpad-command-palette").map(e=>({id:e,name:VA(t[e]?.name??e)})).sort((e,i)=>e.name.localeCompare(i.name))}getSuggestions(a){return this.commands.filter(t=>Ji(a,t.name))}renderSuggestion(a,t){t.createDiv({text:a.name,cls:"stashpad-cmd-palette-name"})}onChooseSuggestion(a){this.app.commands?.executeCommandById?.(a.id)}};function VA(c){return c.replace(/^(?:\s*Stashpad:\s*)+/i,"").trim()||c}Ft();var oo=require("obsidian");function $A(c,a){return!a||c.metaKey||c.ctrlKey||c.altKey?!1:c.key.toLowerCase()===a.toLowerCase()}function Ze(c,a){return a?a.includes("+")?WA(c,a):$A(c,a):!1}function G(c,a){if(!a)return!1;let{primary:t,secondary:e,preferRight:i,useBoth:s}=a;return t&&e?s?Ze(c,t)||Ze(c,e):i?Ze(c,e):Ze(c,t):Ze(c,t)||Ze(c,e)}function Pi(c){if(!c)return"";let a=oo.Platform.isMacOS;return c.split("+").map(t=>{let e=t.trim();return e?e.toLowerCase()==="mod"?a?"Cmd":"Ctrl":e.toLowerCase()==="alt"?a?"Opt":"Alt":e.length===1?e.toUpperCase():e:""}).filter(Boolean).join("+")}function WA(c,a){if(!a)return!1;let t=a.split("+").map(p=>p.trim()).filter(Boolean);if(t.length<2)return!1;let e=t[t.length-1].toLowerCase(),i=new Set(t.slice(0,-1).map(p=>p.toLowerCase())),s=i.has("mod"),n=i.has("ctrl")||i.has("control"),o=i.has("cmd")||i.has("meta")||i.has("command"),r=i.has("alt")||i.has("option"),A=i.has("shift"),d=oo.Platform.isMacOS?c.metaKey:c.ctrlKey;return s&&!d||n&&!c.ctrlKey||o&&!c.metaKey||r!==c.altKey||A!==c.shiftKey||!s&&(!n&&c.ctrlKey||!o&&c.metaKey)?!1:c.key.toLowerCase()===e}var xe=require("obsidian");Ft();var Nt=class Nt{constructor(a){this.host=a;this.knownBodies=new Map;this.contribTimers=new Map;this.recentSelfWrites=new Map;this.lastExternalModify=new Map}dispose(){for(let a of this.contribTimers.values())clearTimeout(a);this.contribTimers.clear(),this.knownBodies.clear(),this.recentSelfWrites.clear(),this.lastExternalModify.clear()}currentAuthorLink(){let a=(this.host.plugin.settings.authorName??"").trim(),t=(this.host.plugin.settings.authorId??"").trim();if(!a||!t)return null;let e=a.replace(/[^\w\- ]+/g,"").trim().replace(/\s+/g,"-")||"author",i=`${this.host.noteFolder}/_authors/${e}-${t}.md`,s=a.replace(/[\[\]|]/g,"").trim()||e;return{link:`[[${i}|${s}]]`,path:i,name:a,id:t}}claimSelectedAsAuthor(){this.claimAuthorship({scope:"selection",contributorMode:!1})}claimFolderAsAuthor(){this.claimAuthorship({scope:"folder",contributorMode:!1})}claimSelectedWithContributor(){this.claimAuthorship({scope:"selection",contributorMode:!0})}claimFolderWithContributor(){this.claimAuthorship({scope:"folder",contributorMode:!0})}fileBackedNotesInFolder(){let a=this.host.noteFolder.replace(/\/+$/,"");return this.host.app.vault.getMarkdownFiles().filter(t=>{let e=t.parent?.path?.replace(/\/+$/,"")??"";if(e!==a&&!e.startsWith(a+"/")||t.path.includes("/_authors/"))return!1;let i=this.host.app.metadataCache.getFileCache(t)?.frontmatter;return typeof i?.id=="string"&&!!i.id})}async pacedFrontmatter(a,t){for(let s=0;s<a.length;s++){let n=this.host.app.vault.getAbstractFileByPath(a[s]);if(n instanceof xe.TFile){this.recentSelfWrites.set(n.path,Date.now());try{await this.host.app.fileManager.processFrontMatter(n,o=>t(o,a[s]))}catch(o){console.warn("[Stashpad] claim: frontmatter write failed",a[s],o)}}(s+1)%25===0&&await new Promise(o=>setTimeout(o,30))}}async claimAuthorship(a){let t=this.currentAuthorLink();if(!t){new xe.Notice("Set your author name in Stashpad settings first.");return}let e=`-${t.id}`,i=a.scope==="selection"?this.host.getActionTargets().map(g=>g.file).filter(g=>!!g):this.fileBackedNotesInFolder();if(i.length===0){new xe.Notice(a.scope==="selection"?"No notes selected.":"No notes in this folder.");return}let s=[],n=[];for(let g of i){let h=this.host.app.metadataCache.getFileCache(g)?.frontmatter,I=typeof h?.author=="string"?h.author:"";if(!I.trim()){s.push(g.path);continue}if(I.includes(e)||!a.contributorMode)continue;(Array.isArray(h?.contributors)?h.contributors.filter(f=>typeof f=="string"):[]).some(f=>f.includes(e))||n.push(g.path)}let o=s.length+n.length;if(o===0){new xe.Notice("Nothing to claim \u2014 those notes are already authored by you.");return}if(a.scope==="folder"){let g=[`Stamp yourself as author on ${s.length} unauthored note(s)`];if(n.length&&g.push(`and as a contributor on ${n.length} already-authored note(s)`),!await new Promise(I=>{new pt(this.host.app,"Claim authorship",`${g.join(" ")}? +Existing authors are never overwritten. This can be undone.`,"Claim",I).open()}))return}let r=this.host.noteFolder,A=t.link,l=new Set,d=async()=>{await this.pacedFrontmatter(s,(g,h)=>{typeof g.author=="string"&&g.author.trim()||(g.author=A),Array.isArray(g.contributors)&&g.contributors.some(I=>typeof I=="string"&&I.includes(e))&&(g.contributors=g.contributors.filter(I=>!(typeof I=="string"&&I.includes(e))),l.add(h))}),await this.pacedFrontmatter(n,g=>{let h=Array.isArray(g.contributors)?g.contributors.filter(I=>typeof I=="string"):[];h.some(I=>I.includes(e))||h.push(A),g.contributors=h})};this.ensureAuthorFile(t),await d(),this.host.plugin.getUndoStack(r).push({label:`Claim authorship (${o} note${o===1?"":"s"})`,undo:async()=>{await this.pacedFrontmatter(s,(g,h)=>{if(typeof g.author=="string"&&g.author.includes(e)&&delete g.author,l.has(h)){let I=Array.isArray(g.contributors)?g.contributors.filter(u=>typeof u=="string"):[];I.some(u=>u.includes(e))||I.push(A),g.contributors=I}}),await this.pacedFrontmatter(n,g=>{Array.isArray(g.contributors)&&(g.contributors=g.contributors.filter(h=>!(typeof h=="string"&&h.includes(e))))}),this.host.debouncedRender()},redo:async()=>{l.clear(),await d(),this.host.debouncedRender()}});let p=[];s.length&&p.push(`authored ${s.length}`),n.length&&p.push(`contributing to ${n.length}`),new xe.Notice(`Claimed authorship: ${p.join(", ")}. Undo available.`),this.host.debouncedRender()}async ensureAuthorFile(a){try{a.id&&this.host.plugin.authorRegistry.record({id:a.id,name:a.name});let t=`${this.host.noteFolder}/_authors`;if(await this.host.ensureFolder(t),await this.host.app.vault.adapter.exists(a.path))return;let e=a.id===(this.host.plugin.settings.authorId??"").trim(),i=this.host.plugin.buildAuthorStub({id:a.id,name:a.name,role:e?this.host.plugin.settings.authorRole:void 0,department:e?this.host.plugin.settings.authorDepartment:void 0},new Date().toISOString());await this.host.app.vault.create(a.path,i)}catch(t){console.warn("[Stashpad] ensureAuthorFile failed",t)}}collectAuthorIds(a){let t=new Set,e=i=>{if(typeof i!="string")return null;let s=i.match(/-([a-z0-9]{4,12})(?:\.md)?(?:\||\]\])/i);return s?s[1]:null};for(let i of a){if(!i.file)continue;let s=this.host.app.metadataCache.getFileCache(i.file)?.frontmatter;if(!s)continue;let n=e(s.author);if(n&&t.add(n),Array.isArray(s.contributors))for(let o of s.contributors){let r=e(o);r&&t.add(r)}}return Array.from(t)}pruneContribMaps(){let a=Date.now(),t=Nt.EXTERNAL_WRITE_GRACE_MS*20,e=Nt.EXTERNAL_QUIESCENCE_MS*12;for(let[i,s]of this.recentSelfWrites)a-s>t&&this.recentSelfWrites.delete(i);for(let[i,s]of this.lastExternalModify)a-s>e&&this.lastExternalModify.delete(i);if(this.knownBodies.size>64)for(let i of this.knownBodies.keys())this.host.tree.idForPath(i)||this.knownBodies.delete(i)}noteModify(a){let t=Date.now(),e=this.recentSelfWrites.get(a.path);e!==void 0&&t-e<Nt.EXTERNAL_WRITE_GRACE_MS||this.lastExternalModify.set(a.path,t),this.scheduleContribution(a)}scheduleContribution(a){let t=this.contribTimers.get(a.path);t&&clearTimeout(t);let e=this.isFileActivelyEdited(a),i=Nt.CONTRIB_DEBOUNCE_MS+(e?Nt.CONTRIB_ACTIVE_EDITOR_BONUS_MS:0),s=setTimeout(()=>{if(this.contribTimers.delete(a.path),this.isFileActivelyEdited(a)){this.scheduleContribution(a);return}let n=this.lastExternalModify.get(a.path);if(n!==void 0&&Date.now()-n<Nt.EXTERNAL_QUIESCENCE_MS){this.scheduleContribution(a);return}this.maybeRecordContribution(a)},i);this.contribTimers.set(a.path,s)}isFileActivelyEdited(a){try{let t=this.host.app.workspace.activeLeaf;if(!t)return!1;let e=t.view;if(!e||e.getViewType?.()!=="markdown"||e.file?.path!==a.path)return!1;let i=e.containerEl??null;return!!i&&i.contains(document.activeElement)}catch{return!1}}async maybeRecordContribution(a){let t="";try{t=await this.host.app.vault.cachedRead(a)}catch{return}let e=this.host.stripFrontmatter(t),i=this.knownBodies.get(a.path);if(this.knownBodies.set(a.path,e),i===void 0||i===e||this.host.plugin.rebootstrapInProgress)return;let s=this.currentAuthorLink();if(!s)return;this.ensureAuthorFile(s);let n=new Date().toISOString();this.recentSelfWrites.set(a.path,Date.now());try{await this.host.app.fileManager.processFrontMatter(a,o=>{o.modified=n;let r=typeof o.author=="string"?o.author:"",A=Array.isArray(o.contributors)?o.contributors.filter(g=>typeof g=="string"):[],l=`-${s.id}`,d=r.includes(l),p=A.some(g=>g.includes(l));!d&&!p&&A.push(s.link),o.contributors=A})}catch(o){console.warn("[Stashpad] maybeRecordContribution failed",o)}}};Nt.CONTRIB_DEBOUNCE_MS=4e3,Nt.CONTRIB_ACTIVE_EDITOR_BONUS_MS=2e3,Nt.EXTERNAL_WRITE_GRACE_MS=1500,Nt.EXTERNAL_QUIESCENCE_MS=5e3;var Ts=Nt;var Hs=class{constructor(a){this.host=a;this.dragSourceIds=null;this.dragPlaceholder=null;this.dragRowHeight=0}attachRowDnD(a,t,e){a.addEventListener("dragstart",i=>{let s=this.host.selection.has(t.id)&&this.host.selection.size>1?[...this.host.selection]:[t.id];if(this.dragSourceIds=s,this.dragRowHeight=a.offsetHeight,a.addClass("is-dragging"),this.host.listEl&&(this.dragPlaceholder=this.host.listEl.createDiv({cls:"stashpad-drop-placeholder"}),this.dragPlaceholder.setCssStyles({height:"0px"}),this.dragPlaceholder.addEventListener("dragover",n=>{this.dragSourceIds&&(n.preventDefault(),n.dataTransfer&&(n.dataTransfer.dropEffect="move"))}),this.dragPlaceholder.addEventListener("drop",n=>{if(!this.dragSourceIds||!this.dragPlaceholder)return;n.preventDefault(),n.stopPropagation();let o=this.dragSourceIds.slice();this.dragSourceIds=null;let r=this.dragPlaceholder.nextElementSibling,A=this.dragPlaceholder.previousElementSibling;this.removeDragPlaceholder();let l,d="before";r&&r.classList.contains("stashpad-note")?(l=r.dataset.id,d="before"):A&&A.classList.contains("stashpad-note")&&(l=A.dataset.id,d="after"),l&&this.host.reorderToTarget(o,l,d)}),this.dragPlaceholder.remove()),i.dataTransfer?.setData("text/plain",s.join(",")),i.dataTransfer){i.dataTransfer.effectAllowed="move";try{i.dataTransfer.setDragImage(a,12,12)}catch{}}}),a.addEventListener("dragend",()=>{a.removeClass("is-dragging"),this.clearDropIndicators(),this.removeDragPlaceholder(),this.dragSourceIds=null}),a.addEventListener("dragover",i=>{if(!this.dragSourceIds)return;i.preventDefault(),i.dataTransfer&&(i.dataTransfer.dropEffect="move");let s=this.dropZone(i,a);this.clearDropIndicators(),s==="drop-into"?(this.removeDragPlaceholder(),a.addClass("drop-into")):(a.removeClass("drop-into"),this.placePlaceholder(a,s==="drop-above"?"before":"after"))}),a.addEventListener("dragleave",i=>{let s=a.getBoundingClientRect();(i.clientX<s.left||i.clientX>s.right||i.clientY<s.top||i.clientY>s.bottom)&&a.removeClass("drop-into")}),a.addEventListener("drop",i=>{if(!this.dragSourceIds)return;i.preventDefault(),i.stopPropagation();let s=this.dragSourceIds.slice();this.dragSourceIds=null;let n=this.dropZone(i,a);this.clearDropIndicators(),this.removeDragPlaceholder(),a.removeClass("is-dragging"),n==="drop-into"?this.host.reorderToTarget(s,t.id,"into"):this.host.reorderToTarget(s,t.id,n==="drop-above"?"before":"after")})}attachListDnD(a){a.addEventListener("dragover",t=>{if(!this.dragSourceIds)return;let e=t.target;if(e&&e.closest&&e.closest(".stashpad-note"))return;t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="move");let i=Array.from(a.querySelectorAll(".stashpad-note"));if(i.length!==0){for(let s of i){let n=s.getBoundingClientRect();if(t.clientY<n.top+n.height/2){this.placePlaceholder(s,"before");return}}this.placePlaceholder(i[i.length-1],"after")}}),a.addEventListener("drop",t=>{if(!this.dragSourceIds)return;t.preventDefault();let e=this.dragSourceIds.slice();if(this.dragSourceIds=null,!this.dragPlaceholder)return;let i=this.dragPlaceholder.nextElementSibling,s=this.dragPlaceholder.previousElementSibling;if(this.removeDragPlaceholder(),i&&i.classList.contains("stashpad-note")){let n=i.dataset.id;n&&this.host.reorderToTarget(e,n,"before")}else if(s&&s.classList.contains("stashpad-note")){let n=s.dataset.id;n&&this.host.reorderToTarget(e,n,"after")}})}placePlaceholder(a,t){if(!this.dragPlaceholder||!this.host.listEl)return;let e=t==="before"?a:a.nextSibling;if(t==="before"&&this.dragPlaceholder.nextSibling===a||t==="after"&&this.dragPlaceholder.previousSibling===a)return;let i=!!this.dragPlaceholder.parentElement;this.host.listEl.insertBefore(this.dragPlaceholder,e),this.dragPlaceholder.setCssStyles({opacity:"1"}),i?this.dragPlaceholder.setCssStyles({height:`${this.dragRowHeight}px`}):(this.dragPlaceholder.setCssStyles({height:"0px"}),this.dragPlaceholder.offsetHeight,this.dragPlaceholder.setCssStyles({height:`${this.dragRowHeight}px`}))}removeDragPlaceholder(){if(!this.dragPlaceholder?.parentElement)return;let a=this.dragPlaceholder;a.setCssStyles({height:"0px",opacity:"0"}),setTimeout(()=>{a.parentElement&&a.remove()},150)}dropZone(a,t){let e=t.getBoundingClientRect(),i=a.clientY-e.top;return i<e.height*.3?"drop-above":i>e.height*.7?"drop-below":"drop-into"}clearDropIndicators(){if(this.host.listEl)for(let a of Array.from(this.host.listEl.querySelectorAll(".drop-into")))a.removeClass("drop-into")}};var Va=require("obsidian");var Ps=class{constructor(a,t,e){this.host=a;this.component=t;this.bodyObserver=null;this.lazyBodies=new WeakMap;this.renderCache=e??new Map}async getOrComputeRender(a){let t=this.renderCache.get(a.path);if(t&&t.mtime===a.stat.mtime)return wt.record("render.row.cacheHit",0),t;let e=await wt.timeAsync("render.row.read",()=>this.host.app.vault.cachedRead(a)),i=this.host.stripFrontmatter(e),{text:s,attachments:n}=this.splitAttachments(i),o=createDiv({cls:"stashpad-note-text"});await wt.timeAsync("render.row.markdown",()=>Va.MarkdownRenderer.render(this.host.app,s,o,a.path,this.component));let r=o.innerHTML,A={mtime:a.stat.mtime,text:s,attachments:n,html:r};return this.renderCache.set(a.path,A),A}arm(){this.bodyObserver?.disconnect(),this.lazyBodies=new WeakMap,this.bodyObserver=new IntersectionObserver(a=>{for(let t of a){if(!t.isIntersecting)continue;let e=t.target,i=this.lazyBodies.get(e);this.bodyObserver?.unobserve(e),this.lazyBodies.delete(e),i&&i()}},{root:this.host.contentEl,rootMargin:"1400px 0px"})}dispose(){this.bodyObserver?.disconnect(),this.bodyObserver=null}isArmed(){return!!this.bodyObserver}hasFreshRenderCache(a){let t=this.renderCache.get(a.path);return!!t&&t.mtime===a.stat.mtime}defer(a,t){this.lazyBodies.set(a,t),this.bodyObserver?.observe(a)}splitAttachments(a){let t=[];return{text:a.replace(/!\[\[([^\]\|]+)(?:\|[^\]]+)?\]\]/g,(i,s)=>(t.push(s),"")).replace(/\n{3,}/g,` -`).trim(),attachments:t}}};function Ga(c,a,t){return c.tree.getChildren(a).slice().sort((i,s)=>HA(c,i,s,t)).map(i=>i.id)}function HA(c,a,t,e){switch(e){case"created-asc":return(a.created||"").localeCompare(t.created||"");case"created-desc":return(t.created||"").localeCompare(a.created||"");case"modified-asc":case"modified-desc":{let i=Ua(c,a)||a.created||"",s=Ua(c,t)||t.created||"";return e==="modified-asc"?i.localeCompare(s):s.localeCompare(i)}case"title-az":case"title-za":{let i=c.titleForNode(a),s=c.titleForNode(t),n={numeric:!0,sensitivity:"base"};return e==="title-az"?i.localeCompare(s,void 0,n):s.localeCompare(i,void 0,n)}default:return 0}}function Ua(c,a){if(!a.file)return"";let t=c.app.metadataCache.getFileCache(a.file)?.frontmatter;return(typeof t?.modified=="string"?t.modified:"")||""}var $e=require("obsidian");ei();async function _n(c){let a=c.getActionTargets();if(!a.length)return;let t=j().prefixTimestampsOnCopy,e=[];for(let i of a){if(!i.file)continue;let s=await c.app.vault.cachedRead(i.file),n=c.stripFrontmatter(s).trim();e.push(t?`${c.formatTimeInline(i.created)} ${n}`:n)}await navigator.clipboard.writeText(e.join(` +`).trim(),attachments:t}}};function Wa(c,a,t){return c.tree.getChildren(a).slice().sort((i,s)=>XA(c,i,s,t)).map(i=>i.id)}function XA(c,a,t,e){switch(e){case"created-asc":return(a.created||"").localeCompare(t.created||"");case"created-desc":return(t.created||"").localeCompare(a.created||"");case"modified-asc":case"modified-desc":{let i=$a(c,a)||a.created||"",s=$a(c,t)||t.created||"";return e==="modified-asc"?i.localeCompare(s):s.localeCompare(i)}case"title-az":case"title-za":{let i=c.titleForNode(a),s=c.titleForNode(t),n={numeric:!0,sensitivity:"base"};return e==="title-az"?i.localeCompare(s,void 0,n):s.localeCompare(i,void 0,n)}default:return 0}}function $a(c,a){if(!a.file)return"";let t=c.app.metadataCache.getFileCache(a.file)?.frontmatter;return(typeof t?.modified=="string"?t.modified:"")||""}var Us="sheet-group",je="sheet-order",Ui="sheet-final",ZA="sheet-label";function se(c){if(!c)return null;let a=c[Us];return typeof a=="string"&&a.trim()?a:null}function ao(c){let a=c?.[je];return typeof a=="number"?a:null}function Gi(c){return se(c)!==null&&ao(c)!==null}function Ri(c){return c?.[Ui]===!0}function jA(c){let a=c?.[ZA];return typeof a=="string"&&a.trim()?a:null}function Xa(){let c=Date.now().toString(36),a=Math.floor(Math.random()*1e6).toString(36);return`s-${c}-${a}`}function Ct(c,a){return a.file?c.metadataCache.getFileCache(a.file)?.frontmatter:null}function ro(c,a){return a.slice().sort((t,e)=>{let i=ao(Ct(c,t)),s=ao(Ct(c,e));if(i!=null&&s!=null&&i!==s)return i-s;if(i!=null&&s==null)return-1;if(i==null&&s!=null)return 1;let n=t.created??"",o=e.created??"";return n!==o?n<o?-1:1:t.id<e.id?-1:t.id>e.id?1:0})}function Za(c,a){if(a.length===0)return null;let t=ro(c,a);return t.find(e=>Ri(Ct(c,e)))??t[0]}function ja(c,a,t){let e=jA(Ct(c,a));return e||t}var _e=require("obsidian");ri();async function Ao(c){let a=c.getActionTargets();if(!a.length)return;let t=j().prefixTimestampsOnCopy,e=[];for(let i of a){if(!i.file)continue;let s=await c.app.vault.cachedRead(i.file),n=c.stripFrontmatter(s).trim();e.push(t?`${c.formatTimeInline(i.created)} ${n}`:n)}await navigator.clipboard.writeText(e.join(` -`)),c.plugin.notifications.show({message:`Copied ${c.titleList(a)} to clipboard`,kind:"success",category:"system",affectedIds:a.map(i=>i.id),folder:c.noteFolder})}async function Ra(c){let a=c.getActionTargets();if(!a.length||!a[0].file){new $e.Notice("Nothing to copy from.");return}let t=a[0],e=await c.app.vault.cachedRead(t.file),i=c.stripFrontmatter(e),s=Co(i);if(s.length===0){c.plugin.notifications.show({message:`No codeblock found in "${c.titleForNode(t)}".`,kind:"info",category:"system",affectedIds:[t.id],folder:c.noteFolder});return}if(s.length===1){await navigator.clipboard.writeText(s[0].code),c.plugin.notifications.show({message:`Copied codeblock${s[0].lang?` (${s[0].lang})`:""} from "${c.titleForNode(t)}".`,kind:"success",category:"system",affectedIds:[t.id],folder:c.noteFolder});return}let n=s.map((r,A)=>({kind:"one",idx:A,label:`${A+1}. ${r.lang||"(no language)"} \u2014 ${r.code.split(` +`)),c.plugin.notifications.show({message:`Copied ${c.titleList(a)} to clipboard`,kind:"success",category:"system",affectedIds:a.map(i=>i.id),folder:c.noteFolder})}async function _a(c){let a=c.getActionTargets();if(!a.length||!a[0].file){new _e.Notice("Nothing to copy from.");return}let t=a[0],e=await c.app.vault.cachedRead(t.file),i=c.stripFrontmatter(e),s=ko(i);if(s.length===0){c.plugin.notifications.show({message:`No codeblock found in "${c.titleForNode(t)}".`,kind:"info",category:"system",affectedIds:[t.id],folder:c.noteFolder});return}if(s.length===1){await navigator.clipboard.writeText(s[0].code),c.plugin.notifications.show({message:`Copied codeblock${s[0].lang?` (${s[0].lang})`:""} from "${c.titleForNode(t)}".`,kind:"success",category:"system",affectedIds:[t.id],folder:c.noteFolder});return}let n=s.map((r,A)=>({kind:"one",idx:A,label:`${A+1}. ${r.lang||"(no language)"} \u2014 ${r.code.split(` `)[0].slice(0,60)}${r.code.includes(` -`)?"\u2026":""}`}));n.push({kind:"all",idx:-1,label:`Copy all ${s.length} blocks (joined with blank lines)`});let o=new class extends $e.SuggestModal{getSuggestions(r){let A=r.trim().toLowerCase();if(!A)return n;let l=A.split(/\s+/).filter(Boolean);return n.filter(d=>{let g=d.label.toLowerCase();return l.every(p=>g.includes(p))})}renderSuggestion(r,A){A.createDiv({cls:"stashpad-suggest-title",text:r.label})}async onChooseSuggestion(r){let A=r.kind==="all"?s.map(l=>l.code).join(` +`)?"\u2026":""}`}));n.push({kind:"all",idx:-1,label:`Copy all ${s.length} blocks (joined with blank lines)`});let o=new class extends _e.SuggestModal{getSuggestions(r){let A=r.trim().toLowerCase();if(!A)return n;let l=A.split(/\s+/).filter(Boolean);return n.filter(d=>{let p=d.label.toLowerCase();return l.every(g=>p.includes(g))})}renderSuggestion(r,A){A.createDiv({cls:"stashpad-suggest-title",text:r.label})}async onChooseSuggestion(r){let A=r.kind==="all"?s.map(l=>l.code).join(` -`):s[r.idx].code;await navigator.clipboard.writeText(A),c.plugin.notifications.show({message:r.kind==="all"?`Copied all ${s.length} codeblocks from "${c.titleForNode(t)}".`:`Copied codeblock${s[r.idx].lang?` (${s[r.idx].lang})`:""} from "${c.titleForNode(t)}".`,kind:"success",category:"system",affectedIds:[t.id],folder:c.noteFolder})}}(c.app);o.setPlaceholder(`${s.length} codeblocks in "${c.titleForNode(t)}" \u2014 pick one to copy.`),o.open()}async function La(c){let a=c.getActionTargets();if(a.length===0){let n=c.tree.get(c.focusId);n?.file&&(a=[n])}if(a.length===0){new $e.Notice("Nothing to copy.");return}let t=j().prefixTimestampsOnCopy,e=[],i=async(n,o)=>{if(n.file){let r=await c.app.vault.cachedRead(n.file),A=c.stripFrontmatter(r).trim().split(/\r?\n/).join(" "),l=t?`${c.formatTimeInline(n.created)} `:"";e.push(`${" ".repeat(o)}- ${l}${A}`)}for(let r of c.tree.getChildren(n.id))await i(r,o+1)};for(let n of a)await i(n,0);let s=e.join(` -`);await navigator.clipboard.writeText(s),c.plugin.clearNoteClipboard(),c.plugin.noteClipboard={mode:"copy",folder:c.noteFolder,ids:a.map(n=>n.id),text:s},c.render(),c.plugin.notifications.show({message:`Copied tree of ${c.titleList(a)} (${e.length} entries) \u2014 paste in the list to clone, in a note to drop the outline in`,kind:"success",category:"system",affectedIds:a.map(n=>n.id),folder:c.noteFolder})}async function qa(c){let a=c.getActionTargets();if(a.length===0){let i=c.tree.get(c.focusId);i?.file&&(a=[i])}if(a.length===0){new $e.Notice("Nothing to copy.");return}let t=[],e=(i,s)=>{if(!i.file)return;let n=" ".repeat(s);t.push(`${n}- ![[${i.file.basename}]]`);for(let o of c.tree.getChildren(i.id))e(o,s+1)};for(let i of a)e(i,0);await navigator.clipboard.writeText(t.join(` -`)),c.plugin.notifications.show({message:`Copied outline of ${c.titleList(a)} (${t.length} entr${t.length===1?"y":"ies"})`,kind:"success",category:"system",affectedIds:a.map(i=>i.id),folder:c.noteFolder})}var Nt=require("obsidian");rt();Gi();vt();function UA(c){return c.replace(/[^\w.\-]+/g,"_").replace(/^\.+/,"").slice(0,60)||"stash-export"}async function Ja(c,a){let t=Oa(c,a);if(t.length===0){new Nt.Notice("Nothing to export.");return}let e=Ya(c,t);if(e.length===0){new Nt.Notice("No exportable notes (no files attached).");return}let i=(c.noteFolder.split("/").pop()||c.noteFolder).trim(),s=t.length===1?c.titleForNode(t[0]):`${i}-${t.length}notes`;new oi(c.app,s,e.length,(n,o,r)=>{GA(c,t,e,n,o,r)},Zi).open()}async function Ka(c,a){let t=Oa(c,a);if(t.length===0){new Nt.Notice("Nothing to export.");return}let e=Ya(c,t);if(e.length===0){new Nt.Notice("No exportable notes.");return}let i=(c.noteFolder.split("/").pop()||c.noteFolder).trim(),s=t.length===1?c.titleForNode(t[0]):`${i}-okf`;new hi(c.app,s,e.length,(n,o)=>{(async()=>{try{let r=await c.plugin.exportOkf(c.noteFolder,t.map(A=>A.id),n,o);if(!r.length){new Nt.Notice("Nothing exported.");return}c.plugin.notifications.show({message:`Exported OKF \u2014 ${r.length} file${r.length===1?"":"s"} \u2192 \`${c.noteFolder}/${c.plugin.settings.exportFolder||"_exports"}\``,kind:"success",category:"export",affectedPaths:r,folder:c.noteFolder,duration:0}),await c.log.append({type:"stash_export",id:t[0].id,payload:{okf:!0,paths:r,noteCount:e.length,rootIds:t.map(A=>A.id)}})}catch(r){new Nt.Notice(`OKF export failed: ${r.message}`),console.error(r)}})()}).open()}async function GA(c,a,t,e,i,s=!1){try{let n=await Ae(c.app,{rootNotes:a.filter(h=>!!h.file).map(h=>({id:h.id,file:h.file})),allDescendants:t.filter(h=>!a.some(I=>I.id===h.id)).filter(h=>!!h.file).map(h=>({id:h.id,file:h.file})),sourceFolder:c.noteFolder}),o="";if(i){let h=await Ge(n,i);n=h.data;let I=Ko[h.kdf];o=I.strong?` (encrypted \xB7 ${I.label})`:` (encrypted \xB7 ${I.label} \u2014 Argon2id unavailable on this device, this export is weaker)`}let r=(0,Nt.moment)().format("YYYYMMDD-HHmmss"),A=UA(e),l=(c.plugin.settings.exportFolder||"_exports").trim().replace(/^\/+|\/+$/g,""),d=`${c.noteFolder}/${l}`;await c.ensureFolder(d);let g=`${A}-${r}`,p=`${d}/${g}.${jt}`;if(await c.app.vault.createBinary(p,n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength)),s&&i){let h=c.app.secretStorage;try{h?.setSecret(ii(g),i)}catch(I){console.warn("[Stashpad] couldn't save export passphrase to secret storage",I)}}await c.log.append({type:"stash_export",id:a[0].id,payload:{path:p,noteCount:t.length,rootIds:a.map(h=>h.id)}}),c.plugin.notifications.show({message:`Exported ${t.length} note${t.length===1?"":"s"}${o} \u2192 \`${p}\``,kind:i&&o.includes("weaker")?"warning":"success",category:"export",affectedPaths:[p],folder:c.noteFolder,actions:c.actionsForFile(p),duration:0})}catch(n){c.plugin.notifications.show({message:`Stashpad: export failed +`):s[r.idx].code;await navigator.clipboard.writeText(A),c.plugin.notifications.show({message:r.kind==="all"?`Copied all ${s.length} codeblocks from "${c.titleForNode(t)}".`:`Copied codeblock${s[r.idx].lang?` (${s[r.idx].lang})`:""} from "${c.titleForNode(t)}".`,kind:"success",category:"system",affectedIds:[t.id],folder:c.noteFolder})}}(c.app);o.setPlaceholder(`${s.length} codeblocks in "${c.titleForNode(t)}" \u2014 pick one to copy.`),o.open()}async function tr(c){let a=c.getActionTargets();if(a.length===0){let n=c.tree.get(c.focusId);n?.file&&(a=[n])}if(a.length===0){new _e.Notice("Nothing to copy.");return}let t=j().prefixTimestampsOnCopy,e=[],i=async(n,o)=>{if(n.file){let r=await c.app.vault.cachedRead(n.file),A=c.stripFrontmatter(r).trim().split(/\r?\n/).join(" "),l=t?`${c.formatTimeInline(n.created)} `:"";e.push(`${" ".repeat(o)}- ${l}${A}`)}for(let r of c.tree.getChildren(n.id))await i(r,o+1)};for(let n of a)await i(n,0);let s=e.join(` +`);await navigator.clipboard.writeText(s),c.plugin.clearNoteClipboard(),c.plugin.noteClipboard={mode:"copy",folder:c.noteFolder,ids:a.map(n=>n.id),text:s},c.render(),c.plugin.notifications.show({message:`Copied tree of ${c.titleList(a)} (${e.length} entries) \u2014 paste in the list to clone, in a note to drop the outline in`,kind:"success",category:"system",affectedIds:a.map(n=>n.id),folder:c.noteFolder})}async function er(c){let a=c.getActionTargets();if(a.length===0){let i=c.tree.get(c.focusId);i?.file&&(a=[i])}if(a.length===0){new _e.Notice("Nothing to copy.");return}let t=[],e=(i,s)=>{if(!i.file)return;let n=" ".repeat(s);t.push(`${n}- ![[${i.file.basename}]]`);for(let o of c.tree.getChildren(i.id))e(o,s+1)};for(let i of a)e(i,0);await navigator.clipboard.writeText(t.join(` +`)),c.plugin.notifications.show({message:`Copied outline of ${c.titleList(a)} (${t.length} entr${t.length===1?"y":"ies"})`,kind:"success",category:"system",affectedIds:a.map(i=>i.id),folder:c.noteFolder})}var xt=require("obsidian");rt();Yi();Ft();function tl(c){return c.replace(/[^\w.\-]+/g,"_").replace(/^\.+/,"").slice(0,60)||"stash-export"}async function ir(c,a){let t=nr(c,a);if(t.length===0){new xt.Notice("Nothing to export.");return}let e=or(c,t);if(e.length===0){new xt.Notice("No exportable notes (no files attached).");return}let i=(c.noteFolder.split("/").pop()||c.noteFolder).trim(),s=t.length===1?c.titleForNode(t[0]):`${i}-${t.length}notes`;new di(c.app,s,e.length,(n,o,r)=>{el(c,t,e,n,o,r)},ns).open()}async function sr(c,a){let t=nr(c,a);if(t.length===0){new xt.Notice("Nothing to export.");return}let e=or(c,t);if(e.length===0){new xt.Notice("No exportable notes.");return}let i=(c.noteFolder.split("/").pop()||c.noteFolder).trim(),s=t.length===1?c.titleForNode(t[0]):`${i}-okf`;new ui(c.app,s,e.length,(n,o)=>{(async()=>{try{let r=await c.plugin.exportOkf(c.noteFolder,t.map(A=>A.id),n,o);if(!r.length){new xt.Notice("Nothing exported.");return}c.plugin.notifications.show({message:`Exported OKF \u2014 ${r.length} file${r.length===1?"":"s"} \u2192 \`${c.noteFolder}/${c.plugin.settings.exportFolder||"_exports"}\``,kind:"success",category:"export",affectedPaths:r,folder:c.noteFolder,duration:0}),await c.log.append({type:"stash_export",id:t[0].id,payload:{okf:!0,paths:r,noteCount:e.length,rootIds:t.map(A=>A.id)}})}catch(r){new xt.Notice(`OKF export failed: ${r.message}`),console.error(r)}})()}).open()}async function el(c,a,t,e,i,s=!1){try{let n=await he(c.app,{rootNotes:a.filter(h=>!!h.file).map(h=>({id:h.id,file:h.file})),allDescendants:t.filter(h=>!a.some(I=>I.id===h.id)).filter(h=>!!h.file).map(h=>({id:h.id,file:h.file})),sourceFolder:c.noteFolder}),o="";if(i){let h=await Ke(n,i);n=h.data;let I=ta[h.kdf];o=I.strong?` (encrypted \xB7 ${I.label})`:` (encrypted \xB7 ${I.label} \u2014 Argon2id unavailable on this device, this export is weaker)`}let r=(0,xt.moment)().format("YYYYMMDD-HHmmss"),A=tl(e),l=(c.plugin.settings.exportFolder||"_exports").trim().replace(/^\/+|\/+$/g,""),d=`${c.noteFolder}/${l}`;await c.ensureFolder(d);let p=`${A}-${r}`,g=`${d}/${p}.${ee}`;if(await c.app.vault.createBinary(g,n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength)),s&&i){let h=c.app.secretStorage;try{h?.setSecret(Ai(p),i)}catch(I){console.warn("[Stashpad] couldn't save export passphrase to secret storage",I)}}await c.log.append({type:"stash_export",id:a[0].id,payload:{path:g,noteCount:t.length,rootIds:a.map(h=>h.id)}}),c.plugin.notifications.show({message:`Exported ${t.length} note${t.length===1?"":"s"}${o} \u2192 \`${g}\``,kind:i&&o.includes("weaker")?"warning":"success",category:"export",affectedPaths:[g],folder:c.noteFolder,actions:c.actionsForFile(g),duration:0})}catch(n){c.plugin.notifications.show({message:`Stashpad: export failed Error: ${n.message} -Check disk space + write permissions on the export folder.`,kind:"error",category:"export"}),console.error(n)}}function Oa(c,a){if(a?.file)return[a];if(c.selection.size>0)return[...c.selection].map(e=>c.tree.get(e)).filter(e=>!!e?.file);if(c.cursorIdx>=0&&c.currentChildren[c.cursorIdx])return[c.currentChildren[c.cursorIdx]];let t=c.tree.get(c.focusId);return t?.file?[t]:[]}function Ya(c,a){let t=new Set,e=[],i=s=>{if(!t.has(s.id)){t.add(s.id),s.file&&e.push(s);for(let n of c.tree.getChildren(s.id))i(n)}};for(let s of a)i(s);return e}async function za(c){let a=c.app.vault.getFiles().filter(e=>e.extension===jt);if(a.length===0){new Nt.Notice("No .stash files found in this vault.");return}let t=new class extends Nt.FuzzySuggestModal{getItems(){return a}getItemText(e){return e.path}onChooseItem(e){to(c,e)}}(c.app);t.setPlaceholder("Pick a .stash file to import\u2026"),t.open()}async function to(c,a){try{let t=new Uint8Array(await c.app.vault.readBinary(a)),e=await Re(c.app,t,{secretId:ii(a.basename)});if(!e)return;let i=await Kt(c.app,e,c.noteFolder,RA(c));c.tree.rebuild(c.noteFolder),c.render(),await c.log.append({type:"stash_import",id:F,payload:{from:a.path,into:c.noteFolder,noteCount:i.notesWritten,attachmentsWritten:i.attachmentsWritten,collisionsRenamed:i.collisionsRenamed}});try{await c.app.fileManager.trashFile(a)}catch{}c.plugin.importService.clearPendingEncrypted(a.path);let s=[`Imported ${i.notesWritten} note${i.notesWritten===1?"":"s"}`];i.attachmentsWritten&&s.push(`+ ${i.attachmentsWritten} attachment${i.attachmentsWritten===1?"":"s"}`),i.collisionsRenamed&&s.push(`(${i.collisionsRenamed} id collision${i.collisionsRenamed===1?"":"s"} renamed)`),c.plugin.notifications.show({message:s.join(" "),kind:"success",category:"import",folder:c.noteFolder})}catch(t){c.plugin.notifications.show({message:`Stashpad: import failed +Check disk space + write permissions on the export folder.`,kind:"error",category:"export"}),console.error(n)}}function nr(c,a){if(a?.file)return[a];if(c.selection.size>0)return[...c.selection].map(e=>c.tree.get(e)).filter(e=>!!e?.file);if(c.cursorIdx>=0&&c.currentChildren[c.cursorIdx])return[c.currentChildren[c.cursorIdx]];let t=c.tree.get(c.focusId);return t?.file?[t]:[]}function or(c,a){let t=new Set,e=[],i=s=>{if(!t.has(s.id)){t.add(s.id),s.file&&e.push(s);for(let n of c.tree.getChildren(s.id))i(n)}};for(let s of a)i(s);return e}async function ar(c){let a=c.app.vault.getFiles().filter(e=>e.extension===ee);if(a.length===0){new xt.Notice("No .stash files found in this vault.");return}let t=new class extends xt.FuzzySuggestModal{getItems(){return a}getItemText(e){return e.path}onChooseItem(e){lo(c,e)}}(c.app);t.setPlaceholder("Pick a .stash file to import\u2026"),t.open()}async function lo(c,a){try{let t=new Uint8Array(await c.app.vault.readBinary(a)),e=await Oe(c.app,t,{secretId:Ai(a.basename)});if(!e)return;let i=await Yt(c.app,e,c.noteFolder,il(c));c.tree.rebuild(c.noteFolder),c.render(),await c.log.append({type:"stash_import",id:F,payload:{from:a.path,into:c.noteFolder,noteCount:i.notesWritten,attachmentsWritten:i.attachmentsWritten,collisionsRenamed:i.collisionsRenamed}});try{await c.app.fileManager.trashFile(a)}catch{}c.plugin.importService.clearPendingEncrypted(a.path);let s=[`Imported ${i.notesWritten} note${i.notesWritten===1?"":"s"}`];i.attachmentsWritten&&s.push(`+ ${i.attachmentsWritten} attachment${i.attachmentsWritten===1?"":"s"}`),i.collisionsRenamed&&s.push(`(${i.collisionsRenamed} id collision${i.collisionsRenamed===1?"":"s"} renamed)`),c.plugin.notifications.show({message:s.join(" "),kind:"success",category:"import",folder:c.noteFolder})}catch(t){c.plugin.notifications.show({message:`Stashpad: import failed File: \`${a.name}\` Error: ${t.message} -Inspect with the buttons below \u2014 rename to .zip to crack it open in an archive tool.`,kind:"error",category:"import",affectedPaths:[a.path],actions:c.actionsForFile(a.path)}),console.error(t)}}function RA(c){let a=new Set,t=e=>{if(a.add(e),!!c.tree.get(e))for(let s of c.tree.getChildren(e))t(s.id)};return t(F),a}ei();ei();var qA=new Set(["png","jpg","jpeg","gif","webp","svg","bmp","avif"]),bs={nested:"Nested",flat:"Flat",everything:"Everything"},Ns=[{key:"day",calShort:"Today",rollShort:"24h",calLong:"Since midnight today",rollLong:"Last 24 hours"},{key:"week",calShort:"Week",rollShort:"7d",calLong:"Since Monday this week",rollLong:"Last 7 days"},{key:"month",calShort:"Month",rollShort:"30d",calLong:"Since the 1st of this month",rollLong:"Last 30 days"},{key:"year",calShort:"Year",rollShort:"365d",calLong:"Since January 1 this year",rollLong:"Last 365 days"},{key:"all",calShort:"All",rollShort:"ad infinitum",calLong:"All time",rollLong:"All time"}],xs=class extends k.ItemView{constructor(t,e){super(t);this.focusId=F;this.timeFilter="all";this.timeFilterCalendar=!1;this.tagFilter=null;this.colorFilter=null;this.importedOnly=!1;this.authorFilter=null;this.noteFolder="Stashpad";this.folderOverride=null;this.tinyMode=!1;this.tinyAlwaysOnTop=!1;this.tinyOpacity=1;this.compactMode=!1;this.detachTreeHook=null;this.detachSettings=null;this.slugDebouncers=new Map;this.attachmentDebouncers=new Map;this.bulkRenderDepth=0;this.bulkSettleTimer=null;this.bootstrappedFolders=new Set;this.selection=new Set;this.lastSelected=null;this.cursorIdx=-1;this.pendingCursorId=null;this.currentChildren=[];this.modeSplit=null;this.modeEnterSubmits=!0;this.nextDestination=null;this.nextDestinationFolder=null;this.nextDestinationLabel=null;this.inListPicker=null;this.pickerEscapeAt=0;this.composerExitAt=0;this.listEl=null;this.composerInputEl=null;this.composerDraft="";this.draftsLoadedFor=null;this.autoSelectNewest=!1;this.scrollToBottomOnNextRender=!1;this.scrollListenerSaveTimer=null;this.suppressScrollSave=!1;this.selectionGuardKey=0;this.pendingRenderPolicy=null;this.stickToListBottom=!1;this.keyboardTransitionUntil=0;this.stickyRowObserver=null;this.listResizeObserver=null;this.composerNarrowObserver=null;this.lastCursorByFocus=new Map;this.lastSelectionByFocus=new Map;this.expandedNotes=new Set;this.focusComposerOnNextRender=!1;this.suppressComposerFocusUntil=0;this.composerAutocomplete=null;this.firstSelectedId=null;this.mobileSelectMode=!1;this.focusedMiniObserver=null;this.pendingComposerCaret=null;this.navBackStack=[];this.navForwardSnapshots=[];this.treeReconcileTimer=null;this.stampLastCursorTimer=null;this.stampSelectionTimer=null;this._renderT0=null;this.tinyOpacityPopover=null;this.lastListWidth=0;this.onDocKeyDown=t=>{if(!this.viewRoot.isConnected||this.app.workspace.activeLeaf!==this.leaf||fo(t.target))return;let e=j().bindings;if(L(t,e.toggleSplit)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.toggleSplit();return}if(L(t,e.pickDestination)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.openDestinationPicker();return}if(L(t,e.search)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.openSearchModal();return}if(L(t,e.commandPalette)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.openStashpadCommandPalette();return}if(L(t,e.lockSelection)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdLockSelection();return}if(L(t,e.unlockAll)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdUnlockAll();return}if(L(t,e.moveToArchive)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdMoveToArchive();return}if(L(t,e.encryptDelete)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdEncryptDelete();return}if(L(t,e.searchInParent)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.openSearchInParentModal();return}if(L(t,e.exportStash)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdExportStash();return}if(L(t,e.importStash)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdImportStash();return}if(L(t,e.pickFolder)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdOpenFolderPicker();return}if(L(t,e.cloneStashpadTab)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdCloneStashpadTab();return}let i=t.target,s=!!i&&(i.tagName==="INPUT"||i.tagName==="TEXTAREA");if(t.key===" "&&!t.metaKey&&!t.ctrlKey&&!t.altKey&&!t.shiftKey&&!s){let A=this.composerInputEl;if(A){t.preventDefault(),t.stopPropagation(),A.focus();let l=A.value.length;A.setSelectionRange(l,l);return}}let n=!!i&&(i.tagName==="INPUT"||i.tagName==="TEXTAREA"||i.tagName==="BUTTON"||i.tagName==="SELECT");if(t.key==="Escape"&&i instanceof HTMLElement&&(i.tagName==="BUTTON"||i.tagName==="SELECT")&&this.viewRoot.contains(i)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.viewRoot.focus();return}if(this.inListPicker&&t.key==="Escape"){t.preventDefault(),t.stopPropagation(),this.inListPicker=null,this.pickerEscapeAt=Date.now();let A=this.listEl,l=!!A&&A.scrollTop+A.clientHeight>=A.scrollHeight-2,d=A?.scrollTop??0;if(this.render(),A){let g=l?A.scrollHeight:d;A.scrollTop=g,requestAnimationFrame(()=>{A.scrollTop=l?A.scrollHeight:d}),setTimeout(()=>{A.scrollTop=l?A.scrollHeight:d},60),this.revealCursorRow()}return}if(this.inListPicker&&!n){if(t.key==="ArrowDown"){t.preventDefault(),this.inListPicker.activeIdx=this.nextPickableIdx(this.inListPicker.activeIdx,1),this.repaintSelectionClasses(),this.revealRowAt(this.inListPicker.activeIdx);return}if(t.key==="ArrowUp"){t.preventDefault(),this.inListPicker.activeIdx=this.nextPickableIdx(this.inListPicker.activeIdx,-1),this.repaintSelectionClasses(),this.revealRowAt(this.inListPicker.activeIdx);return}if(t.key==="Enter"){t.preventDefault(),this.commitInListPicker();return}if(L(t,j().bindings.move)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.inListPicker=null,this.repaintSelectionClasses(),this.cmdMovePicker();return}return}if(n)return;if(L(t,e.delete)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdDelete();return}if(L(t,e.toggleComplete)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdToggleComplete();return}if(L(t,e.moveToTop)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdMoveToTop();return}if(L(t,e.moveToBottom)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdMoveToBottom();return}if(L(t,e.moveUp)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdMoveUp();return}if(L(t,e.moveDown)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdMoveDown();return}if(L(t,e.outdent)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdOutdent();return}if(L(t,e.setColor)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdSetColor();return}if(L(t,e.selectAll)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdSelectAll();return}if(L(t,e.swapWithParent)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdSwapWithParent();return}if(L(t,e.undo)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdUndo();return}if(L(t,e.redo)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdRedo();return}if(t.key===" "){t.preventDefault();let A=this.composerInputEl;if(A){A.focus();let l=A.value.length;A.setSelectionRange(l,l)}return}if(t.key==="ArrowDown"){t.preventDefault(),this.cursorIdx>=this.currentChildren.length-1?this.cursorIdx=0:this.cursorIdx++,this.selectCursor(t.shiftKey);return}if(t.key==="ArrowUp"){t.preventDefault(),this.cursorIdx<=0?this.cursorIdx=this.currentChildren.length-1:this.cursorIdx--,this.selectCursor(t.shiftKey);return}if(t.altKey&&t.key==="ArrowLeft"){t.preventDefault(),this.navigateBack();return}if(t.altKey&&t.key==="ArrowRight"){t.preventDefault(),this.navigateForward();return}if(t.key==="ArrowRight"){let A=this.currentChildren[this.cursorIdx];A&&(t.preventDefault(),this.navigateTo(A.id));return}if(t.key==="ArrowLeft"||t.key==="Backspace"){t.preventDefault(),this.navigateUp();return}if(t.key==="Escape"){if(t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),Date.now()-this.pickerEscapeAt<350||Date.now()-this.composerExitAt<400)return;if(this.plugin.noteClipboard&&this.plugin.noteClipboard.folder===this.noteFolder){this.plugin.clearNoteClipboard(),this.render();return}let A=this.firstSelectedId??(this.selection.size>0?this.selection.values().next().value:null);if(this.selection.clear(),this.firstSelectedId=null,A){let l=this.currentChildren.findIndex(d=>d.id===A);this.selection.add(A),this.lastSelected=A,l>=0&&(this.cursorIdx=l)}this.repaintSelectionClasses(),this.revealCursorRow();return}let o=j().bindings;if(L(t,o.pasteNotes)&&this.plugin.noteClipboard){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdPasteNotes();return}if(this.selection.size>0||this.cursorIdx>=0&&this.currentChildren[this.cursorIdx]){if(L(t,o.move)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdMovePicker();return}if(L(t,o.pickMove)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdInListPicker();return}if(L(t,o.merge)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdMerge();return}if(L(t,o.copy)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdCopy();return}if(L(t,o.copyNotes)&&!window.getSelection()?.toString()){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdCopyNotes();return}if(L(t,o.cutNotes)&&!window.getSelection()?.toString()){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdCutNotes();return}if(L(t,o.copyTree)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdCopyTree();return}if(L(t,o.copyOutline)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdCopyOutline();return}if(L(t,o.copyCodeBlock)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdCopyCodeBlock();return}if(L(t,o.openEditor)){if(t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),t.shiftKey){let A=this.tree.get(this.focusId);A?.file&&this.cmdOpenInEditor(A)}else this.cmdOpenInEditor();return}if(L(t,o.openTab)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdOpenInNewStashpadTab();return}if(L(t,o.split)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdSplit();return}if(L(t,o.clone)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdClone();return}if(L(t,o.insertTemplate)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdInsertTemplate();return}if(L(t,o.toggleExpand)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdToggleExpand();return}if(L(t,o.togglePin)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdTogglePin();return}if(L(t,o.toggleTask)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdToggleTask();return}if(L(t,o.setDue)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdSetDue();return}}if(this.currentChildren.length>0){if(L(t,o.jumpToTop)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.jumpToTop();return}if(L(t,o.jumpToBottom)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.jumpToBottom();return}}let r=this.tree.get(this.focusId);if(r?.file){if(L(t,o.openEditor)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdOpenInEditor(r);return}if(L(t,o.openTab)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdOpenInNewStashpadTab(r);return}}};this.openSearchInstance=null;this.fmSyncUnsubscribe=null;this.completedState=new Map;this.taskTaggedState=new Map;this.pendingFocusIds=null;this.onFileModify=t=>{!(t instanceof k.TFile)||t.extension!=="md"||t.path.startsWith(this.noteFolder+"/")&&(this.scheduleSlugRename(t),this.scheduleAttachmentSync(t),this.authorship.noteModify(t),this.debouncedRender())};this.onFileCreate=t=>{!(t instanceof k.TFile)||t.extension!=="md"||t.path.startsWith(this.noteFolder+"/")&&this.debouncedRender()};this.plugin=e,this.tree=new ms(this.app),this.log=e.newLog(),this.integrity=new vs(this.tree,this.log),this.order=new Ke(this.app),this.sortStore=new Qs(this.app),this.fmSync=new Es(this.app,()=>this.tree),this.tree.setOrderProvider(i=>{let s=this.noteFolder,n=this.sortStore.getMode(s,i);return n==="manual"?this.order.getOrder(s,i):Ga(this,i,n)}),this.debouncedRender=(0,k.debounce)(()=>{this.renderSuppressed()||this.render()},80),this.authorship=new ks(this),this.dnd=new Ss(this),this.bodyRenderer=new Ds(this,this,this.plugin.renderCacheStore)}getViewType(){return J}getDisplayText(){let t=(this.noteFolder||"").trim(),e=t.split("/").pop()||t||"Stashpad";if(this.focusId&&this.focusId!==F){let i=this.tree.get(this.focusId);if(i){let s=this.titleForNode(i).trim(),n=s.length>40?s.slice(0,40)+"\u2026":s;if(n)return`${e} \u2014 ${n} \xB7 ${this.focusId}`}}return e}refreshHeaderTitle(){let t=this.getDisplayText();try{this.leaf.updateHeader?.()}catch{}let i=(this.headerEl??this.containerEl?.querySelector?.(".view-header"))?.querySelector?.(".view-header-title")??this.titleEl;i&&i.textContent!==t&&i.setText(t)}getIcon(){return"list-tree"}async onOpen(){let t=this.contentEl;t.empty(),t.addClass("stashpad-scroll-host"),this.viewRoot=t.createDiv({cls:"stashpad-view"}),this.viewRoot.setAttribute("tabindex","0"),this.viewRoot.addEventListener("focusin",()=>ps(this)),this.viewRoot.addEventListener("click",()=>ps(this)),this.viewRoot.addEventListener("mouseup",A=>{A.button===3?(A.preventDefault(),this.navigateBack()):A.button===4&&(A.preventDefault(),this.navigateForward())}),this.viewRoot.addEventListener("auxclick",A=>{A.button===3?(A.preventDefault(),this.navigateBack()):A.button===4&&(A.preventDefault(),this.navigateForward())}),ps(this),this.registerInterval(window.setInterval(()=>this.authorship.pruneContribMaps(),6e4));let e=null,i=()=>{e||(e=new k.Scope(this.app.scope),e.register([],"Escape",()=>{if(this.inListPicker)return this.inListPicker=null,this.pickerEscapeAt=Date.now(),this.repaintSelectionClasses(),!1;if(Date.now()-this.pickerEscapeAt<350||Date.now()-this.composerExitAt<400)return!1;if(this.selection.size>1){let A=this.firstSelectedId??this.selection.values().next().value??null;if(this.selection.clear(),this.firstSelectedId=null,A){let l=this.currentChildren.findIndex(d=>d.id===A);this.selection.add(A),this.lastSelected=A,l>=0&&(this.cursorIdx=l)}this.render(),this.revealCursorRow()}return!1}),this.app.keymap?.pushScope(e))},s=()=>{if(e){try{this.app.keymap?.popScope(e)}catch{}e=null}};this.viewRoot.addEventListener("focusin",i),this.viewRoot.addEventListener("focusout",A=>{let l=A.relatedTarget;l&&this.viewRoot&&this.viewRoot.contains(l)||s()}),this.register(()=>s()),this.detachTreeHook=this.tree.hookMetadataCache(()=>this.debouncedRender()),this.registerEvent(this.app.metadataCache.on("resolved",()=>this.scheduleTreeReconcile())),this.registerEvent(this.app.metadataCache.on("changed",A=>{if(A.extension!=="md")return;let l=this.app.metadataCache.getFileCache(A)?.frontmatter;this.completedState.set(A.path,!!l?.completed),this.taskTaggedState.set(A.path,this.taggedFromFm(l))})),this.registerEvent(this.app.vault.on("rename",(A,l)=>{for(let d of[this.completedState,this.taskTaggedState])d.has(l)&&(d.set(A.path,d.get(l)),d.delete(l))})),this.registerEvent(this.app.vault.on("delete",A=>{this.completedState.delete(A.path),this.taskTaggedState.delete(A.path);let l=A.path.lastIndexOf("/"),d=(l>=0?A.path.slice(0,l):"").replace(/\/+$/,"");A.path.endsWith(".md")&&d===this.noteFolder.replace(/\/+$/,"")&&(this.tree.rebuild(this.noteFolder),this.debouncedRender())})),this.detachSettings=ba(()=>{this.loadConfig();let A=this.plugin.settings.drafts?.[this.noteFolder]??"",l=this.composerInputEl?.value??"";A===""&&this.composerDraft!==""&&l===""?(this.composerDraft="",this.composerInputEl&&(this.composerInputEl.value="")):A===""&&l!==""&&(this.composerDraft=l),!!this.composerInputEl&&document.activeElement===this.composerInputEl&&(this.focusComposerOnNextRender=!0),this.debouncedRender()}),this.app.vault.on("modify",this.onFileModify),this.app.vault.on("create",this.onFileCreate),window.addEventListener("keydown",this.onDocKeyDown,!0),this.loadConfig();try{await this.bootstrapFolder()}catch(A){let l=A?.message??"";/already exists/i.test(l)||console.warn("[Stashpad] bootstrapFolder failed:",A)}this.tree.rebuild(this.noteFolder),this.installFmSyncActivityNotice(),this.backfillFrontmatterSync(),this.plugin.maybeSweepFolder(this.noteFolder),this.defaultCursorToLast(),this.refreshHeaderTitle(),await this.loadDraftsForFolder();try{let A=this.plugin.loadLastCursor(this.noteFolder);for(let[l,d]of A)this.lastCursorByFocus.set(l,d);this.lastSelectionByFocus=this.plugin.loadLastSelection(this.noteFolder)}catch{}let n=this.lastCursorByFocus.get(this.focusId),o;n&&this.tree.get(n)?(o={kind:"scroll-to-id",id:n,align:"start"},this.pendingFocusIds=[n]):(this.scrollToBottomOnNextRender=!0,o={kind:"pin-bottom",until:"next-user-input"});let r=this.foldRestoredSelection(n);r&&(this.pendingFocusIds=r),this.render(o),this.scheduleSelectionRestore(),this.tinyMode&&(setTimeout(()=>this.applyTinyWindow(),1e3),setTimeout(()=>this.applyTinyWindow(),1500)),this.registerDomEvent(window,"beforeunload",()=>{this.flushDrafts(),this.stampSelectedCursor(!0)}),this.registerDomEvent(window,"blur",()=>{this.flushDrafts(),this.stampSelectedCursor(!0)}),this.focusComposer(),this.registerEvent(this.app.workspace.on("active-leaf-change",A=>{A===this.leaf?this.focusComposer():this.stickToListBottom=!1}))}renderSuppressed(){return this.bulkRenderDepth>0||this.bulkSettleTimer!=null||this.plugin.rebootstrapInProgress||this.plugin.okfRebuildingFolders.has(this.noteFolder)}beginBulkRender(){this.bulkRenderDepth++,this.bulkSettleTimer!=null&&(window.clearTimeout(this.bulkSettleTimer),this.bulkSettleTimer=null)}endBulkRender(t=500){this.bulkRenderDepth>0&&this.bulkRenderDepth--,!(this.bulkRenderDepth>0)&&(this.bulkSettleTimer!=null&&window.clearTimeout(this.bulkSettleTimer),this.bulkSettleTimer=window.setTimeout(()=>{this.bulkSettleTimer=null,this.viewRoot?.isConnected&&(this.tree.rebuild(this.noteFolder),this.render())},t))}forceReconcileRender(){this.viewRoot?.isConnected&&(this.tree.rebuild(this.noteFolder),this.render())}scheduleTreeReconcile(){this.renderSuppressed()||this.treeReconcileTimer==null&&(this.treeReconcileTimer=window.setTimeout(()=>{if(this.treeReconcileTimer=null,!this.viewRoot?.isConnected)return;let t=this.noteFolder,e=t+"/",i=0;for(let s of this.app.vault.getMarkdownFiles()){let n=s.parent?.path?.replace(/\/+$/,"")??"";if(!(n===t||t!==""&&n.startsWith(e)))continue;let o=this.app.metadataCache.getFileCache(s)?.frontmatter?.id;typeof o=="string"&&o&&i++}i!==this.tree.fileBackedCount()&&(this.tree.rebuild(t),this.debouncedRender())},400))}focusView(){requestAnimationFrame(()=>{this.viewRoot?.isConnected&&(document.activeElement instanceof HTMLElement&&(document.activeElement.tagName==="INPUT"||document.activeElement.tagName==="TEXTAREA")||this.viewRoot.focus({preventScroll:!0}))})}focusComposer(){if(!j().autofocusComposerAfterSend)return;let t=()=>{if(!this.viewRoot?.isConnected||Date.now()<this.suppressComposerFocusUntil||Date.now()<this.plugin.suppressComposerAutofocusUntil)return;let e=document.activeElement;e&&(e.tagName==="INPUT"||e.tagName==="TEXTAREA")&&e!==this.composerInputEl||(e&&e.tagName==="BUTTON"&&this.viewRoot.contains(e),this.composerInputEl?.focus({preventScroll:!0}))};requestAnimationFrame(t),setTimeout(t,50),setTimeout(t,200)}async onClose(){ka(this),this.detachTreeHook?.(),this.detachSettings?.(),this.app.vault.off("modify",this.onFileModify),this.app.vault.off("create",this.onFileCreate),window.removeEventListener("keydown",this.onDocKeyDown,!0),this.listResizeObserver?.disconnect(),this.listResizeObserver=null,this.stickyRowObserver?.disconnect(),this.stickyRowObserver=null,this.bodyRenderer.dispose(),this.composerNarrowObserver?.disconnect(),this.composerNarrowObserver=null,this.focusedMiniObserver?.disconnect(),this.focusedMiniObserver=null,this.treeReconcileTimer!=null&&(window.clearTimeout(this.treeReconcileTimer),this.treeReconcileTimer=null),this.composerAutocomplete?.detach(),this.composerAutocomplete=null;for(let t of this.slugDebouncers.values())t.cancel();for(let t of this.attachmentDebouncers.values())t.cancel();this.authorship.dispose();try{await this.flushDrafts()}catch{}try{await this.order.flush(this.noteFolder)}catch{}try{await this.sortStore.flush(this.noteFolder)}catch{}try{await this.fmSync.flush()}catch{}this.stampSelectedCursor(!0),this.fmSyncUnsubscribe?.(),this.fmSyncUnsubscribe=null}setEphemeralState(t){let e=t;e?.focusId&&(this.focusId=e.focusId),e?.timeFilter&&(this.timeFilter=e.timeFilter)}getEphemeralState(){return{focusId:this.focusId,timeFilter:this.timeFilter}}getState(){return{...super.getState()??{},folderOverride:this.folderOverride,timeFilter:this.timeFilter,focusId:this.focusId,tagFilter:this.tagFilter,colorFilter:this.colorFilter,timeFilterCalendar:this.timeFilterCalendar,tinyMode:this.tinyMode,tinyAlwaysOnTop:this.tinyAlwaysOnTop,tinyOpacity:this.tinyOpacity,compactMode:this.compactMode,navBackStack:this.navBackStack,navForwardSnapshots:this.navForwardSnapshots}}async setState(t,e){let i=t??null;if(i){"folderOverride"in i&&(this.folderOverride=i.folderOverride??null),i.timeFilter&&(this.timeFilter=i.timeFilter),i.focusId&&(this.focusId=i.focusId),"tagFilter"in i&&(this.tagFilter=i.tagFilter??null),"colorFilter"in i&&(this.colorFilter=i.colorFilter??null),"timeFilterCalendar"in i&&(this.timeFilterCalendar=!!i.timeFilterCalendar),"tinyMode"in i&&(this.tinyMode=!!i.tinyMode),"tinyAlwaysOnTop"in i&&(this.tinyAlwaysOnTop=!!i.tinyAlwaysOnTop),typeof i.tinyOpacity=="number"&&Number.isFinite(i.tinyOpacity)&&(this.tinyOpacity=Math.min(1,Math.max(.3,i.tinyOpacity))),"compactMode"in i&&(this.compactMode=!!i.compactMode);let o=r=>r&&typeof r.folder=="string"&&typeof r.focusId=="string";Array.isArray(i.navBackStack)&&(this.navBackStack=i.navBackStack.filter(o)),Array.isArray(i.navForwardSnapshots)&&(this.navForwardSnapshots=i.navForwardSnapshots.filter(o))}let s=(this.plugin?.settings?.folder??"Stashpad").trim().replace(/^\/+|\/+$/g,""),n=this.folderOverride?.trim().replace(/^\/+|\/+$/g,"")||null;if(this.noteFolder=n||s||"Stashpad",await super.setState(t,e),this.refreshHeaderTitle(),this.viewRoot){this.loadConfig(),await this.bootstrapFolder(),this.tree.rebuild(this.noteFolder),this.backfillFrontmatterSync(),this.defaultCursorToLast(),this.draftsLoadedFor=null,this.composerDraft="",await this.loadDraftsForFolder(),this.lastCursorByFocus.clear(),this.lastSelectionByFocus.clear();try{let l=this.plugin.loadLastCursor(this.noteFolder);for(let[d,g]of l)this.lastCursorByFocus.set(d,g);this.lastSelectionByFocus=this.plugin.loadLastSelection(this.noteFolder)}catch{}let o=this.lastCursorByFocus.get(this.focusId),r;o&&this.tree.get(o)?(this.pendingFocusIds=[o],r={kind:"scroll-to-id",id:o,align:"start"}):r={kind:"pin-bottom",until:"next-user-input"};let A=this.foldRestoredSelection(o);A&&(this.pendingFocusIds=A),this.render(r),this.scheduleSelectionRestore()}}focus(){this.viewRoot?.focus({preventScroll:!0})}foldRestoredSelection(t){let e=this.lastSelectionByFocus.get(this.focusId)??null;if(!e||!e.length)return null;let i=e.filter(s=>!!this.tree.get(s));return i.length?t&&i.includes(t)?[t,...i.filter(s=>s!==t)]:i:null}stampSelection(t=!1){let e=[...this.selection],i=()=>{try{this.plugin.saveLastSelection(this.noteFolder,this.focusId,e)}catch{}};if(this.stampSelectionTimer!=null&&(window.clearTimeout(this.stampSelectionTimer),this.stampSelectionTimer=null),t){i();return}this.stampSelectionTimer=window.setTimeout(()=>{this.stampSelectionTimer=null,i()},400)}scheduleSelectionRestore(){let t=this.lastSelectionByFocus.get(this.focusId);if(!t||!t.length)return;let e=()=>{let i=t.filter(r=>this.currentChildren.some(A=>A.id===r));if(!i.length)return;let s=[...this.selection],n=new Set(i);if(s.length<i.length&&s.every(r=>n.has(r))){this.selection.clear();for(let r of i)this.selection.add(r);this.firstSelectedId=i[0],this.lastSelected=i[i.length-1],this.repaintSelectionClasses()}};for(let i of[120,400,900,1600])window.setTimeout(e,i)}loadConfig(){let t=(this.plugin?.settings?.folder??"Stashpad").trim().replace(/^\/+|\/+$/g,""),i=this.folderOverride?.trim().replace(/^\/+|\/+$/g,"")||null||t||"Stashpad";i!==this.noteFolder?(this.noteFolder=i,this.tree.rebuild(this.noteFolder)):this.noteFolder=i}captureNavSnapshot(){return{folder:this.noteFolder,focusId:this.focusId}}recordNavState(t={}){let e=this.captureNavSnapshot(),i=this.navBackStack[this.navBackStack.length-1];i&&i.folder===e.folder&&i.focusId===e.focusId||(this.navBackStack.push(e),t.keepForward||(this.navForwardSnapshots=[]))}async setFolderOverride(t,e={}){let i=t?.trim().replace(/^\/+|\/+$/g,"")||null;if(i&&this.isReservedFolder(i)){new k.Notice(`"${i}" is a reserved Stashpad subfolder (imports/exports/attachments). Pick a different folder.`);return}if((i||null)!==(this.folderOverride||null)){e.skipHistory||this.recordNavState(),this.folderOverride=i,this.focusId=F,this.lastCursorByFocus.clear(),this.selection.clear(),this.cursorIdx=-1,this.lastSelected=null,this.composerDraft="",await this.flushDrafts(),this.draftsLoadedFor=null,this.loadConfig();try{await this.bootstrapFolder()}catch(s){let n=s?.message??"";/already exists/i.test(n)||console.warn("[Stashpad] bootstrapFolder failed:",s)}this.tree.rebuild(this.noteFolder),this.backfillFrontmatterSync(),this.plugin.maybeSweepFolder(this.noteFolder),this.defaultCursorToLast(),await this.loadDraftsForFolder();try{let s=this.app.workspace;typeof s.saveLayout=="function"?await s.saveLayout():this.app.workspace.requestSaveLayout()}catch{this.app.workspace.requestSaveLayout()}this.refreshHeaderTitle(),this.render()}}cmdOpenFolderPicker(){this.openFolderPicker()}openFolderPicker(){this.plugin.openFolderPicker()}listVaultFolders(){let t=[];for(let e of this.app.vault.getAllLoadedFiles())if(e instanceof k.TFolder){if(e.path==="/"||e.path===""||e.path.startsWith(".")||this.isReservedFolder(e.path))continue;t.push(e.path)}return t.sort((e,i)=>e.localeCompare(i))}isReservedFolder(t){let e=t.split("/").filter(Boolean).pop()??"";return e?new Set([this.plugin.settings.importDropFolder,this.plugin.settings.exportFolder,"_attachments","_processed","_authors"].map(s=>(s??"").trim().replace(/^\/+|\/+$/g,"")).filter(Boolean)).has(e):!1}persistFocus(){try{this.app.workspace.requestSaveLayout()}catch{}}cmdUndo(){let t=this.plugin.getUndoStack(this.noteFolder);if(!t.canUndo()){new k.Notice("Nothing to undo.");return}let e=t.peekUndoLabel(),i=this.plugin.notifications.recent()[0]?.category??"system";t.undo().then(()=>this.plugin.notifications.show({message:`Undid: ${e}`,kind:"info",category:i,folder:this.noteFolder})).catch(s=>this.plugin.notifications.show({message:`Undo failed: ${s.message}`,kind:"error",category:"system",folder:this.noteFolder}))}cmdRedo(){let t=this.plugin.getUndoStack(this.noteFolder);if(!t.canRedo()){new k.Notice("Nothing to redo.");return}let e=t.peekRedoLabel(),i=this.plugin.notifications.recent()[0]?.category??"system";t.redo().then(()=>this.plugin.notifications.show({message:`Redid: ${e}`,kind:"info",category:i,folder:this.noteFolder})).catch(s=>this.plugin.notifications.show({message:`Redo failed: ${s.message}`,kind:"error",category:"system",folder:this.noteFolder}))}async snapshotNotes(t,e){let i=[],s=new Set;for(let A of t)!A.file||s.has(A.file.path)||(s.add(A.file.path),i.push(A.file));let n=await Promise.all(i.map(A=>this.app.vault.read(A))),o=i.map((A,l)=>({path:A.path,content:n[l]})),r=[];if(e){let A=new Set,l=[];for(let g of n)for(let p of this.extractAttachments(this.stripFrontmatter(g))){let h=this.app.metadataCache.getFirstLinkpathDest(p,"");h&&!A.has(h.path)&&(A.add(h.path),l.push(h))}let d=await Promise.all(l.map(g=>this.app.vault.readBinary(g)));for(let g=0;g<l.length;g++)r.push({path:l[g].path,data:d[g]})}return{notes:o,attachments:r}}async restoreSnapshots(t,e){for(let s of t.attachments)try{await this.app.vault.adapter.exists(s.path)||await this.app.vault.createBinary(s.path,s.data)}catch{}for(let s of t.notes)try{await this.app.vault.adapter.exists(s.path)||await this.app.vault.create(s.path,s.content)}catch{}let i=()=>{e&&e.some(n=>this.tree.get(n))&&(this.pendingFocusIds=e.slice())};i(),this.tree.rebuild(this.noteFolder),this.render({kind:"follow-cursor"}),setTimeout(()=>{i(),this.tree.rebuild(this.noteFolder),this.render({kind:"follow-cursor"})},100),setTimeout(()=>{i(),this.tree.rebuild(this.noteFolder),this.render({kind:"follow-cursor"})},400),setTimeout(()=>{for(let s of t.notes){let n=this.tree.idForPath(s.path);n&&this.fmSync.schedule(n)}},500)}async trashNotesAndAttachments(t){let e=new Set;for(let i of t.notes){let s=this.tree.idForPath(i.path);if(!s)continue;let n=this.tree.get(s);n?.parent&&e.add(n.parent)}for(let i of t.notes){let s=this.app.vault.getAbstractFileByPath(i.path);if(s)try{await this.app.fileManager.trashFile(s)}catch{}}for(let i of t.attachments){let s=this.app.vault.getAbstractFileByPath(i.path);if(s)try{await this.app.fileManager.trashFile(s)}catch{}}this.tree.rebuild(this.noteFolder),this.render();for(let i of e)this.fmSync.scheduleParentOfDeleted(i)}async loadDraftsForFolder(){if(this.draftsLoadedFor===this.noteFolder)return;this.draftsLoadedFor=this.noteFolder;let t=this.plugin.settings.drafts??{};this.composerDraft=t[this.noteFolder]??"",console.debug("[Stashpad] loadDrafts",{folder:this.noteFolder,has:!!t[this.noteFolder],available:Object.keys(t)})}async saveDraft(t){try{let e=this.noteFolder;if((this.plugin.settings.drafts?.[e]??"")===t)return;let s={...this.plugin.settings.drafts??{}};t.length===0?delete s[e]:s[e]=t,this.plugin.settings.drafts=s,t.length===0?await this.plugin.saveSettings():await this.plugin.persistSettingsQuiet()}catch(e){console.warn("Stashpad: drafts save failed",e)}}async recordLastSubmitted(t){try{let e={...this.plugin.settings.lastSubmitted??{}};e[this.noteFolder]=t,this.plugin.settings.lastSubmitted=e,await this.plugin.persistSettingsQuiet()}catch{}}hasRestorableDraft(){let t=this.plugin.settings.drafts?.[this.noteFolder];if(!t||!t.trim())return!1;let e=this.plugin.settings.lastSubmitted?.[this.noteFolder];return!(e&&e===t)}syncComposerDraftForFocus(){}async flushDrafts(){this.composerInputEl?await this.saveDraft(this.composerInputEl.value):await this.saveDraft(this.composerDraft)}timeFilterCutoff(){if(this.timeFilter==="all")return null;if(this.timeFilterCalendar){let e=(0,k.moment)();switch(this.timeFilter){case"day":return e.startOf("day").valueOf();case"week":return e.startOf("isoWeek").valueOf();case"month":return e.startOf("month").valueOf();case"year":return e.startOf("year").valueOf()}}let t=Date.now();switch(this.timeFilter){case"day":return t-864e5;case"week":return t-7*864e5;case"month":return t-30*864e5;case"year":return t-365*864e5}return null}allowedByBases(){return null}currentViewMode(){return this.plugin.settings.viewModes?.[this.noteFolder]??"nested"}currentIncludeAttachments(){return!!this.plugin.settings.includeAttachmentsInEverything?.[this.noteFolder]}async setIncludeAttachments(t){let e={...this.plugin.settings.includeAttachmentsInEverything??{}};t?e[this.noteFolder]=!0:delete e[this.noteFolder],this.plugin.settings.includeAttachmentsInEverything=e,await this.plugin.saveSettings()}currentEncryptionFilter(){return this.plugin.settings.encryptionFilter?.[this.noteFolder]??"all"}async setEncryptionFilter(t){let e={...this.plugin.settings.encryptionFilter??{}};t==="all"?delete e[this.noteFolder]:e[this.noteFolder]=t,this.plugin.settings.encryptionFilter=e,await this.plugin.saveSettings()}currentHideChildless(){return!!this.plugin.settings.hideChildlessNotes?.[this.noteFolder]}async setHideChildless(t){let e={...this.plugin.settings.hideChildlessNotes??{}};t?e[this.noteFolder]=!0:delete e[this.noteFolder],this.plugin.settings.hideChildlessNotes=e,await this.plugin.saveSettings()}currentHideCompleted(){return!!this.plugin.settings.hideCompletedNotes?.[this.noteFolder]}async setHideCompleted(t){let e={...this.plugin.settings.hideCompletedNotes??{}};t?e[this.noteFolder]=!0:delete e[this.noteFolder],this.plugin.settings.hideCompletedNotes=e,await this.plugin.saveSettings()}currentAttachmentsOnly(){return!!this.plugin.settings.attachmentsOnlyNotes?.[this.noteFolder]}async setAttachmentsOnly(t){let e={...this.plugin.settings.attachmentsOnlyNotes??{}};t?e[this.noteFolder]=!0:delete e[this.noteFolder],this.plugin.settings.attachmentsOnlyNotes=e,await this.plugin.saveSettings()}nodeHasAttachment(t){if(!t.file)return!1;let e=this.app.metadataCache.getFileCache(t.file)?.frontmatter?.attachments;return Array.isArray(e)&&e.length>0}hasAttachmentInSubtree(t){if(this.nodeHasAttachment(t))return!0;for(let e of this.tree.getChildren(t.id))if(this.hasAttachmentInSubtree(e))return!0;return!1}hasIncompleteDescendant(t){for(let e of t.children){let i=this.tree.get(e);if(i&&(!this.isCompleted(i)||this.hasIncompleteDescendant(i)))return!0}return!1}collectEmbeddedAttachmentPaths(){let t=new Set,e=this.noteFolder,i=this.app.vault.getAbstractFileByPath(e);if(!(i instanceof k.TFolder))return t;let s=[i];for(;s.length;){let n=s.pop();for(let o of n.children){if(o instanceof k.TFolder){s.push(o);continue}if(!(o instanceof k.TFile)||o.extension!=="md")continue;let r=this.app.metadataCache.getFileCache(o)?.frontmatter;if(!(!r||!Array.isArray(r.attachments)))for(let A of r.attachments){if(typeof A!="string")continue;let l=Be(A),d=this.app.metadataCache.getFirstLinkpathDest(l,o.path);d?t.add(d.path):t.add(l)}}}return t}collectFileItems(t){let e=this.noteFolder,i=this.app.vault.getAbstractFileByPath(e);if(!(i instanceof k.TFolder))return[];let s=this.currentIncludeAttachments(),n=s?new Set:this.collectEmbeddedAttachmentPaths(),o=new Set(["_authors","_imports","_exports","_processed","_attachments","_archive",".archive"]),r=[],A=[i];for(;A.length;){let l=A.pop();for(let d of l.children){if(d instanceof k.TFolder){let g=d.name;if(l===i&&o.has(g)||l===i&&g==="_attachments"&&!s)continue;A.push(d);continue}d instanceof k.TFile&&d.extension!=="md"&&(d.name===".stashpad-order.json"||d.name===".stashpad-sort.json"||!s&&n.has(d.path)||r.push(d))}}return r}populateListBody(t,e){if(this.lastListWidth=t.clientWidth||this.lastListWidth,this.bodyRenderer.arm(),this.pendingCursorId){let d=this.currentChildren.findIndex(g=>g.id===this.pendingCursorId);d>=0&&(this.cursorIdx=d,this.selection.clear(),this.selection.add(this.pendingCursorId),this.lastSelected=this.pendingCursorId,this.pendingCursorId=null)}e.file&&k.Platform.isMobile&&(this.renderFocusedHeaderMini(t,e),this.renderFocusedHeader(t,e));let i=this.currentViewMode(),s=i==="everything"?this.collectFileItems(e.id):[],n=d=>d.created&&Number.isFinite(Date.parse(d.created))?Date.parse(d.created):Number.POSITIVE_INFINITY,o=this.currentEncryptionFilter(),r;if(o==="unlocked")r=[];else if(i==="nested")r=this.plugin.lockedSubtreesFor(this.noteFolder,e.id);else{let d=new Set([e.id,...this.currentChildren.map(p=>p.id)]),g=new Set;r=[];for(let p of d)for(let h of this.plugin.lockedSubtreesFor(this.noteFolder,p))g.has(h.blob)||(g.add(h.blob),r.push(h))}let A=r.map(d=>({lk:d,ts:n(d)})).sort((d,g)=>d.ts-g.ts),l=i==="nested"&&this.sortStore.getMode(this.noteFolder,e.id)==="manual";if(this.currentChildren.length===0&&s.length===0&&A.length===0)t.createDiv({cls:"stashpad-empty",text:"No notes here yet. Type below to add one."});else if(l&&A.length>0){let d=new Map(this.currentChildren.map((u,f)=>[u.id,f])),g=new Map;for(let{lk:u}of A)u.rootId&&g.set(u.rootId,u);let p=this.currentChildren.map(u=>u.id),h=A.map(({lk:u})=>u).filter(u=>u.rootId).sort((u,f)=>n(f)-n(u)),I=!0;for(;h.length&&I;){I=!1;for(let u=0;u<h.length;u++){let f=h[u],C=f.prevSibling??null,B;if(C==null)B=0;else{let m=p.indexOf(C);if(m<0)continue;B=m+1}p.splice(B,0,f.rootId),h.splice(u,1),u--,I=!0}}for(let u of h)p.push(u.rootId);for(let u of p){let f=d.get(u);if(f!==void 0)this.renderNote(t,this.currentChildren[f],f);else{let C=g.get(u);C&&this.renderLockedPlaceholder(t,C)}}for(let u of s.slice().sort((f,C)=>f.stat.ctime-C.stat.ctime))this.renderFileRow(t,u)}else if(s.length===0){let d=0;for(let g=0;g<this.currentChildren.length;g++){let p=Number.isFinite(Date.parse(this.currentChildren[g].created))?Date.parse(this.currentChildren[g].created):0;for(;d<A.length&&A[d].ts<=p;)this.renderLockedPlaceholder(t,A[d].lk),d++;this.renderNote(t,this.currentChildren[g],g)}for(;d<A.length;)this.renderLockedPlaceholder(t,A[d].lk),d++}else{let d=[...this.currentChildren.map((g,p)=>({kind:"note",ts:Number.isFinite(Date.parse(g.created))?Date.parse(g.created):0,idx:p})),...s.map(g=>({kind:"file",ts:g.stat.ctime,file:g})),...A.map(g=>({kind:"lock",ts:g.ts,lk:g.lk}))];d.sort((g,p)=>g.ts-p.ts);for(let g of d)g.kind==="note"?this.renderNote(t,this.currentChildren[g.idx],g.idx):g.kind==="file"?this.renderFileRow(t,g.file):this.renderLockedPlaceholder(t,g.lk)}e.file&&k.Platform.isMobile&&this.installFocusedMiniObserver(t)}renderLockedPlaceholder(t,e){let i=t.createDiv({cls:"stashpad-locked-row"});e.created&&i.createSpan({cls:"stashpad-note-time stashpad-locked-time",text:this.formatTime(e.created)});let s=i.createSpan({cls:"stashpad-locked-icon"});(0,k.setIcon)(s,"lock");let n=(this.plugin.settings.hideLockedTitles??!1)||!e.title;i.createSpan({cls:"stashpad-locked-title",text:n?"Locked note":e.title}),i.createSpan({cls:"stashpad-locked-count",text:e.count>1?`${e.count} notes \xB7 locked`:"locked"});let o=i.createEl("button",{cls:"stashpad-locked-unlock",text:"Unlock"});(0,k.setIcon)(o.createSpan({cls:"stashpad-btn-icon"}),"unlock");let r=async l=>{l.preventDefault(),l.stopPropagation();let d=(this.plugin.settings.lockedSubtrees??[]).find(u=>u.blob===e.blob),g=e.rootId??d?.rootId??null,p=e.parentId??d?.parentId??F,h=e.prevSibling??d?.prevSibling??null;if(await this.plugin.unlockBundleAt(e.blob)){if(this.selection.clear(),this.lastSelected=null,g){let u=this.order.getOrder(this.noteFolder,p),f=this.sortStore.getMode(this.noteFolder,p)==="manual";if(u.length===0&&f&&(u=this.tree.getChildren(p).map(C=>C.id)),u.length>0){let C=u.filter(m=>m!==g),B=h&&C.includes(h)?C.indexOf(h)+1:0;C.splice(Math.max(0,B),0,g),this.order.setOrder(this.noteFolder,p,C),this.order.flush(this.noteFolder)}this.pendingCursorId=g}this.render()}};o.onclick=r;let A=l=>{l.preventDefault(),l.stopPropagation();let d=new k.Menu;if(d.addItem(g=>g.setTitle("Decrypt (unlock)").setIcon("unlock").onClick(()=>void r(l))),!k.Platform.isMobile){let g=k.Platform.isMacOS?"Finder":k.Platform.isWin?"File Explorer":"file manager";d.addItem(p=>p.setTitle(`Show in ${g}`).setIcon("folder-search").onClick(()=>{try{let h=window.require?.("electron")?.shell,I=this.app.vault.adapter?.getFullPath?.(e.blob);I&&h?.showItemInFolder&&h.showItemInFolder(I)}catch(h){console.warn("[Stashpad] showItemInFolder failed",h)}}))}d.addItem(g=>g.setTitle("Copy encrypted file path").setIcon("copy").onClick(()=>{let p=e.blob;if(!k.Platform.isMobile)try{p=this.app.vault.adapter?.getFullPath?.(e.blob)||e.blob}catch{}navigator.clipboard.writeText(p),new k.Notice("Path copied.")})),d.showAtMouseEvent(l)};if(i.oncontextmenu=A,k.Platform.isMobile){let l=i.createEl("button",{cls:"stashpad-locked-menu"});(0,k.setIcon)(l,"more-vertical"),l.setAttr("aria-label","Locked note menu"),l.onclick=d=>A(d)}i.setAttr("aria-label",`${n?"Locked note":`Locked: ${e.title}`}. Use the Unlock button to decrypt.`)}refreshList(){if(!this.listEl){this.render();return}let t=this.tree.get(this.focusId)??this.tree.getRoot();this.currentChildren=this.filterChildren(this.collectViewItems(t.id)),this.cursorIdx>=this.currentChildren.length&&(this.cursorIdx=this.currentChildren.length-1);let e=this.listEl.scrollTop+this.listEl.clientHeight>=this.listEl.scrollHeight-2,i=this.listEl.scrollTop;this.listEl.empty(),this.populateListBody(this.listEl,t),e?this.listEl.scrollTop=this.listEl.scrollHeight:this.listEl.scrollTop=i}renderFileRow(t,e){if(this.currentEncryptionFilter()==="locked")return;let i=t.createDiv({cls:"stashpad-file-row"});i.dataset.path=e.path,i.createDiv({cls:"stashpad-file-meta"}).createSpan({cls:"stashpad-file-time",text:this.formatTime(new Date(e.stat.ctime).toISOString())});let n=i.createDiv({cls:"stashpad-file-body"});n.createSpan({cls:"stashpad-file-name",text:e.name}),n.createSpan({cls:"stashpad-file-ext",text:e.extension.toUpperCase()}),i.title=`${e.path} \u2014 click to open`,i.onclick=o=>{o.preventDefault(),this.app.workspace.openLinkText(e.path,"",!1)}}async setViewMode(t){let e={...this.plugin.settings.viewModes??{}};t==="nested"?delete e[this.noteFolder]:e[this.noteFolder]=t,this.plugin.settings.viewModes=e,await this.plugin.saveSettings()}collectViewItems(t){let e=this.currentViewMode(),i=this.currentHideChildless(),s=this.tree.getChildren(t),n=i?s.filter(A=>A.children.length>0):s;if(e==="nested")return n;let o=[],r=A=>{o.push(A);for(let l of this.tree.getChildren(A.id))r(l)};for(let A of n)r(A);return o}filterChildren(t){let e=this.timeFilterCutoff(),i=this.tagFilter?.toLowerCase(),s=this.colorFilter?.toLowerCase()??null,n=this.currentHideCompleted(),o=this.currentAttachmentsOnly(),r=this.importedOnly,A=this.authorFilter;return!e&&!i&&!s&&!n&&!o&&!r&&!A?t:t.filter(l=>{if(r&&(!l.file||this.app.metadataCache.getFileCache(l.file)?.frontmatter?.imported!==!0))return!1;if(A){if(!l.file)return!1;let d=ne(this.app.metadataCache.getFileCache(l.file)?.frontmatter?.author);if(!d||d.id!==A)return!1}if(e&&l.created){let d=Date.parse(l.created);if(!Number.isNaN(d)&&d<e)return!1}return!(i&&(!l.file||!this.nodeHasTag(l,i))||s&&(this.colorForNode(l)?.toLowerCase()??null)!==s||n&&this.isCompleted(l)&&!this.hasIncompleteDescendant(l)||o&&!this.hasAttachmentInSubtree(l))})}nodeHasTag(t,e){if(!t.file)return!1;let i=this.app.metadataCache.getFileCache(t.file);if(!i)return!1;if(i.tags){for(let n of i.tags)if((n.tag||"").replace(/^#/,"").toLowerCase()===e)return!0}let s=i.frontmatter?.tags;if(s){let n=Array.isArray(s)?s:[s];for(let o of n)if(typeof o=="string"&&o.replace(/^#/,"").toLowerCase()===e)return!0}return!1}collectFolderTags(){let t=new Map,e=this.tree.getChildren(this.focusId);for(let s of e){if(!s.file)continue;let n=this.app.metadataCache.getFileCache(s.file);if(n?.tags)for(let r of n.tags){let A=(r.tag||"").replace(/^#/,"");A&&t.set(A,(t.get(A)??0)+1)}let o=n?.frontmatter?.tags;if(o){let r=Array.isArray(o)?o:[o];for(let A of r){if(typeof A!="string")continue;let l=A.replace(/^#/,"");l&&t.set(l,(t.get(l)??0)+1)}}}let i=[...t.entries()].map(([s,n])=>({raw:s,count:n,label:this.formatTagLabel(s)}));return i.sort((s,n)=>n.count-s.count||s.label.localeCompare(n.label)),i}formatTagLabel(t){return t&&t.split("/").map(e=>e.replace(/([a-z0-9])([A-Z])/g,"$1 $2").split(/[-_\s]+/).filter(Boolean).map(n=>n.charAt(0).toUpperCase()+n.slice(1)).join(" ")).join(" / ")}collectFolderColors(){let t=new Map,e=this.tree.getChildren(this.focusId);for(let s of e){let n=this.colorForNode(s);if(!n)continue;let o=n.toLowerCase();t.set(o,(t.get(o)??0)+1)}let i=[...t.entries()].map(([s,n])=>({hex:s,count:n}));return i.sort((s,n)=>n.count-s.count||s.hex.localeCompare(n.hex)),i}defaultCursorToLast(){let t=this.tree.get(this.focusId)??this.tree.getRoot(),e=this.filterChildren(this.collectViewItems(t.id));this.cursorIdx=e.length-1,this.selection.clear(),e.length>0&&(this.selection.add(e[e.length-1].id),this.lastSelected=e[e.length-1].id)}stampSelectedCursor(t=!1){this.stampSelection(t);let i=this.currentChildren[this.cursorIdx]?.id??this.lastSelected;if(!i)return;this.lastCursorByFocus.set(this.focusId,i);let s=()=>{let n=this.lastCursorByFocus.get(this.focusId);n&&this.plugin.saveLastCursor(this.noteFolder,this.focusId,n)};if(t){this.stampLastCursorTimer!=null&&window.clearTimeout(this.stampLastCursorTimer),this.stampLastCursorTimer=null,s();return}this.stampLastCursorTimer!=null&&window.clearTimeout(this.stampLastCursorTimer),this.stampLastCursorTimer=window.setTimeout(()=>{this.stampLastCursorTimer=null,s()},400)}captureScrollAnchor(){let t=this.listEl;if(!t)return null;let e=t.getBoundingClientRect().top,i=Array.from(t.querySelectorAll(".stashpad-note"));if(i.length===0)return null;let s=null;for(let n of i){let o=n.dataset.id;if(!o)continue;let r=n.getBoundingClientRect().top-e;if(r>=0){s={id:o,offsetFromListTop:r};break}s={id:o,offsetFromListTop:r}}return s}restoreScrollAnchor(t,e){let i=this.listEl;if(i){if(t){let s=i.querySelector(`[data-id="${t.id}"]`);if(s){let n=i.getBoundingClientRect().top,o=s.getBoundingClientRect().top-n;i.scrollTop+=o-t.offsetFromListTop;return}}e>0&&(i.scrollTop=e)}}render(t){Qt.enabled&&(this._renderT0=performance.now()),this.pendingRenderPolicy=t??{kind:"preserve"},this.loadConfig();let e=this.viewRoot,i=this.listEl?.scrollTop??0,n=(t??{kind:"preserve"}).kind==="preserve"?this.captureScrollAnchor():null;!!this.composerInputEl&&document.activeElement===this.composerInputEl&&(this.focusComposerOnNextRender=!0,this.pendingComposerCaret=this.composerInputEl?.selectionStart??null);let r=!!this.listEl&&(this.stickToListBottom||this.listEl.scrollTop+this.listEl.clientHeight>=this.listEl.scrollHeight-2);e.empty(),e.toggleClass("is-mobile",k.Platform.isMobile),e.toggleClass("is-tiny",this.tinyMode),e.toggleClass("is-compact",this.compactMode);let A=this.containerEl.closest(".workspace-leaf");A&&(A.classList.toggle("stashpad-is-tiny",this.tinyMode),A.classList.toggle("stashpad-is-compact",this.compactMode));let l=this.containerEl.closest(".workspace-tabs");l&&l.classList.toggle("stashpad-has-tiny",this.tinyMode),this.tinyMode?this.renderTinyHeader(e):(this.compactMode||this.renderTimeFilterBar(e),this.renderBreadcrumb(e));let d=this.tree.get(this.focusId)??this.tree.getRoot();d.file&&!k.Platform.isMobile&&!this.tinyMode&&!this.compactMode&&this.renderFocusedHeader(e,d),this.currentChildren=this.filterChildren(this.collectViewItems(d.id));let g=!1;if(this.autoSelectNewest&&this.currentChildren.length>0){let I=this.currentChildren[this.currentChildren.length-1];this.cursorIdx=this.currentChildren.length-1,this.selection.clear(),this.selection.add(I.id),this.lastSelected=I.id,this.autoSelectNewest=!1,g=!0}else if(this.pendingFocusIds){let I=this.pendingFocusIds;this.pendingFocusIds=null,this.selection.clear();let u=-1;for(let f of I){let C=this.currentChildren.findIndex(B=>B.id===f);C>=0&&(this.selection.add(f),u<0&&(u=C))}this.cursorIdx=u,u>=0&&(this.lastSelected=I.find(f=>this.currentChildren.some(C=>C.id===f))??null)}else this.cursorIdx>=this.currentChildren.length&&(this.cursorIdx=this.currentChildren.length-1);let p=e.createDiv({cls:"stashpad-list"});if(this.listEl=p,this.dnd.attachListDnD(p),this.populateListBody(p,d),this.renderComposer(e),k.Platform.isMobile&&this.renderMobileNav(e),this._renderT0!=null&&(Qt.record("render.total",performance.now()-this._renderT0),this._renderT0=null),this.plugin.notifyStashpadContentChanged(),g&&this.plugin.notifyStashpadSelectionChanged(),this.focusComposerOnNextRender){this.focusComposerOnNextRender=!1;let I=this.pendingComposerCaret;this.pendingComposerCaret=null;let u=this.composerInputEl;if(u&&u.isConnected){if(u.focus({preventScroll:!0}),I!=null){let f=Math.min(I,u.value.length);try{u.setSelectionRange(f,f)}catch{}}}else requestAnimationFrame(()=>{let f=this.composerInputEl;if(f&&(f.focus({preventScroll:!0}),I!=null)){let C=Math.min(I,f.value.length);try{f.setSelectionRange(C,C)}catch{}}})}let h=this.pendingRenderPolicy;if(this.pendingRenderPolicy=null,h&&this.listEl){let I=this.scrollToBottomOnNextRender;switch(this.scrollToBottomOnNextRender=!1,h.kind){case"preserve":I?this.scrollListToBottom():r?this.scrollListToBottom():this.restoreScrollAnchor(n,i);break;case"pin-bottom":this.scrollListToBottom();break;case"restore":{let u=h.scrollTop,f=this.listEl,C=()=>{this.suppressScrollSave=!0;let B=Math.max(0,f.scrollHeight-f.clientHeight);f.scrollTop=Math.min(u,B),Promise.resolve().then(()=>{this.suppressScrollSave=!1})};C(),requestAnimationFrame(C),setTimeout(C,60),setTimeout(C,200),setTimeout(C,600);break}case"follow-cursor":i>0&&(this.listEl.scrollTop=i),this.revealCursorRow();break;case"scroll-to-id":{let u=h.id,f=h.align,C=this.listEl,B=()=>{this.suppressScrollSave=!0;let m=C.querySelector(`[data-id="${u}"]`);m&&m.scrollIntoView({block:f,behavior:"auto"}),Promise.resolve().then(()=>{this.suppressScrollSave=!1})};B(),requestAnimationFrame(B),setTimeout(B,60),setTimeout(B,200),setTimeout(B,600),setTimeout(()=>{this.suppressScrollSave=!1},700);break}}}else this.scrollToBottomOnNextRender?(this.scrollToBottomOnNextRender=!1,this.scrollListToBottom()):this.listEl&&r?this.scrollListToBottom():this.listEl&&i>0&&(this.listEl.scrollTop=i);if(this.stampSelectedCursor(),this.listEl){this.listResizeObserver?.disconnect();let I=this.listEl,u=I.scrollTop,f=new ResizeObserver(()=>{if(Date.now()<this.keyboardTransitionUntil)return;if(this.stickToListBottom){I.scrollTop=I.scrollHeight,u=I.scrollTop;return}let B=Math.max(0,I.scrollHeight-I.clientHeight);I.scrollTop<u&&u<=B?I.scrollTop=u:u=I.scrollTop});f.observe(I),this.listResizeObserver=f,I.addEventListener("wheel",B=>{B.deltaY<0&&(this.stickToListBottom=!1)},{passive:!0});let C=0;I.addEventListener("touchstart",B=>{C=B.touches[0]?.clientY??0},{passive:!0}),I.addEventListener("touchmove",B=>{let m=B.touches[0]?.clientY??C;m>C&&(this.stickToListBottom=!1),C=m},{passive:!0}),I.addEventListener("mousedown",()=>{this.stickToListBottom=!1}),I.addEventListener("keydown",()=>{this.stickToListBottom=!1})}}renderTimeFilterBar(t){let e=t.createDiv({cls:"stashpad-time-filter-bar"}),i=e.createEl("button",{cls:"stashpad-folder-btn"}),s=!!this.folderOverride,n=this.noteFolder.split("/").pop()||this.noteFolder||"Stashpad";(0,k.setIcon)(i.createSpan({cls:"stashpad-btn-icon"}),"folder"),i.createSpan({text:n,cls:"stashpad-btn-text"}),i.title=s?`Folder (override): ${this.noteFolder} +Inspect with the buttons below \u2014 rename to .zip to crack it open in an archive tool.`,kind:"error",category:"import",affectedPaths:[a.path],actions:c.actionsForFile(a.path)}),console.error(t)}}function il(c){let a=new Set,t=e=>{if(a.add(e),!!c.tree.get(e))for(let s of c.tree.getChildren(e))t(s.id)};return t(F),a}ri();ri();var nl=new Set(["png","jpg","jpeg","gif","webp","svg","bmp","avif"]),Gs={nested:"Nested",flat:"Flat",everything:"Everything"},Rs=[{key:"day",calShort:"Today",rollShort:"24h",calLong:"Since midnight today",rollLong:"Last 24 hours"},{key:"week",calShort:"Week",rollShort:"7d",calLong:"Since Monday this week",rollLong:"Last 7 days"},{key:"month",calShort:"Month",rollShort:"30d",calLong:"Since the 1st of this month",rollLong:"Last 30 days"},{key:"year",calShort:"Year",rollShort:"365d",calLong:"Since January 1 this year",rollLong:"Last 365 days"},{key:"all",calShort:"All",rollShort:"ad infinitum",calLong:"All time",rollLong:"All time"}],Ls=class extends k.ItemView{constructor(t,e){super(t);this.focusId=F;this.timeFilter="all";this.timeFilterCalendar=!1;this.tagFilter=null;this.colorFilter=null;this.importedOnly=!1;this.authorFilter=null;this.noteFolder="Stashpad";this.folderOverride=null;this.tinyMode=!1;this.tinyAlwaysOnTop=!1;this.tinyOpacity=1;this.compactMode=!1;this.detachTreeHook=null;this.detachSettings=null;this.slugDebouncers=new Map;this.attachmentDebouncers=new Map;this.bulkRenderDepth=0;this.bulkSettleTimer=null;this.bootstrappedFolders=new Set;this.selection=new Set;this.lastSelected=null;this.cursorIdx=-1;this.pendingCursorId=null;this.currentChildren=[];this.modeSplit=null;this.modeEnterSubmits=!0;this.nextDestination=null;this.nextDestinationFolder=null;this.nextDestinationLabel=null;this.inListPicker=null;this.pickerEscapeAt=0;this.composerExitAt=0;this.listEl=null;this.composerInputEl=null;this.composerDraft="";this.draftsLoadedFor=null;this.autoSelectNewest=!1;this.scrollToBottomOnNextRender=!1;this.scrollListenerSaveTimer=null;this.suppressScrollSave=!1;this.selectionGuardKey=0;this.pendingRenderPolicy=null;this.stickToListBottom=!1;this.keyboardTransitionUntil=0;this.stickyRowObserver=null;this.listResizeObserver=null;this.composerNarrowObserver=null;this.lastCursorByFocus=new Map;this.lastSelectionByFocus=new Map;this.expandedNotes=new Set;this.activeVersionByGroup=new Map;this.focusComposerOnNextRender=!1;this.suppressComposerFocusUntil=0;this.composerAutocomplete=null;this.firstSelectedId=null;this.mobileSelectMode=!1;this.focusedMiniObserver=null;this.pendingComposerCaret=null;this.navBackStack=[];this.navForwardSnapshots=[];this.treeReconcileTimer=null;this.stampLastCursorTimer=null;this.stampSelectionTimer=null;this._renderT0=null;this.tinyOpacityPopover=null;this.lastListWidth=0;this.onDocKeyDown=t=>{if(!this.viewRoot.isConnected||this.app.workspace.activeLeaf!==this.leaf||Fo(t.target))return;let e=j().bindings;if(G(t,e.toggleSplit)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.toggleSplit();return}if(G(t,e.pickDestination)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.openDestinationPicker();return}if(G(t,e.search)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.openSearchModal();return}if(G(t,e.commandPalette)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.openStashpadCommandPalette();return}if(G(t,e.lockSelection)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdLockSelection();return}if(G(t,e.unlockAll)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdUnlockAll();return}if(G(t,e.moveToArchive)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdMoveToArchive();return}if(G(t,e.encryptDelete)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdEncryptDelete();return}if(G(t,e.searchInParent)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.openSearchInParentModal();return}if(G(t,e.exportStash)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdExportStash();return}if(G(t,e.importStash)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdImportStash();return}if(G(t,e.pickFolder)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdOpenFolderPicker();return}if(G(t,e.cloneStashpadTab)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdCloneStashpadTab();return}let i=t.target,s=!!i&&(i.tagName==="INPUT"||i.tagName==="TEXTAREA");if(t.key===" "&&!t.metaKey&&!t.ctrlKey&&!t.altKey&&!t.shiftKey&&!s){let A=this.composerInputEl;if(A){t.preventDefault(),t.stopPropagation(),A.focus();let l=A.value.length;A.setSelectionRange(l,l);return}}let n=!!i&&(i.tagName==="INPUT"||i.tagName==="TEXTAREA"||i.tagName==="BUTTON"||i.tagName==="SELECT");if(t.key==="Escape"&&i instanceof HTMLElement&&(i.tagName==="BUTTON"||i.tagName==="SELECT")&&this.viewRoot.contains(i)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.viewRoot.focus();return}if(this.inListPicker&&t.key==="Escape"){t.preventDefault(),t.stopPropagation(),this.inListPicker=null,this.pickerEscapeAt=Date.now();let A=this.listEl,l=!!A&&A.scrollTop+A.clientHeight>=A.scrollHeight-2,d=A?.scrollTop??0;if(this.render(),A){let p=l?A.scrollHeight:d;A.scrollTop=p,requestAnimationFrame(()=>{A.scrollTop=l?A.scrollHeight:d}),setTimeout(()=>{A.scrollTop=l?A.scrollHeight:d},60),this.revealCursorRow()}return}if(this.inListPicker&&!n){if(t.key==="ArrowDown"){t.preventDefault(),this.inListPicker.activeIdx=this.nextPickableIdx(this.inListPicker.activeIdx,1),this.repaintSelectionClasses(),this.revealRowAt(this.inListPicker.activeIdx);return}if(t.key==="ArrowUp"){t.preventDefault(),this.inListPicker.activeIdx=this.nextPickableIdx(this.inListPicker.activeIdx,-1),this.repaintSelectionClasses(),this.revealRowAt(this.inListPicker.activeIdx);return}if(t.key==="Enter"){t.preventDefault(),this.commitInListPicker();return}if(G(t,j().bindings.move)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.inListPicker=null,this.repaintSelectionClasses(),this.cmdMovePicker();return}return}if(n)return;if(G(t,e.delete)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdDelete();return}if(G(t,e.toggleComplete)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdToggleComplete();return}if(G(t,e.moveToTop)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdMoveToTop();return}if(G(t,e.moveToBottom)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdMoveToBottom();return}if(G(t,e.moveUp)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdMoveUp();return}if(G(t,e.moveDown)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdMoveDown();return}if(G(t,e.outdent)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdOutdent();return}if(G(t,e.setColor)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdSetColor();return}if(G(t,e.selectAll)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdSelectAll();return}if(G(t,e.swapWithParent)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdSwapWithParent();return}if(G(t,e.undo)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdUndo();return}if(G(t,e.redo)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdRedo();return}if(t.key===" "){t.preventDefault();let A=this.composerInputEl;if(A){A.focus();let l=A.value.length;A.setSelectionRange(l,l)}return}if(t.key==="ArrowDown"){t.preventDefault(),this.cursorIdx>=this.currentChildren.length-1?this.cursorIdx=0:this.cursorIdx++,this.selectCursor(t.shiftKey);return}if(t.key==="ArrowUp"){t.preventDefault(),this.cursorIdx<=0?this.cursorIdx=this.currentChildren.length-1:this.cursorIdx--,this.selectCursor(t.shiftKey);return}if(t.altKey&&t.key==="ArrowLeft"){t.preventDefault(),this.navigateBack();return}if(t.altKey&&t.key==="ArrowRight"){t.preventDefault(),this.navigateForward();return}if(t.key==="ArrowRight"){let A=this.currentChildren[this.cursorIdx];A&&(t.preventDefault(),this.navigateTo(A.id));return}if(t.key==="ArrowLeft"||t.key==="Backspace"){t.preventDefault(),this.navigateUp();return}if(t.key==="Escape"){if(t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),Date.now()-this.pickerEscapeAt<350||Date.now()-this.composerExitAt<400)return;if(this.plugin.noteClipboard&&this.plugin.noteClipboard.folder===this.noteFolder){this.plugin.clearNoteClipboard(),this.render();return}let A=this.firstSelectedId??(this.selection.size>0?this.selection.values().next().value:null);if(this.selection.clear(),this.firstSelectedId=null,A){let l=this.currentChildren.findIndex(d=>d.id===A);this.selection.add(A),this.lastSelected=A,l>=0&&(this.cursorIdx=l)}this.repaintSelectionClasses(),this.revealCursorRow();return}let o=j().bindings;if(G(t,o.pasteNotes)&&this.plugin.noteClipboard){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdPasteNotes();return}if(this.selection.size>0||this.cursorIdx>=0&&this.currentChildren[this.cursorIdx]){if(G(t,o.move)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdMovePicker();return}if(G(t,o.pickMove)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdInListPicker();return}if(G(t,o.merge)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdMerge();return}if(G(t,o.copy)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdCopy();return}if(G(t,o.copyNotes)&&!window.getSelection()?.toString()){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdCopyNotes();return}if(G(t,o.cutNotes)&&!window.getSelection()?.toString()){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdCutNotes();return}if(G(t,o.copyTree)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdCopyTree();return}if(G(t,o.copyOutline)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdCopyOutline();return}if(G(t,o.copyCodeBlock)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdCopyCodeBlock();return}if(G(t,o.openEditor)){if(t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),t.shiftKey){let A=this.tree.get(this.focusId);A?.file&&this.cmdOpenInEditor(A)}else this.cmdOpenInEditor();return}if(G(t,o.openTab)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdOpenInNewStashpadTab();return}if(G(t,o.split)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdSplit();return}if(G(t,o.clone)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdClone();return}if(G(t,o.forkNote)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdForkNote();return}if(G(t,o.insertTemplate)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdInsertTemplate();return}if(G(t,o.toggleExpand)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdToggleExpand();return}if(G(t,o.expandAll)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdExpandAll();return}if(G(t,o.collapseAll)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdCollapseAll();return}if(G(t,o.togglePin)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdTogglePin();return}if(G(t,o.listPin)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdToggleListPin();return}if(G(t,o.toggleTask)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdToggleTask();return}if(G(t,o.setDue)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdSetDue();return}}if(this.currentChildren.length>0){if(G(t,o.jumpToTop)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.jumpToTop();return}if(G(t,o.jumpToBottom)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.jumpToBottom();return}}let r=this.tree.get(this.focusId);if(r?.file){if(G(t,o.openEditor)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdOpenInEditor(r);return}if(G(t,o.openTab)){t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.cmdOpenInNewStashpadTab(r);return}}};this.openSearchInstance=null;this.fmSyncUnsubscribe=null;this.completedState=new Map;this.taskTaggedState=new Map;this.listPinnedState=new Map;this.pendingFocusIds=null;this.onFileModify=t=>{!(t instanceof k.TFile)||t.extension!=="md"||t.path.startsWith(this.noteFolder+"/")&&(this.scheduleSlugRename(t),this.scheduleAttachmentSync(t),this.authorship.noteModify(t),this.debouncedRender())};this.onFileCreate=t=>{!(t instanceof k.TFile)||t.extension!=="md"||t.path.startsWith(this.noteFolder+"/")&&this.debouncedRender()};this.plugin=e,this.tree=new ks(this.app),this.log=e.newLog(),this.integrity=new xs(this.tree,this.log),this.order=new $e(this.app),this.sortStore=new Ss(this.app),this.fmSync=new bs(this.app,()=>this.tree),this.tree.setOrderProvider(i=>{let s=this.noteFolder,n=this.sortStore.getMode(s,i),o=n==="manual"?this.order.getOrder(s,i):Wa(this,i,n);return this.hoistListPinned(i,o)}),this.debouncedRender=(0,k.debounce)(()=>{this.renderSuppressed()||this.render()},80),this.authorship=new Ts(this),this.dnd=new Hs(this),this.bodyRenderer=new Ps(this,this,this.plugin.renderCacheStore)}getViewType(){return J}getDisplayText(){let t=(this.noteFolder||"").trim(),e=t.split("/").pop()||t||"Stashpad";if(this.focusId&&this.focusId!==F){let i=this.tree.get(this.focusId);if(i){let s=this.titleForNode(i).trim(),n=s.length>40?s.slice(0,40)+"\u2026":s;if(n)return`${e} \u2014 ${n} \xB7 ${this.focusId}`}}return e}refreshHeaderTitle(){let t=this.getDisplayText();try{this.leaf.updateHeader?.()}catch{}let i=(this.headerEl??this.containerEl?.querySelector?.(".view-header"))?.querySelector?.(".view-header-title")??this.titleEl;i&&i.textContent!==t&&i.setText(t)}getIcon(){return"list-tree"}async onOpen(){let t=this.contentEl;t.empty(),t.addClass("stashpad-scroll-host"),this.viewRoot=t.createDiv({cls:"stashpad-view"}),this.viewRoot.setAttribute("tabindex","0"),this.viewRoot.addEventListener("focusin",()=>Qs(this)),this.viewRoot.addEventListener("click",()=>Qs(this)),this.viewRoot.addEventListener("mouseup",A=>{A.button===3?(A.preventDefault(),this.navigateBack()):A.button===4&&(A.preventDefault(),this.navigateForward())}),this.viewRoot.addEventListener("auxclick",A=>{A.button===3?(A.preventDefault(),this.navigateBack()):A.button===4&&(A.preventDefault(),this.navigateForward())}),Qs(this),this.registerInterval(window.setInterval(()=>this.authorship.pruneContribMaps(),6e4));let e=null,i=()=>{e||(e=new k.Scope(this.app.scope),e.register([],"Escape",()=>{if(this.inListPicker)return this.inListPicker=null,this.pickerEscapeAt=Date.now(),this.repaintSelectionClasses(),!1;if(Date.now()-this.pickerEscapeAt<350||Date.now()-this.composerExitAt<400)return!1;if(this.selection.size>1){let A=this.firstSelectedId??this.selection.values().next().value??null;if(this.selection.clear(),this.firstSelectedId=null,A){let l=this.currentChildren.findIndex(d=>d.id===A);this.selection.add(A),this.lastSelected=A,l>=0&&(this.cursorIdx=l)}this.render(),this.revealCursorRow()}return!1}),this.app.keymap?.pushScope(e))},s=()=>{if(e){try{this.app.keymap?.popScope(e)}catch{}e=null}};this.viewRoot.addEventListener("focusin",i),this.viewRoot.addEventListener("focusout",A=>{let l=A.relatedTarget;l&&this.viewRoot&&this.viewRoot.contains(l)||s()}),this.register(()=>s()),this.detachTreeHook=this.tree.hookMetadataCache(()=>this.debouncedRender()),this.registerEvent(this.app.metadataCache.on("resolved",()=>this.scheduleTreeReconcile())),this.registerEvent(this.app.metadataCache.on("changed",A=>{if(A.extension!=="md")return;let l=this.app.metadataCache.getFileCache(A)?.frontmatter;this.completedState.set(A.path,!!l?.completed),this.taskTaggedState.set(A.path,this.taggedFromFm(l))})),this.registerEvent(this.app.vault.on("rename",(A,l)=>{for(let d of[this.completedState,this.taskTaggedState])d.has(l)&&(d.set(A.path,d.get(l)),d.delete(l))})),this.registerEvent(this.app.vault.on("delete",A=>{this.completedState.delete(A.path),this.taskTaggedState.delete(A.path);let l=A.path.lastIndexOf("/"),d=(l>=0?A.path.slice(0,l):"").replace(/\/+$/,"");A.path.endsWith(".md")&&d===this.noteFolder.replace(/\/+$/,"")&&(this.tree.rebuild(this.noteFolder),this.debouncedRender())})),this.detachSettings=qa(()=>{this.loadConfig();let A=this.plugin.settings.drafts?.[this.noteFolder]??"",l=this.composerInputEl?.value??"";A===""&&this.composerDraft!==""&&l===""?(this.composerDraft="",this.composerInputEl&&(this.composerInputEl.value="")):A===""&&l!==""&&(this.composerDraft=l),!!this.composerInputEl&&document.activeElement===this.composerInputEl&&(this.focusComposerOnNextRender=!0),this.debouncedRender()}),this.app.vault.on("modify",this.onFileModify),this.app.vault.on("create",this.onFileCreate),window.addEventListener("keydown",this.onDocKeyDown,!0),this.loadConfig();try{await this.bootstrapFolder()}catch(A){let l=A?.message??"";/already exists/i.test(l)||console.warn("[Stashpad] bootstrapFolder failed:",A)}this.tree.rebuild(this.noteFolder),this.installFmSyncActivityNotice(),this.backfillFrontmatterSync(),this.plugin.maybeSweepFolder(this.noteFolder),this.defaultCursorToLast(),this.refreshHeaderTitle(),await this.loadDraftsForFolder();try{let A=this.plugin.loadLastCursor(this.noteFolder);for(let[l,d]of A)this.lastCursorByFocus.set(l,d);this.lastSelectionByFocus=this.plugin.loadLastSelection(this.noteFolder),this.activeVersionByGroup=this.plugin.loadActiveVersions(this.noteFolder)}catch{}let n=this.lastCursorByFocus.get(this.focusId),o;n&&this.tree.get(n)?(o={kind:"scroll-to-id",id:n,align:"start"},this.pendingFocusIds=[n]):(this.scrollToBottomOnNextRender=!0,o={kind:"pin-bottom",until:"next-user-input"});let r=this.foldRestoredSelection(n);r&&(this.pendingFocusIds=r),this.render(o),this.scheduleSelectionRestore(),this.tinyMode&&(setTimeout(()=>this.applyTinyWindow(),1e3),setTimeout(()=>this.applyTinyWindow(),1500)),this.registerDomEvent(window,"beforeunload",()=>{this.flushDrafts(),this.stampSelectedCursor(!0)}),this.registerDomEvent(window,"blur",()=>{this.flushDrafts(),this.stampSelectedCursor(!0)}),this.focusComposer(),this.registerEvent(this.app.workspace.on("active-leaf-change",A=>{A===this.leaf?this.focusComposer():this.stickToListBottom=!1}))}renderSuppressed(){return this.bulkRenderDepth>0||this.bulkSettleTimer!=null||this.plugin.rebootstrapInProgress||this.plugin.okfRebuildingFolders.has(this.noteFolder)}beginBulkRender(){this.bulkRenderDepth++,this.bulkSettleTimer!=null&&(window.clearTimeout(this.bulkSettleTimer),this.bulkSettleTimer=null)}endBulkRender(t=500){this.bulkRenderDepth>0&&this.bulkRenderDepth--,!(this.bulkRenderDepth>0)&&(this.bulkSettleTimer!=null&&window.clearTimeout(this.bulkSettleTimer),this.bulkSettleTimer=window.setTimeout(()=>{this.bulkSettleTimer=null,this.viewRoot?.isConnected&&(this.tree.rebuild(this.noteFolder),this.render())},t))}forceReconcileRender(){this.viewRoot?.isConnected&&(this.tree.rebuild(this.noteFolder),this.render())}scheduleTreeReconcile(){this.renderSuppressed()||this.treeReconcileTimer==null&&(this.treeReconcileTimer=window.setTimeout(()=>{if(this.treeReconcileTimer=null,!this.viewRoot?.isConnected)return;let t=this.noteFolder,e=t+"/",i=0;for(let s of this.app.vault.getMarkdownFiles()){let n=s.parent?.path?.replace(/\/+$/,"")??"";if(!(n===t||t!==""&&n.startsWith(e)))continue;let o=this.app.metadataCache.getFileCache(s)?.frontmatter?.id;typeof o=="string"&&o&&i++}i!==this.tree.fileBackedCount()&&(this.tree.rebuild(t),this.debouncedRender())},400))}focusView(){requestAnimationFrame(()=>{this.viewRoot?.isConnected&&(document.activeElement instanceof HTMLElement&&(document.activeElement.tagName==="INPUT"||document.activeElement.tagName==="TEXTAREA")||this.viewRoot.focus({preventScroll:!0}))})}focusComposer(){if(!j().autofocusComposerAfterSend)return;let t=()=>{if(!this.viewRoot?.isConnected||Date.now()<this.suppressComposerFocusUntil||Date.now()<this.plugin.suppressComposerAutofocusUntil)return;let e=document.activeElement;e&&(e.tagName==="INPUT"||e.tagName==="TEXTAREA")&&e!==this.composerInputEl||(e&&e.tagName==="BUTTON"&&this.viewRoot.contains(e),this.composerInputEl?.focus({preventScroll:!0}))};requestAnimationFrame(t),setTimeout(t,50),setTimeout(t,200)}async onClose(){Ga(this),this.detachTreeHook?.(),this.detachSettings?.(),this.app.vault.off("modify",this.onFileModify),this.app.vault.off("create",this.onFileCreate),window.removeEventListener("keydown",this.onDocKeyDown,!0),this.listResizeObserver?.disconnect(),this.listResizeObserver=null,this.stickyRowObserver?.disconnect(),this.stickyRowObserver=null,this.bodyRenderer.dispose(),this.composerNarrowObserver?.disconnect(),this.composerNarrowObserver=null,this.focusedMiniObserver?.disconnect(),this.focusedMiniObserver=null,this.treeReconcileTimer!=null&&(window.clearTimeout(this.treeReconcileTimer),this.treeReconcileTimer=null),this.composerAutocomplete?.detach(),this.composerAutocomplete=null;for(let t of this.slugDebouncers.values())t.cancel();for(let t of this.attachmentDebouncers.values())t.cancel();this.authorship.dispose();try{await this.flushDrafts()}catch{}try{await this.order.flush(this.noteFolder)}catch{}try{await this.sortStore.flush(this.noteFolder)}catch{}try{await this.fmSync.flush()}catch{}this.stampSelectedCursor(!0),this.fmSyncUnsubscribe?.(),this.fmSyncUnsubscribe=null}setEphemeralState(t){let e=t;e?.focusId&&(this.focusId=e.focusId),e?.timeFilter&&(this.timeFilter=e.timeFilter)}getEphemeralState(){return{focusId:this.focusId,timeFilter:this.timeFilter}}getState(){return{...super.getState()??{},folderOverride:this.folderOverride,timeFilter:this.timeFilter,focusId:this.focusId,tagFilter:this.tagFilter,colorFilter:this.colorFilter,timeFilterCalendar:this.timeFilterCalendar,tinyMode:this.tinyMode,tinyAlwaysOnTop:this.tinyAlwaysOnTop,tinyOpacity:this.tinyOpacity,compactMode:this.compactMode,navBackStack:this.navBackStack,navForwardSnapshots:this.navForwardSnapshots}}async setState(t,e){let i=t??null;if(i){"folderOverride"in i&&(this.folderOverride=i.folderOverride??null),i.timeFilter&&(this.timeFilter=i.timeFilter),i.focusId&&(this.focusId=i.focusId),"tagFilter"in i&&(this.tagFilter=i.tagFilter??null),"colorFilter"in i&&(this.colorFilter=i.colorFilter??null),"timeFilterCalendar"in i&&(this.timeFilterCalendar=!!i.timeFilterCalendar),"tinyMode"in i&&(this.tinyMode=!!i.tinyMode),"tinyAlwaysOnTop"in i&&(this.tinyAlwaysOnTop=!!i.tinyAlwaysOnTop),typeof i.tinyOpacity=="number"&&Number.isFinite(i.tinyOpacity)&&(this.tinyOpacity=Math.min(1,Math.max(.3,i.tinyOpacity))),"compactMode"in i&&(this.compactMode=!!i.compactMode);let o=r=>r&&typeof r.folder=="string"&&typeof r.focusId=="string";Array.isArray(i.navBackStack)&&(this.navBackStack=i.navBackStack.filter(o)),Array.isArray(i.navForwardSnapshots)&&(this.navForwardSnapshots=i.navForwardSnapshots.filter(o))}let s=(this.plugin?.settings?.folder??"Stashpad").trim().replace(/^\/+|\/+$/g,""),n=this.folderOverride?.trim().replace(/^\/+|\/+$/g,"")||null;if(this.noteFolder=n||s||"Stashpad",await super.setState(t,e),this.refreshHeaderTitle(),this.viewRoot){this.loadConfig(),await this.bootstrapFolder(),this.tree.rebuild(this.noteFolder),this.backfillFrontmatterSync(),this.defaultCursorToLast(),this.draftsLoadedFor=null,this.composerDraft="",await this.loadDraftsForFolder(),this.lastCursorByFocus.clear(),this.lastSelectionByFocus.clear();try{let l=this.plugin.loadLastCursor(this.noteFolder);for(let[d,p]of l)this.lastCursorByFocus.set(d,p);this.lastSelectionByFocus=this.plugin.loadLastSelection(this.noteFolder),this.activeVersionByGroup=this.plugin.loadActiveVersions(this.noteFolder)}catch{}let o=this.lastCursorByFocus.get(this.focusId),r;o&&this.tree.get(o)?(this.pendingFocusIds=[o],r={kind:"scroll-to-id",id:o,align:"start"}):r={kind:"pin-bottom",until:"next-user-input"};let A=this.foldRestoredSelection(o);A&&(this.pendingFocusIds=A),this.render(r),this.scheduleSelectionRestore()}}focus(){this.viewRoot?.focus({preventScroll:!0})}foldRestoredSelection(t){let e=this.lastSelectionByFocus.get(this.focusId)??null;if(!e||!e.length)return null;let i=e.filter(s=>!!this.tree.get(s));return i.length?t&&i.includes(t)?[t,...i.filter(s=>s!==t)]:i:null}stampSelection(t=!1){let e=[...this.selection],i=()=>{try{this.plugin.saveLastSelection(this.noteFolder,this.focusId,e)}catch{}};if(this.stampSelectionTimer!=null&&(window.clearTimeout(this.stampSelectionTimer),this.stampSelectionTimer=null),t){i();return}this.stampSelectionTimer=window.setTimeout(()=>{this.stampSelectionTimer=null,i()},400)}scheduleSelectionRestore(){let t=this.lastSelectionByFocus.get(this.focusId);if(!t||!t.length)return;let e=()=>{let i=t.filter(r=>this.currentChildren.some(A=>A.id===r));if(!i.length)return;let s=[...this.selection],n=new Set(i);if(s.length<i.length&&s.every(r=>n.has(r))){this.selection.clear();for(let r of i)this.selection.add(r);this.firstSelectedId=i[0],this.lastSelected=i[i.length-1],this.repaintSelectionClasses()}};for(let i of[120,400,900,1600])window.setTimeout(e,i)}loadConfig(){let t=(this.plugin?.settings?.folder??"Stashpad").trim().replace(/^\/+|\/+$/g,""),i=this.folderOverride?.trim().replace(/^\/+|\/+$/g,"")||null||t||"Stashpad";i!==this.noteFolder?(this.noteFolder=i,this.tree.rebuild(this.noteFolder)):this.noteFolder=i}captureNavSnapshot(){return{folder:this.noteFolder,focusId:this.focusId}}recordNavState(t={}){let e=this.captureNavSnapshot(),i=this.navBackStack[this.navBackStack.length-1];i&&i.folder===e.folder&&i.focusId===e.focusId||(this.navBackStack.push(e),t.keepForward||(this.navForwardSnapshots=[]))}async setFolderOverride(t,e={}){let i=t?.trim().replace(/^\/+|\/+$/g,"")||null;if(i&&this.isReservedFolder(i)){new k.Notice(`"${i}" is a reserved Stashpad subfolder (imports/exports/attachments). Pick a different folder.`);return}if((i||null)!==(this.folderOverride||null)){e.skipHistory||this.recordNavState(),this.folderOverride=i,this.focusId=F,this.lastCursorByFocus.clear(),this.selection.clear(),this.cursorIdx=-1,this.lastSelected=null,this.composerDraft="",await this.flushDrafts(),this.draftsLoadedFor=null,this.loadConfig();try{await this.bootstrapFolder()}catch(s){let n=s?.message??"";/already exists/i.test(n)||console.warn("[Stashpad] bootstrapFolder failed:",s)}this.tree.rebuild(this.noteFolder),this.backfillFrontmatterSync(),this.plugin.maybeSweepFolder(this.noteFolder),this.defaultCursorToLast(),await this.loadDraftsForFolder();try{let s=this.app.workspace;typeof s.saveLayout=="function"?await s.saveLayout():this.app.workspace.requestSaveLayout()}catch{this.app.workspace.requestSaveLayout()}this.refreshHeaderTitle(),this.render()}}cmdOpenFolderPicker(){this.openFolderPicker()}openFolderPicker(){this.plugin.openFolderPicker()}listVaultFolders(){let t=[];for(let e of this.app.vault.getAllLoadedFiles())if(e instanceof k.TFolder){if(e.path==="/"||e.path===""||e.path.startsWith(".")||this.isReservedFolder(e.path))continue;t.push(e.path)}return t.sort((e,i)=>e.localeCompare(i))}isReservedFolder(t){let e=t.split("/").filter(Boolean).pop()??"";return e?new Set([this.plugin.settings.importDropFolder,this.plugin.settings.exportFolder,"_attachments","_processed","_authors"].map(s=>(s??"").trim().replace(/^\/+|\/+$/g,"")).filter(Boolean)).has(e):!1}persistFocus(){try{this.app.workspace.requestSaveLayout()}catch{}}cmdUndo(){let t=this.plugin.getUndoStack(this.noteFolder);if(!t.canUndo()){new k.Notice("Nothing to undo.");return}let e=t.peekUndoLabel(),i=this.plugin.notifications.recent()[0]?.category??"system";t.undo().then(()=>this.plugin.notifications.show({message:`Undid: ${e}`,kind:"info",category:i,folder:this.noteFolder})).catch(s=>this.plugin.notifications.show({message:`Undo failed: ${s.message}`,kind:"error",category:"system",folder:this.noteFolder}))}cmdRedo(){let t=this.plugin.getUndoStack(this.noteFolder);if(!t.canRedo()){new k.Notice("Nothing to redo.");return}let e=t.peekRedoLabel(),i=this.plugin.notifications.recent()[0]?.category??"system";t.redo().then(()=>this.plugin.notifications.show({message:`Redid: ${e}`,kind:"info",category:i,folder:this.noteFolder})).catch(s=>this.plugin.notifications.show({message:`Redo failed: ${s.message}`,kind:"error",category:"system",folder:this.noteFolder}))}async snapshotNotes(t,e){let i=[],s=new Set;for(let A of t)!A.file||s.has(A.file.path)||(s.add(A.file.path),i.push(A.file));let n=await Promise.all(i.map(A=>this.app.vault.read(A))),o=i.map((A,l)=>({path:A.path,content:n[l]})),r=[];if(e){let A=new Set,l=[];for(let p of n)for(let g of this.extractAttachments(this.stripFrontmatter(p))){let h=this.app.metadataCache.getFirstLinkpathDest(g,"");h&&!A.has(h.path)&&(A.add(h.path),l.push(h))}let d=await Promise.all(l.map(p=>this.app.vault.readBinary(p)));for(let p=0;p<l.length;p++)r.push({path:l[p].path,data:d[p]})}return{notes:o,attachments:r}}async restoreSnapshots(t,e){for(let s of t.attachments)try{await this.app.vault.adapter.exists(s.path)||await this.app.vault.createBinary(s.path,s.data)}catch{}for(let s of t.notes)try{await this.app.vault.adapter.exists(s.path)||await this.app.vault.create(s.path,s.content)}catch{}let i=()=>{e&&e.some(n=>this.tree.get(n))&&(this.pendingFocusIds=e.slice())};i(),this.tree.rebuild(this.noteFolder),this.render({kind:"follow-cursor"}),setTimeout(()=>{i(),this.tree.rebuild(this.noteFolder),this.render({kind:"follow-cursor"})},100),setTimeout(()=>{i(),this.tree.rebuild(this.noteFolder),this.render({kind:"follow-cursor"})},400),setTimeout(()=>{for(let s of t.notes){let n=this.tree.idForPath(s.path);n&&this.fmSync.schedule(n)}},500)}async trashNotesAndAttachments(t){let e=new Set;for(let i of t.notes){let s=this.tree.idForPath(i.path);if(!s)continue;let n=this.tree.get(s);n?.parent&&e.add(n.parent)}for(let i of t.notes){let s=this.app.vault.getAbstractFileByPath(i.path);if(s)try{await this.app.fileManager.trashFile(s)}catch{}}for(let i of t.attachments){let s=this.app.vault.getAbstractFileByPath(i.path);if(s)try{await this.app.fileManager.trashFile(s)}catch{}}this.tree.rebuild(this.noteFolder),this.render();for(let i of e)this.fmSync.scheduleParentOfDeleted(i)}async loadDraftsForFolder(){if(this.draftsLoadedFor===this.noteFolder)return;this.draftsLoadedFor=this.noteFolder;let t=this.plugin.settings.drafts??{};this.composerDraft=t[this.noteFolder]??"",console.debug("[Stashpad] loadDrafts",{folder:this.noteFolder,has:!!t[this.noteFolder],available:Object.keys(t)})}async saveDraft(t){try{let e=this.noteFolder;if((this.plugin.settings.drafts?.[e]??"")===t)return;let s={...this.plugin.settings.drafts??{}};t.length===0?delete s[e]:s[e]=t,this.plugin.settings.drafts=s,t.length===0?await this.plugin.saveSettings():await this.plugin.persistSettingsQuiet()}catch(e){console.warn("Stashpad: drafts save failed",e)}}async recordLastSubmitted(t){try{let e={...this.plugin.settings.lastSubmitted??{}};e[this.noteFolder]=t,this.plugin.settings.lastSubmitted=e,await this.plugin.persistSettingsQuiet()}catch{}}hasRestorableDraft(){let t=this.plugin.settings.drafts?.[this.noteFolder];if(!t||!t.trim())return!1;let e=this.plugin.settings.lastSubmitted?.[this.noteFolder];return!(e&&e===t)}syncComposerDraftForFocus(){}async flushDrafts(){this.composerInputEl?await this.saveDraft(this.composerInputEl.value):await this.saveDraft(this.composerDraft)}timeFilterCutoff(){if(this.timeFilter==="all")return null;if(this.timeFilterCalendar){let e=(0,k.moment)();switch(this.timeFilter){case"day":return e.startOf("day").valueOf();case"week":return e.startOf("isoWeek").valueOf();case"month":return e.startOf("month").valueOf();case"year":return e.startOf("year").valueOf()}}let t=Date.now();switch(this.timeFilter){case"day":return t-864e5;case"week":return t-7*864e5;case"month":return t-30*864e5;case"year":return t-365*864e5}return null}allowedByBases(){return null}currentViewMode(){return this.plugin.settings.viewModes?.[this.noteFolder]??"nested"}currentIncludeAttachments(){return!!this.plugin.settings.includeAttachmentsInEverything?.[this.noteFolder]}async setIncludeAttachments(t){let e={...this.plugin.settings.includeAttachmentsInEverything??{}};t?e[this.noteFolder]=!0:delete e[this.noteFolder],this.plugin.settings.includeAttachmentsInEverything=e,await this.plugin.saveSettings()}currentEncryptionFilter(){return this.plugin.settings.encryptionFilter?.[this.noteFolder]??"all"}async setEncryptionFilter(t){let e={...this.plugin.settings.encryptionFilter??{}};t==="all"?delete e[this.noteFolder]:e[this.noteFolder]=t,this.plugin.settings.encryptionFilter=e,await this.plugin.saveSettings()}currentHideChildless(){return!!this.plugin.settings.hideChildlessNotes?.[this.noteFolder]}async setHideChildless(t){let e={...this.plugin.settings.hideChildlessNotes??{}};t?e[this.noteFolder]=!0:delete e[this.noteFolder],this.plugin.settings.hideChildlessNotes=e,await this.plugin.saveSettings()}currentHideCompleted(){return!!this.plugin.settings.hideCompletedNotes?.[this.noteFolder]}async setHideCompleted(t){let e={...this.plugin.settings.hideCompletedNotes??{}};t?e[this.noteFolder]=!0:delete e[this.noteFolder],this.plugin.settings.hideCompletedNotes=e,await this.plugin.saveSettings()}currentAttachmentsOnly(){return!!this.plugin.settings.attachmentsOnlyNotes?.[this.noteFolder]}async setAttachmentsOnly(t){let e={...this.plugin.settings.attachmentsOnlyNotes??{}};t?e[this.noteFolder]=!0:delete e[this.noteFolder],this.plugin.settings.attachmentsOnlyNotes=e,await this.plugin.saveSettings()}nodeHasAttachment(t){if(!t.file)return!1;let e=this.app.metadataCache.getFileCache(t.file)?.frontmatter?.attachments;return Array.isArray(e)&&e.length>0}hasAttachmentInSubtree(t){if(this.nodeHasAttachment(t))return!0;for(let e of this.tree.getChildren(t.id))if(this.hasAttachmentInSubtree(e))return!0;return!1}hasIncompleteDescendant(t){for(let e of t.children){let i=this.tree.get(e);if(i&&(!this.isCompleted(i)||this.hasIncompleteDescendant(i)))return!0}return!1}collectEmbeddedAttachmentPaths(){let t=new Set,e=this.noteFolder,i=this.app.vault.getAbstractFileByPath(e);if(!(i instanceof k.TFolder))return t;let s=[i];for(;s.length;){let n=s.pop();for(let o of n.children){if(o instanceof k.TFolder){s.push(o);continue}if(!(o instanceof k.TFile)||o.extension!=="md")continue;let r=this.app.metadataCache.getFileCache(o)?.frontmatter;if(!(!r||!Array.isArray(r.attachments)))for(let A of r.attachments){if(typeof A!="string")continue;let l=Ee(A),d=this.app.metadataCache.getFirstLinkpathDest(l,o.path);d?t.add(d.path):t.add(l)}}}return t}collectFileItems(t){let e=this.noteFolder,i=this.app.vault.getAbstractFileByPath(e);if(!(i instanceof k.TFolder))return[];let s=this.currentIncludeAttachments(),n=s?new Set:this.collectEmbeddedAttachmentPaths(),o=new Set(["_authors","_imports","_exports","_processed","_attachments","_archive",".archive"]),r=[],A=[i];for(;A.length;){let l=A.pop();for(let d of l.children){if(d instanceof k.TFolder){let p=d.name;if(l===i&&o.has(p)||l===i&&p==="_attachments"&&!s)continue;A.push(d);continue}d instanceof k.TFile&&d.extension!=="md"&&(d.name===".stashpad-order.json"||d.name===".stashpad-sort.json"||!s&&n.has(d.path)||r.push(d))}}return r}populateListBody(t,e){if(this.lastListWidth=t.clientWidth||this.lastListWidth,this.bodyRenderer.arm(),this.pendingCursorId){let d=this.currentChildren.findIndex(p=>p.id===this.pendingCursorId);d>=0&&(this.cursorIdx=d,this.selection.clear(),this.selection.add(this.pendingCursorId),this.lastSelected=this.pendingCursorId,this.pendingCursorId=null)}e.file&&k.Platform.isMobile&&(this.renderFocusedHeaderMini(t,e),this.renderFocusedHeader(t,e));let i=this.currentViewMode(),s=i==="everything"?this.collectFileItems(e.id):[],n=d=>d.created&&Number.isFinite(Date.parse(d.created))?Date.parse(d.created):Number.POSITIVE_INFINITY,o=this.currentEncryptionFilter(),r;if(o==="unlocked")r=[];else if(i==="nested")r=this.plugin.lockedSubtreesFor(this.noteFolder,e.id);else{let d=new Set([e.id,...this.currentChildren.map(g=>g.id)]),p=new Set;r=[];for(let g of d)for(let h of this.plugin.lockedSubtreesFor(this.noteFolder,g))p.has(h.blob)||(p.add(h.blob),r.push(h))}let A=r.map(d=>({lk:d,ts:n(d)})).sort((d,p)=>d.ts-p.ts),l=i==="nested"&&this.sortStore.getMode(this.noteFolder,e.id)==="manual";if(this.currentChildren.length===0&&s.length===0&&A.length===0)t.createDiv({cls:"stashpad-empty",text:"No notes here yet. Type below to add one."});else if(l&&A.length>0){let d=new Map(this.currentChildren.map((u,f)=>[u.id,f])),p=new Map;for(let{lk:u}of A)u.rootId&&p.set(u.rootId,u);let g=this.currentChildren.map(u=>u.id),h=A.map(({lk:u})=>u).filter(u=>u.rootId).sort((u,f)=>n(f)-n(u)),I=!0;for(;h.length&&I;){I=!1;for(let u=0;u<h.length;u++){let f=h[u],C=f.prevSibling??null,B;if(C==null)B=0;else{let m=g.indexOf(C);if(m<0)continue;B=m+1}g.splice(B,0,f.rootId),h.splice(u,1),u--,I=!0}}for(let u of h)g.push(u.rootId);for(let u of g){let f=d.get(u);if(f!==void 0)this.renderNote(t,this.currentChildren[f],f);else{let C=p.get(u);C&&this.renderLockedPlaceholder(t,C)}}for(let u of s.slice().sort((f,C)=>f.stat.ctime-C.stat.ctime))this.renderFileRow(t,u)}else if(s.length===0){let d=0;for(let p=0;p<this.currentChildren.length;p++){let g=Number.isFinite(Date.parse(this.currentChildren[p].created))?Date.parse(this.currentChildren[p].created):0;for(;d<A.length&&A[d].ts<=g;)this.renderLockedPlaceholder(t,A[d].lk),d++;this.renderNote(t,this.currentChildren[p],p)}for(;d<A.length;)this.renderLockedPlaceholder(t,A[d].lk),d++}else{let d=[...this.currentChildren.map((p,g)=>({kind:"note",ts:Number.isFinite(Date.parse(p.created))?Date.parse(p.created):0,idx:g})),...s.map(p=>({kind:"file",ts:p.stat.ctime,file:p})),...A.map(p=>({kind:"lock",ts:p.ts,lk:p.lk}))];d.sort((p,g)=>p.ts-g.ts);for(let p of d)p.kind==="note"?this.renderNote(t,this.currentChildren[p.idx],p.idx):p.kind==="file"?this.renderFileRow(t,p.file):this.renderLockedPlaceholder(t,p.lk)}e.file&&k.Platform.isMobile&&this.installFocusedMiniObserver(t)}renderLockedPlaceholder(t,e){let i=t.createDiv({cls:"stashpad-locked-row"});e.created&&i.createSpan({cls:"stashpad-note-time stashpad-locked-time",text:this.formatTime(e.created)});let s=i.createSpan({cls:"stashpad-locked-icon"});(0,k.setIcon)(s,"lock");let n=(this.plugin.settings.hideLockedTitles??!1)||!e.title;i.createSpan({cls:"stashpad-locked-title",text:n?"Locked note":e.title}),i.createSpan({cls:"stashpad-locked-count",text:e.count>1?`${e.count} notes \xB7 locked`:"locked"});let o=i.createEl("button",{cls:"stashpad-locked-unlock",text:"Unlock"});(0,k.setIcon)(o.createSpan({cls:"stashpad-btn-icon"}),"unlock");let r=async l=>{l.preventDefault(),l.stopPropagation();let d=(this.plugin.settings.lockedSubtrees??[]).find(u=>u.blob===e.blob),p=e.rootId??d?.rootId??null,g=e.parentId??d?.parentId??F,h=e.prevSibling??d?.prevSibling??null;if(await this.plugin.unlockBundleAt(e.blob)){if(this.selection.clear(),this.lastSelected=null,p){let u=this.order.getOrder(this.noteFolder,g),f=this.sortStore.getMode(this.noteFolder,g)==="manual";if(u.length===0&&f&&(u=this.tree.getChildren(g).map(C=>C.id)),u.length>0){let C=u.filter(m=>m!==p),B=h&&C.includes(h)?C.indexOf(h)+1:0;C.splice(Math.max(0,B),0,p),this.order.setOrder(this.noteFolder,g,C),this.order.flush(this.noteFolder)}this.pendingCursorId=p}this.render()}};o.onclick=r;let A=l=>{l.preventDefault(),l.stopPropagation();let d=new k.Menu;if(d.addItem(p=>p.setTitle("Decrypt (unlock)").setIcon("unlock").onClick(()=>void r(l))),!k.Platform.isMobile){let p=k.Platform.isMacOS?"Finder":k.Platform.isWin?"File Explorer":"file manager";d.addItem(g=>g.setTitle(`Show in ${p}`).setIcon("folder-search").onClick(()=>{try{let h=window.require?.("electron")?.shell,I=this.app.vault.adapter?.getFullPath?.(e.blob);I&&h?.showItemInFolder&&h.showItemInFolder(I)}catch(h){console.warn("[Stashpad] showItemInFolder failed",h)}}))}d.addItem(p=>p.setTitle("Copy encrypted file path").setIcon("copy").onClick(()=>{let g=e.blob;if(!k.Platform.isMobile)try{g=this.app.vault.adapter?.getFullPath?.(e.blob)||e.blob}catch{}navigator.clipboard.writeText(g),new k.Notice("Path copied.")})),d.showAtMouseEvent(l)};if(i.oncontextmenu=A,k.Platform.isMobile){let l=i.createEl("button",{cls:"stashpad-locked-menu"});(0,k.setIcon)(l,"more-vertical"),l.setAttr("aria-label","Locked note menu"),l.onclick=d=>A(d)}i.setAttr("aria-label",`${n?"Locked note":`Locked: ${e.title}`}. Use the Unlock button to decrypt.`)}refreshList(){if(!this.listEl){this.render();return}let t=this.tree.get(this.focusId)??this.tree.getRoot();this.currentChildren=this.filterChildren(this.collectViewItems(t.id)),this.cursorIdx>=this.currentChildren.length&&(this.cursorIdx=this.currentChildren.length-1);let e=this.listEl.scrollTop+this.listEl.clientHeight>=this.listEl.scrollHeight-2,i=this.listEl.scrollTop;this.listEl.empty(),this.populateListBody(this.listEl,t),e?this.listEl.scrollTop=this.listEl.scrollHeight:this.listEl.scrollTop=i}renderFileRow(t,e){if(this.currentEncryptionFilter()==="locked")return;let i=t.createDiv({cls:"stashpad-file-row"});i.dataset.path=e.path,i.createDiv({cls:"stashpad-file-meta"}).createSpan({cls:"stashpad-file-time",text:this.formatTime(new Date(e.stat.ctime).toISOString())});let n=i.createDiv({cls:"stashpad-file-body"});n.createSpan({cls:"stashpad-file-name",text:e.name}),n.createSpan({cls:"stashpad-file-ext",text:e.extension.toUpperCase()}),i.title=`${e.path} \u2014 click to open`,i.onclick=o=>{o.preventDefault(),this.app.workspace.openLinkText(e.path,"",!1)}}async setViewMode(t){let e={...this.plugin.settings.viewModes??{}};t==="nested"?delete e[this.noteFolder]:e[this.noteFolder]=t,this.plugin.settings.viewModes=e,await this.plugin.saveSettings()}collectViewItems(t){let e=this.currentViewMode(),i=this.currentHideChildless(),s=this.tree.getChildren(t),n=i?s.filter(A=>A.children.length>0):s;if(e==="nested")return n;let o=[],r=A=>{o.push(A);for(let l of this.tree.getChildren(A.id))r(l)};for(let A of n)r(A);return o}filterChildren(t){t=this.collapseVersions(t);let e=this.timeFilterCutoff(),i=this.tagFilter?.toLowerCase(),s=this.colorFilter?.toLowerCase()??null,n=this.currentHideCompleted(),o=this.currentAttachmentsOnly(),r=this.importedOnly,A=this.authorFilter;return!e&&!i&&!s&&!n&&!o&&!r&&!A?t:t.filter(l=>{if(r&&(!l.file||this.app.metadataCache.getFileCache(l.file)?.frontmatter?.imported!==!0))return!1;if(A){if(!l.file)return!1;let d=re(this.app.metadataCache.getFileCache(l.file)?.frontmatter?.author);if(!d||d.id!==A)return!1}if(e&&l.created){let d=Date.parse(l.created);if(!Number.isNaN(d)&&d<e)return!1}if(i){if(!l.file)return!1;if(this.tagFilter===ve){if(!this.nodeHasAnyTag(l))return!1}else if(this.tagFilter===Fe){if(this.nodeHasAnyTag(l))return!1}else if(!this.nodeHasTag(l,i))return!1}return!(s&&(this.colorForNode(l)?.toLowerCase()??null)!==s||n&&this.isCompleted(l)&&!this.hasIncompleteDescendant(l)||o&&!this.hasAttachmentInSubtree(l))})}collapseVersions(t){if(!this.plugin.settings.enableSheetVersions)return t;let e=new Map,i=!1;for(let n of t){let o=Ct(this.app,n);if(!Gi(o))continue;i=!0;let r=se(o),A=e.get(r);A?A.push(n):e.set(r,[n])}if(!i)return t;let s=new Set;for(let[n,o]of e){let r=this.activeVersionNode(n,o);r&&s.add(r.id)}return t.filter(n=>Gi(Ct(this.app,n))?s.has(n.id):!0)}activeVersionNode(t,e){let i=this.activeVersionByGroup.get(t);if(i){let s=e.find(n=>n.id===i);if(s)return s}return Za(this.app,e)}setActiveVersion(t,e){this.activeVersionByGroup.set(t,e),this.plugin.saveActiveVersion(this.noteFolder,t,e),this.render()}nodeHasAnyTag(t){if(!t.file)return!1;let e=this.app.metadataCache.getFileCache(t.file);if(!e)return!1;if(e.tags&&e.tags.length>0)return!0;let i=e.frontmatter?.tags;return!!(i&&(Array.isArray(i)?i:[i]).some(n=>typeof n=="string"&&n.trim().length>0))}nodeHasTag(t,e){if(!t.file)return!1;let i=this.app.metadataCache.getFileCache(t.file);if(!i)return!1;if(i.tags){for(let n of i.tags)if((n.tag||"").replace(/^#/,"").toLowerCase()===e)return!0}let s=i.frontmatter?.tags;if(s){let n=Array.isArray(s)?s:[s];for(let o of n)if(typeof o=="string"&&o.replace(/^#/,"").toLowerCase()===e)return!0}return!1}collectFolderTags(){let t=new Map,e=this.tree.getChildren(this.focusId);for(let s of e){if(!s.file)continue;let n=this.app.metadataCache.getFileCache(s.file);if(n?.tags)for(let r of n.tags){let A=(r.tag||"").replace(/^#/,"");A&&t.set(A,(t.get(A)??0)+1)}let o=n?.frontmatter?.tags;if(o){let r=Array.isArray(o)?o:[o];for(let A of r){if(typeof A!="string")continue;let l=A.replace(/^#/,"");l&&t.set(l,(t.get(l)??0)+1)}}}let i=[...t.entries()].map(([s,n])=>({raw:s,count:n,label:this.formatTagLabel(s)}));return i.sort((s,n)=>n.count-s.count||s.label.localeCompare(n.label)),i}formatTagLabel(t){return t&&t.split("/").map(e=>e.replace(/([a-z0-9])([A-Z])/g,"$1 $2").split(/[-_\s]+/).filter(Boolean).map(n=>n.charAt(0).toUpperCase()+n.slice(1)).join(" ")).join(" / ")}collectFolderColors(){let t=new Map,e=this.tree.getChildren(this.focusId);for(let s of e){let n=this.colorForNode(s);if(!n)continue;let o=n.toLowerCase();t.set(o,(t.get(o)??0)+1)}let i=[...t.entries()].map(([s,n])=>({hex:s,count:n}));return i.sort((s,n)=>n.count-s.count||s.hex.localeCompare(n.hex)),i}defaultCursorToLast(){let t=this.tree.get(this.focusId)??this.tree.getRoot(),e=this.filterChildren(this.collectViewItems(t.id));this.cursorIdx=e.length-1,this.selection.clear(),e.length>0&&(this.selection.add(e[e.length-1].id),this.lastSelected=e[e.length-1].id)}stampSelectedCursor(t=!1){this.stampSelection(t);let i=this.currentChildren[this.cursorIdx]?.id??this.lastSelected;if(!i)return;this.lastCursorByFocus.set(this.focusId,i);let s=()=>{let n=this.lastCursorByFocus.get(this.focusId);n&&this.plugin.saveLastCursor(this.noteFolder,this.focusId,n)};if(t){this.stampLastCursorTimer!=null&&window.clearTimeout(this.stampLastCursorTimer),this.stampLastCursorTimer=null,s();return}this.stampLastCursorTimer!=null&&window.clearTimeout(this.stampLastCursorTimer),this.stampLastCursorTimer=window.setTimeout(()=>{this.stampLastCursorTimer=null,s()},400)}captureScrollAnchor(){let t=this.listEl;if(!t)return null;let e=t.getBoundingClientRect().top,i=Array.from(t.querySelectorAll(".stashpad-note"));if(i.length===0)return null;let s=null;for(let n of i){let o=n.dataset.id;if(!o)continue;let r=n.getBoundingClientRect().top-e;if(r>=0){s={id:o,offsetFromListTop:r};break}s={id:o,offsetFromListTop:r}}return s}restoreScrollAnchor(t,e){let i=this.listEl;if(i){if(t){let s=i.querySelector(`[data-id="${t.id}"]`);if(s){let n=i.getBoundingClientRect().top,o=s.getBoundingClientRect().top-n;i.scrollTop+=o-t.offsetFromListTop;return}}e>0&&(i.scrollTop=e)}}render(t){wt.enabled&&(this._renderT0=performance.now()),this.pendingRenderPolicy=t??{kind:"preserve"},this.loadConfig();let e=this.viewRoot,i=this.listEl?.scrollTop??0,n=(t??{kind:"preserve"}).kind==="preserve"?this.captureScrollAnchor():null;!!this.composerInputEl&&document.activeElement===this.composerInputEl&&(this.focusComposerOnNextRender=!0,this.pendingComposerCaret=this.composerInputEl?.selectionStart??null);let r=!!this.listEl&&(this.stickToListBottom||this.listEl.scrollTop+this.listEl.clientHeight>=this.listEl.scrollHeight-2);e.empty(),e.toggleClass("is-mobile",k.Platform.isMobile),e.toggleClass("is-tiny",this.tinyMode),e.toggleClass("is-compact",this.compactMode);let A=this.containerEl.closest(".workspace-leaf");A&&(A.classList.toggle("stashpad-is-tiny",this.tinyMode),A.classList.toggle("stashpad-is-compact",this.compactMode));let l=this.containerEl.closest(".workspace-tabs");l&&l.classList.toggle("stashpad-has-tiny",this.tinyMode),this.tinyMode?this.renderTinyHeader(e):(this.compactMode||this.renderTimeFilterBar(e),this.renderBreadcrumb(e));let d=this.tree.get(this.focusId)??this.tree.getRoot();d.file&&!k.Platform.isMobile&&!this.tinyMode&&!this.compactMode&&this.renderFocusedHeader(e,d),this.currentChildren=this.filterChildren(this.collectViewItems(d.id));let p=!1;if(this.autoSelectNewest&&this.currentChildren.length>0){let I=this.currentChildren[this.currentChildren.length-1];this.cursorIdx=this.currentChildren.length-1,this.selection.clear(),this.selection.add(I.id),this.lastSelected=I.id,this.autoSelectNewest=!1,p=!0}else if(this.pendingFocusIds){let I=this.pendingFocusIds;this.pendingFocusIds=null,this.selection.clear();let u=-1;for(let f of I){let C=this.currentChildren.findIndex(B=>B.id===f);C>=0&&(this.selection.add(f),u<0&&(u=C))}this.cursorIdx=u,u>=0&&(this.lastSelected=I.find(f=>this.currentChildren.some(C=>C.id===f))??null)}else this.cursorIdx>=this.currentChildren.length&&(this.cursorIdx=this.currentChildren.length-1);let g=e.createDiv({cls:"stashpad-list"});if(this.listEl=g,this.dnd.attachListDnD(g),this.populateListBody(g,d),this.renderComposer(e),k.Platform.isMobile&&this.renderMobileNav(e),this._renderT0!=null&&(wt.record("render.total",performance.now()-this._renderT0),this._renderT0=null),this.plugin.notifyStashpadContentChanged(),p&&this.plugin.notifyStashpadSelectionChanged(),this.focusComposerOnNextRender){this.focusComposerOnNextRender=!1;let I=this.pendingComposerCaret;this.pendingComposerCaret=null;let u=this.composerInputEl;if(u&&u.isConnected){if(u.focus({preventScroll:!0}),I!=null){let f=Math.min(I,u.value.length);try{u.setSelectionRange(f,f)}catch{}}}else requestAnimationFrame(()=>{let f=this.composerInputEl;if(f&&(f.focus({preventScroll:!0}),I!=null)){let C=Math.min(I,f.value.length);try{f.setSelectionRange(C,C)}catch{}}})}let h=this.pendingRenderPolicy;if(this.pendingRenderPolicy=null,h&&this.listEl){let I=this.scrollToBottomOnNextRender;switch(this.scrollToBottomOnNextRender=!1,h.kind){case"preserve":I?this.scrollListToBottom():r?this.scrollListToBottom():this.restoreScrollAnchor(n,i);break;case"pin-bottom":this.scrollListToBottom();break;case"restore":{let u=h.scrollTop,f=this.listEl,C=()=>{this.suppressScrollSave=!0;let B=Math.max(0,f.scrollHeight-f.clientHeight);f.scrollTop=Math.min(u,B),Promise.resolve().then(()=>{this.suppressScrollSave=!1})};C(),requestAnimationFrame(C),setTimeout(C,60),setTimeout(C,200),setTimeout(C,600);break}case"follow-cursor":i>0&&(this.listEl.scrollTop=i),this.revealCursorRow();break;case"scroll-to-id":{let u=h.id,f=h.align,C=this.listEl,B=()=>{this.suppressScrollSave=!0;let m=C.querySelector(`[data-id="${u}"]`);m&&m.scrollIntoView({block:f,behavior:"auto"}),Promise.resolve().then(()=>{this.suppressScrollSave=!1})};B(),requestAnimationFrame(B),setTimeout(B,60),setTimeout(B,200),setTimeout(B,600),setTimeout(()=>{this.suppressScrollSave=!1},700);break}}}else this.scrollToBottomOnNextRender?(this.scrollToBottomOnNextRender=!1,this.scrollListToBottom()):this.listEl&&r?this.scrollListToBottom():this.listEl&&i>0&&(this.listEl.scrollTop=i);if(this.stampSelectedCursor(),this.listEl){this.listResizeObserver?.disconnect();let I=this.listEl,u=I.scrollTop,f=new ResizeObserver(()=>{if(Date.now()<this.keyboardTransitionUntil)return;if(this.stickToListBottom){I.scrollTop=I.scrollHeight,u=I.scrollTop;return}let B=Math.max(0,I.scrollHeight-I.clientHeight);I.scrollTop<u&&u<=B?I.scrollTop=u:u=I.scrollTop});f.observe(I),this.listResizeObserver=f,I.addEventListener("wheel",B=>{B.deltaY<0&&(this.stickToListBottom=!1)},{passive:!0});let C=0;I.addEventListener("touchstart",B=>{C=B.touches[0]?.clientY??0},{passive:!0}),I.addEventListener("touchmove",B=>{let m=B.touches[0]?.clientY??C;m>C&&(this.stickToListBottom=!1),C=m},{passive:!0}),I.addEventListener("mousedown",()=>{this.stickToListBottom=!1}),I.addEventListener("keydown",()=>{this.stickToListBottom=!1})}}renderTimeFilterBar(t){let e=t.createDiv({cls:"stashpad-time-filter-bar"}),i=e.createEl("button",{cls:"stashpad-folder-btn"}),s=!!this.folderOverride,n=this.noteFolder.split("/").pop()||this.noteFolder||"Stashpad";(0,k.setIcon)(i.createSpan({cls:"stashpad-btn-icon"}),"folder"),i.createSpan({text:n,cls:"stashpad-btn-text"}),i.title=s?`Folder (override): ${this.noteFolder} Click to change or revert to default.`:`Folder: ${this.noteFolder} -Click to override for this tab.`,s&&i.addClass("is-override"),i.onclick=h=>{h.preventDefault(),this.openFolderPicker()};let o=e.createEl("button",{cls:"stashpad-search-btn"});oe(o,"search","\u{1F50D}"),o.title="Search notes (Mod+F)",o.onclick=h=>{h.preventDefault(),this.openSearchModal()},k.Platform.isMobile?this.renderMobileFiltersButton(e):(this.renderTagFilterDropdown(e),this.renderColorFilterDropdown(e),this.renderSortDropdown(e),this.renderViewDropdown(e));let r=e.createDiv({cls:"stashpad-time-filter-btns"}),A=r.createEl("button",{cls:"stashpad-time-filter-btn stashpad-time-filter-cal"});(0,k.setIcon)(A,this.timeFilterCalendar?"calendar":"history"),A.title=this.timeFilterCalendar?"Calendar mode: filters use start-of-day/week/month/year. Click for rolling windows.":"Rolling mode: filters look back N days from now. Click for calendar boundaries.",this.timeFilterCalendar&&A.addClass("is-active"),A.onclick=h=>{h.preventDefault(),this.timeFilterCalendar=!this.timeFilterCalendar,this.persistFocus(),this.render()};for(let h of Ns){let I=this.timeFilterCalendar?h.calShort:h.rollShort,u=this.timeFilterCalendar?h.calLong:h.rollLong,f=r.createEl("button",{cls:"stashpad-time-filter-btn",text:I});f.title=u,this.timeFilter===h.key&&f.addClass("is-active"),f.onclick=C=>{C.preventDefault(),this.setTimeFilter(h.key)}}let l=e.createEl("select",{cls:"stashpad-time-filter-select"});for(let h of Ns){let I=this.timeFilterCalendar?h.calLong:h.rollLong,u=l.createEl("option",{text:I});u.value=h.key,this.timeFilter===h.key&&(u.selected=!0)}l.onchange=()=>this.setTimeFilter(l.value);let d=e.createDiv({cls:"stashpad-view-mode-btns"});if(!k.Platform.isMobile){let h=d.createEl("button",{cls:"stashpad-view-mode-btn"});(0,k.setIcon)(h,"minimize-2"),h.title="Tiny mode \u2014 open this tab in a small always-on-top-capable popout window.",h.onclick=I=>{I.preventDefault(),this.plugin.openTinyWindow()}}let g=d.createEl("button",{cls:"stashpad-view-mode-btn"});if((0,k.setIcon)(g,this.compactMode?"panel-top":"rows-2"),g.title=this.compactMode?"Compact mode is ON \u2014 click to restore full chrome.":"Compact mode \u2014 hide the filter row + focused header; keep breadcrumb + list + composer.",this.compactMode&&g.addClass("is-active"),g.onclick=h=>{h.preventDefault(),this.toggleCompactMode()},k.Platform.isMobile)return;let p=d.createEl("button",{cls:"stashpad-view-mode-btn"});(0,k.setIcon)(p,"external-link"),p.title=j().popoutDuplicates?"Duplicate this Stashpad tab into a new Obsidian window. (Toggle in Settings \u2192 Open in new window \u2014 duplicate tab.)":"Move this Stashpad tab to a new Obsidian window. (Toggle in Settings \u2192 Open in new window \u2014 duplicate tab.)",p.onclick=h=>{h.preventDefault();let I=j().popoutDuplicates;try{let u=this.app.workspace;if(I){let f=this.leaf.getViewState(),C=u.openPopoutLeaf?.();C?C.setViewState({...f,active:!0}):new k.Notice("Stashpad: this Obsidian build doesn't expose openPopoutLeaf.")}else u.moveLeafToPopout?.(this.leaf)}catch(u){new k.Notice(`Stashpad: open-in-new-window failed (${u.message})`)}}}toggleCompactMode(){this.compactMode=!this.compactMode,this.render();try{this.app.workspace.requestSaveLayout?.()}catch{}}renderActionsCluster(t){let e=t.createDiv({cls:"stashpad-mobile-actions"}),i=e.createEl("button",{cls:"stashpad-mobile-action-btn"});oe(i,"arrow-left","\u2039");let s=this.navBackStack.length>0||this.focusId!==F;i.title=this.navBackStack.length>0?"Back":this.focusId!==F?"Back (up to parent)":"No back history",s||i.addClass("is-disabled"),i.onclick=d=>{d.preventDefault(),this.navigateBack()};let n=e.createEl("button",{cls:"stashpad-mobile-action-btn"});oe(n,"arrow-right","\u203A");let o=this.navForwardSnapshots.length>0;n.title=o?"Forward":"No forward history",o||n.addClass("is-disabled"),n.onclick=d=>{d.preventDefault(),this.navigateForward()};let r=e.createEl("button",{cls:"stashpad-mobile-action-btn"}),A=this.mobileSelectMode;oe(r,A?"check-square":"square",A?"\u2611":"\u2610"),r.title=A?`${this.selection.size} selected \u2014 tap to exit (keeps the first selection)`:"Enter select mode (tap notes to add)",A&&r.addClass("is-active"),r.onclick=d=>{if(d.preventDefault(),this.mobileSelectMode){let g=this.firstSelectedId??this.selection.values().next().value;if(this.selection.clear(),g){let p=this.currentChildren.findIndex(h=>h.id===g);this.selection.add(g),this.lastSelected=g,p>=0&&(this.cursorIdx=p)}this.firstSelectedId=null,this.mobileSelectMode=!1,this.render()}else{let g=this.currentChildren[Math.max(0,this.cursorIdx)];this.mobileSelectMode=!0,this.selection.clear(),g&&(this.selection.add(g.id),this.lastSelected=g.id,this.firstSelectedId=g.id),this.render(),new k.Notice("Select mode: tap notes to add, press \u26A1 for actions")}};let l=e.createEl("button",{cls:"stashpad-mobile-action-btn"});oe(l,"zap","\u26A1"),l.title="Actions (move, delete, undo, \u2026)",l.onclick=d=>{d.preventDefault(),this.openMobileActionsMenu(l)}}openMobileActionsMenu(t){let e=new k.Menu,i=this.selection.size>0||this.cursorIdx>=0&&!!this.currentChildren[this.cursorIdx],s=this.selection.size<=1;e.addItem(o=>o.setTitle("Undo").setIcon("undo").onClick(()=>this.cmdUndo())),e.addItem(o=>o.setTitle("Redo").setIcon("redo").onClick(()=>this.cmdRedo())),e.addSeparator(),e.addItem(o=>o.setTitle("Notification history\u2026").setIcon("bell").onClick(()=>{this.app.commands?.executeCommandById?.("stashpad:stashpad-open-notification-history")})),e.addItem(o=>o.setTitle("Reload without saving").setIcon("rotate-ccw").onClick(()=>this.plugin.reloadAppForUpdate())),e.addSeparator(),e.addItem(o=>o.setTitle("Open in new Stashpad tab").setIcon("list-tree").setDisabled(!i).onClick(()=>this.cmdOpenInNewStashpadTab())),e.addItem(o=>o.setTitle("Open in editor").setIcon("pencil").setDisabled(!i).onClick(()=>this.cmdOpenInEditor())),e.addSeparator(),e.addItem(o=>o.setTitle("Move\u2026").setIcon("arrow-right-circle").setDisabled(!i).onClick(()=>this.cmdMovePicker())),e.addItem(o=>o.setTitle("Nest under\u2026 (in-list)").setIcon("indent").setDisabled(!i).onClick(()=>this.cmdInListPicker())),e.addItem(o=>o.setTitle("Outdent").setIcon("outdent").setDisabled(!i).onClick(()=>void this.cmdOutdent())),e.addItem(o=>o.setTitle("Set color\u2026").setIcon("palette").setDisabled(!i).onClick(()=>this.cmdSetColor())),e.addItem(o=>o.setTitle("Toggle complete").setIcon("check-circle").setDisabled(!i).onClick(()=>void this.cmdToggleComplete())),e.addItem(o=>o.setTitle("Toggle task (todo)").setIcon("check-square").setDisabled(!i).onClick(()=>void this.cmdToggleTask())),e.addItem(o=>o.setTitle("Set due date\u2026").setIcon("calendar-clock").setDisabled(!i).onClick(()=>this.cmdSetDue())),e.addItem(o=>o.setTitle("Assign to\u2026").setIcon("user-plus").setDisabled(!i).onClick(()=>this.cmdAssign())),e.addSeparator(),e.addItem(o=>o.setTitle("Copy").setIcon("copy").setDisabled(!i).onClick(()=>void this.cmdCopy())),e.addItem(o=>o.setTitle("Copy tree").setIcon("copy-plus").setDisabled(!i).onClick(()=>void this.cmdCopyTree())),e.addItem(o=>o.setTitle("Clone (duplicate / copy)").setIcon("files").setDisabled(!i).onClick(()=>void this.cmdClone())),e.addItem(o=>o.setTitle("Insert template\u2026").setIcon("file-plus-2").onClick(()=>this.cmdInsertTemplate())),e.addItem(o=>o.setTitle("Merge").setIcon("merge").setDisabled(this.selection.size<2).onClick(()=>void this.cmdMerge())),e.addItem(o=>o.setTitle("Split note\u2026").setIcon("scissors").setDisabled(!i||!s).onClick(()=>void this.cmdSplit())),e.addSeparator(),e.addItem(o=>o.setTitle("Delete").setIcon("trash-2").setDisabled(!i).onClick(()=>void this.cmdDelete())),e.addSeparator(),e.addItem(o=>o.setTitle("More commands\u2026").setIcon("terminal").onClick(()=>this.openCommandPalette()));let n=t.getBoundingClientRect();e.showAtPosition({x:n.left,y:n.bottom+4})}openCommandPalette(){this.app.commands?.executeCommandById?.("command-palette:open")}openStashpadCommandPalette(){new Fs(this.app).open()}renderTagFilterDropdown(t){let e=t.createEl("select",{cls:"stashpad-tag-filter-select"}),i=e.createEl("option",{text:"All tags"});i.value="",this.tagFilter||(i.selected=!0);let s=this.collectFolderTags();if(s.length===0)e.disabled=!0,i.text="No tags";else for(let n of s){let o=e.createEl("option",{text:`${n.label} (${n.count})`});o.value=n.raw,this.tagFilter&&this.tagFilter.toLowerCase()===n.raw.toLowerCase()&&(o.selected=!0)}e.onchange=()=>this.setTagFilter(e.value||null)}renderColorFilterDropdown(t){let e=this.collectFolderColors(),i=t.createDiv({cls:"stashpad-color-filter-btn"});i.setAttribute("role","button"),i.setAttribute("tabindex","0"),(()=>{i.empty();let o=i.createSpan({cls:"stashpad-color-filter-swatch"}),r=i.createSpan({cls:"stashpad-color-filter-label"});if(this.colorFilter){let A=this.colorFilter.toLowerCase();o.setCssStyles({background:A});let l=this.plugin.getColorAlias(this.noteFolder,A);r.setText(l??A)}else e.length===0?(o.addClass("is-empty"),r.setText("No colors"),i.addClass("is-disabled")):(o.addClass("is-empty"),r.setText("All colors"))})();let n=o=>{o.preventDefault(),!(e.length===0&&!this.colorFilter)&&this.openColorFilterMenu(i,e)};i.onclick=n,i.onkeydown=o=>{(o.key==="Enter"||o.key===" ")&&n(o)}}openColorFilterMenu(t,e){let i=t.ownerDocument??document;i.querySelectorAll(".stashpad-color-filter-popover").forEach(l=>l.remove());let s=i.body.createDiv({cls:"stashpad-color-filter-popover"}),n=t.getBoundingClientRect();s.setCssStyles({left:`${Math.max(8,n.left)}px`,top:`${n.bottom+4}px`,minWidth:`${n.width}px`,maxWidth:"min(280px, calc(100vw - 16px))",width:"max-content"});let o=new k.Scope(this.app.scope),r=()=>{s.remove(),i.removeEventListener("mousedown",A,!0);try{this.app.keymap?.popScope(o)}catch{}},A=l=>{!s.contains(l.target)&&l.target!==t&&!t.contains(l.target)&&r()};o.register([],"Escape",l=>(l.preventDefault(),r(),!1)),this.app.keymap?.pushScope(o),this.populateColorMenuBody(s,e,r),setTimeout(()=>{i.addEventListener("mousedown",A,!0)},0)}renderSortDropdown(t){let e=this.noteFolder,i=this.focusId,s=this.sortStore.getMode(e,i),n=this.currentViewMode(),o=n!=="nested",r=t.createDiv({cls:"stashpad-sort-btn"});r.setAttribute("role","button"),r.setAttribute("tabindex",o?"-1":"0"),o&&r.addClass("is-disabled");let A=r.createSpan({cls:"stashpad-sort-icon"});(0,k.setIcon)(A,"arrow-up-down");let l=r.createSpan({cls:"stashpad-sort-label"});o?(l.setText("Sort: \u2014"),r.title=`Sort is per-parent and applies only to Nested view. The current view (${bs[n]}) shows a synthesized flat list sorted by created time \u2014 switch back to Nested to change sort.`):(l.setText(Ni[s]),s!=="manual"&&r.addClass("is-active"),r.title=s==="manual"?"Sort children of this view. Click to change. Drag-reorder always reverts the affected parent to Manual.":`Currently: ${Ni[s]}. Drag-reorder will revert this parent to Manual.`);let d=g=>{o||(g.preventDefault(),this.openSortMenu(r))};r.onclick=d,r.onkeydown=g=>{o||(g.key==="Enter"||g.key===" ")&&d(g)}}openSortMenu(t){let e=t.ownerDocument??document;e.querySelectorAll(".stashpad-sort-popover").forEach(A=>A.remove());let i=e.body.createDiv({cls:"stashpad-sort-popover"}),s=t.getBoundingClientRect();i.setCssStyles({left:`${Math.max(8,s.left)}px`,top:`${s.bottom+4}px`,minWidth:`${s.width}px`,maxWidth:"min(280px, calc(100vw - 16px))",width:"max-content"});let n=()=>{i.remove(),e.removeEventListener("mousedown",o,!0);try{this.app.keymap?.popScope(r)}catch{}},o=A=>{!i.contains(A.target)&&A.target!==t&&!t.contains(A.target)&&n()};this.populateSortMenuBody(i,n);let r=new k.Scope(this.app.scope);r.register([],"Escape",A=>(A.preventDefault(),n(),!1)),this.app.keymap?.pushScope(r),setTimeout(()=>{e.addEventListener("mousedown",o,!0)},0)}renderMobileFiltersButton(t){let e=t.createDiv({cls:"stashpad-mobile-filters-btn"});e.setAttribute("role","button"),e.setAttribute("tabindex","0");let i=e.createSpan({cls:"stashpad-mobile-filters-icon"});(0,k.setIcon)(i,"sliders-horizontal"),e.title="Filters / view options";let s=!!this.tagFilter,n=!!this.colorFilter,o=this.timeFilter!=="all",r=this.sortStore.getMode(this.noteFolder,this.focusId)!=="manual",A=this.currentViewMode()!=="nested"||this.currentHideChildless()||this.currentHideCompleted()||this.currentAttachmentsOnly()||this.currentIncludeAttachments();(s||n||o||r||A)&&e.addClass("is-active");let l=d=>{d.preventDefault(),this.openMobileFiltersMenu(e)};e.onclick=l,e.onkeydown=d=>{(d.key==="Enter"||d.key===" ")&&l(d)}}openMobileFiltersMenu(t){let e=t.ownerDocument??document;e.querySelectorAll(".stashpad-mobile-filters-popover").forEach(p=>p.remove());let i=e.body.createDiv({cls:"stashpad-mobile-filters-popover"}),s=t.getBoundingClientRect(),n=e.defaultView??window;i.setCssStyles({right:`${Math.max(8,n.innerWidth-s.right)}px`,left:"auto",top:`${s.bottom+4}px`,maxWidth:"min(360px, calc(100vw - 16px))",width:"max-content",minWidth:"260px"});let o=()=>{i.remove(),e.removeEventListener("mousedown",r,!0);try{this.app.keymap?.popScope(g)}catch{}},r=p=>{!i.contains(p.target)&&p.target!==t&&!t.contains(p.target)&&o()},A=[{key:"tag",title:"Tag filter",summary:()=>this.tagFilter?`#${this.tagFilter}`:"All tags",populate:p=>this.populateTagMenuBody(p,o)},{key:"color",title:"Color filter",summary:()=>this.colorFilter?this.plugin.getColorAlias(this.noteFolder,this.colorFilter)??this.colorFilter:"All colors",populate:p=>this.populateColorMenuBody(p,this.collectFolderColors(),o)},{key:"time",title:"Time filter",summary:()=>{let p=Ns.find(h=>h.key===this.timeFilter);return p?this.timeFilterCalendar?p.calShort:p.rollShort:"All"},populate:p=>this.populateTimeMenuBody(p,o)},{key:"sort",title:"Sort",summary:()=>this.currentViewMode()!=="nested"?"\u2014 (Nested only)":Ni[this.sortStore.getMode(this.noteFolder,this.focusId)],populate:p=>{if(this.currentViewMode()!=="nested"){p.createDiv({cls:"stashpad-mobile-filters-note",text:"Sort applies only in Nested view."});return}this.populateSortMenuBody(p,o)}},{key:"view",title:"View",summary:()=>bs[this.currentViewMode()],populate:p=>this.populateViewMenuBody(p,o)}],l="",d=()=>{i.empty();for(let p of A){let h=i.createDiv({cls:"stashpad-mobile-filters-section"}),I=h.createDiv({cls:"stashpad-mobile-filters-header"}),u=I.createSpan({cls:"stashpad-mobile-filters-chev"});if((0,k.setIcon)(u,l===p.key?"chevron-down":"chevron-right"),I.createSpan({cls:"stashpad-mobile-filters-title",text:p.title}),I.createSpan({cls:"stashpad-mobile-filters-summary",text:p.summary()}),I.onclick=f=>{f.preventDefault(),f.stopPropagation(),l=l===p.key?"":p.key,d()},l===p.key){let f=h.createDiv({cls:"stashpad-mobile-filters-body"});p.populate(f)}}};d();let g=new k.Scope(this.app.scope);g.register([],"Escape",p=>(p.preventDefault(),o(),!1)),this.app.keymap?.pushScope(g),setTimeout(()=>{e.addEventListener("mousedown",r,!0)},0)}renderViewDropdown(t){let e=this.currentViewMode(),i=t.createDiv({cls:"stashpad-view-btn"});i.setAttribute("role","button"),i.setAttribute("tabindex","0");let s=i.createSpan({cls:"stashpad-view-icon"});(0,k.setIcon)(s,e==="flat"?"list":e==="everything"?"layout-grid":"list-tree"),i.createSpan({cls:"stashpad-view-label"}).setText(bs[e]),(e!=="nested"||this.currentEncryptionFilter()!=="all")&&i.addClass("is-active"),i.title=e==="nested"?"View: Nested (the default). Click to switch to Flat or Everything.":e==="flat"?"View: Flat \u2014 all descendants of the current focus, flat by sort order. Drag-reorder is disabled in this mode. Click to change.":"View: Everything \u2014 all descendants of the current focus PLUS non-Stashpad files in the folder, flat by created/ctime. Click to change.";let o=r=>{r.preventDefault(),this.openViewMenu(i)};i.onclick=o,i.onkeydown=r=>{(r.key==="Enter"||r.key===" ")&&o(r)}}openViewMenu(t){let e=t.ownerDocument??document;e.querySelectorAll(".stashpad-view-popover").forEach(A=>A.remove());let i=e.body.createDiv({cls:"stashpad-view-popover"});k.Platform.isMobile&&i.addClass("is-mobile");let s=t.getBoundingClientRect();i.setCssStyles({left:`${Math.max(8,s.left)}px`,top:`${s.bottom+4}px`,minWidth:`${s.width}px`,maxWidth:"min(320px, calc(100vw - 16px))",width:"max-content"});let n=()=>{i.remove(),e.removeEventListener("mousedown",o,!0);try{this.app.keymap?.popScope(r)}catch{}},o=A=>{!i.contains(A.target)&&A.target!==t&&!t.contains(A.target)&&n()};this.populateViewMenuBody(i,n);let r=new k.Scope(this.app.scope);r.register([],"Escape",A=>(A.preventDefault(),n(),!1)),this.app.keymap?.pushScope(r),setTimeout(()=>{e.addEventListener("mousedown",o,!0)},0)}populateViewMenuBody(t,e){let i=this.currentViewMode(),s=(Q,E)=>{let v=t.createDiv({cls:"stashpad-view-popover-row"});Q===i&&v.addClass("is-active"),v.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:bs[Q]}),v.createDiv({cls:"stashpad-view-popover-desc",text:E}),v.onclick=async b=>{b.preventDefault(),b.stopPropagation(),e(),Q!==i&&(await this.setViewMode(Q),this.render())}};if(s("nested","Tree of immediate children (default)."),s("flat","All descendants of the current focus, flat by sort."),s("everything","All descendants PLUS non-Stashpad files in the folder."),t.createDiv({cls:"stashpad-view-popover-divider"}),this.plugin.encryption?.isConfigured?.()){let Q=this.currentEncryptionFilter(),E=(v,y,b)=>{let N=t.createDiv({cls:"stashpad-view-popover-row"});v===Q&&N.addClass("is-active"),N.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:y}),N.createDiv({cls:"stashpad-view-popover-desc",text:b}),N.onclick=async P=>{P.preventDefault(),P.stopPropagation(),v!==Q&&(await this.setEncryptionFilter(v),this.refreshList()),e()}};E("all","Encryption: show all","Both locked \u{1F512} and decrypted notes."),E("locked","Encryption: locked only","Show only locked \u{1F512} stubs."),E("unlocked","Encryption: decrypted only","Hide locked \u{1F512} stubs."),t.createDiv({cls:"stashpad-view-popover-divider"})}let n=t.createDiv({cls:"stashpad-view-popover-row stashpad-view-popover-toggle"}),o=n.createEl("input",{type:"checkbox"});o.checked=this.currentHideChildless(),n.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:"Hide childless notes"}),n.createDiv({cls:"stashpad-view-popover-desc",text:i==="nested"?"Show only notes that have children. Applied at this level.":"Hide top-level notes without children; keep every parent's full subtree so no task is overlooked."}),n.onclick=async Q=>{Q.target!==o&&(Q.preventDefault(),o.checked=!o.checked),await this.setHideChildless(o.checked),this.refreshList()};let r=t.createDiv({cls:"stashpad-view-popover-row stashpad-view-popover-toggle"}),A=r.createEl("input",{type:"checkbox"});A.checked=this.currentHideCompleted(),r.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:"Hide completed notes"}),r.createDiv({cls:"stashpad-view-popover-desc",text:"Hide notes marked complete. A completed parent stays visible while any descendant is still incomplete."}),r.onclick=async Q=>{Q.target!==A&&(Q.preventDefault(),A.checked=!A.checked),await this.setHideCompleted(A.checked),this.refreshList()};let l=t.createDiv({cls:"stashpad-view-popover-row stashpad-view-popover-toggle"}),d=l.createEl("input",{type:"checkbox"});d.checked=this.currentAttachmentsOnly(),l.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:"Hide notes without attachments"}),l.createDiv({cls:"stashpad-view-popover-desc",text:"Show only notes that have an attachment. A parent stays visible while any descendant has one."}),l.onclick=async Q=>{Q.target!==d&&(Q.preventDefault(),d.checked=!d.checked),await this.setAttachmentsOnly(d.checked),this.refreshList()},t.createDiv({cls:"stashpad-view-popover-divider"});let g=t.createDiv({cls:"stashpad-view-popover-row stashpad-view-popover-toggle"});i!=="everything"&&g.addClass("is-disabled");let p=g.createEl("input",{type:"checkbox"});p.checked=this.currentIncludeAttachments(),p.disabled=i!=="everything",g.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:"Include attachments"}),g.createDiv({cls:"stashpad-view-popover-desc",text:i==="everything"?"Show attachments referenced by notes as their own rows in the file list. Off by default \u2014 they already appear inline on the notes that embed them.":"Only applies in Everything mode."}),g.onclick=async Q=>{i==="everything"&&(Q.target!==p&&(Q.preventDefault(),p.checked=!p.checked),await this.setIncludeAttachments(p.checked),this.refreshList())},t.createDiv({cls:"stashpad-view-popover-divider"});let h=t.createDiv({cls:"stashpad-view-popover-row stashpad-view-popover-toggle"}),I=h.createEl("input",{type:"checkbox"});I.checked=this.importedOnly,h.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:"Imported notes only"}),h.createDiv({cls:"stashpad-view-popover-desc",text:"Show only notes that came in via import."}),h.onclick=Q=>{Q.target!==I&&(Q.preventDefault(),I.checked=!I.checked),this.importedOnly=I.checked,this.reconcileSelectionAfterFilter(),this.refreshList()};let u=new Map,f=this.noteFolder.replace(/\/+$/,"");for(let Q of this.app.vault.getMarkdownFiles()){if((Q.parent?.path?.replace(/\/+$/,"")??"")!==f)continue;let E=ne(this.app.metadataCache.getFileCache(Q)?.frontmatter?.author);E&&u.set(E.id,E.name)}let C=t.createDiv({cls:"stashpad-view-popover-row stashpad-view-popover-toggle"}),B=C.createDiv({cls:"stashpad-view-popover-main"});B.createSpan({cls:"stashpad-view-popover-label",text:"By author"});let m=B.createEl("select",{cls:"stashpad-view-author-select"}),w=m.createEl("option",{text:"All authors",value:""});this.authorFilter||(w.selected=!0);for(let[Q,E]of[...u.entries()].sort((v,y)=>v[1].localeCompare(y[1]))){let v=m.createEl("option",{text:E,value:Q});this.authorFilter===Q&&(v.selected=!0)}m.onclick=Q=>Q.stopPropagation(),m.onchange=()=>{this.authorFilter=m.value||null,this.reconcileSelectionAfterFilter(),this.refreshList()},C.createDiv({cls:"stashpad-view-popover-desc",text:u.size?"Show only notes by the chosen author.":"No authored notes in this folder yet."})}setTagFilter(t){(this.tagFilter??null)!==(t??null)&&(this.tagFilter=t,this.reconcileSelectionAfterFilter(),this.persistFocus(),this.render())}populateSortMenuBody(t,e){let i=this.noteFolder,s=this.focusId,n=this.sortStore.getMode(i,s);for(let o of Wn){let r=t.createDiv({cls:"stashpad-sort-popover-row"});o===n&&r.addClass("is-active"),r.createSpan({cls:"stashpad-sort-popover-label",text:Ni[o]}),r.onclick=async A=>{A.preventDefault(),A.stopPropagation(),e(),o!==n&&(this.sortStore.setMode(i,s,o),await this.sortStore.save(i),this.tree.rebuild(i),this.render())}}}populateTimeMenuBody(t,e){let i=t.createDiv({cls:"stashpad-view-popover-row stashpad-view-popover-toggle"}),s=i.createEl("input",{type:"checkbox"});s.checked=this.timeFilterCalendar,i.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:"Calendar mode"}),i.createDiv({cls:"stashpad-view-popover-desc",text:"Use calendar boundaries (start of today/week/month/year). Off = rolling windows back from now."}),i.onclick=n=>{n.target!==s&&(n.preventDefault(),s.checked=!s.checked),this.timeFilterCalendar=s.checked,this.persistFocus(),this.refreshList()};for(let n of Ns){let o=t.createDiv({cls:"stashpad-sort-popover-row"});this.timeFilter===n.key&&o.addClass("is-active");let r=this.timeFilterCalendar?n.calLong:n.rollLong;o.createSpan({cls:"stashpad-sort-popover-label",text:r}),o.onclick=A=>{A.preventDefault(),A.stopPropagation(),e(),this.timeFilter!==n.key&&this.setTimeFilter(n.key)}}}populateColorMenuBody(t,e,i){let s=(n,o,r)=>{let A=t.createDiv({cls:"stashpad-color-filter-popover-row"}),l=A.createSpan({cls:"stashpad-color-filter-swatch"});o?l.setCssStyles({background:o}):l.addClass("is-empty");let d=A.createSpan({cls:"stashpad-color-filter-popover-label"});d.setText(n),o&&(d.style.color=o),A.onclick=g=>{g.preventDefault(),g.stopPropagation(),r(),i()}};s("All colors",null,()=>this.setColorFilter(null));for(let n of e){let o=this.plugin.getColorAlias(this.noteFolder,n.hex),r=o?`${o} (${n.count})`:`${n.hex} (${n.count})`;s(r,n.hex,()=>this.setColorFilter(n.hex))}}populateTagMenuBody(t,e){let i=this.collectFolderTags(),s=(n,o)=>{let r=t.createDiv({cls:"stashpad-color-filter-popover-row"});r.createSpan({cls:"stashpad-color-filter-swatch is-empty"}),r.createSpan({cls:"stashpad-color-filter-popover-label"}).setText(n),(this.tagFilter??"")===(o??"")&&r.addClass("is-active"),r.onclick=d=>{d.preventDefault(),d.stopPropagation(),this.setTagFilter(o),e()}};s(i.length===0?"No tags":"All tags",null);for(let n of i)s(`${n.label} (${n.count})`,n.raw)}setColorFilter(t){let e=t?t.toLowerCase():null;(this.colorFilter??null)!==e&&(this.colorFilter=e,this.reconcileSelectionAfterFilter(),this.persistFocus(),this.render())}setTimeFilter(t){this.timeFilter!==t&&(this.timeFilter=t,this.reconcileSelectionAfterFilter(),this.persistFocus(),this.render())}reconcileSelectionAfterFilter(){let t=this.filterChildren(this.collectViewItems(this.focusId)),e=new Set(t.map(i=>i.id));for(let i of[...this.selection])e.has(i)||this.selection.delete(i);if(this.firstSelectedId&&!e.has(this.firstSelectedId)&&(this.firstSelectedId=null),this.lastSelected&&!e.has(this.lastSelected)&&(this.lastSelected=null),this.selection.size>0){let i=t.findIndex(s=>this.selection.has(s.id));this.cursorIdx=i>=0?i:Math.min(this.cursorIdx,t.length-1)}else this.cursorIdx>=t.length&&(this.cursorIdx=t.length-1)}renderTinyHeader(t){let e=t.createDiv({cls:"stashpad-tiny-header"}),i=e.createEl("button",{cls:"stashpad-tiny-nav-btn"});oe(i,"arrow-left","\u2039"),i.title="Back (up to parent)",this.navBackStack.length>0||this.focusId!==F||i.addClass("is-disabled"),i.title=this.navBackStack.length>0?"Back":this.focusId!==F?"Back (up to parent)":"No back history",i.onclick=()=>this.navigateBack();let n=e.createEl("button",{cls:"stashpad-tiny-nav-btn"});oe(n,"arrow-right","\u203A"),n.title=this.navForwardSnapshots.length>0?"Forward":"No forward history",this.navForwardSnapshots.length===0&&n.addClass("is-disabled"),n.onclick=()=>this.navigateForward();let o=this.tree.get(this.focusId)??this.tree.getRoot(),r=(this.noteFolder.split("/").pop()||this.noteFolder).trim(),A=this.focusId===F?r:`${r} / ${this.titleForNode(o).trim()}`,l=e.createEl("button",{cls:"stashpad-tiny-title stashpad-folder-btn"}),d=l.createSpan({cls:"stashpad-tiny-title-icon stashpad-btn-icon"});(0,k.setIcon)(d,"folder"),l.createSpan({cls:"stashpad-tiny-title-text stashpad-btn-text",text:A}),l.title=`${this.noteFolder}${this.focusId!==F?` / ${this.titleForNode(o).trim()}`:""} -Click to switch / create folder.`,l.onclick=u=>{u.preventDefault(),this.plugin.openFolderPicker()};let g=e.createDiv({cls:"stashpad-tiny-sticky"}),p=g.createEl("input",{type:"checkbox"});if(p.checked=this.tinyAlwaysOnTop,g.createSpan({text:"Sticky"}),p.onchange=()=>{this.tinyAlwaysOnTop=p.checked,this.applyTinyAlwaysOnTop()},!k.Platform.isMobile){let u=e.createEl("button",{cls:"stashpad-tiny-nav-btn stashpad-tiny-opacity-btn"});(0,k.setIcon)(u,"contrast"),u.title="Window transparency",this.tinyOpacity<1&&u.addClass("is-active"),u.onclick=f=>{f.stopPropagation(),this.toggleTinyOpacityPopover(u)}}let h=e.createEl("button",{cls:"stashpad-tiny-expand stashpad-tiny-exit-compact"});(0,k.setIcon)(h,this.compactMode?"panel-top":"rows-2"),h.title=this.compactMode?"Compact mode is ON \u2014 click to turn off.":"Compact mode \u2014 click to turn on (strips row metadata).",this.compactMode&&h.addClass("is-active"),h.onclick=()=>{this.toggleCompactMode()};let I=e.createEl("button",{cls:"stashpad-tiny-expand"});(0,k.setIcon)(I,"maximize-2"),I.title="Exit tiny mode",I.onclick=()=>{this.exitTinyMode()}}toggleTinyOpacityPopover(t){if(this.tinyOpacityPopover){this.tinyOpacityPopover.remove(),this.tinyOpacityPopover=null;return}let e=document.createElement("div");e.className="stashpad-tiny-opacity-popover",e.createSpan({cls:"stashpad-tiny-opacity-label",text:"Transparency"});let i=e.createEl("input",{type:"range"});i.min="30",i.max="100",i.step="1",i.value=String(Math.round(this.tinyOpacity*100));let s=e.createSpan({cls:"stashpad-tiny-opacity-pct",text:`${i.value}%`});i.addEventListener("input",()=>{let d=Math.min(100,Math.max(30,parseInt(i.value,10)||100));this.tinyOpacity=d/100,s.setText(`${d}%`),this.applyTinyOpacity(),t.toggleClass("is-active",this.tinyOpacity<1)}),i.addEventListener("change",()=>{this.app.workspace.requestSaveLayout()}),this.viewRoot.appendChild(e);let n=t.getBoundingClientRect(),o=this.viewRoot.getBoundingClientRect();e.setCssStyles({top:`${n.bottom-o.top+4}px`,left:`${Math.max(4,Math.min(n.left-o.left,o.width-180))}px`});let r=d=>{e.contains(d.target)||d.target===t||t.contains(d.target)||l()},A=d=>{d.key==="Escape"&&l()},l=()=>{e.remove(),this.tinyOpacityPopover=null,document.removeEventListener("mousedown",r,!0),document.removeEventListener("keydown",A,!0)};setTimeout(()=>{document.addEventListener("mousedown",r,!0),document.addEventListener("keydown",A,!0)},0),this.tinyOpacityPopover=e,i.focus()}getOwnElectronWindow(){try{let t=this.containerEl?.ownerDocument?.defaultView??window,s=((t?.require?.("electron")??window.require?.("electron"))?.remote??t?.electron?.remote??t?.["@electron/remote"])?.getCurrentWindow?.()??t?.electronWindow??null;if(!s)try{let n=window.require?.("electron"),o=n?.remote??n?.["@electron/remote"],A=(o?.BrowserWindow??n?.BrowserWindow)?.getAllWindows?.()??[];A.length===1?s=A[0]:A.length>1&&(s=o?.getFocusedWindow?.()??null??A[A.length-1])}catch(n){console.debug("[Stashpad] BrowserWindow.getAllWindows fallback failed",n)}return s||console.debug("[Stashpad] couldn't resolve own electron window"),s??null}catch(t){return console.debug("[Stashpad] resolve own electron window failed",t),null}}applyTinyAlwaysOnTop(){let t=this.getOwnElectronWindow();if(t)try{t.setAlwaysOnTop?.(!!this.tinyAlwaysOnTop)}catch(e){console.debug("[Stashpad] setAlwaysOnTop failed",e)}}applyTinyOpacity(){let t=this.getOwnElectronWindow();if(!t)return;let e=Math.min(1,Math.max(.3,this.tinyOpacity));try{t.setOpacity?.(e)}catch(i){console.debug("[Stashpad] setOpacity failed",i)}}applyTinyWindow(){let t=this.getOwnElectronWindow();if(t)try{if(this.tinyMode){t.setMinimumSize?.(220,260);let s=100,n=100;try{let o=t.getBounds?.();o&&typeof o.x=="number"&&(s=o.x,n=o.y)}catch{}try{t.setBounds?.({x:s,y:n,width:280,height:360})}catch{}try{t.setSize?.(280,360)}catch{}t.setAlwaysOnTop?.(!!this.tinyAlwaysOnTop);try{t.setOpacity?.(Math.min(1,Math.max(.3,this.tinyOpacity)))}catch{}}else t.setAlwaysOnTop?.(!1)}catch(e){console.debug("[Stashpad] tiny window apply failed",e)}}async exitTinyMode(){this.tinyMode=!1,this.tinyAlwaysOnTop=!1,this.tinyOpacity=1;try{this.getOwnElectronWindow()?.setOpacity?.(1)}catch{}this.compactMode=!1,this.applyTinyWindow();let t=this.getOwnElectronWindow();try{if(t?.setMinimumSize?.(400,300),k.Platform.isMacOS??!1){let i=this.containerEl?.ownerDocument?.defaultView?.require?.("electron")??window.require?.("electron"),n=(i?.remote?.screen??i?.screen)?.getPrimaryDisplay?.().workArea;n?t?.setBounds?.({x:n.x,y:n.y,width:n.width,height:n.height}):t?.maximize?.()}else t?.maximize?.()}catch{}this.render();try{await this.app.workspace.requestSaveLayout?.()}catch{}}enterTinyMode(){this.tinyMode=!0,this.applyTinyWindow(),this.render();try{this.app.workspace.requestSaveLayout?.()}catch{}}renderBreadcrumb(t){let e=t.createDiv({cls:"stashpad-breadcrumb"});this.renderActionsCluster(e);let i=e.createSpan({cls:"stashpad-crumb stashpad-crumb-home"});if(k.Platform.isMobile?((0,k.setIcon)(i,"home"),i.title="Home"):i.setText("Home"),i.onclick=()=>this.navigateTo(F),this.focusId===F){let d=this.tree.getChildren(this.focusId).length;if(d>0&&(e.createSpan({cls:"stashpad-crumb-count",text:`\xB7 ${d}`}).title=`${d} direct child${d===1?"":"ren"}`),this.compactMode){let g=e.createEl("button",{cls:"stashpad-compact-exit-btn"});(0,k.setIcon)(g,"panel-top"),g.title="Exit compact mode",g.onclick=p=>{p.preventDefault(),this.toggleCompactMode()}}return}let s=28,n=100,o=this.tree.pathTo(this.focusId),r=o.map(d=>{let g=this.titleForNode(d),p=g.length>s?g.slice(0,s-1)+"\u2026":g;return{id:d.id,label:p}}),A=d=>d.reduce((g,p)=>g+p.label.length+3,0);if(A(r)>n&&r.length>2){let d=!1;for(;A(r)>n&&r.length>2;)r.splice(1,1),d||(r.splice(1,0,{id:"__ellipsis__",label:"\u2026",isEllipsis:!0}),d=!0)}for(let d of r)if(e.createSpan({cls:"stashpad-crumb-sep",text:" / "}),d.isEllipsis)e.createSpan({cls:"stashpad-crumb stashpad-crumb-ellipsis",text:d.label}).title=o.map(g=>this.titleForNode(g)).join(" / ");else{let g=d.id,p=e.createSpan({cls:"stashpad-crumb",text:d.label});p.title=d.label,p.onclick=()=>this.navigateTo(g),p.oncontextmenu=h=>{h.preventDefault(),this.openCrumbMenu(h,g)},k.Platform.isMobile&&this.attachLongPress(p,()=>this.openCrumbMenu(null,g))}if(e.querySelector(".stashpad-crumb-home")?.addEventListener("contextmenu",d=>{d.preventDefault(),this.openCrumbMenu(d,F)}),k.Platform.isMobile){let d=e.querySelector(".stashpad-crumb-home");d&&this.attachLongPress(d,()=>this.openCrumbMenu(null,F))}let l=this.tree.getChildren(this.focusId).length;if(l>0&&(e.createSpan({cls:"stashpad-crumb-count",text:`\xB7 ${l}`}).title=`${l} direct child${l===1?"":"ren"}`),this.compactMode){let d=e.createEl("button",{cls:"stashpad-compact-exit-btn"});(0,k.setIcon)(d,"panel-top"),d.title="Exit compact mode",d.onclick=g=>{g.preventDefault(),this.toggleCompactMode()}}}attachLongPress(t,e){let i=null,s=0,n=0,o=()=>{i!=null&&(window.clearTimeout(i),i=null)};t.addEventListener("touchstart",r=>{let A=r.touches[0];s=A?.clientX??0,n=A?.clientY??0,o(),i=window.setTimeout(()=>{i=null,e()},500)},{passive:!0}),t.addEventListener("touchmove",r=>{let A=r.touches[0];A&&(Math.abs(A.clientX-s)>10||Math.abs(A.clientY-n)>10)&&o()},{passive:!0}),t.addEventListener("touchend",o),t.addEventListener("touchcancel",o)}openCrumbMenu(t,e){let i=this.tree.get(e);if(!i)return;let s=new k.Menu;if(s.addItem(n=>n.setTitle("Navigate here").setIcon("arrow-right-circle").onClick(()=>this.navigateTo(e))),s.addItem(n=>n.setTitle("Open in new Stashpad tab").setIcon("list-tree").onClick(()=>this.cmdOpenInNewStashpadTab(i))),i.file&&s.addItem(n=>n.setTitle("Open in editor (new tab)").setIcon("pencil").onClick(()=>this.cmdOpenInEditor(i))),t&&(t.clientX>0||t.clientY>0))s.showAtMouseEvent(t);else{let o=(t?.target??null)?.getBoundingClientRect();s.showAtPosition({x:o?.left??8,y:(o?.bottom??60)+4})}}renderFocusedHeaderMini(t,e){if(!e.file)return;let i=e.file,s=t.createDiv({cls:"stashpad-focused-mini"});s.dataset.id=e.id,s.createDiv({cls:"stashpad-focused-mini-text"}).setText(this.titleForNode(e).trim());let o=s.createEl("button",{cls:"stashpad-pencil stashpad-focused-mini-pencil"});(0,k.setIcon)(o,"pencil"),o.title="Edit in new tab",o.onclick=r=>{r.stopPropagation(),this.openFileAtEnd(i)}}installFocusedMiniObserver(t){let e=t.querySelector(".stashpad-focused"),i=t.querySelector(".stashpad-focused-mini");!e||!i||(this.focusedMiniObserver&&this.focusedMiniObserver.disconnect(),this.focusedMiniObserver=new IntersectionObserver(s=>{for(let n of s)i.toggleClass("is-visible",!n.isIntersecting)},{root:t,threshold:.05}),this.focusedMiniObserver.observe(e))}renderFocusedHeader(t,e){if(!e.file)return;let i=e.file,s=t.createDiv({cls:"stashpad-focused"}),o=s.createDiv({cls:"stashpad-focused-meta"}).createDiv({cls:"stashpad-focused-meta-top"});o.createSpan({cls:"stashpad-focused-time stashpad-note-time",text:this.formatTime(e.created)}),o.createDiv({cls:"stashpad-focused-grip-spacer"});let r=s.createDiv({cls:"stashpad-focused-body"});r.addEventListener("click",g=>this.handleRenderedClick(g,e));let A=s.createDiv({cls:"stashpad-focused-actions"}),l=A.createEl("button",{cls:"stashpad-pencil stashpad-focused-pencil"});(0,k.setIcon)(l,"pencil"),l.title="Edit in new tab",l.onclick=()=>void this.openFileAtEnd(i);let d=A.createEl("button",{cls:"stashpad-pencil stashpad-focused-dup"});(0,k.setIcon)(d,"copy"),d.title="Open this Stashpad in a new tab (clone)",d.onclick=()=>this.cmdOpenInNewStashpadTab(e),this.renderNoteBody(r,e,{clamp:k.Platform.isMobile,toggleHost:A,toggleAnchor:l})}renderRowBreadcrumb(t,e){let i=this.tree.pathTo(e.id),s=i.findIndex(r=>r.id===this.focusId),n=i.slice(s+1,i.length-1);if(n.length===0)return;let o=t.createDiv({cls:"stashpad-row-breadcrumb"});n.forEach((r,A)=>{let l=o.createSpan({cls:"stashpad-row-breadcrumb-seg",text:this.titleForNode(r)});l.title=`Focus into "${this.titleForNode(r)}"`,l.onclick=d=>{d.stopPropagation(),this.navigateTo(r.id)},A<n.length-1&&o.createSpan({cls:"stashpad-row-breadcrumb-sep",text:" / "})})}actionsForFile(t){return Vi(this.app,t,k.Platform.isMobile)}bulkActionMessage(t){let e=t.nodes.map(r=>`"${this.titleForNode(r).trim()||"(untitled)"}"`),i=t.suffix?` ${t.suffix}`:"",s=t.destination?` ${t.destination}`:"";if(e.length===0)return`${t.verb}${i}${s}`;if(e.length===1)return`${t.verb} ${e[0]}${i}${s}`;let n=t.bulletMax??10,o=e.length<=n?e.map(r=>`\u2022 ${r}`).join(` +Click to override for this tab.`,s&&i.addClass("is-override"),i.onclick=h=>{h.preventDefault(),this.openFolderPicker()};let o=e.createEl("button",{cls:"stashpad-search-btn"});Mt(o,"search","\u{1F50D}"),o.title="Search notes (Mod+F)",o.onclick=h=>{h.preventDefault(),this.openSearchModal()},k.Platform.isMobile?this.renderMobileFiltersButton(e):(this.renderTagFilterDropdown(e),this.renderColorFilterDropdown(e),this.renderSortDropdown(e),this.renderViewDropdown(e));let r=e.createDiv({cls:"stashpad-time-filter-btns"}),A=r.createEl("button",{cls:"stashpad-time-filter-btn stashpad-time-filter-cal"});(0,k.setIcon)(A,this.timeFilterCalendar?"calendar":"history"),A.title=this.timeFilterCalendar?"Calendar mode: filters use start-of-day/week/month/year. Click for rolling windows.":"Rolling mode: filters look back N days from now. Click for calendar boundaries.",this.timeFilterCalendar&&A.addClass("is-active"),A.onclick=h=>{h.preventDefault(),this.timeFilterCalendar=!this.timeFilterCalendar,this.persistFocus(),this.render()};for(let h of Rs){let I=this.timeFilterCalendar?h.calShort:h.rollShort,u=this.timeFilterCalendar?h.calLong:h.rollLong,f=r.createEl("button",{cls:"stashpad-time-filter-btn",text:I});f.title=u,this.timeFilter===h.key&&f.addClass("is-active"),f.onclick=C=>{C.preventDefault(),this.setTimeFilter(h.key)}}let l=e.createEl("select",{cls:"stashpad-time-filter-select"});for(let h of Rs){let I=this.timeFilterCalendar?h.calLong:h.rollLong,u=l.createEl("option",{text:I});u.value=h.key,this.timeFilter===h.key&&(u.selected=!0)}l.onchange=()=>this.setTimeFilter(l.value);let d=e.createDiv({cls:"stashpad-view-mode-btns"});if(!k.Platform.isMobile){let h=d.createEl("button",{cls:"stashpad-view-mode-btn"});(0,k.setIcon)(h,"minimize-2"),h.title="Tiny mode \u2014 open this tab in a small always-on-top-capable popout window.",h.onclick=I=>{I.preventDefault(),this.plugin.openTinyWindow()}}let p=d.createEl("button",{cls:"stashpad-view-mode-btn"});if((0,k.setIcon)(p,this.compactMode?"panel-top":"rows-2"),p.title=this.compactMode?"Compact mode is ON \u2014 click to restore full chrome.":"Compact mode \u2014 hide the filter row + focused header; keep breadcrumb + list + composer.",this.compactMode&&p.addClass("is-active"),p.onclick=h=>{h.preventDefault(),this.toggleCompactMode()},k.Platform.isMobile)return;let g=d.createEl("button",{cls:"stashpad-view-mode-btn"});(0,k.setIcon)(g,"external-link"),g.title=j().popoutDuplicates?"Duplicate this Stashpad tab into a new Obsidian window. (Toggle in Settings \u2192 Open in new window \u2014 duplicate tab.)":"Move this Stashpad tab to a new Obsidian window. (Toggle in Settings \u2192 Open in new window \u2014 duplicate tab.)",g.onclick=h=>{h.preventDefault();let I=j().popoutDuplicates;try{let u=this.app.workspace;if(I){let f=this.leaf.getViewState(),C=u.openPopoutLeaf?.();C?C.setViewState({...f,active:!0}):new k.Notice("Stashpad: this Obsidian build doesn't expose openPopoutLeaf.")}else u.moveLeafToPopout?.(this.leaf)}catch(u){new k.Notice(`Stashpad: open-in-new-window failed (${u.message})`)}}}toggleCompactMode(){this.compactMode=!this.compactMode,this.render();try{this.app.workspace.requestSaveLayout?.()}catch{}}renderActionsCluster(t){let e=t.createDiv({cls:"stashpad-mobile-actions"}),i=e.createEl("button",{cls:"stashpad-mobile-action-btn"});Mt(i,"arrow-left","\u2039");let s=this.navBackStack.length>0||this.focusId!==F;i.title=this.navBackStack.length>0?"Back":this.focusId!==F?"Back (up to parent)":"No back history",s||i.addClass("is-disabled"),i.onclick=d=>{d.preventDefault(),this.navigateBack()};let n=e.createEl("button",{cls:"stashpad-mobile-action-btn"});Mt(n,"arrow-right","\u203A");let o=this.navForwardSnapshots.length>0;n.title=o?"Forward":"No forward history",o||n.addClass("is-disabled"),n.onclick=d=>{d.preventDefault(),this.navigateForward()};let r=e.createEl("button",{cls:"stashpad-mobile-action-btn"}),A=this.mobileSelectMode;Mt(r,A?"check-square":"square",A?"\u2611":"\u2610"),r.title=A?`${this.selection.size} selected \u2014 tap to exit (keeps the first selection)`:"Enter select mode (tap notes to add)",A&&r.addClass("is-active"),r.onclick=d=>{if(d.preventDefault(),this.mobileSelectMode){let p=this.firstSelectedId??this.selection.values().next().value;if(this.selection.clear(),p){let g=this.currentChildren.findIndex(h=>h.id===p);this.selection.add(p),this.lastSelected=p,g>=0&&(this.cursorIdx=g)}this.firstSelectedId=null,this.mobileSelectMode=!1,this.render()}else{let p=this.currentChildren[Math.max(0,this.cursorIdx)];this.mobileSelectMode=!0,this.selection.clear(),p&&(this.selection.add(p.id),this.lastSelected=p.id,this.firstSelectedId=p.id),this.render(),new k.Notice("Select mode: tap notes to add, press \u26A1 for actions")}};let l=e.createEl("button",{cls:"stashpad-mobile-action-btn"});Mt(l,"zap","\u26A1"),l.title="Actions (move, delete, undo, \u2026)",l.onclick=d=>{d.preventDefault(),this.openMobileActionsMenu(l)}}openMobileActionsMenu(t){let e=new k.Menu,i=this.selection.size>0||this.cursorIdx>=0&&!!this.currentChildren[this.cursorIdx],s=this.selection.size<=1;e.addItem(o=>o.setTitle("Undo").setIcon("undo").onClick(()=>this.cmdUndo())),e.addItem(o=>o.setTitle("Redo").setIcon("redo").onClick(()=>this.cmdRedo())),e.addSeparator(),e.addItem(o=>o.setTitle("Notification history\u2026").setIcon("bell").onClick(()=>{this.app.commands?.executeCommandById?.("stashpad:stashpad-open-notification-history")})),e.addItem(o=>o.setTitle("Reload without saving").setIcon("rotate-ccw").onClick(()=>this.plugin.reloadAppForUpdate())),e.addSeparator(),e.addItem(o=>o.setTitle("Expand all").setIcon("unfold-vertical").onClick(()=>this.cmdExpandAll())),e.addItem(o=>o.setTitle("Collapse all").setIcon("fold-vertical").onClick(()=>this.cmdCollapseAll())),e.addSeparator(),e.addItem(o=>o.setTitle("Open in new Stashpad tab").setIcon("list-tree").setDisabled(!i).onClick(()=>this.cmdOpenInNewStashpadTab())),e.addItem(o=>o.setTitle("Open in editor").setIcon("pencil").setDisabled(!i).onClick(()=>this.cmdOpenInEditor())),e.addSeparator(),e.addItem(o=>o.setTitle("Move\u2026").setIcon("arrow-right-circle").setDisabled(!i).onClick(()=>this.cmdMovePicker())),e.addItem(o=>o.setTitle("Nest under\u2026 (in-list)").setIcon("indent").setDisabled(!i).onClick(()=>this.cmdInListPicker())),e.addItem(o=>o.setTitle("Outdent").setIcon("outdent").setDisabled(!i).onClick(()=>void this.cmdOutdent())),e.addItem(o=>o.setTitle("Set color\u2026").setIcon("palette").setDisabled(!i).onClick(()=>this.cmdSetColor())),e.addItem(o=>o.setTitle("Toggle complete").setIcon("check-circle").setDisabled(!i).onClick(()=>void this.cmdToggleComplete())),e.addItem(o=>o.setTitle("Toggle task (todo)").setIcon("check-square").setDisabled(!i).onClick(()=>void this.cmdToggleTask())),e.addItem(o=>o.setTitle("Set due date\u2026").setIcon("calendar-clock").setDisabled(!i).onClick(()=>this.cmdSetDue())),e.addItem(o=>o.setTitle("Assign to\u2026").setIcon("user-plus").setDisabled(!i).onClick(()=>this.cmdAssign())),e.addSeparator(),e.addItem(o=>o.setTitle("Copy").setIcon("copy").setDisabled(!i).onClick(()=>void this.cmdCopy())),e.addItem(o=>o.setTitle("Copy tree").setIcon("copy-plus").setDisabled(!i).onClick(()=>void this.cmdCopyTree())),e.addItem(o=>o.setTitle("Clone (duplicate / copy)").setIcon("files").setDisabled(!i).onClick(()=>void this.cmdClone())),this.plugin.settings.enableSheetVersions&&(e.addItem(o=>o.setTitle("Fork as version").setIcon("git-fork").setDisabled(!i||!s).onClick(()=>void this.cmdForkVersion())),e.addItem(o=>o.setTitle("Mark version as final").setIcon("star").setDisabled(!i||!s).onClick(()=>void this.cmdMarkVersionFinal()))),e.addItem(o=>o.setTitle("Insert template\u2026").setIcon("file-plus-2").onClick(()=>this.cmdInsertTemplate())),e.addItem(o=>o.setTitle("Merge").setIcon("merge").setDisabled(this.selection.size<2).onClick(()=>void this.cmdMerge())),e.addItem(o=>o.setTitle("Split note\u2026").setIcon("scissors").setDisabled(!i||!s).onClick(()=>void this.cmdSplit())),e.addSeparator(),e.addItem(o=>o.setTitle("Delete").setIcon("trash-2").setDisabled(!i).onClick(()=>void this.cmdDelete())),e.addSeparator(),e.addItem(o=>o.setTitle("More commands\u2026").setIcon("terminal").onClick(()=>this.openCommandPalette()));let n=t.getBoundingClientRect();e.showAtPosition({x:n.left,y:n.bottom+4})}openCommandPalette(){this.app.commands?.executeCommandById?.("command-palette:open")}openStashpadCommandPalette(){new Ms(this.app).open()}tagFilterLabel(){return this.tagFilter===ve?"Tagged":this.tagFilter===Fe?"Untagged":this.tagFilter?`#${this.formatTagLabel(this.tagFilter)}`:this.collectFolderTags().length===0?"No tags":"All tags"}renderTagFilterDropdown(t){let e=this.collectFolderTags(),i=t.createDiv({cls:"stashpad-tag-filter-btn"});i.setAttribute("role","button"),i.setAttribute("tabindex","0");let s=i.createSpan({cls:"stashpad-tag-filter-btn-icon"});Mt(s,"tag","#"),i.createSpan({cls:"stashpad-tag-filter-label",text:this.tagFilterLabel()}),e.length===0&&!this.tagFilter&&i.addClass("is-disabled");let n=o=>{o.preventDefault(),!(e.length===0&&!this.tagFilter)&&this.openTagFilterMenu(i)};i.onclick=n,i.onkeydown=o=>{(o.key==="Enter"||o.key===" ")&&n(o)}}openTagFilterMenu(t){let e=t.ownerDocument??document;e.querySelectorAll(".stashpad-tag-filter-popover").forEach(y=>y.remove());let i=e.body.createDiv({cls:"stashpad-tag-filter-popover"}),s=t.getBoundingClientRect();i.setCssStyles({left:`${Math.max(8,s.left)}px`,top:`${s.bottom+4}px`,minWidth:`${Math.max(s.width,200)}px`,maxWidth:"min(320px, calc(100vw - 16px))",width:"max-content"});let n=new k.Scope(this.app.scope),o=()=>{i.remove(),e.removeEventListener("mousedown",r,!0);try{this.app.keymap?.popScope(n)}catch{}},r=y=>{!i.contains(y.target)&&y.target!==t&&!t.contains(y.target)&&o()},A=i.createDiv({cls:"stashpad-tag-filter-search"}),l=A.createSpan({cls:"stashpad-tag-filter-search-icon"});Mt(l,"search","\u2315");let d=A.createEl("input",{type:"text",cls:"stashpad-tag-filter-input",attr:{placeholder:"Filter tags\u2026"}}),p=A.createSpan({cls:"stashpad-tag-filter-clear",attr:{"aria-label":"Clear"}});Mt(p,"x","\xD7"),p.setCssStyles({display:"none"});let g=i.createDiv({cls:"stashpad-tag-filter-list"}),h=this.collectFolderTags(),I=[],u=0,f=y=>{this.setTagFilter(y),o()},C=y=>{if(I.length===0){u=0;return}u=(y+I.length)%I.length,I.forEach((Q,E)=>Q.el.toggleClass("is-highlighted",E===u)),I[u].el.scrollIntoView({block:"nearest"})},B=(y,Q,E,v)=>{let w=g.createDiv({cls:"stashpad-tag-filter-row"});v&&w.addClass("is-active"),w.createSpan({cls:"stashpad-tag-filter-row-label",text:y}),typeof E=="number"&&w.createSpan({cls:"stashpad-tag-filter-row-count",text:String(E)});let D=I.length;I.push({value:Q,el:w}),w.onmousedown=N=>{N.preventDefault(),f(Q)},w.onmouseenter=()=>C(D)},m=()=>{let y=d.value;p.setCssStyles({display:y?"":"none"}),g.empty(),I=[];let Q=this.tagFilter?.toLowerCase();if(y.trim()){let E=Do(y,h);if(E.length===0)g.createDiv({cls:"stashpad-tag-filter-empty",text:"No matching tags"});else for(let v of E)B(`#${v.label}`,v.raw,v.count,Q===v.raw.toLowerCase())}else{B("All tags",null,void 0,!this.tagFilter),B("Tagged",ve,void 0,this.tagFilter===ve),B("Untagged",Fe,void 0,this.tagFilter===Fe);for(let E of h)B(`#${E.label}`,E.raw,E.count,Q===E.raw.toLowerCase())}C(0)};p.onclick=()=>{d.value="",m(),d.focus()},d.addEventListener("input",m),d.addEventListener("keydown",y=>{y.key==="ArrowDown"?(y.preventDefault(),C(u+1)):y.key==="ArrowUp"?(y.preventDefault(),C(u-1)):y.key==="Enter"&&(y.preventDefault(),I[u]&&f(I[u].value))}),n.register([],"Escape",y=>(y.preventDefault(),o(),!1)),this.app.keymap?.pushScope(n),m(),setTimeout(()=>{e.addEventListener("mousedown",r,!0),d.focus()},0)}renderColorFilterDropdown(t){let e=this.collectFolderColors(),i=t.createDiv({cls:"stashpad-color-filter-btn"});i.setAttribute("role","button"),i.setAttribute("tabindex","0"),(()=>{i.empty();let o=i.createSpan({cls:"stashpad-color-filter-swatch"}),r=i.createSpan({cls:"stashpad-color-filter-label"});if(this.colorFilter){let A=this.colorFilter.toLowerCase();o.setCssStyles({background:A});let l=this.plugin.getColorAlias(this.noteFolder,A);r.setText(l??A)}else e.length===0?(o.addClass("is-empty"),r.setText("No colors"),i.addClass("is-disabled")):(o.addClass("is-empty"),r.setText("All colors"))})();let n=o=>{o.preventDefault(),!(e.length===0&&!this.colorFilter)&&this.openColorFilterMenu(i,e)};i.onclick=n,i.onkeydown=o=>{(o.key==="Enter"||o.key===" ")&&n(o)}}openColorFilterMenu(t,e){let i=t.ownerDocument??document;i.querySelectorAll(".stashpad-color-filter-popover").forEach(l=>l.remove());let s=i.body.createDiv({cls:"stashpad-color-filter-popover"}),n=t.getBoundingClientRect();s.setCssStyles({left:`${Math.max(8,n.left)}px`,top:`${n.bottom+4}px`,minWidth:`${n.width}px`,maxWidth:"min(280px, calc(100vw - 16px))",width:"max-content"});let o=new k.Scope(this.app.scope),r=()=>{s.remove(),i.removeEventListener("mousedown",A,!0);try{this.app.keymap?.popScope(o)}catch{}},A=l=>{!s.contains(l.target)&&l.target!==t&&!t.contains(l.target)&&r()};o.register([],"Escape",l=>(l.preventDefault(),r(),!1)),this.app.keymap?.pushScope(o),this.populateColorMenuBody(s,e,r),setTimeout(()=>{i.addEventListener("mousedown",A,!0)},0)}renderSortDropdown(t){let e=this.noteFolder,i=this.focusId,s=this.sortStore.getMode(e,i),n=this.currentViewMode(),o=n!=="nested",r=t.createDiv({cls:"stashpad-sort-btn"});r.setAttribute("role","button"),r.setAttribute("tabindex",o?"-1":"0"),o&&r.addClass("is-disabled");let A=r.createSpan({cls:"stashpad-sort-icon"});(0,k.setIcon)(A,"arrow-up-down");let l=r.createSpan({cls:"stashpad-sort-label"});o?(l.setText("Sort: \u2014"),r.title=`Sort is per-parent and applies only to Nested view. The current view (${Gs[n]}) shows a synthesized flat list sorted by created time \u2014 switch back to Nested to change sort.`):(l.setText(Hi[s]),s!=="manual"&&r.addClass("is-active"),r.title=s==="manual"?"Sort children of this view. Click to change. Drag-reorder always reverts the affected parent to Manual.":`Currently: ${Hi[s]}. Drag-reorder will revert this parent to Manual.`);let d=p=>{o||(p.preventDefault(),this.openSortMenu(r))};r.onclick=d,r.onkeydown=p=>{o||(p.key==="Enter"||p.key===" ")&&d(p)}}openSortMenu(t){let e=t.ownerDocument??document;e.querySelectorAll(".stashpad-sort-popover").forEach(A=>A.remove());let i=e.body.createDiv({cls:"stashpad-sort-popover"}),s=t.getBoundingClientRect();i.setCssStyles({left:`${Math.max(8,s.left)}px`,top:`${s.bottom+4}px`,minWidth:`${s.width}px`,maxWidth:"min(280px, calc(100vw - 16px))",width:"max-content"});let n=()=>{i.remove(),e.removeEventListener("mousedown",o,!0);try{this.app.keymap?.popScope(r)}catch{}},o=A=>{!i.contains(A.target)&&A.target!==t&&!t.contains(A.target)&&n()};this.populateSortMenuBody(i,n);let r=new k.Scope(this.app.scope);r.register([],"Escape",A=>(A.preventDefault(),n(),!1)),this.app.keymap?.pushScope(r),setTimeout(()=>{e.addEventListener("mousedown",o,!0)},0)}renderMobileFiltersButton(t){let e=t.createDiv({cls:"stashpad-mobile-filters-btn"});e.setAttribute("role","button"),e.setAttribute("tabindex","0");let i=e.createSpan({cls:"stashpad-mobile-filters-icon"});(0,k.setIcon)(i,"sliders-horizontal"),e.title="Filters / view options";let s=!!this.tagFilter,n=!!this.colorFilter,o=this.timeFilter!=="all",r=this.sortStore.getMode(this.noteFolder,this.focusId)!=="manual",A=this.currentViewMode()!=="nested"||this.currentHideChildless()||this.currentHideCompleted()||this.currentAttachmentsOnly()||this.currentIncludeAttachments();(s||n||o||r||A)&&e.addClass("is-active");let l=d=>{d.preventDefault(),this.openMobileFiltersMenu(e)};e.onclick=l,e.onkeydown=d=>{(d.key==="Enter"||d.key===" ")&&l(d)}}openMobileFiltersMenu(t){let e=t.ownerDocument??document;e.querySelectorAll(".stashpad-mobile-filters-popover").forEach(g=>g.remove());let i=e.body.createDiv({cls:"stashpad-mobile-filters-popover"}),s=t.getBoundingClientRect(),n=e.defaultView??window;i.setCssStyles({right:`${Math.max(8,n.innerWidth-s.right)}px`,left:"auto",top:`${s.bottom+4}px`,maxWidth:"min(360px, calc(100vw - 16px))",width:"max-content",minWidth:"260px"});let o=()=>{i.remove(),e.removeEventListener("mousedown",r,!0);try{this.app.keymap?.popScope(p)}catch{}},r=g=>{!i.contains(g.target)&&g.target!==t&&!t.contains(g.target)&&o()},A=[{key:"tag",title:"Tag filter",summary:()=>this.tagFilter?`#${this.tagFilter}`:"All tags",populate:g=>this.populateTagMenuBody(g,o)},{key:"color",title:"Color filter",summary:()=>this.colorFilter?this.plugin.getColorAlias(this.noteFolder,this.colorFilter)??this.colorFilter:"All colors",populate:g=>this.populateColorMenuBody(g,this.collectFolderColors(),o)},{key:"time",title:"Time filter",summary:()=>{let g=Rs.find(h=>h.key===this.timeFilter);return g?this.timeFilterCalendar?g.calShort:g.rollShort:"All"},populate:g=>this.populateTimeMenuBody(g,o)},{key:"sort",title:"Sort",summary:()=>this.currentViewMode()!=="nested"?"\u2014 (Nested only)":Hi[this.sortStore.getMode(this.noteFolder,this.focusId)],populate:g=>{if(this.currentViewMode()!=="nested"){g.createDiv({cls:"stashpad-mobile-filters-note",text:"Sort applies only in Nested view."});return}this.populateSortMenuBody(g,o)}},{key:"view",title:"View",summary:()=>Gs[this.currentViewMode()],populate:g=>this.populateViewMenuBody(g,o)}],l="",d=()=>{i.empty();for(let g of A){let h=i.createDiv({cls:"stashpad-mobile-filters-section"}),I=h.createDiv({cls:"stashpad-mobile-filters-header"}),u=I.createSpan({cls:"stashpad-mobile-filters-chev"});if((0,k.setIcon)(u,l===g.key?"chevron-down":"chevron-right"),I.createSpan({cls:"stashpad-mobile-filters-title",text:g.title}),I.createSpan({cls:"stashpad-mobile-filters-summary",text:g.summary()}),I.onclick=f=>{f.preventDefault(),f.stopPropagation(),l=l===g.key?"":g.key,d()},l===g.key){let f=h.createDiv({cls:"stashpad-mobile-filters-body"});g.populate(f)}}};d();let p=new k.Scope(this.app.scope);p.register([],"Escape",g=>(g.preventDefault(),o(),!1)),this.app.keymap?.pushScope(p),setTimeout(()=>{e.addEventListener("mousedown",r,!0)},0)}renderViewDropdown(t){let e=this.currentViewMode(),i=t.createDiv({cls:"stashpad-view-btn"});i.setAttribute("role","button"),i.setAttribute("tabindex","0");let s=i.createSpan({cls:"stashpad-view-icon"});(0,k.setIcon)(s,e==="flat"?"list":e==="everything"?"layout-grid":"list-tree"),i.createSpan({cls:"stashpad-view-label"}).setText(Gs[e]),(e!=="nested"||this.currentEncryptionFilter()!=="all")&&i.addClass("is-active"),i.title=e==="nested"?"View: Nested (the default). Click to switch to Flat or Everything.":e==="flat"?"View: Flat \u2014 all descendants of the current focus, flat by sort order. Drag-reorder is disabled in this mode. Click to change.":"View: Everything \u2014 all descendants of the current focus PLUS non-Stashpad files in the folder, flat by created/ctime. Click to change.";let o=r=>{r.preventDefault(),this.openViewMenu(i)};i.onclick=o,i.onkeydown=r=>{(r.key==="Enter"||r.key===" ")&&o(r)}}openViewMenu(t){let e=t.ownerDocument??document;e.querySelectorAll(".stashpad-view-popover").forEach(A=>A.remove());let i=e.body.createDiv({cls:"stashpad-view-popover"});k.Platform.isMobile&&i.addClass("is-mobile");let s=t.getBoundingClientRect();i.setCssStyles({left:`${Math.max(8,s.left)}px`,top:`${s.bottom+4}px`,minWidth:`${s.width}px`,maxWidth:"min(320px, calc(100vw - 16px))",width:"max-content"});let n=()=>{i.remove(),e.removeEventListener("mousedown",o,!0);try{this.app.keymap?.popScope(r)}catch{}},o=A=>{!i.contains(A.target)&&A.target!==t&&!t.contains(A.target)&&n()};this.populateViewMenuBody(i,n);let r=new k.Scope(this.app.scope);r.register([],"Escape",A=>(A.preventDefault(),n(),!1)),this.app.keymap?.pushScope(r),setTimeout(()=>{e.addEventListener("mousedown",o,!0)},0)}populateViewMenuBody(t,e){let i=this.currentViewMode(),s=(Q,E)=>{let v=t.createDiv({cls:"stashpad-view-popover-row"});Q===i&&v.addClass("is-active"),v.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:Gs[Q]}),v.createDiv({cls:"stashpad-view-popover-desc",text:E}),v.onclick=async D=>{D.preventDefault(),D.stopPropagation(),e(),Q!==i&&(await this.setViewMode(Q),this.render())}};if(s("nested","Tree of immediate children (default)."),s("flat","All descendants of the current focus, flat by sort."),s("everything","All descendants PLUS non-Stashpad files in the folder."),t.createDiv({cls:"stashpad-view-popover-divider"}),this.plugin.encryption?.isConfigured?.()){let Q=this.currentEncryptionFilter(),E=(v,w,D)=>{let N=t.createDiv({cls:"stashpad-view-popover-row"});v===Q&&N.addClass("is-active"),N.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:w}),N.createDiv({cls:"stashpad-view-popover-desc",text:D}),N.onclick=async P=>{P.preventDefault(),P.stopPropagation(),v!==Q&&(await this.setEncryptionFilter(v),this.refreshList()),e()}};E("all","Encryption: show all","Both locked \u{1F512} and decrypted notes."),E("locked","Encryption: locked only","Show only locked \u{1F512} stubs."),E("unlocked","Encryption: decrypted only","Hide locked \u{1F512} stubs."),t.createDiv({cls:"stashpad-view-popover-divider"})}let n=t.createDiv({cls:"stashpad-view-popover-row stashpad-view-popover-toggle"}),o=n.createEl("input",{type:"checkbox"});o.checked=this.currentHideChildless(),n.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:"Hide childless notes"}),n.createDiv({cls:"stashpad-view-popover-desc",text:i==="nested"?"Show only notes that have children. Applied at this level.":"Hide top-level notes without children; keep every parent's full subtree so no task is overlooked."}),n.onclick=async Q=>{Q.target!==o&&(Q.preventDefault(),o.checked=!o.checked),await this.setHideChildless(o.checked),this.refreshList()};let r=t.createDiv({cls:"stashpad-view-popover-row stashpad-view-popover-toggle"}),A=r.createEl("input",{type:"checkbox"});A.checked=this.currentHideCompleted(),r.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:"Hide completed notes"}),r.createDiv({cls:"stashpad-view-popover-desc",text:"Hide notes marked complete. A completed parent stays visible while any descendant is still incomplete."}),r.onclick=async Q=>{Q.target!==A&&(Q.preventDefault(),A.checked=!A.checked),await this.setHideCompleted(A.checked),this.refreshList()};let l=t.createDiv({cls:"stashpad-view-popover-row stashpad-view-popover-toggle"}),d=l.createEl("input",{type:"checkbox"});d.checked=this.currentAttachmentsOnly(),l.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:"Hide notes without attachments"}),l.createDiv({cls:"stashpad-view-popover-desc",text:"Show only notes that have an attachment. A parent stays visible while any descendant has one."}),l.onclick=async Q=>{Q.target!==d&&(Q.preventDefault(),d.checked=!d.checked),await this.setAttachmentsOnly(d.checked),this.refreshList()},t.createDiv({cls:"stashpad-view-popover-divider"});let p=t.createDiv({cls:"stashpad-view-popover-row stashpad-view-popover-toggle"});i!=="everything"&&p.addClass("is-disabled");let g=p.createEl("input",{type:"checkbox"});g.checked=this.currentIncludeAttachments(),g.disabled=i!=="everything",p.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:"Include attachments"}),p.createDiv({cls:"stashpad-view-popover-desc",text:i==="everything"?"Show attachments referenced by notes as their own rows in the file list. Off by default \u2014 they already appear inline on the notes that embed them.":"Only applies in Everything mode."}),p.onclick=async Q=>{i==="everything"&&(Q.target!==g&&(Q.preventDefault(),g.checked=!g.checked),await this.setIncludeAttachments(g.checked),this.refreshList())},t.createDiv({cls:"stashpad-view-popover-divider"});let h=t.createDiv({cls:"stashpad-view-popover-row stashpad-view-popover-toggle"}),I=h.createEl("input",{type:"checkbox"});I.checked=this.importedOnly,h.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:"Imported notes only"}),h.createDiv({cls:"stashpad-view-popover-desc",text:"Show only notes that came in via import."}),h.onclick=Q=>{Q.target!==I&&(Q.preventDefault(),I.checked=!I.checked),this.importedOnly=I.checked,this.reconcileSelectionAfterFilter(),this.refreshList()};let u=new Map,f=this.noteFolder.replace(/\/+$/,"");for(let Q of this.app.vault.getMarkdownFiles()){if((Q.parent?.path?.replace(/\/+$/,"")??"")!==f)continue;let E=re(this.app.metadataCache.getFileCache(Q)?.frontmatter?.author);E&&u.set(E.id,E.name)}let C=t.createDiv({cls:"stashpad-view-popover-row stashpad-view-popover-toggle"}),B=C.createDiv({cls:"stashpad-view-popover-main"});B.createSpan({cls:"stashpad-view-popover-label",text:"By author"});let m=B.createEl("select",{cls:"stashpad-view-author-select"}),y=m.createEl("option",{text:"All authors",value:""});this.authorFilter||(y.selected=!0);for(let[Q,E]of[...u.entries()].sort((v,w)=>v[1].localeCompare(w[1]))){let v=m.createEl("option",{text:E,value:Q});this.authorFilter===Q&&(v.selected=!0)}m.onclick=Q=>Q.stopPropagation(),m.onchange=()=>{this.authorFilter=m.value||null,this.reconcileSelectionAfterFilter(),this.refreshList()},C.createDiv({cls:"stashpad-view-popover-desc",text:u.size?"Show only notes by the chosen author.":"No authored notes in this folder yet."})}setTagFilter(t){(this.tagFilter??null)!==(t??null)&&(this.tagFilter=t,this.reconcileSelectionAfterFilter(),this.persistFocus(),this.render())}populateSortMenuBody(t,e){let i=this.noteFolder,s=this.focusId,n=this.sortStore.getMode(i,s);for(let o of io){let r=t.createDiv({cls:"stashpad-sort-popover-row"});o===n&&r.addClass("is-active"),r.createSpan({cls:"stashpad-sort-popover-label",text:Hi[o]}),r.onclick=async A=>{A.preventDefault(),A.stopPropagation(),e(),o!==n&&(this.sortStore.setMode(i,s,o),await this.sortStore.save(i),this.tree.rebuild(i),this.render())}}}populateTimeMenuBody(t,e){let i=t.createDiv({cls:"stashpad-view-popover-row stashpad-view-popover-toggle"}),s=i.createEl("input",{type:"checkbox"});s.checked=this.timeFilterCalendar,i.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:"Calendar mode"}),i.createDiv({cls:"stashpad-view-popover-desc",text:"Use calendar boundaries (start of today/week/month/year). Off = rolling windows back from now."}),i.onclick=n=>{n.target!==s&&(n.preventDefault(),s.checked=!s.checked),this.timeFilterCalendar=s.checked,this.persistFocus(),this.refreshList()};for(let n of Rs){let o=t.createDiv({cls:"stashpad-sort-popover-row"});this.timeFilter===n.key&&o.addClass("is-active");let r=this.timeFilterCalendar?n.calLong:n.rollLong;o.createSpan({cls:"stashpad-sort-popover-label",text:r}),o.onclick=A=>{A.preventDefault(),A.stopPropagation(),e(),this.timeFilter!==n.key&&this.setTimeFilter(n.key)}}}populateColorMenuBody(t,e,i){let s=(n,o,r)=>{let A=t.createDiv({cls:"stashpad-color-filter-popover-row"}),l=A.createSpan({cls:"stashpad-color-filter-swatch"});o?l.setCssStyles({background:o}):l.addClass("is-empty");let d=A.createSpan({cls:"stashpad-color-filter-popover-label"});d.setText(n),o&&(d.style.color=o),A.onclick=p=>{p.preventDefault(),p.stopPropagation(),r(),i()}};s("All colors",null,()=>this.setColorFilter(null));for(let n of e){let o=this.plugin.getColorAlias(this.noteFolder,n.hex),r=o?`${o} (${n.count})`:`${n.hex} (${n.count})`;s(r,n.hex,()=>this.setColorFilter(n.hex))}}populateTagMenuBody(t,e){let i=this.collectFolderTags(),s=(n,o)=>{let r=t.createDiv({cls:"stashpad-color-filter-popover-row"});r.createSpan({cls:"stashpad-color-filter-swatch is-empty"}),r.createSpan({cls:"stashpad-color-filter-popover-label"}).setText(n),(this.tagFilter??"")===(o??"")&&r.addClass("is-active"),r.onclick=d=>{d.preventDefault(),d.stopPropagation(),this.setTagFilter(o),e()}};s(i.length===0?"No tags":"All tags",null),s("Tagged",ve),s("Untagged",Fe);for(let n of i)s(`${n.label} (${n.count})`,n.raw)}setColorFilter(t){let e=t?t.toLowerCase():null;(this.colorFilter??null)!==e&&(this.colorFilter=e,this.reconcileSelectionAfterFilter(),this.persistFocus(),this.render())}setTimeFilter(t){this.timeFilter!==t&&(this.timeFilter=t,this.reconcileSelectionAfterFilter(),this.persistFocus(),this.render())}reconcileSelectionAfterFilter(){let t=this.filterChildren(this.collectViewItems(this.focusId)),e=new Set(t.map(i=>i.id));for(let i of[...this.selection])e.has(i)||this.selection.delete(i);if(this.firstSelectedId&&!e.has(this.firstSelectedId)&&(this.firstSelectedId=null),this.lastSelected&&!e.has(this.lastSelected)&&(this.lastSelected=null),this.selection.size>0){let i=t.findIndex(s=>this.selection.has(s.id));this.cursorIdx=i>=0?i:Math.min(this.cursorIdx,t.length-1)}else this.cursorIdx>=t.length&&(this.cursorIdx=t.length-1)}renderTinyHeader(t){let e=t.createDiv({cls:"stashpad-tiny-header"}),i=e.createEl("button",{cls:"stashpad-tiny-nav-btn"});Mt(i,"arrow-left","\u2039"),i.title="Back (up to parent)",this.navBackStack.length>0||this.focusId!==F||i.addClass("is-disabled"),i.title=this.navBackStack.length>0?"Back":this.focusId!==F?"Back (up to parent)":"No back history",i.onclick=()=>this.navigateBack();let n=e.createEl("button",{cls:"stashpad-tiny-nav-btn"});Mt(n,"arrow-right","\u203A"),n.title=this.navForwardSnapshots.length>0?"Forward":"No forward history",this.navForwardSnapshots.length===0&&n.addClass("is-disabled"),n.onclick=()=>this.navigateForward();let o=this.tree.get(this.focusId)??this.tree.getRoot(),r=(this.noteFolder.split("/").pop()||this.noteFolder).trim(),A=this.focusId===F?r:`${r} / ${this.titleForNode(o).trim()}`,l=e.createEl("button",{cls:"stashpad-tiny-title stashpad-folder-btn"}),d=l.createSpan({cls:"stashpad-tiny-title-icon stashpad-btn-icon"});(0,k.setIcon)(d,"folder"),l.createSpan({cls:"stashpad-tiny-title-text stashpad-btn-text",text:A}),l.title=`${this.noteFolder}${this.focusId!==F?` / ${this.titleForNode(o).trim()}`:""} +Click to switch / create folder.`,l.onclick=u=>{u.preventDefault(),this.plugin.openFolderPicker()};let p=e.createDiv({cls:"stashpad-tiny-sticky"}),g=p.createEl("input",{type:"checkbox"});if(g.checked=this.tinyAlwaysOnTop,p.createSpan({text:"Sticky"}),g.onchange=()=>{this.tinyAlwaysOnTop=g.checked,this.applyTinyAlwaysOnTop()},!k.Platform.isMobile){let u=e.createEl("button",{cls:"stashpad-tiny-nav-btn stashpad-tiny-opacity-btn"});(0,k.setIcon)(u,"contrast"),u.title="Window transparency",this.tinyOpacity<1&&u.addClass("is-active"),u.onclick=f=>{f.stopPropagation(),this.toggleTinyOpacityPopover(u)}}let h=e.createEl("button",{cls:"stashpad-tiny-expand stashpad-tiny-exit-compact"});(0,k.setIcon)(h,this.compactMode?"panel-top":"rows-2"),h.title=this.compactMode?"Compact mode is ON \u2014 click to turn off.":"Compact mode \u2014 click to turn on (strips row metadata).",this.compactMode&&h.addClass("is-active"),h.onclick=()=>{this.toggleCompactMode()};let I=e.createEl("button",{cls:"stashpad-tiny-expand"});(0,k.setIcon)(I,"maximize-2"),I.title="Exit tiny mode",I.onclick=()=>{this.exitTinyMode()}}toggleTinyOpacityPopover(t){if(this.tinyOpacityPopover){this.tinyOpacityPopover.remove(),this.tinyOpacityPopover=null;return}let e=document.createElement("div");e.className="stashpad-tiny-opacity-popover",e.createSpan({cls:"stashpad-tiny-opacity-label",text:"Transparency"});let i=e.createEl("input",{type:"range"});i.min="30",i.max="100",i.step="1",i.value=String(Math.round(this.tinyOpacity*100));let s=e.createSpan({cls:"stashpad-tiny-opacity-pct",text:`${i.value}%`});i.addEventListener("input",()=>{let d=Math.min(100,Math.max(30,parseInt(i.value,10)||100));this.tinyOpacity=d/100,s.setText(`${d}%`),this.applyTinyOpacity(),t.toggleClass("is-active",this.tinyOpacity<1)}),i.addEventListener("change",()=>{this.app.workspace.requestSaveLayout()}),this.viewRoot.appendChild(e);let n=t.getBoundingClientRect(),o=this.viewRoot.getBoundingClientRect();e.setCssStyles({top:`${n.bottom-o.top+4}px`,left:`${Math.max(4,Math.min(n.left-o.left,o.width-180))}px`});let r=d=>{e.contains(d.target)||d.target===t||t.contains(d.target)||l()},A=d=>{d.key==="Escape"&&l()},l=()=>{e.remove(),this.tinyOpacityPopover=null,document.removeEventListener("mousedown",r,!0),document.removeEventListener("keydown",A,!0)};setTimeout(()=>{document.addEventListener("mousedown",r,!0),document.addEventListener("keydown",A,!0)},0),this.tinyOpacityPopover=e,i.focus()}getOwnElectronWindow(){try{let t=this.containerEl?.ownerDocument?.defaultView??window,s=((t?.require?.("electron")??window.require?.("electron"))?.remote??t?.electron?.remote??t?.["@electron/remote"])?.getCurrentWindow?.()??t?.electronWindow??null;if(!s)try{let n=window.require?.("electron"),o=n?.remote??n?.["@electron/remote"],A=(o?.BrowserWindow??n?.BrowserWindow)?.getAllWindows?.()??[];A.length===1?s=A[0]:A.length>1&&(s=o?.getFocusedWindow?.()??null??A[A.length-1])}catch(n){console.debug("[Stashpad] BrowserWindow.getAllWindows fallback failed",n)}return s||console.debug("[Stashpad] couldn't resolve own electron window"),s??null}catch(t){return console.debug("[Stashpad] resolve own electron window failed",t),null}}applyTinyAlwaysOnTop(){let t=this.getOwnElectronWindow();if(t)try{t.setAlwaysOnTop?.(!!this.tinyAlwaysOnTop)}catch(e){console.debug("[Stashpad] setAlwaysOnTop failed",e)}}applyTinyOpacity(){let t=this.getOwnElectronWindow();if(!t)return;let e=Math.min(1,Math.max(.3,this.tinyOpacity));try{t.setOpacity?.(e)}catch(i){console.debug("[Stashpad] setOpacity failed",i)}}applyTinyWindow(){let t=this.getOwnElectronWindow();if(t)try{if(this.tinyMode){t.setMinimumSize?.(220,260);let s=100,n=100;try{let o=t.getBounds?.();o&&typeof o.x=="number"&&(s=o.x,n=o.y)}catch{}try{t.setBounds?.({x:s,y:n,width:280,height:360})}catch{}try{t.setSize?.(280,360)}catch{}t.setAlwaysOnTop?.(!!this.tinyAlwaysOnTop);try{t.setOpacity?.(Math.min(1,Math.max(.3,this.tinyOpacity)))}catch{}}else t.setAlwaysOnTop?.(!1)}catch(e){console.debug("[Stashpad] tiny window apply failed",e)}}async exitTinyMode(){this.tinyMode=!1,this.tinyAlwaysOnTop=!1,this.tinyOpacity=1;try{this.getOwnElectronWindow()?.setOpacity?.(1)}catch{}this.compactMode=!1,this.applyTinyWindow();let t=this.getOwnElectronWindow();try{if(t?.setMinimumSize?.(400,300),k.Platform.isMacOS??!1){let i=this.containerEl?.ownerDocument?.defaultView?.require?.("electron")??window.require?.("electron"),n=(i?.remote?.screen??i?.screen)?.getPrimaryDisplay?.().workArea;n?t?.setBounds?.({x:n.x,y:n.y,width:n.width,height:n.height}):t?.maximize?.()}else t?.maximize?.()}catch{}this.render();try{await this.app.workspace.requestSaveLayout?.()}catch{}}enterTinyMode(){this.tinyMode=!0,this.applyTinyWindow(),this.render();try{this.app.workspace.requestSaveLayout?.()}catch{}}renderBreadcrumb(t){let e=t.createDiv({cls:"stashpad-breadcrumb"});this.renderActionsCluster(e);let i=e.createSpan({cls:"stashpad-crumb stashpad-crumb-home"});if(k.Platform.isMobile?((0,k.setIcon)(i,"home"),i.title="Home"):i.setText("Home"),i.onclick=()=>this.navigateTo(F),this.focusId===F){let d=this.tree.getChildren(this.focusId).length;if(d>0&&(e.createSpan({cls:"stashpad-crumb-count",text:`\xB7 ${d}`}).title=`${d} direct child${d===1?"":"ren"}`),this.compactMode){let p=e.createEl("button",{cls:"stashpad-compact-exit-btn"});(0,k.setIcon)(p,"panel-top"),p.title="Exit compact mode",p.onclick=g=>{g.preventDefault(),this.toggleCompactMode()}}return}let s=28,n=100,o=this.tree.pathTo(this.focusId),r=o.map(d=>{let p=this.titleForNode(d),g=p.length>s?p.slice(0,s-1)+"\u2026":p;return{id:d.id,label:g}}),A=d=>d.reduce((p,g)=>p+g.label.length+3,0);if(A(r)>n&&r.length>2){let d=!1;for(;A(r)>n&&r.length>2;)r.splice(1,1),d||(r.splice(1,0,{id:"__ellipsis__",label:"\u2026",isEllipsis:!0}),d=!0)}for(let d of r)if(e.createSpan({cls:"stashpad-crumb-sep",text:" / "}),d.isEllipsis)e.createSpan({cls:"stashpad-crumb stashpad-crumb-ellipsis",text:d.label}).title=o.map(p=>this.titleForNode(p)).join(" / ");else{let p=d.id,g=e.createSpan({cls:"stashpad-crumb",text:d.label});g.title=d.label,g.onclick=()=>this.navigateTo(p),g.oncontextmenu=h=>{h.preventDefault(),this.openCrumbMenu(h,p)},k.Platform.isMobile&&this.attachLongPress(g,()=>this.openCrumbMenu(null,p))}if(e.querySelector(".stashpad-crumb-home")?.addEventListener("contextmenu",d=>{d.preventDefault(),this.openCrumbMenu(d,F)}),k.Platform.isMobile){let d=e.querySelector(".stashpad-crumb-home");d&&this.attachLongPress(d,()=>this.openCrumbMenu(null,F))}let l=this.tree.getChildren(this.focusId).length;if(l>0&&(e.createSpan({cls:"stashpad-crumb-count",text:`\xB7 ${l}`}).title=`${l} direct child${l===1?"":"ren"}`),this.compactMode){let d=e.createEl("button",{cls:"stashpad-compact-exit-btn"});(0,k.setIcon)(d,"panel-top"),d.title="Exit compact mode",d.onclick=p=>{p.preventDefault(),this.toggleCompactMode()}}}attachLongPress(t,e){let i=null,s=0,n=0,o=()=>{i!=null&&(window.clearTimeout(i),i=null)};t.addEventListener("touchstart",r=>{let A=r.touches[0];s=A?.clientX??0,n=A?.clientY??0,o(),i=window.setTimeout(()=>{i=null,e()},500)},{passive:!0}),t.addEventListener("touchmove",r=>{let A=r.touches[0];A&&(Math.abs(A.clientX-s)>10||Math.abs(A.clientY-n)>10)&&o()},{passive:!0}),t.addEventListener("touchend",o),t.addEventListener("touchcancel",o)}openCrumbMenu(t,e){let i=this.tree.get(e);if(!i)return;let s=new k.Menu;if(s.addItem(n=>n.setTitle("Navigate here").setIcon("arrow-right-circle").onClick(()=>this.navigateTo(e))),s.addItem(n=>n.setTitle("Open in new Stashpad tab").setIcon("list-tree").onClick(()=>this.cmdOpenInNewStashpadTab(i))),i.file&&s.addItem(n=>n.setTitle("Open in editor (new tab)").setIcon("pencil").onClick(()=>this.cmdOpenInEditor(i))),t&&(t.clientX>0||t.clientY>0))s.showAtMouseEvent(t);else{let o=(t?.target??null)?.getBoundingClientRect();s.showAtPosition({x:o?.left??8,y:(o?.bottom??60)+4})}}renderFocusedHeaderMini(t,e){if(!e.file)return;let i=e.file,s=t.createDiv({cls:"stashpad-focused-mini"});s.dataset.id=e.id,s.createDiv({cls:"stashpad-focused-mini-text"}).setText(this.titleForNode(e).trim());let o=s.createEl("button",{cls:"stashpad-pencil stashpad-focused-mini-pencil"});(0,k.setIcon)(o,"pencil"),o.title="Edit in new tab",o.onclick=r=>{r.stopPropagation(),this.openFileAtEnd(i)}}installFocusedMiniObserver(t){let e=t.querySelector(".stashpad-focused"),i=t.querySelector(".stashpad-focused-mini");!e||!i||(this.focusedMiniObserver&&this.focusedMiniObserver.disconnect(),this.focusedMiniObserver=new IntersectionObserver(s=>{for(let n of s)i.toggleClass("is-visible",!n.isIntersecting)},{root:t,threshold:.05}),this.focusedMiniObserver.observe(e))}renderFocusedHeader(t,e){if(!e.file)return;let i=e.file,s=t.createDiv({cls:"stashpad-focused"}),o=s.createDiv({cls:"stashpad-focused-meta"}).createDiv({cls:"stashpad-focused-meta-top"});o.createSpan({cls:"stashpad-focused-time stashpad-note-time",text:this.formatTime(e.created)}),o.createDiv({cls:"stashpad-focused-grip-spacer"});let r=s.createDiv({cls:"stashpad-focused-body"});r.addEventListener("click",p=>this.handleRenderedClick(p,e));let A=s.createDiv({cls:"stashpad-focused-actions"}),l=A.createEl("button",{cls:"stashpad-pencil stashpad-focused-pencil"});(0,k.setIcon)(l,"pencil"),l.title="Edit in new tab",l.onclick=()=>void this.openFileAtEnd(i);let d=A.createEl("button",{cls:"stashpad-pencil stashpad-focused-dup"});(0,k.setIcon)(d,"copy"),d.title="Open this Stashpad in a new tab (clone)",d.onclick=()=>this.cmdOpenInNewStashpadTab(e),this.renderNoteBody(r,e,{clamp:k.Platform.isMobile,toggleHost:A,toggleAnchor:l})}renderRowBreadcrumb(t,e){let i=this.tree.pathTo(e.id),s=i.findIndex(r=>r.id===this.focusId),n=i.slice(s+1,i.length-1);if(n.length===0)return;let o=t.createDiv({cls:"stashpad-row-breadcrumb"});n.forEach((r,A)=>{let l=o.createSpan({cls:"stashpad-row-breadcrumb-seg",text:this.titleForNode(r)});l.title=`Focus into "${this.titleForNode(r)}"`,l.onclick=d=>{d.stopPropagation(),this.navigateTo(r.id)},A<n.length-1&&o.createSpan({cls:"stashpad-row-breadcrumb-sep",text:" / "})})}actionsForFile(t){return es(this.app,t,k.Platform.isMobile)}bulkActionMessage(t){let e=t.nodes.map(r=>`"${this.titleForNode(r).trim()||"(untitled)"}"`),i=t.suffix?` ${t.suffix}`:"",s=t.destination?` ${t.destination}`:"";if(e.length===0)return`${t.verb}${i}${s}`;if(e.length===1)return`${t.verb} ${e[0]}${i}${s}`;let n=t.bulletMax??10,o=e.length<=n?e.map(r=>`\u2022 ${r}`).join(` `):e.slice(0,n).map(r=>`\u2022 ${r}`).join(` `)+` \u2026+ ${e.length-n} more`;return`${t.verb} ${e.length} notes${i}${s}: -${o}`}titleList(t,e=3){if(!t.length)return"";let i=t.map(n=>this.titleForNode(n).trim()||"(untitled)");return i.length<=e?i.map(n=>`"${n}"`).join(", "):`${i.slice(0,e).map(n=>`"${n}"`).join(", ")}, +${i.length-e} more`}titleForNode(t){if(!t.file)return"Untitled";let i=this.app.metadataCache.getFileCache(t.file)?.headings?.[0]?.heading;return i||t.file.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ")||"Untitled"}async forceManualMode(t){let e=this.noteFolder;this.sortStore.getMode(e,t)!=="manual"&&(this.sortStore.setMode(e,t,"manual"),await this.sortStore.save(e))}renderNote(t,e,i){if(!e.file||this.currentEncryptionFilter()==="locked")return;let s=e.file,n=this.tree.getChildren(e.id).length,o=this.selection.has(e.id),r=i===this.cursorIdx,A=this.inListPicker?.activeIdx===i,l=t.createDiv({cls:"stashpad-note"});o&&l.addClass("is-selected"),r&&l.addClass("is-cursor"),r&&this.plugin.settings.autoExpandCursorRow&&l.addClass("is-cursor-expanded"),A&&l.addClass("is-pick-target"),this.isCompleted(e)&&l.addClass("is-completed"),this.isCutPending(e.id)?l.addClass("is-cut-pending"):this.isCopyPending(e.id)&&l.addClass("is-copy-pending"),l.dataset.idx=String(i),l.dataset.id=e.id;let d=this.currentViewMode()==="nested";l.draggable=d,d&&this.dnd.attachRowDnD(l,e,i),l.addEventListener("click",Q=>this.handleRowClick(Q,i,e)),l.addEventListener("dblclick",Q=>{!this.plugin.settings.doubleClickToFocus||Q.target?.closest?.(".internal-link, .tag, a, .stashpad-note-task-checkbox")||(Q.preventDefault(),window.getSelection()?.removeAllRanges(),this.navigateTo(e.id))});let g=this.isTask(e)||this.compactMode;g&&(l.addClass("is-task"),k.Platform.isMobile||this.addTaskCheckbox(l,e));let p=l.createDiv({cls:"stashpad-note-meta"}),h=p.createDiv({cls:"stashpad-note-meta-top"});h.createSpan({cls:"stashpad-note-time",text:this.formatTime(e.created)});let I=this.colorForNode(e),u=h.createDiv({cls:"stashpad-note-grip"});I&&u.addClass("has-color"),(0,k.setIcon)(u,"grip-vertical"),u.title=I?"Drag to reorder \xB7 right-click to change color":"Drag to reorder",u.draggable=d,d||(u.title=I?"Right-click to change color \xB7 drag disabled in this view mode":"Drag disabled in this view mode"),I&&u.style.setProperty("--stashpad-note-color",I);let f=g&&k.Platform.isMobile;if(n>0||f){let Q=p.createDiv({cls:"stashpad-note-meta-bottom"});if(f&&this.addTaskCheckbox(Q,e),n>0){let E=Q.createSpan({cls:"stashpad-note-enter"});I&&(E.style.color=I),(0,k.setIcon)(E.createSpan({cls:"stashpad-btn-icon"}),"corner-down-right"),E.createSpan({text:` ${n}`}),E.onclick=v=>{v.stopPropagation(),this.navigateTo(e.id)}}}if(I)l.addClass("has-color"),l.style.setProperty("--stashpad-note-color",I);else{let Q=this.inheritedColorForNode(e);Q&&Q.depth>0&&(l.addClass("has-inherited-color"),l.style.setProperty("--stashpad-inherited-color",Q.hex),l.style.setProperty("--stashpad-inherited-depth",String(Q.depth)))}let C=l.createDiv({cls:"stashpad-note-body"});this.currentViewMode()!=="nested"&&this.renderRowBreadcrumb(C,e);let B=C.createDiv({cls:"stashpad-note-body-content"}),m=l.createDiv({cls:"stashpad-note-actions"}),w;if(k.Platform.isMobile){let Q=m.createEl("button",{cls:"stashpad-pencil stashpad-note-more"});(0,k.setIcon)(Q,"ellipsis-vertical"),Q.title="Actions",Q.onclick=E=>{E.stopPropagation(),this.openNoteMenu(E,e)},w=Q}else{let Q=m.createEl("button",{cls:"stashpad-pencil"});(0,k.setIcon)(Q,"pencil"),Q.title="Edit in new tab",Q.onclick=v=>{v.stopPropagation(),this.openFileAtEnd(s)};let E=m.createEl("button",{cls:"stashpad-pencil stashpad-enter-btn"});(0,k.setIcon)(E,"arrow-right"),E.title="Open in Stashpad view",E.onclick=v=>{v.stopPropagation(),this.navigateTo(e.id)},w=Q}this.renderNoteBody(B,e,{clamp:!0,toggleHost:m,toggleAnchor:w}),l.oncontextmenu=Q=>{Q.preventDefault(),this.openNoteMenu(Q,e)}}addTaskCheckbox(t,e){let i=t.createSpan({cls:"stashpad-note-task-checkbox"}),s=this.isCompleted(e);(0,k.setIcon)(i,s?"check-square":"square"),i.title=s?"Mark not done":"Mark done",i.addEventListener("mousedown",n=>n.stopPropagation()),i.addEventListener("dblclick",n=>{n.preventDefault(),n.stopPropagation()}),i.onclick=n=>{n.preventDefault(),n.stopPropagation(),this.toggleCompletedForNode(e)}}renderNoteBody(t,e,i={clamp:!0}){if(!e.file)return;if(this.bodyRenderer.hasFreshRenderCache(e.file)||!this.bodyRenderer.isArmed()){this.renderNoteBodyNow(t,e,i);return}t.empty();let s=t.createDiv({cls:"stashpad-note-text is-plain is-lazy-placeholder"});s.textContent=this.titleForNode(e),this.bodyRenderer.defer(t,()=>this.renderNoteBodyNow(t,e,i))}renderNoteBodyNow(t,e,i={clamp:!0}){if(!e.file)return;let s=e.file,n=(t.__stashpadRenderToken??0)+1;t.__stashpadRenderToken=n,this.bodyRenderer.getOrComputeRender(s).then(o=>{if(t.__stashpadRenderToken!==n)return;let{text:r,attachments:A,html:l}=o;t.empty();let d=t.createDiv({cls:"stashpad-note-text"}),g=this.expandedNotes.has(e.id);if(i.clamp&&!g&&d.addClass("is-clamped"),this.compactMode||this.tinyMode?(d.addClass("is-plain"),d.textContent=r):d.append((0,k.sanitizeHTMLToDom)(l)),A.length>0&&this.renderAttachmentRail(t,A),this.renderAuthorshipFooter(t,e),!i.clamp)return;let p=this.lastListWidth;if(o.ovW===p&&o.ovV!==void 0&&!g){o.ovV?this.attachExpandToggle(i,t,e,g):d.removeClass("is-clamped");return}requestAnimationFrame(()=>{if(t.closest?.(".stashpad-note.is-cursor-expanded"))return;let h=d.scrollHeight>d.clientHeight+4;if(o.ovW=p,o.ovV=h,!h&&!g){d.removeClass("is-clamped");return}this.attachExpandToggle(i,t,e,g)})})}attachExpandToggle(t,e,i,s){let n=!!t.toggleHost,o=t.toggleHost??e;o.querySelector(".stashpad-expand-toggle")?.remove();let r=o.createEl("button",{cls:"stashpad-expand-toggle"});r.title=s?"Show less":"Show more",n||k.Platform.isMobile?((0,k.setIcon)(r,s?"chevron-up":"chevron-down"),r.addClass("is-icon"),n&&r.addClass("is-inline")):r.setText(s?"Show less":"Show more"),t.toggleAnchor&&t.toggleAnchor.parentElement===o&&o.insertBefore(r,t.toggleAnchor),r.onclick=A=>{A.stopPropagation(),this.expandedNotes.has(i.id)?this.expandedNotes.delete(i.id):this.expandedNotes.add(i.id),e.empty(),this.renderNoteBody(e,i,t)}}renderAttachmentRail(t,e){let i=t.createDiv({cls:"stashpad-rail"});for(let s of e){let n=this.app.metadataCache.getFirstLinkpathDest(s,""),o=(s.split(".").pop()??"").toLowerCase(),r=i.createDiv({cls:"stashpad-att"});if(r.title=s,n&&qA.has(o)){let A=r.createEl("img",{cls:"stashpad-att-img"});A.src=this.app.vault.getResourcePath(n),A.alt=s}else{r.createDiv({cls:"stashpad-att-ext",text:o.toUpperCase()||"?"});let A=(s.split("/").pop()??s).replace(/\.[^.]+$/,"");r.createDiv({cls:"stashpad-att-name",text:A})}r.onclick=A=>{A.stopPropagation(),n&&this.app.workspace.getLeaf("tab").openFile(n)}}}renderComposer(t){let e=j(),i=this.modeEnterSubmits,s=this.modeSplit??e.splitOnLines,n=t.createDiv({cls:"stashpad-composer"}),r=n.createDiv({cls:"stashpad-composer-input-wrap"}).createEl("textarea",{cls:"stashpad-composer-input",attr:{rows:"2",placeholder:this.composerPlaceholder(i,s)}});r.value=this.composerDraft,this.debouncedSaveDraft||(this.debouncedSaveDraft=(0,k.debounce)(D=>{this.saveDraft(D)},250)),r.addEventListener("input",()=>{this.composerDraft=r.value,this.debouncedSaveDraft(r.value)}),r.addEventListener("blur",()=>{this.saveDraft(r.value)});let A=null,l=()=>{A||(A=new k.Scope(this.app.scope),A.register([],"Escape",()=>(this.composerExitAt=Date.now(),r.blur(),this.viewRoot?.focus({preventScroll:!0}),!1)),A.register(["Mod"],"z",()=>!0),A.register(["Mod","Shift"],"z",()=>!0),this.app.keymap?.pushScope(A))},d=()=>{if(A){try{this.app.keymap?.popScope(A)}catch{}A=null}};if(r.addEventListener("focus",l),r.addEventListener("blur",d),document.activeElement===r&&l(),k.Platform.isMobile){let D=()=>{this.keyboardTransitionUntil=Date.now()+600};r.addEventListener("focus",()=>{document.body.classList.add("stashpad-keyboard-open"),D()}),r.addEventListener("blur",()=>{document.body.classList.remove("stashpad-keyboard-open"),D(),k.Platform.isMobile&&this.cursorIdx>=0&&setTimeout(()=>this.revealCursorRow(),350)})}this.composerInputEl=r,this.composerAutocomplete&&this.composerAutocomplete.detach(),this.composerAutocomplete=new Je(this.app,r),this.composerAutocomplete.attach();let g=async D=>{let S="";for(let M of D){let U=await this.importAttachment(M);if(!U)continue;let R=r.value+S,W=R&&!R.endsWith(` +${o}`}titleList(t,e=3){if(!t.length)return"";let i=t.map(n=>this.titleForNode(n).trim()||"(untitled)");return i.length<=e?i.map(n=>`"${n}"`).join(", "):`${i.slice(0,e).map(n=>`"${n}"`).join(", ")}, +${i.length-e} more`}titleForNode(t){if(!t.file)return"Untitled";let i=this.app.metadataCache.getFileCache(t.file)?.headings?.[0]?.heading;return i||t.file.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ")||"Untitled"}async forceManualMode(t){let e=this.noteFolder;this.sortStore.getMode(e,t)!=="manual"&&(this.sortStore.setMode(e,t,"manual"),await this.sortStore.save(e))}renderNote(t,e,i){if(!e.file||this.currentEncryptionFilter()==="locked")return;let s=e.file,n=this.tree.getChildren(e.id).length,o=this.selection.has(e.id),r=i===this.cursorIdx,A=this.inListPicker?.activeIdx===i,l=t.createDiv({cls:"stashpad-note"});o&&l.addClass("is-selected"),r&&l.addClass("is-cursor"),r&&this.plugin.settings.autoExpandCursorRow&&l.addClass("is-cursor-expanded"),A&&l.addClass("is-pick-target"),this.isCompleted(e)&&l.addClass("is-completed"),this.isListPinned(e.id)&&l.addClass("is-list-pinned"),this.isCutPending(e.id)?l.addClass("is-cut-pending"):this.isCopyPending(e.id)&&l.addClass("is-copy-pending"),l.dataset.idx=String(i),l.dataset.id=e.id;let d=this.currentViewMode()==="nested";l.draggable=d,d&&this.dnd.attachRowDnD(l,e,i),l.addEventListener("click",E=>this.handleRowClick(E,i,e)),l.addEventListener("dblclick",E=>{!this.plugin.settings.doubleClickToFocus||E.target?.closest?.(".internal-link, .tag, a, .stashpad-note-task-checkbox")||(E.preventDefault(),window.getSelection()?.removeAllRanges(),this.navigateTo(e.id))});let p=this.isTask(e)||this.compactMode;p&&(l.addClass("is-task"),k.Platform.isMobile||this.addTaskCheckbox(l,e));let g=l.createDiv({cls:"stashpad-note-meta"}),h=g.createDiv({cls:"stashpad-note-meta-top"});h.createSpan({cls:"stashpad-note-time",text:this.formatTime(e.created)});let I=this.colorForNode(e),u=h.createDiv({cls:"stashpad-note-grip"});I&&u.addClass("has-color"),(0,k.setIcon)(u,"grip-vertical"),u.title=I?"Drag to reorder \xB7 right-click to change color":"Drag to reorder",u.draggable=d,d||(u.title=I?"Right-click to change color \xB7 drag disabled in this view mode":"Drag disabled in this view mode"),I&&u.style.setProperty("--stashpad-note-color",I);let f=p&&k.Platform.isMobile,C=this.isListPinned(e.id);if(n>0||f||C){let E=g.createDiv({cls:"stashpad-note-meta-bottom"});if(C){let v=E.createSpan({cls:"stashpad-note-listpin"});(0,k.setIcon)(v,"pin"),v.setAttr("aria-label","Pinned to top of list")}if(f&&this.addTaskCheckbox(E,e),n>0){let v=E.createSpan({cls:"stashpad-note-enter"});I&&(v.style.color=I),(0,k.setIcon)(v.createSpan({cls:"stashpad-btn-icon"}),"corner-down-right"),v.createSpan({text:` ${n}`}),v.onclick=w=>{w.stopPropagation(),this.navigateTo(e.id)}}}if(I)l.addClass("has-color"),l.style.setProperty("--stashpad-note-color",I);else{let E=this.inheritedColorForNode(e);E&&E.depth>0&&(l.addClass("has-inherited-color"),l.style.setProperty("--stashpad-inherited-color",E.hex),l.style.setProperty("--stashpad-inherited-depth",String(E.depth)))}let B=l.createDiv({cls:"stashpad-note-body"});this.currentViewMode()!=="nested"&&this.renderRowBreadcrumb(B,e);let m=B.createDiv({cls:"stashpad-note-body-content"}),y=l.createDiv({cls:"stashpad-note-actions"}),Q;if(k.Platform.isMobile){let E=y.createEl("button",{cls:"stashpad-pencil stashpad-note-more"});(0,k.setIcon)(E,"ellipsis-vertical"),E.title="Actions",E.onclick=v=>{v.stopPropagation(),this.openNoteMenu(v,e)},Q=E}else{let E=y.createEl("button",{cls:"stashpad-pencil"});(0,k.setIcon)(E,"pencil"),E.title="Edit in new tab",E.onclick=w=>{w.stopPropagation(),this.openFileAtEnd(s)};let v=y.createEl("button",{cls:"stashpad-pencil stashpad-enter-btn"});(0,k.setIcon)(v,"arrow-right"),v.title="Open in Stashpad view",v.onclick=w=>{w.stopPropagation(),this.navigateTo(e.id)},Q=E}this.renderNoteBody(m,e,{clamp:!0,toggleHost:y,toggleAnchor:Q}),this.renderVersionTabs(B,e),l.oncontextmenu=E=>{E.preventDefault(),this.openNoteMenu(E,e)}}renderVersionTabs(t,e){if(!this.plugin.settings.enableSheetVersions||!Gi(Ct(this.app,e)))return;let i=se(Ct(this.app,e)),s=e.parent??this.focusId,n=this.tree.getChildren(s),o=ro(this.app,n.filter(l=>{let d=Ct(this.app,l);return Gi(d)&&se(d)===i}));if(o.length<2)return;let r=t.createDiv({cls:"stashpad-version-tabs"});for(let l of o){let d=l.id===e.id,p=Ri(Ct(this.app,l)),g=r.createDiv({cls:"stashpad-version-tab"+(d?" is-active":"")+(p?" is-final":"")});p&&g.createSpan({cls:"stashpad-version-star",text:"\u2605"}),g.createSpan({cls:"stashpad-version-tab-label",text:ja(this.app,l,this.titleForNode(l).trim()||"Untitled")}),g.title=this.titleForNode(l).trim(),d||(g.onclick=h=>{h.stopPropagation(),this.setActiveVersion(i,l.id)})}let A=r.createEl("button",{cls:"stashpad-version-add",text:"+"});A.title="New version",A.onclick=l=>{l.stopPropagation(),this.cmdForkVersion(e,!0)}}addTaskCheckbox(t,e){let i=t.createSpan({cls:"stashpad-note-task-checkbox"}),s=this.isCompleted(e);(0,k.setIcon)(i,s?"check-square":"square"),i.title=s?"Mark not done":"Mark done",i.addEventListener("mousedown",n=>n.stopPropagation()),i.addEventListener("dblclick",n=>{n.preventDefault(),n.stopPropagation()}),i.onclick=n=>{n.preventDefault(),n.stopPropagation(),this.toggleCompletedForNode(e)}}renderNoteBody(t,e,i={clamp:!0}){if(!e.file)return;if(this.bodyRenderer.hasFreshRenderCache(e.file)||!this.bodyRenderer.isArmed()){this.renderNoteBodyNow(t,e,i);return}t.empty();let s=t.createDiv({cls:"stashpad-note-text is-plain is-lazy-placeholder"});s.textContent=this.titleForNode(e),this.bodyRenderer.defer(t,()=>this.renderNoteBodyNow(t,e,i))}renderNoteBodyNow(t,e,i={clamp:!0}){if(!e.file)return;let s=e.file,n=(t.__stashpadRenderToken??0)+1;t.__stashpadRenderToken=n,this.bodyRenderer.getOrComputeRender(s).then(o=>{if(t.__stashpadRenderToken!==n)return;let{text:r,attachments:A,html:l}=o;t.empty();let d=t.createDiv({cls:"stashpad-note-text"}),p=this.isNoteExpanded(e.id);if(i.clamp&&!p&&d.addClass("is-clamped"),this.compactMode||this.tinyMode?(d.addClass("is-plain"),d.textContent=r):d.append((0,k.sanitizeHTMLToDom)(l)),A.length>0&&this.renderAttachmentRail(t,A),this.renderAuthorshipFooter(t,e),!i.clamp)return;let g=this.lastListWidth;if(o.ovW===g&&o.ovV!==void 0&&!p){o.ovV?this.attachExpandToggle(i,t,e,p):d.removeClass("is-clamped");return}requestAnimationFrame(()=>{if(t.closest?.(".stashpad-note.is-cursor-expanded"))return;let h=d.scrollHeight>d.clientHeight+4;if(o.ovW=g,o.ovV=h,!h&&!p){d.removeClass("is-clamped");return}this.attachExpandToggle(i,t,e,p)})})}attachExpandToggle(t,e,i,s){let n=!!t.toggleHost,o=t.toggleHost??e;o.querySelector(".stashpad-expand-toggle")?.remove();let r=o.createEl("button",{cls:"stashpad-expand-toggle"});r.title=s?"Show less":"Show more",n||k.Platform.isMobile?((0,k.setIcon)(r,s?"chevron-up":"chevron-down"),r.addClass("is-icon"),n&&r.addClass("is-inline")):r.setText(s?"Show less":"Show more"),t.toggleAnchor&&t.toggleAnchor.parentElement===o&&o.insertBefore(r,t.toggleAnchor),r.onclick=A=>{A.stopPropagation(),this.setNoteExpanded(i.id,!this.isNoteExpanded(i.id)),e.empty(),this.renderNoteBody(e,i,t)}}renderAttachmentRail(t,e){let i=t.createDiv({cls:"stashpad-rail"});for(let s of e){let n=this.app.metadataCache.getFirstLinkpathDest(s,""),o=(s.split(".").pop()??"").toLowerCase(),r=i.createDiv({cls:"stashpad-att"});if(r.title=s,n&&nl.has(o)){let A=r.createEl("img",{cls:"stashpad-att-img"});A.src=this.app.vault.getResourcePath(n),A.alt=s}else{r.createDiv({cls:"stashpad-att-ext",text:o.toUpperCase()||"?"});let A=(s.split("/").pop()??s).replace(/\.[^.]+$/,"");r.createDiv({cls:"stashpad-att-name",text:A})}r.onclick=A=>{A.stopPropagation(),n&&this.app.workspace.getLeaf("tab").openFile(n)}}}renderComposer(t){let e=j(),i=this.modeEnterSubmits,s=this.modeSplit??e.splitOnLines,n=t.createDiv({cls:"stashpad-composer"}),r=n.createDiv({cls:"stashpad-composer-input-wrap"}).createEl("textarea",{cls:"stashpad-composer-input",attr:{rows:"2",placeholder:this.composerPlaceholder(i,s)}});r.value=this.composerDraft,this.debouncedSaveDraft||(this.debouncedSaveDraft=(0,k.debounce)(b=>{this.saveDraft(b)},250)),r.addEventListener("input",()=>{this.composerDraft=r.value,this.debouncedSaveDraft(r.value)}),r.addEventListener("blur",()=>{this.saveDraft(r.value)});let A=null,l=()=>{A||(A=new k.Scope(this.app.scope),A.register([],"Escape",()=>(this.composerExitAt=Date.now(),r.blur(),this.viewRoot?.focus({preventScroll:!0}),!1)),A.register(["Mod"],"z",()=>!0),A.register(["Mod","Shift"],"z",()=>!0),this.app.keymap?.pushScope(A))},d=()=>{if(A){try{this.app.keymap?.popScope(A)}catch{}A=null}};if(r.addEventListener("focus",l),r.addEventListener("blur",d),document.activeElement===r&&l(),k.Platform.isMobile){let b=()=>{this.keyboardTransitionUntil=Date.now()+600};r.addEventListener("focus",()=>{document.body.classList.add("stashpad-keyboard-open"),b()}),r.addEventListener("blur",()=>{document.body.classList.remove("stashpad-keyboard-open"),b(),k.Platform.isMobile&&this.cursorIdx>=0&&setTimeout(()=>this.revealCursorRow(),350)})}this.composerInputEl=r,this.composerAutocomplete&&this.composerAutocomplete.detach(),this.composerAutocomplete=new Ve(this.app,r),this.composerAutocomplete.attach();let p=async b=>{let S="";for(let M of b){let U=await this.importAttachment(M);if(!U)continue;let L=r.value+S,W=L&&!L.endsWith(` `)?` `:"";S+=`${W}${U} -`}S&&(r.value=r.value+S,this.composerDraft=r.value,this.saveDraft(r.value),r.focus(),r.setSelectionRange(r.value.length,r.value.length))};r.addEventListener("dragover",D=>{if(!(!D.dataTransfer||!Array.from(D.dataTransfer.types).includes("Files"))){D.preventDefault(),D.stopPropagation();try{D.dataTransfer.dropEffect="copy"}catch{}}}),r.addEventListener("drop",D=>{let S=Array.from(D.dataTransfer?.files??[]);S.length!==0&&(D.preventDefault(),D.stopPropagation(),g(S))}),r.addEventListener("paste",D=>{let S=this.plugin.noteClipboard;if(S?.mode==="cut"&&S.text&&D.clipboardData?.getData("text/plain")===S.text){if(this.focusedInsideCut(S.ids)){D.preventDefault(),new k.Notice("Can't paste a cut note into the note you're cutting.");return}D.preventDefault(),this.completeCutIntoComposer();return}let M=[],U=D.clipboardData;if(U){for(let R of Array.from(U.files??[]))M.push(R);if(M.length===0){for(let R of Array.from(U.items??[]))if(R.kind==="file"){let W=R.getAsFile();W&&M.push(W)}}M.length!==0&&(D.preventDefault(),D.stopPropagation(),g(M))}});let p=n.createEl("input",{cls:"stashpad-composer-file-input",type:"file",attr:{multiple:"true"}});p.setCssStyles({display:"none"});let h=n.createDiv({cls:"stashpad-composer-btn-rail"}),I=h.createDiv({cls:"stashpad-composer-btn-group"}),u=I.createEl("button",{cls:"stashpad-composer-btn"});(0,k.setIcon)(u,"list-end");let f=je[j().splitMode].toLowerCase();u.title=s?`Split: ON \u2014 ${f} (Mod+/ to toggle, right-click to change)`:`Split into notes (Mod+/) \u2014 right-click to choose: ${f}`,s&&u.addClass("is-active"),u.onmousedown=D=>D.preventDefault(),u.onclick=D=>{D.preventDefault(),this.toggleSplit()},u.oncontextmenu=D=>{D.preventDefault();let S=new k.Menu,M=j().splitMode;["lines","paragraphs","headings"].forEach(U=>{S.addItem(R=>R.setTitle(je[U]).setChecked(U===M).onClick(async()=>{this.plugin.settings.splitMode=U,await this.plugin.saveSettings(),this.render()}))}),S.showAtMouseEvent(D)};let C=I.createEl("button",{cls:"stashpad-composer-btn"});(0,k.setIcon)(C,"map-pin"),this.nextDestination&&C.createSpan({text:` ${this.destinationLabel()}`,cls:"stashpad-btn-text"}),C.title="Set destination (Mod+D)",this.nextDestination&&C.addClass("is-active"),C.onmousedown=D=>D.preventDefault(),C.onclick=D=>{D.preventDefault();let S=document.activeElement===r;this.openDestinationPicker(S)};let B=I.createEl("button",{cls:"stashpad-composer-btn"});(0,k.setIcon)(B,i?"corner-down-left":"arrow-big-down-dash"),B.title=i?"Enter sends (click to switch to Shift+Enter)":"Shift+Enter sends (click to switch to Enter)",B.onmousedown=D=>D.preventDefault(),B.onclick=D=>{D.preventDefault(),this.modeEnterSubmits=!i,this.render(),this.composerInputEl?.focus()};let m=D=>{let S=r.value&&!r.value.endsWith(` +`}S&&(r.value=r.value+S,this.composerDraft=r.value,this.saveDraft(r.value),r.focus(),r.setSelectionRange(r.value.length,r.value.length))};r.addEventListener("dragover",b=>{if(!(!b.dataTransfer||!Array.from(b.dataTransfer.types).includes("Files"))){b.preventDefault(),b.stopPropagation();try{b.dataTransfer.dropEffect="copy"}catch{}}}),r.addEventListener("drop",b=>{let S=Array.from(b.dataTransfer?.files??[]);S.length!==0&&(b.preventDefault(),b.stopPropagation(),p(S))}),r.addEventListener("paste",b=>{let S=this.plugin.noteClipboard;if(S?.mode==="cut"&&S.text&&b.clipboardData?.getData("text/plain")===S.text){if(this.focusedInsideCut(S.ids)){b.preventDefault(),new k.Notice("Can't paste a cut note into the note you're cutting.");return}b.preventDefault(),this.completeCutIntoComposer();return}let M=[],U=b.clipboardData;if(U){for(let L of Array.from(U.files??[]))M.push(L);if(M.length===0){for(let L of Array.from(U.items??[]))if(L.kind==="file"){let W=L.getAsFile();W&&M.push(W)}}M.length!==0&&(b.preventDefault(),b.stopPropagation(),p(M))}});let g=n.createEl("input",{cls:"stashpad-composer-file-input",type:"file",attr:{multiple:"true"}});g.setCssStyles({display:"none"});let h=n.createDiv({cls:"stashpad-composer-btn-rail"}),I=h.createDiv({cls:"stashpad-composer-btn-group"}),u=I.createEl("button",{cls:"stashpad-composer-btn"});(0,k.setIcon)(u,"list-end");let f=ni[j().splitMode].toLowerCase();u.title=s?`Split: ON \u2014 ${f} (Mod+/ to toggle, right-click to change)`:`Split into notes (Mod+/) \u2014 right-click to choose: ${f}`,s&&u.addClass("is-active"),u.onmousedown=b=>b.preventDefault(),u.onclick=b=>{b.preventDefault(),this.toggleSplit()},u.oncontextmenu=b=>{b.preventDefault();let S=new k.Menu,M=j().splitMode;["lines","paragraphs","headings"].forEach(U=>{S.addItem(L=>L.setTitle(ni[U]).setChecked(U===M).onClick(async()=>{this.plugin.settings.splitMode=U,await this.plugin.saveSettings(),this.render()}))}),S.showAtMouseEvent(b)};let C=I.createEl("button",{cls:"stashpad-composer-btn"});(0,k.setIcon)(C,"map-pin"),this.nextDestination&&C.createSpan({text:` ${this.destinationLabel()}`,cls:"stashpad-btn-text"}),C.title="Set destination (Mod+D)",this.nextDestination&&C.addClass("is-active"),C.onmousedown=b=>b.preventDefault(),C.onclick=b=>{b.preventDefault();let S=document.activeElement===r;this.openDestinationPicker(S)};let B=I.createEl("button",{cls:"stashpad-composer-btn"});(0,k.setIcon)(B,i?"corner-down-left":"arrow-big-down-dash"),B.title=i?"Enter sends (click to switch to Shift+Enter)":"Shift+Enter sends (click to switch to Enter)",B.onmousedown=b=>b.preventDefault(),B.onclick=b=>{b.preventDefault(),this.modeEnterSubmits=!i,this.render(),this.composerInputEl?.focus()};let m=b=>{let S=r.value&&!r.value.endsWith(` `)?` -`:"";r.value+=`${S}${D} -`,this.composerDraft=r.value},w=I.createEl("button",{cls:"stashpad-composer-btn"});(0,k.setIcon)(w,"paperclip"),w.title="Attach files",w.onmousedown=D=>D.preventDefault(),w.onclick=D=>{D.preventDefault();let S=document.activeElement===r;if(p.click(),S){let M=()=>{r.focus()};setTimeout(M,100),setTimeout(M,500)}},p.addEventListener("change",async()=>{let D=Array.from(p.files??[]);p.value="";for(let S of D){let M=await this.importAttachment(S);M&&m(M)}r.focus()});let Q=h.createEl("button",{cls:"stashpad-composer-btn stashpad-composer-rail-toggle"});(0,k.setIcon)(Q,"chevron-left"),Q.title="Show more composer options",h.insertBefore(Q,I);let E=D=>{h.toggleClass("is-expanded",D),Q.title=D?"Hide options":"Show more composer options",(0,k.setIcon)(Q,D?"chevron-right":"chevron-left")};Q.onmousedown=D=>D.preventDefault(),Q.onclick=D=>{D.preventDefault(),E(!h.hasClass("is-expanded"))},E(!1);let v=()=>n.clientWidth<700,y=()=>{let D=v();n.toggleClass("is-narrow",D),E(!D)};y(),requestAnimationFrame(y);let b=new ResizeObserver(y);b.observe(n),this.composerNarrowObserver?.disconnect(),this.composerNarrowObserver=b;let N=h.createEl("button",{cls:"stashpad-composer-btn stashpad-composer-send"});N.title="Send (Enter)",(0,k.setIcon)(N,"arrow-up");let P=async()=>{let D=r.value.trim();if(!D)return;r.value="",this.composerDraft="";try{await this.saveDraft("")}catch{}try{await this.recordLastSubmitted(D)}catch{}let S=this.modeSplit??j().splitOnLines,M=this.nextDestination,U=this.nextDestinationFolder,R=!!U&&U!==this.noteFolder;this.nextDestination=null,this.nextDestinationFolder=null,this.nextDestinationLabel=null,this.autoSelectNewest=!R,this.scrollToBottomOnNextRender=!R;let W=R?{targetFolder:U}:void 0,Y=M??this.focusId;if(S){let z=_e(D,j().splitMode);z.length===1?await this.createNoteUnder(z[0],Y,W):z.length>1&&await this.createNotesBatch(z,Y,W,D,R?U:this.noteFolder)}else await this.createNoteUnder(D,Y,W);j().autofocusComposerAfterSend&&(this.focusComposerOnNextRender=!0,R&&this.composerInputEl?.focus())};N.onclick=()=>void P(),r.addEventListener("keydown",D=>{let S=this.modeEnterSubmits;if(D.key==="Escape"){D.preventDefault(),D.stopPropagation(),r.blur(),this.viewRoot.focus({preventScroll:!0});return}if(D.key==="ArrowUp"&&r.selectionStart===0&&r.selectionEnd===0){if(D.preventDefault(),r.blur(),this.viewRoot.focus({preventScroll:!0}),this.currentChildren.length>0){let M=this.lastCursorByFocus.get(this.focusId)??this.lastSelected,U=M?this.currentChildren.findIndex(R=>R.id===M):-1;this.cursorIdx=U>=0?U:this.currentChildren.length-1,this.selectCursor(!1)}return}D.key==="Enter"&&!D.isComposing&&(S?!D.shiftKey:D.shiftKey)&&(D.preventDefault(),D.stopPropagation(),D.stopImmediatePropagation(),P())}),t.createDiv({cls:"stashpad-composer-help"}).setText(this.composerHelperText(i,s))}composerPlaceholder(t,e){return k.Platform.isMobile?e?"New notes (split on newlines)":"New note":`Type a note. ${t?"Enter":"Shift+Enter"} = send, ${t?"Shift+Enter":"Enter"} = newline${e?" (each line \u2192 a note)":""}\u2026`}composerHelperText(t,e){let i=t?"Enter":"Shift+Enter",s=t?"Shift+Enter":"Enter",n=j().bindings,o=g=>{let p=n[g];return p.primary&&p.secondary?p.preferRight?p.secondary:p.primary:p.primary||p.secondary},r=xi(o("toggleSplit")),A=xi(o("pickDestination")),l=xi(o("search")),d=this.nextDestination?` \u2022 destination: ${this.destinationLabel()}`:"";return`${i} sends \xB7 ${s} newline \xB7 ${r} split: ${e?"ON":"off"} \xB7 ${A} destination \xB7 ${l} search${d}`}destinationLabel(){if(!this.nextDestination)return"current";if(this.nextDestinationFolder)return this.nextDestinationLabel??this.nextDestinationFolder;if(this.nextDestination===F)return"Home";let t=this.tree.get(this.nextDestination);return t?this.titleForNode(t).trim():"?"}renderMobileNav(t){let e=t.createDiv({cls:"stashpad-mobile-nav"});e.createEl("button",{text:"Home"}).onclick=()=>this.navigateTo(F),e.createEl("button",{text:"Back"}).onclick=()=>this.navigateUp(),e.createEl("button",{text:"Bookmarks"}).onclick=()=>this.openBookmarks()}handleRenderedClick(t,e){let i=t.target,s=i?.closest?.(".tag");if(s){t.preventDefault(),t.stopPropagation();let r=(s.getAttribute("href")||s.textContent||"").replace(/^#/,"").trim();if(r){let A=this.app.internalPlugins?.plugins?.["global-search"],l=A?.instance?.openGlobalSearch?.bind(A.instance);l&&l(`tag:#${r}`)}return}let n=i?.closest?.(".internal-link");if(n){t.preventDefault(),t.stopPropagation();let o=n.getAttribute("data-href")||n.getAttribute("href");if(o){let r=e.file?.path||"";this.app.workspace.openLinkText(o,r,!0)}}}handleRowClick(t,e,i){let s=t.target,n=s?.closest?.(".tag");if(n){t.preventDefault(),t.stopPropagation();let l=(n.getAttribute("href")||n.textContent||"").replace(/^#/,"").trim();if(l){let d=this.app.internalPlugins?.plugins?.["global-search"],g=d?.instance?.openGlobalSearch?.bind(d.instance);g&&g(`tag:#${l}`)}return}let o=s?.closest?.(".internal-link");if(o){t.preventDefault(),t.stopPropagation();let A=o.getAttribute("data-href")||o.getAttribute("href");if(A){let l=i.file?.path||"";this.app.workspace.openLinkText(A,l,!0)}return}if(s?.tagName==="A"&&s.href)return;if(t.stopPropagation(),this.inListPicker){this.inListPicker.activeIdx=e,this.commitInListPicker();return}let r=this.selection.size===0;if(t.shiftKey&&this.lastSelected){this.cursorIdx=e;let A=this.currentChildren.findIndex(l=>l.id===this.lastSelected);if(r&&(this.firstSelectedId=this.lastSelected),A!==-1){let[l,d]=A<e?[A,e]:[e,A];for(let g=l;g<=d;g++)this.selection.add(this.currentChildren[g].id)}else this.selection.add(i.id)}else if(t.metaKey||t.ctrlKey)if(this.selection.has(i.id))if(this.selection.delete(i.id),this.firstSelectedId===i.id&&(this.firstSelectedId=null),this.lastSelected===i.id&&(this.lastSelected=this.selection.size>0?[...this.selection][this.selection.size-1]:null),this.selection.size===0)this.cursorIdx=-1;else{let A=this.lastSelected??[...this.selection][this.selection.size-1],l=A?this.currentChildren.findIndex(d=>d.id===A):-1;l>=0&&(this.cursorIdx=l)}else this.cursorIdx=e,r&&(this.firstSelectedId=i.id),this.selection.add(i.id);else this.mobileSelectMode?(this.cursorIdx=e,this.selection.has(i.id)?(this.selection.delete(i.id),this.firstSelectedId===i.id&&(this.firstSelectedId=null)):this.selection.add(i.id)):(this.cursorIdx=e,this.selection.clear(),this.selection.add(i.id),this.firstSelectedId=i.id,this.lastSelected=i.id);this.selection.size===0&&(this.firstSelectedId=null),this.selection.has(i.id)&&(this.lastSelected=i.id),this.viewRoot.focus({preventScroll:!0}),this.repaintSelectionClasses(),this.revealCursorRow(),this.stampSelectedCursor(),this.plugin.notifyStashpadSelectionChanged()}revealCursorRow(){let t=()=>{if(this.cursorIdx<0)return;let e=this.listEl?.querySelector(`[data-idx="${this.cursorIdx}"]`);if(!e||!this.listEl)return;let i=this.listEl,s=i.getBoundingClientRect(),n=e.getBoundingClientRect(),o=4,r=s.top+o,A=s.bottom-o;if(k.Platform.isMobile&&document.body.classList.contains("stashpad-keyboard-open")){let l=this.viewRoot?.querySelector(".stashpad-composer");l&&(A=Math.min(A,l.getBoundingClientRect().top-o))}n.top<r?i.scrollTop+=n.top-r:n.bottom>A&&(i.scrollTop+=n.bottom-A)};t(),requestAnimationFrame(t),setTimeout(t,60),setTimeout(t,200)}jumpToTop(){this.currentChildren.length!==0&&(this.cursorIdx=0,this.selectCursor(!1))}jumpToBottom(){this.currentChildren.length!==0&&(this.cursorIdx=this.currentChildren.length-1,this.selectCursor(!1))}selectCursor(t){let e=this.currentChildren[this.cursorIdx];if(e){if(!t)this.selection.clear(),this.selection.add(e.id),this.firstSelectedId=e.id,this.lastSelected=e.id;else{let i=this.firstSelectedId??e.id,s=this.currentChildren.findIndex(n=>n.id===i);if(s===-1)this.selection.add(e.id),this.firstSelectedId=e.id;else{let[n,o]=s<this.cursorIdx?[s,this.cursorIdx]:[this.cursorIdx,s];this.selection.clear();for(let r=n;r<=o;r++)this.selection.add(this.currentChildren[r].id);this.firstSelectedId=i}this.lastSelected=e.id}this.repaintSelectionClasses(),this.revealCursorRow(),this.stampSelectedCursor(),this.plugin.notifyStashpadSelectionChanged()}}repaintSelectionClasses(){if(!this.listEl)return;let t=!!this.plugin.settings.autoExpandCursorRow,e=this.inListPicker?.activeIdx??-1;this.listEl.querySelectorAll(".stashpad-note").forEach(s=>{let n=Number(s.dataset.idx),o=s.dataset.id??"",r=n===this.cursorIdx;s.classList.toggle("is-cursor",r),s.classList.toggle("is-selected",this.selection.has(o)),s.classList.toggle("is-cursor-expanded",t&&r),s.classList.toggle("is-pick-target",n===e)})}revealRowAt(t){if(!this.listEl)return;let e=this.listEl.querySelector(`.stashpad-note[data-idx="${t}"]`);if(!e)return;let i=e.getBoundingClientRect(),s=this.listEl.getBoundingClientRect();(i.top<s.top||i.bottom>s.bottom)&&e.scrollIntoView({block:"nearest",behavior:"auto"})}getActionTargets(){if(this.selection.size>0)return[...this.selection].map(e=>this.tree.get(e)).filter(e=>!!e&&!!e.file);let t=this.currentChildren[this.cursorIdx];return t?[t]:[]}async cmdLockSelection(){if(!this.plugin.encryption?.isConfigured?.()){new k.Notice("Set up encryption first (Settings \u2192 Encryption).");return}let t=this.getActionTargets();if(t.length===0)return;let e=new Set(t.map(o=>o.id)),i=new Set((this.plugin.settings.lockedSubtrees??[]).map(o=>o.rootId).filter(o=>!!o)),s=t.filter(o=>{if(i.has(o.id))return!1;let r=o.parent;for(;r;){if(e.has(r))return!1;r=this.tree.get(r)?.parent??null}return!0});if(s.length===0){new k.Notice("Nothing to lock (already locked).");return}let n=0;for(let o of s){let r=this.order.getOrder(this.noteFolder,o.parent??F),A=r.indexOf(o.id),l=A>0?r[A-1]:null;await this.plugin.lockNoteSubtree(this.noteFolder,o.id,l,{silent:!0})&&n++}n>0&&(this.selection.clear(),this.lastSelected=null,this.render(),this.plugin.notifications.show({message:`Locked ${n} stash${n===1?"":"es"}.`,kind:"success",category:"system",folder:this.noteFolder}))}async cmdMoveToArchive(){if(!this.plugin.encryption?.isConfigured?.()){new k.Notice("Set up encryption first (Settings \u2192 Encryption).");return}let t=(this.plugin.settings.archiveFolders??[]).filter(o=>o!==this.noteFolder);if(t.length===0){new k.Notice("No archive folder available. Mark a folder as archive first (folder panel \u2192 right-click \u2192 \u201CMark as archive\u201D).",8e3);return}let e=this.getActionTargets();if(e.length===0)return;let i=this.plugin.settings.defaultArchiveFolder,s=i&&t.includes(i)?i:t.length===1?t[0]:null,n=o=>{this.archiveSources(e,o)};if(s){n(s);return}new eo(this.app,t,n).open()}async archiveSources(t,e){let i=this.noteFolder,s=new Set(t.map(l=>l.id)),n=t.filter(l=>{let d=l.parent;for(;d;){if(s.has(d))return!1;d=this.tree.get(d)?.parent??null}return!0});if(n.length===0)return;let o=n.map(l=>l.id),r=[];for(let l of n){let d=this.order.getOrder(i,l.parent??F),g=d.indexOf(l.id),p=g>0?d[g-1]:null,h=await this.plugin.lockNoteSubtree(i,l.id,p,{silent:!0,blobFolder:e});h&&r.push(h.blobPath)}if(r.length===0)return;this.selection.clear(),this.lastSelected=null,this.tree.rebuild(i),this.render();let A=e.split("/").pop()||e;this.plugin.notifications.show({message:`Archived ${r.length} note${r.length===1?"":"s"} \u2192 \u201C${A}\u201D. Undo to bring ${r.length===1?"it":"them"} back.`,kind:"success",category:"system",folder:i}),this.plugin.getUndoStack(i).push({label:`Archive (${r.length})`,undo:async()=>{for(let l of r)try{await this.plugin.unlockBundleAt(l,{silent:!0,destFolder:i})}catch(d){console.warn("[Stashpad] archive undo failed",l,d)}r=[],this.tree.rebuild(i),this.render()},redo:async()=>{r=[];for(let l of o){let d=await this.plugin.lockNoteSubtree(i,l,null,{silent:!0,blobFolder:e});d&&r.push(d.blobPath)}this.tree.rebuild(i),this.render()}})}async cmdEncryptDelete(){if(!this.plugin.encryption?.isConfigured?.()){new k.Notice("Set up encryption first (Settings \u2192 Encryption).");return}let t=this.getActionTargets();if(t.length===0)return;let e=new Set(t.map(n=>n.id)),i=t.filter(n=>{let o=n.parent;for(;o;){if(e.has(o))return!1;o=this.tree.get(o)?.parent??null}return!0});if(i.length===0)return;let s=i.length;new gt(this.app,`Encrypt & delete ${s} note${s===1?"":"s"}?`,[`The selected note${s===1?"":"s"} (and any children) will be encrypted and moved to Stashpad's encrypted trash.`,"","\u2022 The readable copy is permanently removed from the folder.",`\u2022 You can restore ${s===1?"it":"them"} later from the encrypted trash \u2014 you'll need your encryption password.`,`\u2022 If you lose your password, ${s===1?"it's":"they're"} gone for good.`].join(` -`),"Encrypt & delete",async n=>{n&&await this.secureDeleteSources(i)}).open()}async secureDeleteSources(t){if(!this.plugin.encryption?.isConfigured?.()){new k.Notice("Set up encryption first (Settings \u2192 Encryption).");return}let e=new Set(t.map(r=>r.id)),i=t.filter(r=>{let A=r.parent;for(;A;){if(e.has(A))return!1;A=this.tree.get(A)?.parent??null}return!0});if(i.length===0)return;let s=this.noteFolder,n=i.map(r=>r.id),o=[];for(let r of n){let A=await this.plugin.encryptDeleteSubtree(s,r);A&&o.push(A)}o.length!==0&&(this.selection.clear(),this.lastSelected=null,this.tree.rebuild(s),this.render(),this.plugin.notifications.show({message:`Securely deleted ${o.length} note${o.length===1?"":"s"} \u2192 encrypted trash. Undo to bring ${o.length===1?"it":"them"} back.`,kind:"success",category:"system",folder:s}),this.plugin.getUndoStack(s).push({label:`Secure delete (${o.length})`,undo:async()=>{for(let r of o)try{await this.plugin.restoreDeletedAt(r,{silent:!0})}catch(A){console.warn("[Stashpad] secure-delete undo failed",r,A)}o=[],this.tree.rebuild(s),this.render()},redo:async()=>{o=[];for(let r of n){let A=await this.plugin.encryptDeleteSubtree(s,r);A&&o.push(A)}this.tree.rebuild(s),this.render()}}))}async cmdUnlockAll(){if(!this.plugin.encryption?.isConfigured?.()){new k.Notice("Set up encryption first (Settings \u2192 Encryption).");return}let t=new Set,e=new Set,i=this.getActionTargets().map(n=>n.id);for(;i.length;){let n=i.pop();if(!e.has(n)){e.add(n);for(let o of this.tree.getChildren(n))i.push(o.id)}}for(let n of e)for(let o of this.plugin.lockedSubtreesFor(this.noteFolder,n))t.add(o.blob);if(t.size===0){let n=(this.tree.get(this.focusId)??this.tree.getRoot()).id;for(let o of this.plugin.lockedSubtreesFor(this.noteFolder,n))t.add(o.blob)}if(t.size===0){new k.Notice("No locked notes to unlock here.");return}if(!await this.plugin.ensureEncryptionUnlocked())return;let s=0;for(let n of t)try{await this.plugin.unlockBundleAt(n,{silent:!0})&&s++}catch(o){console.warn("[Stashpad] batch unlock skipped",n,o)}s>0&&(this.selection.clear(),this.lastSelected=null,this.render(),this.plugin.notifications.show({message:`Unlocked ${s} stash${s===1?"":"es"}.`,kind:"success",category:"system",folder:this.noteFolder}))}toggleSplit(){let t=this.modeSplit??j().splitOnLines;this.modeSplit=!t,this.render(),this.composerInputEl?.focus()}openDestinationPicker(t=!1){let e=!1;new te(this.app,this.tree,i=>this.titleForNode(i),{mode:"pick",placeholder:"Send next note(s) under which note?",allowCreate:!0,onPick:async i=>{if(e=!0,i.crossFolder){let s=i.crossId??i.id.replace(/^cross:/,"");this.nextDestination=s,this.nextDestinationFolder=i.crossFolder;let n=i.crossFolder.split("/").pop()||i.crossFolder,o=s===F?"Home":(i.crossFile?.basename??"note").replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ");this.nextDestinationLabel=`${n} \u25B8 ${o}`,this.render(),this.composerInputEl?.focus();return}this.nextDestination=i.id,this.nextDestinationFolder=null,this.nextDestinationLabel=null,this.render(),this.composerInputEl?.focus()},onCreate:async i=>{e=!0;let s=await this.createNoteUnder(i,this.focusId);s&&(this.nextDestination=s,this.nextDestinationFolder=null,this.nextDestinationLabel=null,this.render(),this.composerInputEl?.focus())},crossFolderNotes:()=>this.collectCrossFolderDestinations(),excludedFolderNotes:this.excludedSearchFolders().length>0?()=>this.collectExcludedFolderNotes():void 0,onClose:()=>{t&&!e&&this.composerInputEl?.focus()}}).open()}collectCrossFolderDestinations(){let t=this.collectCrossFolderNotes(),e=this.plugin.searchableFolders(this.noteFolder).filter(n=>n!==this.noteFolder),i=new Map;for(let n of this.app.vault.getMarkdownFiles()){let o=n.parent?.path?.replace(/\/+$/,"")??"";if(!e.includes(o))continue;this.app.metadataCache.getFileCache(n)?.frontmatter?.id===F&&i.set(o,n)}return[...e.map(n=>({file:i.get(n),folder:n,id:F,title:`Home \u2014 ${n.split("/").pop()||n}`,body:""})),...t]}openSearchInParentModal(){let t=this.focusId,e=s=>{if(s===t)return!0;let n=new Set,o=this.tree.get(s);for(;o&&o.id!==F&&!n.has(o.id);){if(n.add(o.id),o.parent===t||o.id===t)return!0;if(!o.parent)return!1;o=this.tree.get(o.parent)}return t===F},i=new Proxy(this.tree,{get:(s,n)=>n==="getRoot"?()=>s.get(t)??s.getRoot():n==="getChildren"?o=>s.getChildren(o):s[n]});new te(this.app,i,s=>this.titleForNode(s),{mode:"search",placeholder:`Search in "${this.titleForNode(this.tree.get(t)??this.tree.getRoot()).trim()}"\u2026`,allowCreate:!1,onPick:s=>{s.node&&e(s.node.id)?this.navigateTo(s.node.id):s.node&&this.navigateTo(s.node.id)}}).open()}openSearchModal(){if(this.openSearchInstance){let i=this.openSearchInstance.inputEl;i&&(i.focus(),i.select());return}let t=new te(this.app,this.tree,i=>this.titleForNode(i),{mode:"search",placeholder:"Search Stashpad notes\u2026",allowCreate:!0,onCreate:async i=>{let s=i.trim();s&&new te(this.app,this.tree,n=>this.titleForNode(n),{mode:"pick",placeholder:`Create "${s}" under which note?`,allowCreate:!1,crossFolderNotes:()=>this.collectCrossFolderDestinations(),excludedFolderNotes:this.excludedSearchFolders().length>0?()=>this.collectExcludedFolderNotes():void 0,folderResults:()=>this.plugin.discoverStashpadFolders().filter(n=>n!==this.noteFolder),localFolder:this.noteFolder,onPick:async n=>{let o=n.crossFolder?n.crossId??n.id.replace(/^cross:/,""):n.node?.id,r=n.crossFolder??this.noteFolder;if(!o)return;let A=(this.plugin.settings.folder||"Stashpad").trim().replace(/^\/+|\/+$/g,"")||"Stashpad",l=this.app.workspace,d=l.getLeaf("tab");await d.setViewState({type:J,active:!0,state:{focusId:o,folderOverride:r===A?null:r}}),l.revealLeaf(d);let g=d.view;if(g&&typeof g.createNoteUnder=="function"){let p=await g.createNoteUnder(s,o);p&&typeof g.navigateTo=="function"&&g.navigateTo(p)}}}).open()},onPick:i=>{if(i.kind==="folder-open"&&i.folder){this.openFolderInNewTab(i.folder);return}let s=this.plugin.settings.searchOpensInNewTab!==!1;if(i.crossFolder&&i.crossFile){let n=i.crossId??i.id.replace(/^cross:/,"");s?this.openNoteInNewTab(i.crossFolder,n):this.switchToFolderAndFocus(i.crossFolder,n);return}i.node&&(s?this.openNoteInNewTab(this.noteFolder,i.node.id):this.navigateTo(i.node.id))},crossFolderNotes:()=>this.collectCrossFolderDestinations(),excludedFolderNotes:this.excludedSearchFolders().length>0?()=>this.collectExcludedFolderNotes():void 0,folderResults:()=>this.plugin.discoverStashpadFolders().filter(i=>i!==this.noteFolder),showFilterChips:!0,localFolder:this.noteFolder});this.openSearchInstance=t;let e=t.onClose.bind(t);t.onClose=()=>{e(),this.openSearchInstance===t&&(this.openSearchInstance=null)},t.open()}excludedSearchFolders(){let t=new Set(this.plugin.searchableFolders(this.noteFolder));return this.plugin.discoverStashpadFolders().filter(e=>e!==this.noteFolder&&!t.has(e))}collectExcludedFolderNotes(){let t=this.excludedSearchFolders();if(!t.length)return[];let e=this.collectCrossFolderNotes(t),i=new Map;for(let n of this.app.vault.getMarkdownFiles()){let o=n.parent?.path?.replace(/\/+$/,"")??"";if(!t.includes(o))continue;this.app.metadataCache.getFileCache(n)?.frontmatter?.id===F&&i.set(o,n)}return[...t.map(n=>({file:i.get(n),folder:n,id:F,title:`Home \u2014 ${n.split("/").pop()||n}`,body:""})),...e]}collectCrossFolderNotes(t){let e=[],i=(t??this.plugin.searchableFolders(this.noteFolder)).filter(o=>o!==this.noteFolder);if(!i.length)return e;let s=new Set(i),n=new Map;for(let o of this.app.vault.getMarkdownFiles()){let r=o.parent?.path?.replace(/\/+$/,"")??"";if(!s.has(r))continue;let A=n.get(r);A||(A=[],n.set(r,A)),A.push(o)}for(let o of i){let r=n.get(o)??[],A=new Map;for(let l of r){let d=this.app.metadataCache.getFileCache(l)?.frontmatter;typeof d?.id=="string"&&A.set(d.id,l)}for(let l of r){let d=this.app.metadataCache.getFileCache(l)?.frontmatter,g=typeof d?.id=="string"?d.id:"";if(!g||g===F)continue;let p=l.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," "),h,I=d?.parent??null;if(I&&I!==F){let u=A.get(I);u&&(h=u.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," "))}e.push({file:l,folder:o,id:g,title:p,body:"",parentBlurb:h,parentId:I??null})}}return e}async switchToFolderAndFocus(t,e){await this.setFolderOverride(t),this.tree.get(e)&&this.navigateTo(e)}async cmdOutdent(){let t=this.getActionTargets();if(!t.length)return;let e=[],i=[];for(let s of t){let n=s.parent?this.tree.get(s.parent):null;if(!n||n.id===F){i.push(s.id);continue}let o=n.parent??F;await this.changeParent(s,o),e.push(s)}if(e.length===0){new k.Notice(i.length?"Already at the top level.":"Nothing to outdent.");return}if(this.render(),i.length&&this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Outdented",nodes:e,suffix:i.length?`(${i.length} already at root)`:void 0}),kind:"success",category:"move",affectedIds:e.map(s=>s.id),folder:this.noteFolder}),this.plugin.settings.autoNavOnMoveOut&&e.length>0){let s=e[0].parent;s!=null&&e.every(o=>o.parent===s)&&s!==this.focusId&&this.navigateTo(s)}}cmdSetColor(){let t=this.getActionTargets();if(!t.length)return;let e=new Set(t.map(n=>this.colorForNode(n)??"")),i=e.size===1&&Array.from(e)[0]||null,s=this.plugin.settings.customPalette??[];new Ee(this.app,i,s,async(n,o)=>{let r=[];for(let g of t)if(g.file){r.push({id:g.id,path:g.file.path,was:this.colorForNode(g)??null});try{await this.app.fileManager.processFrontMatter(g.file,p=>{n?p.color=n:delete p.color})}catch(p){new k.Notice(`Couldn't set color for ${g.id}: ${p.message}`)}}if(o.addToPalette&&typeof n=="string"){let g=[...this.plugin.settings.customPalette??[]],p=n.toLowerCase();g.some(h=>h.toLowerCase()===p)||(g.push(n),this.plugin.settings.customPalette=g,await this.plugin.persistSettingsQuiet(),await this.log.append({type:"palette_color_add",id:F,payload:{color:n}}))}this.render();let A=this.noteFolder,l=n,d=async g=>{for(let p of g){let h=this.app.vault.getAbstractFileByPath(p.path);if(h)try{await this.app.fileManager.processFrontMatter(h,I=>{p.col?I.color=p.col:delete I.color})}catch{}}this.tree.rebuild(A),this.render()};this.plugin.getUndoStack(A).push({label:r.length===1?"Color change":`Color change (${r.length})`,undo:()=>d(r.map(g=>({path:g.path,col:g.was}))),redo:()=>d(r.map(g=>({path:g.path,col:l})))})},async n=>{let o=(this.plugin.settings.customPalette??[]).filter(r=>r.toLowerCase()!==n.toLowerCase());return this.plugin.settings.customPalette=o,await this.plugin.persistSettingsQuiet(),await this.log.append({type:"palette_color_remove",id:F,payload:{color:n}}),o}).open()}cmdMovePicker(){let t=this.getActionTargets();t.length&&new te(this.app,this.tree,e=>this.titleForNode(e),{mode:"pick",placeholder:"Move to which note?",allowCreate:!0,onPick:async e=>{if(e.crossFolder){let o=e.crossId??e.id.replace(/^cross:/,"");await this.moveAcrossFolders(t,e.crossFolder,o),this.selection.clear(),this.render();return}let i=e.id,s=new Map(t.map(o=>[o.id,this.tree.getChildren(o.id).length])),n=[];for(let o of t)await this.changeParent(o,i,{silentSuccess:!0})&&n.push(o);this.notifyBatchMove(n,i,s),this.selection.clear(),this.render(),this.plugin.settings.autoNavOnMoveOut&&i!==this.focusId&&this.navigateTo(i)},onCreate:async e=>{let i=await this.createNoteUnder(e,this.focusId);if(!i)return;let s=new Map(t.map(o=>[o.id,this.tree.getChildren(o.id).length])),n=[];for(let o of t)await this.changeParent(o,i,{silentSuccess:!0})&&n.push(o);this.notifyBatchMove(n,i,s),this.selection.clear(),this.render(),this.plugin.settings.autoNavOnMoveOut&&this.navigateTo(i)},crossFolderNotes:()=>this.collectCrossFolderDestinations(),excludedFolderNotes:this.excludedSearchFolders().length>0?()=>this.collectExcludedFolderNotes():void 0,showFilterChips:!0}).open()}async moveAcrossFolders(t,e,i){if(!t.length)return;let s=(e||"").replace(/\/+$/,"");if(!s){new k.Notice("Target folder is empty");return}let n=[],o=new Set;for(let p of this.app.vault.getMarkdownFiles())(p.parent?.path?.replace(/\/+$/,"")??"")===s&&o.add(p.path);let r=(p,h)=>{if(!p.file)return;let I=p.file,u=`${s}/${I.name}`;if(o.has(u)){let f=I.basename.match(/^(.*)(-[a-z0-9]{4,12})$/),C=f?f[1]:I.basename,B=f?f[2]:"";for(let m=1;m<1e3;m++){let w=`${C}-${m}${B}.md`,Q=`${s}/${w}`;if(!o.has(Q)){u=Q;break}}}o.add(u),n.push({id:p.id,file:I,oldPath:I.path,newPath:u,oldParent:p.parent,isRoot:h});for(let f of this.tree.getChildren(p.id))r(f,!1)};for(let p of t)r(p,!0);if(!n.length)return;await this.ensureFolder(s);for(let p of n)try{await this.app.fileManager.renameFile(p.file,p.newPath),p.isRoot&&await this.app.fileManager.processFrontMatter(p.file,h=>{h.parent=i}),await this.log.append({type:"parent_change",id:p.id,payload:{from:p.oldParent,to:p.isRoot?i:p.oldParent,crossFolder:{from:this.noteFolder,to:s}}})}catch(h){new k.Notice(`Move failed for ${p.id}: ${h.message}`)}if(j().writeRecoveryLinks){let p=this.noteFolder;window.setTimeout(()=>{Ye(this.app,p),Ye(this.app,s)},350)}let A=this.titleList(t);this.tree.rebuild(this.noteFolder);let l=i===F?"Open home":"Open parent",d=Math.max(0,n.length-t.length),g=t.length===1?`Moved ${A}${d>0?` and its ${d} nested note${d===1?"":"s"}`:""} \u2192 \`${s}\``:`Moved ${A}${d>0?` (${d} nested)`:""} \u2192 \`${s}\``;this.plugin.notifications.show({message:g,kind:"success",category:"move",duration:0,affectedIds:t.map(p=>p.id),folder:this.noteFolder,actions:[{label:l,onClick:()=>{this.switchToFolderAndFocus(s,i)}}]}),this.plugin.getUndoStack(this.noteFolder).push({label:`Cross-Stashpad move (${n.length})`,undo:async()=>{for(let p of n){let h=this.app.vault.getAbstractFileByPath(p.newPath);if(h)try{await this.app.fileManager.renameFile(h,p.oldPath),p.isRoot&&await this.app.fileManager.processFrontMatter(h,I=>{I.parent=p.oldParent})}catch{}}this.tree.rebuild(this.noteFolder),this.render()},redo:async()=>{for(let p of n){let h=this.app.vault.getAbstractFileByPath(p.oldPath);if(h)try{await this.app.fileManager.renameFile(h,p.newPath),p.isRoot&&await this.app.fileManager.processFrontMatter(h,I=>{I.parent=i})}catch{}}this.tree.rebuild(this.noteFolder),this.render()}})}nextPickableIdx(t,e){for(let i=t+e;i>=0&&i<this.currentChildren.length;i+=e){let s=this.currentChildren[i];if(s&&!this.selection.has(s.id))return i}return t}cmdInListPicker(){if(this.currentChildren.length===0)return;let t=this.cursorIdx>0?this.cursorIdx-1:0;if(this.currentChildren[t]&&this.selection.has(this.currentChildren[t].id)){let n=this.nextPickableIdx(t,-1);t=n!==t?n:this.nextPickableIdx(t,1)}this.inListPicker={activeIdx:t};let e=j().bindings.move,i=xi(e.primary||e.secondary||"M");new k.Notice(`Arrows to pick parent, Enter confirms, ${i} for the full picker, Esc cancels.`);let s=this.listEl?.scrollTop??0;if(this.render(),this.listEl){let n=this.listEl;n.scrollTop=s,requestAnimationFrame(()=>{n.scrollTop=s}),setTimeout(()=>{n.scrollTop=s},60)}}async commitInListPicker(){if(!this.inListPicker)return;let t=this.currentChildren[this.inListPicker.activeIdx];if(this.inListPicker=null,!t){this.render();return}let e=this.getActionTargets().filter(r=>r.id!==t.id),i=new Map(e.map(r=>[r.id,this.tree.getChildren(r.id).length])),s=[];for(let r of e)await this.changeParent(r,t.id,{silentSuccess:!0})&&s.push(r);if(this.notifyBatchMove(s,t.id,i),this.plugin.settings.autoNavOnMoveIn){this.navigateTo(t.id);return}this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=[t.id],this.render({kind:"follow-cursor"});let n=this.selectionGuardKey,o=()=>{if(this.selectionGuardKey!==n)return;let r=this.currentChildren.findIndex(A=>A.id===t.id);r<0||this.selection.size===1&&this.selection.has(t.id)&&this.cursorIdx===r||(this.selection.clear(),this.selection.add(t.id),this.cursorIdx=r,this.render({kind:"follow-cursor"}))};setTimeout(o,120),setTimeout(o,400)}async cmdMerge(){let t=this.getActionTargets();if(t.length<2){new k.Notice("Select 2+ notes to merge.");return}t.sort((u,f)=>(u.created||"").localeCompare(f.created||""));let e=t[0];if(!e.file)return;let i=e.file.path,s=await this.app.vault.read(e.file),n=await this.snapshotNotes(t.slice(1),!1),o=[],r=[];for(let u of t){if(!u.file)continue;let f=await this.app.vault.cachedRead(u.file);r.push(this.stripFrontmatter(f).trim())}let A=r.map(u=>u.trim()).filter(Boolean).join(` +`:"";r.value+=`${S}${b} +`,this.composerDraft=r.value},y=I.createEl("button",{cls:"stashpad-composer-btn"});(0,k.setIcon)(y,"paperclip"),y.title="Attach files",y.onmousedown=b=>b.preventDefault(),y.onclick=b=>{b.preventDefault();let S=document.activeElement===r;if(g.click(),S){let M=()=>{r.focus()};setTimeout(M,100),setTimeout(M,500)}},g.addEventListener("change",async()=>{let b=Array.from(g.files??[]);g.value="";for(let S of b){let M=await this.importAttachment(S);M&&m(M)}r.focus()});let Q=h.createEl("button",{cls:"stashpad-composer-btn stashpad-composer-rail-toggle"});(0,k.setIcon)(Q,"chevron-left"),Q.title="Show more composer options",h.insertBefore(Q,I);let E=b=>{h.toggleClass("is-expanded",b),Q.title=b?"Hide options":"Show more composer options",(0,k.setIcon)(Q,b?"chevron-right":"chevron-left")};Q.onmousedown=b=>b.preventDefault(),Q.onclick=b=>{b.preventDefault(),E(!h.hasClass("is-expanded"))},E(!1);let v=()=>n.clientWidth<700,w=()=>{let b=v();n.toggleClass("is-narrow",b),E(!b)};w(),requestAnimationFrame(w);let D=new ResizeObserver(w);D.observe(n),this.composerNarrowObserver?.disconnect(),this.composerNarrowObserver=D;let N=h.createEl("button",{cls:"stashpad-composer-btn stashpad-composer-send"});N.title="Send (Enter)",(0,k.setIcon)(N,"arrow-up");let P=async()=>{let b=r.value.trim();if(!b)return;r.value="",this.composerDraft="";try{await this.saveDraft("")}catch{}try{await this.recordLastSubmitted(b)}catch{}let S=this.modeSplit??j().splitOnLines,M=this.nextDestination,U=this.nextDestinationFolder,L=!!U&&U!==this.noteFolder;this.nextDestination=null,this.nextDestinationFolder=null,this.nextDestinationLabel=null,this.autoSelectNewest=!L,this.scrollToBottomOnNextRender=!L;let W=L?{targetFolder:U}:void 0,z=M??this.focusId;if(S){let V=oi(b,j().splitMode);V.length===1?await this.createNoteUnder(V[0],z,W):V.length>1&&await this.createNotesBatch(V,z,W,b,L?U:this.noteFolder)}else await this.createNoteUnder(b,z,W);j().autofocusComposerAfterSend&&(this.focusComposerOnNextRender=!0,L&&this.composerInputEl?.focus())};N.onclick=()=>void P(),r.addEventListener("keydown",b=>{let S=this.modeEnterSubmits;if(b.key==="Escape"){b.preventDefault(),b.stopPropagation(),r.blur(),this.viewRoot.focus({preventScroll:!0});return}if(b.key==="ArrowUp"&&r.selectionStart===0&&r.selectionEnd===0){if(b.preventDefault(),r.blur(),this.viewRoot.focus({preventScroll:!0}),this.currentChildren.length>0){let M=this.lastCursorByFocus.get(this.focusId)??this.lastSelected,U=M?this.currentChildren.findIndex(L=>L.id===M):-1;this.cursorIdx=U>=0?U:this.currentChildren.length-1,this.selectCursor(!1)}return}b.key==="Enter"&&!b.isComposing&&(S?!b.shiftKey:b.shiftKey)&&(b.preventDefault(),b.stopPropagation(),b.stopImmediatePropagation(),P())}),t.createDiv({cls:"stashpad-composer-help"}).setText(this.composerHelperText(i,s))}composerPlaceholder(t,e){return k.Platform.isMobile?e?"New notes (split on newlines)":"New note":`Type a note. ${t?"Enter":"Shift+Enter"} = send, ${t?"Shift+Enter":"Enter"} = newline${e?" (each line \u2192 a note)":""}\u2026`}composerHelperText(t,e){let i=t?"Enter":"Shift+Enter",s=t?"Shift+Enter":"Enter",n=j().bindings,o=p=>{let g=n[p];return g.primary&&g.secondary?g.preferRight?g.secondary:g.primary:g.primary||g.secondary},r=Pi(o("toggleSplit")),A=Pi(o("pickDestination")),l=Pi(o("search")),d=this.nextDestination?` \u2022 destination: ${this.destinationLabel()}`:"";return`${i} sends \xB7 ${s} newline \xB7 ${r} split: ${e?"ON":"off"} \xB7 ${A} destination \xB7 ${l} search${d}`}destinationLabel(){if(!this.nextDestination)return"current";if(this.nextDestinationFolder)return this.nextDestinationLabel??this.nextDestinationFolder;if(this.nextDestination===F)return"Home";let t=this.tree.get(this.nextDestination);return t?this.titleForNode(t).trim():"?"}renderMobileNav(t){let e=t.createDiv({cls:"stashpad-mobile-nav"});e.createEl("button",{text:"Home"}).onclick=()=>this.navigateTo(F),e.createEl("button",{text:"Back"}).onclick=()=>this.navigateUp(),e.createEl("button",{text:"Bookmarks"}).onclick=()=>this.openBookmarks()}handleRenderedClick(t,e){let i=t.target,s=i?.closest?.(".tag");if(s){t.preventDefault(),t.stopPropagation();let r=(s.getAttribute("href")||s.textContent||"").replace(/^#/,"").trim();if(r){let A=this.app.internalPlugins?.plugins?.["global-search"],l=A?.instance?.openGlobalSearch?.bind(A.instance);l&&l(`tag:#${r}`)}return}let n=i?.closest?.(".internal-link");if(n){t.preventDefault(),t.stopPropagation();let o=n.getAttribute("data-href")||n.getAttribute("href");if(o){let r=e.file?.path||"";this.app.workspace.openLinkText(o,r,!0)}}}handleRowClick(t,e,i){let s=t.target,n=s?.closest?.(".tag");if(n){t.preventDefault(),t.stopPropagation();let l=(n.getAttribute("href")||n.textContent||"").replace(/^#/,"").trim();if(l){let d=this.app.internalPlugins?.plugins?.["global-search"],p=d?.instance?.openGlobalSearch?.bind(d.instance);p&&p(`tag:#${l}`)}return}let o=s?.closest?.(".internal-link");if(o){t.preventDefault(),t.stopPropagation();let A=o.getAttribute("data-href")||o.getAttribute("href");if(A){let l=i.file?.path||"";this.app.workspace.openLinkText(A,l,!0)}return}if(s?.tagName==="A"&&s.href)return;if(t.stopPropagation(),this.inListPicker){this.inListPicker.activeIdx=e,this.commitInListPicker();return}let r=this.selection.size===0;if(t.shiftKey&&this.lastSelected){this.cursorIdx=e;let A=this.currentChildren.findIndex(l=>l.id===this.lastSelected);if(r&&(this.firstSelectedId=this.lastSelected),A!==-1){let[l,d]=A<e?[A,e]:[e,A];for(let p=l;p<=d;p++)this.selection.add(this.currentChildren[p].id)}else this.selection.add(i.id)}else if(t.metaKey||t.ctrlKey)if(this.selection.has(i.id))if(this.selection.delete(i.id),this.firstSelectedId===i.id&&(this.firstSelectedId=null),this.lastSelected===i.id&&(this.lastSelected=this.selection.size>0?[...this.selection][this.selection.size-1]:null),this.selection.size===0)this.cursorIdx=-1;else{let A=this.lastSelected??[...this.selection][this.selection.size-1],l=A?this.currentChildren.findIndex(d=>d.id===A):-1;l>=0&&(this.cursorIdx=l)}else this.cursorIdx=e,r&&(this.firstSelectedId=i.id),this.selection.add(i.id);else this.mobileSelectMode?(this.cursorIdx=e,this.selection.has(i.id)?(this.selection.delete(i.id),this.firstSelectedId===i.id&&(this.firstSelectedId=null)):this.selection.add(i.id)):(this.cursorIdx=e,this.selection.clear(),this.selection.add(i.id),this.firstSelectedId=i.id,this.lastSelected=i.id);this.selection.size===0&&(this.firstSelectedId=null),this.selection.has(i.id)&&(this.lastSelected=i.id),this.viewRoot.focus({preventScroll:!0}),this.repaintSelectionClasses(),this.revealCursorRow(),this.stampSelectedCursor(),this.plugin.notifyStashpadSelectionChanged()}revealCursorRow(){let t=()=>{if(this.cursorIdx<0)return;let e=this.listEl?.querySelector(`[data-idx="${this.cursorIdx}"]`);if(!e||!this.listEl)return;let i=this.listEl,s=i.getBoundingClientRect(),n=e.getBoundingClientRect(),o=4,r=s.top+o,A=s.bottom-o;if(k.Platform.isMobile&&document.body.classList.contains("stashpad-keyboard-open")){let l=this.viewRoot?.querySelector(".stashpad-composer");l&&(A=Math.min(A,l.getBoundingClientRect().top-o))}n.top<r?i.scrollTop+=n.top-r:n.bottom>A&&(i.scrollTop+=n.bottom-A)};t(),requestAnimationFrame(t),setTimeout(t,60),setTimeout(t,200)}jumpToTop(){this.currentChildren.length!==0&&(this.cursorIdx=0,this.selectCursor(!1))}jumpToBottom(){this.currentChildren.length!==0&&(this.cursorIdx=this.currentChildren.length-1,this.selectCursor(!1))}selectCursor(t){let e=this.currentChildren[this.cursorIdx];if(e){if(!t)this.selection.clear(),this.selection.add(e.id),this.firstSelectedId=e.id,this.lastSelected=e.id;else{let i=this.firstSelectedId??e.id,s=this.currentChildren.findIndex(n=>n.id===i);if(s===-1)this.selection.add(e.id),this.firstSelectedId=e.id;else{let[n,o]=s<this.cursorIdx?[s,this.cursorIdx]:[this.cursorIdx,s];this.selection.clear();for(let r=n;r<=o;r++)this.selection.add(this.currentChildren[r].id);this.firstSelectedId=i}this.lastSelected=e.id}this.repaintSelectionClasses(),this.revealCursorRow(),this.stampSelectedCursor(),this.plugin.notifyStashpadSelectionChanged()}}repaintSelectionClasses(){if(!this.listEl)return;let t=!!this.plugin.settings.autoExpandCursorRow,e=this.inListPicker?.activeIdx??-1;this.listEl.querySelectorAll(".stashpad-note").forEach(s=>{let n=Number(s.dataset.idx),o=s.dataset.id??"",r=n===this.cursorIdx;s.classList.toggle("is-cursor",r),s.classList.toggle("is-selected",this.selection.has(o)),s.classList.toggle("is-cursor-expanded",t&&r),s.classList.toggle("is-pick-target",n===e)})}revealRowAt(t){if(!this.listEl)return;let e=this.listEl.querySelector(`.stashpad-note[data-idx="${t}"]`);if(!e)return;let i=e.getBoundingClientRect(),s=this.listEl.getBoundingClientRect();(i.top<s.top||i.bottom>s.bottom)&&e.scrollIntoView({block:"nearest",behavior:"auto"})}getActionTargets(){if(this.selection.size>0)return[...this.selection].map(e=>this.tree.get(e)).filter(e=>!!e&&!!e.file);let t=this.currentChildren[this.cursorIdx];return t?[t]:[]}async cmdLockSelection(){if(!this.plugin.encryption?.isConfigured?.()){new k.Notice("Set up encryption first (Settings \u2192 Encryption).");return}let t=this.getActionTargets();if(t.length===0)return;let e=new Set(t.map(o=>o.id)),i=new Set((this.plugin.settings.lockedSubtrees??[]).map(o=>o.rootId).filter(o=>!!o)),s=t.filter(o=>{if(i.has(o.id))return!1;let r=o.parent;for(;r;){if(e.has(r))return!1;r=this.tree.get(r)?.parent??null}return!0});if(s.length===0){new k.Notice("Nothing to lock (already locked).");return}let n=0;for(let o of s){let r=this.order.getOrder(this.noteFolder,o.parent??F),A=r.indexOf(o.id),l=A>0?r[A-1]:null;await this.plugin.lockNoteSubtree(this.noteFolder,o.id,l,{silent:!0})&&n++}n>0&&(this.selection.clear(),this.lastSelected=null,this.render(),this.plugin.notifications.show({message:`Locked ${n} stash${n===1?"":"es"}.`,kind:"success",category:"system",folder:this.noteFolder}))}async cmdMoveToArchive(){if(!this.plugin.encryption?.isConfigured?.()){new k.Notice("Set up encryption first (Settings \u2192 Encryption).");return}let t=(this.plugin.settings.archiveFolders??[]).filter(o=>o!==this.noteFolder);if(t.length===0){new k.Notice("No archive folder available. Mark a folder as archive first (folder panel \u2192 right-click \u2192 \u201CMark as archive\u201D).",8e3);return}let e=this.getActionTargets();if(e.length===0)return;let i=this.plugin.settings.defaultArchiveFolder,s=i&&t.includes(i)?i:t.length===1?t[0]:null,n=o=>{this.archiveSources(e,o)};if(s){n(s);return}new co(this.app,t,n).open()}async archiveSources(t,e){let i=this.noteFolder,s=new Set(t.map(l=>l.id)),n=t.filter(l=>{let d=l.parent;for(;d;){if(s.has(d))return!1;d=this.tree.get(d)?.parent??null}return!0});if(n.length===0)return;let o=n.map(l=>l.id),r=[];for(let l of n){let d=this.order.getOrder(i,l.parent??F),p=d.indexOf(l.id),g=p>0?d[p-1]:null,h=await this.plugin.lockNoteSubtree(i,l.id,g,{silent:!0,blobFolder:e});h&&r.push(h.blobPath)}if(r.length===0)return;this.selection.clear(),this.lastSelected=null,this.tree.rebuild(i),this.render();let A=e.split("/").pop()||e;this.plugin.notifications.show({message:`Archived ${r.length} note${r.length===1?"":"s"} \u2192 \u201C${A}\u201D. Undo to bring ${r.length===1?"it":"them"} back.`,kind:"success",category:"system",folder:i}),this.plugin.getUndoStack(i).push({label:`Archive (${r.length})`,undo:async()=>{for(let l of r)try{await this.plugin.unlockBundleAt(l,{silent:!0,destFolder:i})}catch(d){console.warn("[Stashpad] archive undo failed",l,d)}r=[],this.tree.rebuild(i),this.render()},redo:async()=>{r=[];for(let l of o){let d=await this.plugin.lockNoteSubtree(i,l,null,{silent:!0,blobFolder:e});d&&r.push(d.blobPath)}this.tree.rebuild(i),this.render()}})}async cmdEncryptDelete(){if(!this.plugin.encryption?.isConfigured?.()){new k.Notice("Set up encryption first (Settings \u2192 Encryption).");return}let t=this.getActionTargets();if(t.length===0)return;let e=new Set(t.map(n=>n.id)),i=t.filter(n=>{let o=n.parent;for(;o;){if(e.has(o))return!1;o=this.tree.get(o)?.parent??null}return!0});if(i.length===0)return;let s=i.length;new pt(this.app,`Encrypt & delete ${s} note${s===1?"":"s"}?`,[`The selected note${s===1?"":"s"} (and any children) will be encrypted and moved to Stashpad's encrypted trash.`,"","\u2022 The readable copy is permanently removed from the folder.",`\u2022 You can restore ${s===1?"it":"them"} later from the encrypted trash \u2014 you'll need your encryption password.`,`\u2022 If you lose your password, ${s===1?"it's":"they're"} gone for good.`].join(` +`),"Encrypt & delete",async n=>{n&&await this.secureDeleteSources(i)}).open()}async secureDeleteSources(t){if(!this.plugin.encryption?.isConfigured?.()){new k.Notice("Set up encryption first (Settings \u2192 Encryption).");return}let e=new Set(t.map(r=>r.id)),i=t.filter(r=>{let A=r.parent;for(;A;){if(e.has(A))return!1;A=this.tree.get(A)?.parent??null}return!0});if(i.length===0)return;let s=this.noteFolder,n=i.map(r=>r.id),o=[];for(let r of n){let A=await this.plugin.encryptDeleteSubtree(s,r);A&&o.push(A)}o.length!==0&&(this.selection.clear(),this.lastSelected=null,this.tree.rebuild(s),this.render(),this.plugin.notifications.show({message:`Securely deleted ${o.length} note${o.length===1?"":"s"} \u2192 encrypted trash. Undo to bring ${o.length===1?"it":"them"} back.`,kind:"success",category:"system",folder:s}),this.plugin.getUndoStack(s).push({label:`Secure delete (${o.length})`,undo:async()=>{for(let r of o)try{await this.plugin.restoreDeletedAt(r,{silent:!0})}catch(A){console.warn("[Stashpad] secure-delete undo failed",r,A)}o=[],this.tree.rebuild(s),this.render()},redo:async()=>{o=[];for(let r of n){let A=await this.plugin.encryptDeleteSubtree(s,r);A&&o.push(A)}this.tree.rebuild(s),this.render()}}))}async cmdUnlockAll(){if(!this.plugin.encryption?.isConfigured?.()){new k.Notice("Set up encryption first (Settings \u2192 Encryption).");return}let t=new Set,e=new Set,i=this.getActionTargets().map(n=>n.id);for(;i.length;){let n=i.pop();if(!e.has(n)){e.add(n);for(let o of this.tree.getChildren(n))i.push(o.id)}}for(let n of e)for(let o of this.plugin.lockedSubtreesFor(this.noteFolder,n))t.add(o.blob);if(t.size===0){let n=(this.tree.get(this.focusId)??this.tree.getRoot()).id;for(let o of this.plugin.lockedSubtreesFor(this.noteFolder,n))t.add(o.blob)}if(t.size===0){new k.Notice("No locked notes to unlock here.");return}if(!await this.plugin.ensureEncryptionUnlocked())return;let s=0;for(let n of t)try{await this.plugin.unlockBundleAt(n,{silent:!0})&&s++}catch(o){console.warn("[Stashpad] batch unlock skipped",n,o)}s>0&&(this.selection.clear(),this.lastSelected=null,this.render(),this.plugin.notifications.show({message:`Unlocked ${s} stash${s===1?"":"es"}.`,kind:"success",category:"system",folder:this.noteFolder}))}toggleSplit(){let t=this.modeSplit??j().splitOnLines;this.modeSplit=!t,this.render(),this.composerInputEl?.focus()}openDestinationPicker(t=!1){let e=!1;new zt(this.app,this.tree,i=>this.titleForNode(i),{mode:"pick",placeholder:"Send next note(s) under which note?",allowCreate:!0,onPick:async i=>{if(e=!0,i.crossFolder){let s=i.crossId??i.id.replace(/^cross:/,"");this.nextDestination=s,this.nextDestinationFolder=i.crossFolder;let n=i.crossFolder.split("/").pop()||i.crossFolder,o=s===F?"Home":(i.crossFile?.basename??"note").replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ");this.nextDestinationLabel=`${n} \u25B8 ${o}`,this.render(),this.composerInputEl?.focus();return}this.nextDestination=i.id,this.nextDestinationFolder=null,this.nextDestinationLabel=null,this.render(),this.composerInputEl?.focus()},onCreate:async i=>{e=!0;let s=await this.createNoteUnder(i,this.focusId);s&&(this.nextDestination=s,this.nextDestinationFolder=null,this.nextDestinationLabel=null,this.render(),this.composerInputEl?.focus())},crossFolderNotes:()=>this.collectCrossFolderDestinations(),excludedFolderNotes:this.excludedSearchFolders().length>0?()=>this.collectExcludedFolderNotes():void 0,onClose:()=>{t&&!e&&this.composerInputEl?.focus()}}).open()}collectCrossFolderDestinations(){let t=this.collectCrossFolderNotes(),e=this.plugin.searchableFolders(this.noteFolder).filter(n=>n!==this.noteFolder),i=new Map;for(let n of this.app.vault.getMarkdownFiles()){let o=n.parent?.path?.replace(/\/+$/,"")??"";if(!e.includes(o))continue;this.app.metadataCache.getFileCache(n)?.frontmatter?.id===F&&i.set(o,n)}return[...e.map(n=>({file:i.get(n),folder:n,id:F,title:`Home \u2014 ${n.split("/").pop()||n}`,body:""})),...t]}openSearchInParentModal(){let t=this.focusId,e=s=>{if(s===t)return!0;let n=new Set,o=this.tree.get(s);for(;o&&o.id!==F&&!n.has(o.id);){if(n.add(o.id),o.parent===t||o.id===t)return!0;if(!o.parent)return!1;o=this.tree.get(o.parent)}return t===F},i=new Proxy(this.tree,{get:(s,n)=>n==="getRoot"?()=>s.get(t)??s.getRoot():n==="getChildren"?o=>s.getChildren(o):s[n]});new zt(this.app,i,s=>this.titleForNode(s),{mode:"search",placeholder:`Search in "${this.titleForNode(this.tree.get(t)??this.tree.getRoot()).trim()}"\u2026`,allowCreate:!1,onPick:s=>{s.node&&e(s.node.id)?this.navigateTo(s.node.id):s.node&&this.navigateTo(s.node.id)}}).open()}openSearchModal(){if(this.openSearchInstance){let i=this.openSearchInstance.inputEl;i&&(i.focus(),i.select());return}let t=new zt(this.app,this.tree,i=>this.titleForNode(i),{mode:"search",placeholder:"Search Stashpad notes\u2026",allowCreate:!0,onCreate:async i=>{let s=i.trim();s&&new zt(this.app,this.tree,n=>this.titleForNode(n),{mode:"pick",placeholder:`Create "${s}" under which note?`,allowCreate:!1,crossFolderNotes:()=>this.collectCrossFolderDestinations(),excludedFolderNotes:this.excludedSearchFolders().length>0?()=>this.collectExcludedFolderNotes():void 0,folderResults:()=>this.plugin.discoverStashpadFolders().filter(n=>n!==this.noteFolder),localFolder:this.noteFolder,onPick:async n=>{let o=n.crossFolder?n.crossId??n.id.replace(/^cross:/,""):n.node?.id,r=n.crossFolder??this.noteFolder;if(!o)return;let A=(this.plugin.settings.folder||"Stashpad").trim().replace(/^\/+|\/+$/g,"")||"Stashpad",l=this.app.workspace,d=l.getLeaf("tab");await d.setViewState({type:J,active:!0,state:{focusId:o,folderOverride:r===A?null:r}}),l.revealLeaf(d);let p=d.view;if(p&&typeof p.createNoteUnder=="function"){let g=await p.createNoteUnder(s,o);g&&typeof p.navigateTo=="function"&&p.navigateTo(g)}}}).open()},onPick:i=>{if(i.kind==="folder-open"&&i.folder){this.openFolderInNewTab(i.folder);return}let s=this.plugin.settings.searchOpensInNewTab!==!1;if(i.crossFolder&&i.crossFile){let n=i.crossId??i.id.replace(/^cross:/,"");s?this.openNoteInNewTab(i.crossFolder,n):this.switchToFolderAndFocus(i.crossFolder,n);return}i.node&&(s?this.openNoteInNewTab(this.noteFolder,i.node.id):this.navigateTo(i.node.id))},crossFolderNotes:()=>this.collectCrossFolderDestinations(),excludedFolderNotes:this.excludedSearchFolders().length>0?()=>this.collectExcludedFolderNotes():void 0,folderResults:()=>this.plugin.discoverStashpadFolders().filter(i=>i!==this.noteFolder),showFilterChips:!0,localFolder:this.noteFolder});this.openSearchInstance=t;let e=t.onClose.bind(t);t.onClose=()=>{e(),this.openSearchInstance===t&&(this.openSearchInstance=null)},t.open()}excludedSearchFolders(){let t=new Set(this.plugin.searchableFolders(this.noteFolder));return this.plugin.discoverStashpadFolders().filter(e=>e!==this.noteFolder&&!t.has(e))}collectExcludedFolderNotes(){let t=this.excludedSearchFolders();if(!t.length)return[];let e=this.collectCrossFolderNotes(t),i=new Map;for(let n of this.app.vault.getMarkdownFiles()){let o=n.parent?.path?.replace(/\/+$/,"")??"";if(!t.includes(o))continue;this.app.metadataCache.getFileCache(n)?.frontmatter?.id===F&&i.set(o,n)}return[...t.map(n=>({file:i.get(n),folder:n,id:F,title:`Home \u2014 ${n.split("/").pop()||n}`,body:""})),...e]}collectCrossFolderNotes(t){let e=[],i=(t??this.plugin.searchableFolders(this.noteFolder)).filter(o=>o!==this.noteFolder);if(!i.length)return e;let s=new Set(i),n=new Map;for(let o of this.app.vault.getMarkdownFiles()){let r=o.parent?.path?.replace(/\/+$/,"")??"";if(!s.has(r))continue;let A=n.get(r);A||(A=[],n.set(r,A)),A.push(o)}for(let o of i){let r=n.get(o)??[],A=new Map;for(let l of r){let d=this.app.metadataCache.getFileCache(l)?.frontmatter;typeof d?.id=="string"&&A.set(d.id,l)}for(let l of r){let d=this.app.metadataCache.getFileCache(l)?.frontmatter,p=typeof d?.id=="string"?d.id:"";if(!p||p===F)continue;let g=l.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," "),h,I=d?.parent??null;if(I&&I!==F){let u=A.get(I);u&&(h=u.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," "))}e.push({file:l,folder:o,id:p,title:g,body:"",parentBlurb:h,parentId:I??null})}}return e}async switchToFolderAndFocus(t,e){await this.setFolderOverride(t),this.tree.get(e)&&this.navigateTo(e)}async cmdOutdent(){let t=this.getActionTargets();if(!t.length)return;let e=[],i=[];for(let s of t){let n=s.parent?this.tree.get(s.parent):null;if(!n||n.id===F){i.push(s.id);continue}let o=n.parent??F;await this.changeParent(s,o),e.push(s)}if(e.length===0){new k.Notice(i.length?"Already at the top level.":"Nothing to outdent.");return}if(this.render(),i.length&&this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Outdented",nodes:e,suffix:i.length?`(${i.length} already at root)`:void 0}),kind:"success",category:"move",affectedIds:e.map(s=>s.id),folder:this.noteFolder}),this.plugin.settings.autoNavOnMoveOut&&e.length>0){let s=e[0].parent;s!=null&&e.every(o=>o.parent===s)&&s!==this.focusId&&this.navigateTo(s)}}cmdSetColor(){let t=this.getActionTargets();if(!t.length)return;let e=new Set(t.map(n=>this.colorForNode(n)??"")),i=e.size===1&&Array.from(e)[0]||null,s=this.plugin.settings.customPalette??[];new De(this.app,i,s,async(n,o)=>{let r=[];for(let p of t)if(p.file){r.push({id:p.id,path:p.file.path,was:this.colorForNode(p)??null});try{await this.app.fileManager.processFrontMatter(p.file,g=>{n?g.color=n:delete g.color})}catch(g){new k.Notice(`Couldn't set color for ${p.id}: ${g.message}`)}}if(o.addToPalette&&typeof n=="string"){let p=[...this.plugin.settings.customPalette??[]],g=n.toLowerCase();p.some(h=>h.toLowerCase()===g)||(p.push(n),this.plugin.settings.customPalette=p,await this.plugin.persistSettingsQuiet(),await this.log.append({type:"palette_color_add",id:F,payload:{color:n}}))}this.render();let A=this.noteFolder,l=n,d=async p=>{for(let g of p){let h=this.app.vault.getAbstractFileByPath(g.path);if(h)try{await this.app.fileManager.processFrontMatter(h,I=>{g.col?I.color=g.col:delete I.color})}catch{}}this.tree.rebuild(A),this.render()};this.plugin.getUndoStack(A).push({label:r.length===1?"Color change":`Color change (${r.length})`,undo:()=>d(r.map(p=>({path:p.path,col:p.was}))),redo:()=>d(r.map(p=>({path:p.path,col:l})))})},async n=>{let o=(this.plugin.settings.customPalette??[]).filter(r=>r.toLowerCase()!==n.toLowerCase());return this.plugin.settings.customPalette=o,await this.plugin.persistSettingsQuiet(),await this.log.append({type:"palette_color_remove",id:F,payload:{color:n}}),o}).open()}cmdMovePicker(){let t=this.getActionTargets();t.length&&new zt(this.app,this.tree,e=>this.titleForNode(e),{mode:"pick",placeholder:"Move to which note?",allowCreate:!0,onPick:async e=>{if(e.crossFolder){let o=e.crossId??e.id.replace(/^cross:/,"");await this.moveAcrossFolders(t,e.crossFolder,o),this.selection.clear(),this.render();return}let i=e.id,s=new Map(t.map(o=>[o.id,this.tree.getChildren(o.id).length])),n=[];for(let o of t)await this.changeParent(o,i,{silentSuccess:!0})&&n.push(o);this.notifyBatchMove(n,i,s),this.selection.clear(),this.render(),this.plugin.settings.autoNavOnMoveOut&&i!==this.focusId&&this.navigateTo(i)},onCreate:async e=>{let i=await this.createNoteUnder(e,this.focusId);if(!i)return;let s=new Map(t.map(o=>[o.id,this.tree.getChildren(o.id).length])),n=[];for(let o of t)await this.changeParent(o,i,{silentSuccess:!0})&&n.push(o);this.notifyBatchMove(n,i,s),this.selection.clear(),this.render(),this.plugin.settings.autoNavOnMoveOut&&this.navigateTo(i)},crossFolderNotes:()=>this.collectCrossFolderDestinations(),excludedFolderNotes:this.excludedSearchFolders().length>0?()=>this.collectExcludedFolderNotes():void 0,showFilterChips:!0}).open()}async moveAcrossFolders(t,e,i){if(!t.length)return;let s=(e||"").replace(/\/+$/,"");if(!s){new k.Notice("Target folder is empty");return}let n=[],o=new Set;for(let g of this.app.vault.getMarkdownFiles())(g.parent?.path?.replace(/\/+$/,"")??"")===s&&o.add(g.path);let r=(g,h)=>{if(!g.file)return;let I=g.file,u=`${s}/${I.name}`;if(o.has(u)){let f=I.basename.match(/^(.*)(-[a-z0-9]{4,12})$/),C=f?f[1]:I.basename,B=f?f[2]:"";for(let m=1;m<1e3;m++){let y=`${C}-${m}${B}.md`,Q=`${s}/${y}`;if(!o.has(Q)){u=Q;break}}}o.add(u),n.push({id:g.id,file:I,oldPath:I.path,newPath:u,oldParent:g.parent,isRoot:h});for(let f of this.tree.getChildren(g.id))r(f,!1)};for(let g of t)r(g,!0);if(!n.length)return;await this.ensureFolder(s);for(let g of n)try{await this.app.fileManager.renameFile(g.file,g.newPath),g.isRoot&&await this.app.fileManager.processFrontMatter(g.file,h=>{h.parent=i}),await this.log.append({type:"parent_change",id:g.id,payload:{from:g.oldParent,to:g.isRoot?i:g.oldParent,crossFolder:{from:this.noteFolder,to:s}}})}catch(h){new k.Notice(`Move failed for ${g.id}: ${h.message}`)}if(j().writeRecoveryLinks){let g=this.noteFolder;window.setTimeout(()=>{Xe(this.app,g),Xe(this.app,s)},350)}let A=this.titleList(t);this.tree.rebuild(this.noteFolder);let l=i===F?"Open home":"Open parent",d=Math.max(0,n.length-t.length),p=t.length===1?`Moved ${A}${d>0?` and its ${d} nested note${d===1?"":"s"}`:""} \u2192 \`${s}\``:`Moved ${A}${d>0?` (${d} nested)`:""} \u2192 \`${s}\``;this.plugin.notifications.show({message:p,kind:"success",category:"move",duration:0,affectedIds:t.map(g=>g.id),folder:this.noteFolder,actions:[{label:l,onClick:()=>{this.switchToFolderAndFocus(s,i)}}]}),this.plugin.getUndoStack(this.noteFolder).push({label:`Cross-Stashpad move (${n.length})`,undo:async()=>{for(let g of n){let h=this.app.vault.getAbstractFileByPath(g.newPath);if(h)try{await this.app.fileManager.renameFile(h,g.oldPath),g.isRoot&&await this.app.fileManager.processFrontMatter(h,I=>{I.parent=g.oldParent})}catch{}}this.tree.rebuild(this.noteFolder),this.render()},redo:async()=>{for(let g of n){let h=this.app.vault.getAbstractFileByPath(g.oldPath);if(h)try{await this.app.fileManager.renameFile(h,g.newPath),g.isRoot&&await this.app.fileManager.processFrontMatter(h,I=>{I.parent=i})}catch{}}this.tree.rebuild(this.noteFolder),this.render()}})}nextPickableIdx(t,e){for(let i=t+e;i>=0&&i<this.currentChildren.length;i+=e){let s=this.currentChildren[i];if(s&&!this.selection.has(s.id))return i}return t}cmdInListPicker(){if(this.currentChildren.length===0)return;let t=this.cursorIdx>0?this.cursorIdx-1:0;if(this.currentChildren[t]&&this.selection.has(this.currentChildren[t].id)){let n=this.nextPickableIdx(t,-1);t=n!==t?n:this.nextPickableIdx(t,1)}this.inListPicker={activeIdx:t};let e=j().bindings.move,i=Pi(e.primary||e.secondary||"M");new k.Notice(`Arrows to pick parent, Enter confirms, ${i} for the full picker, Esc cancels.`);let s=this.listEl?.scrollTop??0;if(this.render(),this.listEl){let n=this.listEl;n.scrollTop=s,requestAnimationFrame(()=>{n.scrollTop=s}),setTimeout(()=>{n.scrollTop=s},60)}}async commitInListPicker(){if(!this.inListPicker)return;let t=this.currentChildren[this.inListPicker.activeIdx];if(this.inListPicker=null,!t){this.render();return}let e=this.getActionTargets().filter(r=>r.id!==t.id),i=new Map(e.map(r=>[r.id,this.tree.getChildren(r.id).length])),s=[];for(let r of e)await this.changeParent(r,t.id,{silentSuccess:!0})&&s.push(r);if(this.notifyBatchMove(s,t.id,i),this.plugin.settings.autoNavOnMoveIn){this.navigateTo(t.id);return}this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=[t.id],this.render({kind:"follow-cursor"});let n=this.selectionGuardKey,o=()=>{if(this.selectionGuardKey!==n)return;let r=this.currentChildren.findIndex(A=>A.id===t.id);r<0||this.selection.size===1&&this.selection.has(t.id)&&this.cursorIdx===r||(this.selection.clear(),this.selection.add(t.id),this.cursorIdx=r,this.render({kind:"follow-cursor"}))};setTimeout(o,120),setTimeout(o,400)}async cmdMerge(){let t=this.getActionTargets();if(t.length<2){new k.Notice("Select 2+ notes to merge.");return}t.sort((u,f)=>(u.created||"").localeCompare(f.created||""));let e=t[0];if(!e.file)return;let i=e.file.path,s=await this.app.vault.read(e.file),n=await this.snapshotNotes(t.slice(1),!1),o=[],r=[];for(let u of t){if(!u.file)continue;let f=await this.app.vault.cachedRead(u.file);r.push(this.stripFrontmatter(f).trim())}let A=r.map(u=>u.trim()).filter(Boolean).join(` `),l=await this.app.vault.read(e.file),d=l.startsWith("---")?l.indexOf(` ----`,3)+4:0,p=`${l.slice(0,d)} +---`,3)+4:0,g=`${l.slice(0,d)} ${A} -`;await this.app.vault.modify(e.file,p);for(let u=1;u<t.length;u++){let f=t[u];if(f.file){for(let C of this.tree.getChildren(f.id))C.file&&o.push({childId:C.id,childPath:C.file.path,oldParent:C.parent}),await this.changeParent(C,e.id,{record:!1});await this.app.fileManager.trashFile(f.file),await this.log.append({type:"delete",id:f.id,payload:{mergedInto:e.id}})}}this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=[e.id];let h=this.titleForNode(e);this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Merged",nodes:t,destination:`\u2192 kept "${h}"`}),kind:"success",category:"merge",affectedIds:t.map(u=>u.id),folder:this.noteFolder}),this.tree.rebuild(this.noteFolder),this.render({kind:"follow-cursor"});{let u=e.id,f=this.selectionGuardKey,C=()=>{if(this.selectionGuardKey!==f||this.selection.has(u))return;let B=this.currentChildren.findIndex(m=>m.id===u);B<0||(this.selection.add(u),this.cursorIdx=B,this.render({kind:"follow-cursor"}))};setTimeout(C,120),setTimeout(C,400)}let I=this.noteFolder;this.plugin.getUndoStack(I).push({label:`Merge ${t.length} notes`,undo:async()=>{await this.restoreSnapshots(n,t.map(f=>f.id));let u=this.app.vault.getAbstractFileByPath(i);u&&await this.app.vault.modify(u,s);for(let f of o){let C=this.app.vault.getAbstractFileByPath(f.childPath);C&&await this.app.fileManager.processFrontMatter(C,B=>{B.parent=f.oldParent})}this.pendingFocusIds=t.map(f=>f.id),this.tree.rebuild(I),this.render({kind:"follow-cursor"})},redo:async()=>{await this.trashNotesAndAttachments(n);let u=this.app.vault.getAbstractFileByPath(i);u&&await this.app.vault.modify(u,p);for(let f of o){let C=this.app.vault.getAbstractFileByPath(f.childPath);C&&await this.app.fileManager.processFrontMatter(C,B=>{B.parent=e.id})}this.tree.rebuild(I),this.render()}})}cmdCopy(){return _n(this)}cmdCopyCodeBlock(){return Ra(this)}cmdCopyTree(){return La(this)}cmdCopyOutline(){return qa(this)}cmdToggleExpand(){let t=this.getActionTargets();if(!t.length)return;let e=t.some(i=>!this.expandedNotes.has(i.id));for(let i of t)e?this.expandedNotes.add(i.id):this.expandedNotes.delete(i.id);this.render()}async cloneSubtree(t,e,i){if(!t.file)return null;if(t.id===e||this.isDescendant(e,t.id))return new k.Notice(`Can't insert "${this.titleForNode(t)}" into itself or a descendant \u2014 that would loop forever.`),null;let s=this.tree.getChildren(t.id).slice(),n=t.file,o=await this.app.vault.read(n),r=this.stripFrontmatter(o),A=this.app.metadataCache.getFileCache(n)?.frontmatter??{},l=tt(),d=Et(r,this.activeStopwords()),g=wt(d,l),p=`${this.noteFolder}/${g}`,h=new Date().toISOString(),I=this.extractAttachments(r),u=["---",`id: ${l}`,`parent: ${e}`,`created: ${h}`];if(I.length>0){u.push("attachments:");for(let C of I)u.push(` - "${C.replace(/"/g,'\\"')}"`)}else u.push("attachments: []");u.push("---",r),await this.ensureFolder(this.noteFolder),await this.app.vault.create(p,u.join(` -`)),i.push(p);let f=this.app.vault.getAbstractFileByPath(p);if(f){try{await this.app.fileManager.processFrontMatter(f,C=>{for(let[B,m]of Object.entries(A))se.includes(B)||(C[B]=m)})}catch(C){console.warn("[Stashpad] cloneSubtree: processFrontMatter failed",C)}try{this.tree.insertSynthetic({id:l,parent:e,children:[],file:f,created:h})}catch{}this.fmSync.scheduleParentChange(l,null,e)}for(let C of s)await this.cloneSubtree(C,l,i);return l}async cmdClone(){let t=this.getActionTargets();if(!t.length){new k.Notice("Nothing to clone.");return}let e=this.noteFolder,i=[],s=[];for(let A of t){if(!A.file)continue;let l=A.parent??this.focusId,d=await this.cloneSubtree(A,l,i);d&&s.push(d)}if(!s.length)return;this.tree.rebuild(e),this.pendingFocusIds=s.slice(),this.render();let n=i.map(A=>this.app.vault.getAbstractFileByPath(A)).filter(A=>!!A&&A.extension==="md").map(A=>({id:ve(A.basename)??A.basename,parent:null,children:[],file:A,created:new Date().toISOString()})),o=await this.snapshotNotes(n,!1);this.plugin.getUndoStack(e).push({label:`Clone ${s.length} note${s.length===1?"":"s"}`,undo:async()=>{for(let A of[...i].reverse()){let l=this.app.vault.getAbstractFileByPath(A);if(l)try{await this.app.fileManager.trashFile(l)}catch{}}this.tree.rebuild(e),this.render()},redo:async()=>{await this.restoreSnapshots(o,s)}});let r=s.map(A=>this.tree.get(A)).filter(A=>!!A);this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Cloned",nodes:r,suffix:`(${i.length} file${i.length===1?"":"s"} total)`}),kind:"success",category:"clone",affectedIds:s,folder:this.noteFolder})}async cmdCopyNotes(){let t=this.getActionTargets();if(!t.length){new k.Notice("Nothing to copy.");return}await _n(this),this.plugin.clearNoteClipboard(),this.plugin.noteClipboard={mode:"copy",folder:this.noteFolder,ids:t.map(e=>e.id)},this.render()}isCutPending(t){let e=this.plugin.noteClipboard;return!!e&&e.mode==="cut"&&e.folder===this.noteFolder&&e.ids.includes(t)}isCopyPending(t){let e=this.plugin.noteClipboard;return!!e&&e.mode==="copy"&&e.folder===this.noteFolder&&e.ids.includes(t)}insertIntoComposer(t){let e=this.composerInputEl;if(!e){this.composerDraft=this.composerDraft?`${this.composerDraft} +`;await this.app.vault.modify(e.file,g);for(let u=1;u<t.length;u++){let f=t[u];if(f.file){for(let C of this.tree.getChildren(f.id))C.file&&o.push({childId:C.id,childPath:C.file.path,oldParent:C.parent}),await this.changeParent(C,e.id,{record:!1});await this.app.fileManager.trashFile(f.file),await this.log.append({type:"delete",id:f.id,payload:{mergedInto:e.id}})}}this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=[e.id];let h=this.titleForNode(e);this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Merged",nodes:t,destination:`\u2192 kept "${h}"`}),kind:"success",category:"merge",affectedIds:t.map(u=>u.id),folder:this.noteFolder}),this.tree.rebuild(this.noteFolder),this.render({kind:"follow-cursor"});{let u=e.id,f=this.selectionGuardKey,C=()=>{if(this.selectionGuardKey!==f||this.selection.has(u))return;let B=this.currentChildren.findIndex(m=>m.id===u);B<0||(this.selection.add(u),this.cursorIdx=B,this.render({kind:"follow-cursor"}))};setTimeout(C,120),setTimeout(C,400)}let I=this.noteFolder;this.plugin.getUndoStack(I).push({label:`Merge ${t.length} notes`,undo:async()=>{await this.restoreSnapshots(n,t.map(f=>f.id));let u=this.app.vault.getAbstractFileByPath(i);u&&await this.app.vault.modify(u,s);for(let f of o){let C=this.app.vault.getAbstractFileByPath(f.childPath);C&&await this.app.fileManager.processFrontMatter(C,B=>{B.parent=f.oldParent})}this.pendingFocusIds=t.map(f=>f.id),this.tree.rebuild(I),this.render({kind:"follow-cursor"})},redo:async()=>{await this.trashNotesAndAttachments(n);let u=this.app.vault.getAbstractFileByPath(i);u&&await this.app.vault.modify(u,g);for(let f of o){let C=this.app.vault.getAbstractFileByPath(f.childPath);C&&await this.app.fileManager.processFrontMatter(C,B=>{B.parent=e.id})}this.tree.rebuild(I),this.render()}})}cmdCopy(){return Ao(this)}cmdCopyCodeBlock(){return _a(this)}cmdCopyTree(){return tr(this)}cmdCopyOutline(){return er(this)}cmdToggleExpand(){let t=this.getActionTargets();if(!t.length)return;let e=t.some(i=>!this.isNoteExpanded(i.id));for(let i of t)this.setNoteExpanded(i.id,e);this.render()}isNoteExpanded(t){let e=this.expandedNotes.has(t);return this.plugin.settings.expandBodiesByDefault?!e:e}setNoteExpanded(t,e){let i=this.plugin.settings.expandBodiesByDefault;e===i?this.expandedNotes.delete(t):this.expandedNotes.add(t)}cmdExpandAll(){for(let t of this.currentChildren)this.setNoteExpanded(t.id,!0);this.render()}cmdCollapseAll(){for(let t of this.currentChildren)this.setNoteExpanded(t.id,!1);this.render()}async cloneSubtree(t,e,i){if(!t.file)return null;if(t.id===e||this.isDescendant(e,t.id))return new k.Notice(`Can't insert "${this.titleForNode(t)}" into itself or a descendant \u2014 that would loop forever.`),null;let s=this.tree.getChildren(t.id).slice(),n=t.file,o=await this.app.vault.read(n),r=this.stripFrontmatter(o),A=this.app.metadataCache.getFileCache(n)?.frontmatter??{},l=tt(),d=Qt(r,this.activeStopwords()),p=yt(d,l),g=`${this.noteFolder}/${p}`,h=new Date().toISOString(),I=this.extractAttachments(r),u=["---",`id: ${l}`,`parent: ${e}`,`created: ${h}`];if(I.length>0){u.push("attachments:");for(let C of I)u.push(` - "${C.replace(/"/g,'\\"')}"`)}else u.push("attachments: []");u.push("---",r),await this.ensureFolder(this.noteFolder),await this.app.vault.create(g,u.join(` +`)),i.push(g);let f=this.app.vault.getAbstractFileByPath(g);if(f){try{await this.app.fileManager.processFrontMatter(f,C=>{for(let[B,m]of Object.entries(A))ae.includes(B)||(C[B]=m)})}catch(C){console.warn("[Stashpad] cloneSubtree: processFrontMatter failed",C)}try{this.tree.insertSynthetic({id:l,parent:e,children:[],file:f,created:h})}catch{}this.fmSync.scheduleParentChange(l,null,e)}for(let C of s)await this.cloneSubtree(C,l,i);return l}async cmdClone(){let t=this.getActionTargets();if(!t.length){new k.Notice("Nothing to clone.");return}let e=this.noteFolder,i=[],s=[];for(let A of t){if(!A.file)continue;let l=A.parent??this.focusId,d=await this.cloneSubtree(A,l,i);d&&s.push(d)}if(!s.length)return;this.tree.rebuild(e),this.pendingFocusIds=s.slice(),this.render();let n=i.map(A=>this.app.vault.getAbstractFileByPath(A)).filter(A=>!!A&&A.extension==="md").map(A=>({id:le(A.basename)??A.basename,parent:null,children:[],file:A,created:new Date().toISOString()})),o=await this.snapshotNotes(n,!1);this.plugin.getUndoStack(e).push({label:`Clone ${s.length} note${s.length===1?"":"s"}`,undo:async()=>{for(let A of[...i].reverse()){let l=this.app.vault.getAbstractFileByPath(A);if(l)try{await this.app.fileManager.trashFile(l)}catch{}}this.tree.rebuild(e),this.render()},redo:async()=>{await this.restoreSnapshots(o,s)}});let r=s.map(A=>this.tree.get(A)).filter(A=>!!A);this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Cloned",nodes:r,suffix:`(${i.length} file${i.length===1?"":"s"} total)`}),kind:"success",category:"clone",affectedIds:s,folder:this.noteFolder})}cmdForkNote(){let t=this.getActionTargets()[0];if(!t?.file){new k.Notice("Nothing to fork.");return}let e=t.parent??F,i=e===F?null:this.tree.get(e),s=i?this.titleForNode(i):"Home";new zt(this.app,this.tree,n=>this.titleForNode(n),{mode:"pick",allowCreate:!0,placeholder:`Fork "${this.titleForNode(t)}" under\u2026 (default: ${s})`,onPick:n=>{if(n.crossFolder){new k.Notice("Fork stays in this folder for now.");return}this.forkNoteUnder(t,n.id)},onCreate:n=>{(async()=>{let o=await this.createNoteUnder(n,this.focusId);o&&await this.forkNoteUnder(t,o)})()}}).open()}async forkNoteUnder(t,e){if(!t.file)return;let i=this.noteFolder,s=[],n=await this.cloneSubtree(t,e,s);if(!n)return;this.tree.rebuild(i),this.pendingFocusIds=[n],this.render();let o=s.map(l=>this.app.vault.getAbstractFileByPath(l)).filter(l=>!!l&&l.extension==="md").map(l=>({id:le(l.basename)??l.basename,parent:null,children:[],file:l,created:new Date().toISOString()})),r=await this.snapshotNotes(o,!1);this.plugin.getUndoStack(i).push({label:"Fork note",undo:async()=>{for(let l of[...s].reverse()){let d=this.app.vault.getAbstractFileByPath(l);if(d)try{await this.app.fileManager.trashFile(d)}catch{}}this.tree.rebuild(i),this.render()},redo:async()=>{await this.restoreSnapshots(r,[n])}});let A=this.tree.get(n);this.plugin.notifications.show({message:A?`Forked "${this.titleForNode(t)}" \u2192 "${this.titleForNode(A)}" (${s.length} file${s.length===1?"":"s"})`:"Forked note",kind:"success",category:"clone",affectedIds:[n],folder:i})}async ensureSheetGroup(t){let e=se(this.app.metadataCache.getFileCache(t)?.frontmatter);if(e)return e;let i=Xa();return await this.app.fileManager.processFrontMatter(t,s=>{s[Us]=i,typeof s[je]!="number"&&(s[je]=0)}),i}async cmdForkVersion(t,e=!1){if(!this.plugin.settings.enableSheetVersions){new k.Notice("Sheet versions are off \u2014 enable them in Settings \u2192 General.");return}let i=t??this.getActionTargets()[0];if(!i?.file){new k.Notice("Select a note to version.");return}let s=this.noteFolder,n=await this.ensureSheetGroup(i.file),o=i.parent??this.focusId,r=this.tree.getChildren(o).filter(m=>se(Ct(this.app,m))===n),A=-1;for(let m of r){let y=this.app.metadataCache.getFileCache(m.file)?.frontmatter?.[je];typeof y=="number"&&y>A&&(A=y)}let l=A+1,d=e?"":this.stripFrontmatter(await this.app.vault.read(i.file)),p=tt(),g=Qt(d,this.activeStopwords()),h=yt(g,p),I=`${s}/${h}`,u=new Date().toISOString(),f=this.extractAttachments(d),C=["---",`id: ${p}`,`parent: ${o}`,`created: ${u}`];if(f.length>0){C.push("attachments:");for(let m of f)C.push(` - "${m.replace(/"/g,'\\"')}"`)}else C.push("attachments: []");C.push("---",d),await this.ensureFolder(s),await this.app.vault.create(I,C.join(` +`));let B=this.app.vault.getAbstractFileByPath(I);if(!B){new k.Notice("Sheets: could not create version.");return}await this.app.fileManager.processFrontMatter(B,m=>{m[Us]=n,m[je]=l,delete m[Ui]});try{this.tree.insertSynthetic({id:p,parent:o,children:[],file:B,created:u})}catch{}this.fmSync.scheduleParentChange(p,null,o),this.tree.rebuild(s),this.activeVersionByGroup.set(n,p),this.plugin.saveActiveVersion(s,n,p),this.render(),this.plugin.getUndoStack(s).push({label:e?"New version":"Fork version",undo:async()=>{let m=this.app.vault.getAbstractFileByPath(I);if(m)try{await this.app.fileManager.trashFile(m)}catch{}this.activeVersionByGroup.delete(n),this.tree.rebuild(s),this.render()},redo:async()=>{}}),new k.Notice(e?"New version added":"Forked a new version")}async cmdMarkVersionFinal(t){if(!this.plugin.settings.enableSheetVersions){new k.Notice("Sheet versions are off \u2014 enable them in Settings \u2192 General.");return}let e=t??this.getActionTargets()[0];if(!e?.file)return;let i=se(Ct(this.app,e));if(!i){new k.Notice("Not a versioned note.");return}let s=!Ri(Ct(this.app,e)),n=e.parent??this.focusId,o=this.tree.getChildren(n).filter(r=>se(Ct(this.app,r))===i);for(let r of o){if(!r.file)continue;let A=Ri(Ct(this.app,r)),l=s&&r.id===e.id;A!==l&&await this.app.fileManager.processFrontMatter(r.file,d=>{l?d[Ui]=!0:delete d[Ui]})}this.render()}async cmdCopyNotes(){let t=this.getActionTargets();if(!t.length){new k.Notice("Nothing to copy.");return}await Ao(this),this.plugin.clearNoteClipboard(),this.plugin.noteClipboard={mode:"copy",folder:this.noteFolder,ids:t.map(e=>e.id)},this.render()}isCutPending(t){let e=this.plugin.noteClipboard;return!!e&&e.mode==="cut"&&e.folder===this.noteFolder&&e.ids.includes(t)}isCopyPending(t){let e=this.plugin.noteClipboard;return!!e&&e.mode==="copy"&&e.folder===this.noteFolder&&e.ids.includes(t)}insertIntoComposer(t){let e=this.composerInputEl;if(!e){this.composerDraft=this.composerDraft?`${this.composerDraft} ${t}`:t;return}let i=e.selectionStart??e.value.length,s=e.selectionEnd??e.value.length;e.value=e.value.slice(0,i)+t+e.value.slice(s);let n=i+t.length;try{e.setSelectionRange(n,n)}catch{}this.composerDraft=e.value}focusedInsideCut(t){let e=new Set(t),i=this.focusId,s=0;for(;i&&i!==F&&s++<1e3;){if(e.has(i))return!0;i=this.tree.get(i)?.parent??null}return!1}async cmdCutNotes(){let t=this.getActionTargets();if(!t.length){new k.Notice("Nothing to cut.");return}let e=[];for(let s of t)s.file&&e.push(this.stripFrontmatter(await this.app.vault.cachedRead(s.file)).trim());let i=e.join(` -`);await navigator.clipboard.writeText(i),this.plugin.clearNoteClipboard(),this.plugin.noteClipboard={mode:"cut",folder:this.noteFolder,ids:t.map(s=>s.id),text:i},this.render(),this.plugin.noteClipboardNotice=this.plugin.notifications.show({message:`Cut ${this.titleList(t)} \u2014 paste in the LIST to move it there as a note; paste in a note's COMPOSER to drop its text in and delete the original (undoable). Esc cancels. Nothing happens until you paste.`,kind:"info",category:"system",affectedIds:t.map(s=>s.id),folder:this.noteFolder,duration:0})}async cmdPasteNotes(){let t=this.plugin.noteClipboard;if(!t){new k.Notice("The note clipboard is empty \u2014 copy or cut notes first.");return}if(t.folder!==this.noteFolder){let p=(this.currentChildren[this.cursorIdx]??null)?.parent??this.focusId??F,h=t.mode,I=t.folder,u=await this.plugin.crossFolderPaste(I,t.ids,this.noteFolder,p,h);if(!u||!u.rootIds.length)return;h==="cut"&&this.plugin.clearNoteClipboard();let f=this.noteFolder;this.tree.rebuild(f),this.pendingFocusIds=u.rootIds.slice(),this.render(),h==="cut"&&this.plugin.refreshOpenViewsForFolder(I);let C=I.split("/").pop(),B=u.rootIds.length,m=()=>{this.tree.rebuild(f),this.render(),this.plugin.refreshOpenViewsForFolder(I)};this.plugin.getUndoStack(f).push({label:`${h==="cut"?"Move":"Paste"} ${B} note${B===1?"":"s"} from ${C}`,undo:async()=>{await u.undo(),m()},redo:async()=>{await u.redo(),m()}});let w=h==="cut"?"Moved":"Pasted (copied)";this.plugin.notifications.show({message:`${w} ${B} note${B===1?"":"s"} (${u.noteCount} total) from "${C}" into this folder. Undo (in the list) reverses it.`,kind:"success",category:h==="cut"?"move":"clone",affectedIds:u.rootIds,folder:f,duration:0});return}let e=t.ids.map(g=>this.tree.get(g)).filter(g=>!!g&&!!g.file);if(!e.length){this.plugin.clearNoteClipboard(),this.render(),new k.Notice("Those notes no longer exist.");return}let i=this.currentChildren[this.cursorIdx]??null,s=i?.parent??this.focusId??F;if(t.mode==="cut"){let g=new Set(t.ids);for(let h=s;h&&h!==F;h=this.tree.get(h)?.parent??null)if(g.has(h)){new k.Notice("Can't paste cut notes under themselves.");return}let p=i&&!g.has(i.id)?i.id:"";this.plugin.clearNoteClipboard(),await this.moveAcrossThenReorder(e.map(h=>h.id),s,p,"after");return}let n=this.noteFolder,o=[],r=[];for(let g of e){let p=await this.cloneSubtree(g,s,o);p&&r.push(p)}if(!r.length)return;this.tree.rebuild(n),this.pendingFocusIds=r.slice(),this.render();let A=o.map(g=>this.app.vault.getAbstractFileByPath(g)).filter(g=>!!g&&g.extension==="md").map(g=>({id:ve(g.basename)??g.basename,parent:null,children:[],file:g,created:new Date().toISOString()})),l=await this.snapshotNotes(A,!1);this.plugin.getUndoStack(n).push({label:`Paste ${r.length} note${r.length===1?"":"s"}`,undo:async()=>{for(let g of[...o].reverse()){let p=this.app.vault.getAbstractFileByPath(g);if(p)try{await this.app.fileManager.trashFile(p)}catch{}}this.tree.rebuild(n),this.render()},redo:async()=>{await this.restoreSnapshots(l,r)}});let d=r.map(g=>this.tree.get(g)).filter(g=>!!g);this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Pasted (duplicated)",nodes:d,suffix:`(${o.length} file${o.length===1?"":"s"} total)`}),kind:"success",category:"clone",affectedIds:r,folder:n,duration:0})}async completeCutIntoComposer(){let t=this.plugin.noteClipboard;if(!t||t.mode!=="cut")return;if(t.folder!==this.noteFolder){let p=t.folder,h=t.ids.slice();this.plugin.clearNoteClipboard();let I=await this.plugin.orderedSubtreeNodes(p,h),u=j().prefixTimestampsOnCopy,f=[];for(let{file:Q,created:E,depth:v}of I)try{let y=this.stripFrontmatter(await this.app.vault.cachedRead(Q)).trim().split(/\r?\n/).join(" "),b=u?`${this.formatTimeInline(E)} `:"";f.push(`${" ".repeat(v)}- ${b}${y}`)}catch{}this.insertIntoComposer(f.length?f.join(` -`):t.text??"");let C=await this.plugin.subtreeFilePaths(p,h),B=await this.plugin.snapshotPaths(C),m=await this.plugin.trashSubtrees(p,h);this.plugin.refreshOpenViewsForFolder(p);let w=m.filter(Q=>Q.extension==="md").length;this.plugin.getUndoStack(p).push({label:`Cut ${h.length} note${h.length===1?"":"s"} into composer (from ${p.split("/").pop()})`,undo:async()=>{await this.plugin.restoreSnapshot(B),this.plugin.refreshOpenViewsForFolder(p)},redo:async()=>{await this.plugin.trashSubtrees(p,h),this.plugin.refreshOpenViewsForFolder(p)}}),this.plugin.notifications.show({message:`Pasted the text of ${h.length} cut note${h.length===1?"":"s"} from "${p.split("/").pop()}" into the composer and removed the original${w===1?"":"s"} (${w} note${w===1?"":"s"}). Undo restores them.`,kind:"warning",category:"delete",affectedIds:h,folder:p,duration:0});return}this.plugin.clearNoteClipboard();let e=t.ids.map(p=>this.tree.get(p)).filter(p=>!!p&&!!p.file);if(!e.length)return;let i=[],s=new Set,n=(p,h)=>{if(!s.has(p.id)){s.add(p.id),i.push({node:p,depth:h});for(let I of this.tree.getChildren(p.id))n(I,h+1)}};for(let p of e)n(p,0);let o=this.noteFolder,r=j().prefixTimestampsOnCopy,A=[];for(let{node:p,depth:h}of i)if(p.file)try{let I=this.stripFrontmatter(await this.app.vault.cachedRead(p.file)).trim().split(/\r?\n/).join(" "),u=r?`${this.formatTimeInline(p.created)} `:"";A.push(`${" ".repeat(h)}- ${u}${I}`)}catch{}this.insertIntoComposer(A.join(` -`));let l=i.map(p=>p.node),d=await this.snapshotNotes(l,!1);for(let p of[...l].reverse())if(p.file)try{await this.app.fileManager.trashFile(p.file)}catch(h){console.warn("[Stashpad] cut-paste delete failed",p.file.path,h)}this.selection.clear(),this.tree.rebuild(o),this.render();let g=e.map(p=>p.id);this.plugin.getUndoStack(o).push({label:`Cut ${e.length} note${e.length===1?"":"s"} into composer`,undo:async()=>{await this.restoreSnapshots(d,g)},redo:async()=>{for(let p of[...d.notes]){let h=this.app.vault.getAbstractFileByPath(p.path);if(h)try{await this.app.fileManager.trashFile(h)}catch{}}this.tree.rebuild(o),this.render()}}),this.plugin.notifications.show({message:`Pasted the text of ${this.titleList(e)} into the composer and deleted the original${e.length===1?"":"s"} (${l.length} note${l.length===1?"":"s"}). Undo (in the list) restores them.`,kind:"warning",category:"delete",affectedIds:g,folder:o,duration:0})}cmdInsertTemplate(){new te(this.app,this.tree,t=>this.titleForNode(t),{mode:"pick",placeholder:"Insert which note as a template?",allowCreate:!1,onPick:async t=>{if(t.crossFolder){new k.Notice("Cross-Stashpad templates aren't supported yet \u2014 pick a note from this Stashpad.");return}let e=this.tree.get(t.id);if(!e?.file)return;let i=this.noteFolder,s=[],n=await this.cloneSubtree(e,this.focusId,s);if(!n)return;this.tree.rebuild(i),this.pendingFocusIds=[n],this.render();let o=s.map(A=>this.app.vault.getAbstractFileByPath(A)).filter(A=>!!A&&A.extension==="md").map(A=>({id:ve(A.basename)??A.basename,parent:null,children:[],file:A,created:new Date().toISOString()})),r=await this.snapshotNotes(o,!1);this.plugin.getUndoStack(i).push({label:"Insert template",undo:async()=>{for(let A of[...s].reverse()){let l=this.app.vault.getAbstractFileByPath(A);if(l)try{await this.app.fileManager.trashFile(l)}catch{}}this.tree.rebuild(i),this.render()},redo:async()=>{await this.restoreSnapshots(r,[n])}}),this.plugin.notifications.show({message:`Inserted template (${s.length} file${s.length===1?"":"s"})`,kind:"success",category:"clone",folder:this.noteFolder})}}).open()}navigateTo(t,e={}){if(e.keepForwardStack||this.recordNavState(),this.selectionGuardKey++,this.listEl&&this.stampSelectedCursor(!0),this.focusId=t,this.persistFocus(),this.defaultCursorToLast(),this.syncComposerDraftForFocus(),this.tagFilter){let n=this.tagFilter.toLowerCase();this.collectFolderTags().some(r=>r.raw.toLowerCase()===n)||(this.tagFilter=null)}if(this.colorFilter){let n=this.colorFilter.toLowerCase();this.collectFolderColors().some(r=>r.hex===n)||(this.colorFilter=null)}let i=this.lastCursorByFocus.get(t),s;i&&this.tree.get(i)?(this.pendingFocusIds=[i],s={kind:"scroll-to-id",id:i,align:"start"}):s={kind:"preserve"},this.render(s),this.refreshHeaderTitle(),this.viewRoot.focus({preventScroll:!0}),this.plugin.notifyStashpadSelectionChanged()}navigateBack(){let t=this.navBackStack.pop();if(!t){this.focusId!==F&&this.navigateUp();return}this.navForwardSnapshots.push(this.captureNavSnapshot()),this.applyNavSnapshot(t)}navigateForward(){let t=this.navForwardSnapshots.pop();t&&(this.navBackStack.push(this.captureNavSnapshot()),this.applyNavSnapshot(t))}async applyNavSnapshot(t){if(this.tagFilter=null,this.colorFilter=null,t.folder!==this.noteFolder){await this.setFolderOverride(t.folder,{skipHistory:!0}),t.focusId!==this.focusId&&this.tree.get(t.focusId)&&(this.focusId=t.focusId,this.render({kind:"preserve"}));return}if(!this.tree.get(t.focusId))return;this.selectionGuardKey++,this.listEl&&this.stampSelectedCursor(!0),this.focusId=t.focusId,this.persistFocus(),this.defaultCursorToLast(),this.syncComposerDraftForFocus();let e=this.lastCursorByFocus.get(t.focusId),i;e&&this.tree.get(e)?(this.pendingFocusIds=[e],i={kind:"scroll-to-id",id:e,align:"start"}):i={kind:"preserve"},this.render(i),this.refreshHeaderTitle(),this.viewRoot.focus({preventScroll:!0})}navigateUp(){this.selectionGuardKey++,this.tagFilter=null,this.colorFilter=null;let t=this.tree.get(this.focusId);if(!t||t.parent==null){if(this.navBackStack.length>0){this.navigateBack();return}return this.navigateTo(F)}let e=this.focusId;if(this.recordNavState(),this.listEl){let o=this.currentChildren[this.cursorIdx]?.id??this.lastSelected;o&&this.plugin.saveLastCursor(this.noteFolder,e,o)}this.focusId=t.parent,this.persistFocus(),this.syncComposerDraftForFocus();let i=this.filterChildren(this.tree.getChildren(this.focusId)),s=i.findIndex(n=>n.id===e);this.selection.clear(),s>=0?(this.cursorIdx=s,this.selection.add(e),this.lastSelected=e):(this.cursorIdx=i.length-1,i.length>0&&(this.selection.add(i[i.length-1].id),this.lastSelected=i[i.length-1].id)),s>=0?this.render({kind:"scroll-to-id",id:e,align:"start"}):this.render({kind:"follow-cursor"}),this.refreshHeaderTitle(),s<0&&this.revealCursorRow()}openBookmarks(){let t=this.app.internalPlugins?.plugins?.bookmarks?.instance?.items??[],e=this.allowedByBases(),i=new k.Menu,s=0;for(let n of t){if(n.type!=="file"||e&&!e.has(n.path))continue;let o=this.tree.idForPath(n.path);o&&(i.addItem(r=>r.setTitle(n.title||n.path).onClick(()=>this.navigateTo(o))),s++)}s||i.addItem(n=>n.setTitle("(no bookmarks in scope)").setDisabled(!0)),i.showAtMouseEvent(new MouseEvent("click",{clientX:200,clientY:400}))}async bootstrapFolder(){if(this.bootstrappedFolders.has(this.noteFolder))return;await this.ensureFolder(this.noteFolder),await this.ensureHomeNote(),await this.migrateNullParents();let t=(this.plugin.settings.importDropFolder||"").trim().replace(/^\/+|\/+$/g,""),e=(this.plugin.settings.exportFolder||"").trim().replace(/^\/+|\/+$/g,"");t&&await this.ensureFolder(`${this.noteFolder}/${t}`),e&&await this.ensureFolder(`${this.noteFolder}/${e}`),await this.order.load(this.noteFolder),await this.sortStore.load(this.noteFolder),this.bootstrappedFolders.add(this.noteFolder)}backfillFrontmatterSync(){let t=[F],e=this.tree.getRoot(),i=s=>{for(let n of this.tree.getChildren(s))t.push(n.id),i(n.id)};for(let s of e.children)i(s);for(let s of t)this.fmSync.wouldWrite(s)&&this.fmSync.schedule(s)}installFmSyncActivityNotice(){this.fmSyncUnsubscribe||(this.fmSyncUnsubscribe=this.fmSync.onError((t,e)=>{this.plugin.notifications.show({message:`Stashpad: couldn't update recovery metadata +`);await navigator.clipboard.writeText(i),this.plugin.clearNoteClipboard(),this.plugin.noteClipboard={mode:"cut",folder:this.noteFolder,ids:t.map(s=>s.id),text:i},this.render(),this.plugin.noteClipboardNotice=this.plugin.notifications.show({message:`Cut ${this.titleList(t)} \u2014 paste in the LIST to move it there as a note; paste in a note's COMPOSER to drop its text in and delete the original (undoable). Esc cancels. Nothing happens until you paste.`,kind:"info",category:"system",affectedIds:t.map(s=>s.id),folder:this.noteFolder,duration:0})}async cmdPasteNotes(){let t=this.plugin.noteClipboard;if(!t){new k.Notice("The note clipboard is empty \u2014 copy or cut notes first.");return}if(t.folder!==this.noteFolder){let g=(this.currentChildren[this.cursorIdx]??null)?.parent??this.focusId??F,h=t.mode,I=t.folder,u=await this.plugin.crossFolderPaste(I,t.ids,this.noteFolder,g,h);if(!u||!u.rootIds.length)return;h==="cut"&&this.plugin.clearNoteClipboard();let f=this.noteFolder;this.tree.rebuild(f),this.pendingFocusIds=u.rootIds.slice(),this.render(),h==="cut"&&this.plugin.refreshOpenViewsForFolder(I);let C=I.split("/").pop(),B=u.rootIds.length,m=()=>{this.tree.rebuild(f),this.render(),this.plugin.refreshOpenViewsForFolder(I)};this.plugin.getUndoStack(f).push({label:`${h==="cut"?"Move":"Paste"} ${B} note${B===1?"":"s"} from ${C}`,undo:async()=>{await u.undo(),m()},redo:async()=>{await u.redo(),m()}});let y=h==="cut"?"Moved":"Pasted (copied)";this.plugin.notifications.show({message:`${y} ${B} note${B===1?"":"s"} (${u.noteCount} total) from "${C}" into this folder. Undo (in the list) reverses it.`,kind:"success",category:h==="cut"?"move":"clone",affectedIds:u.rootIds,folder:f,duration:0});return}let e=t.ids.map(p=>this.tree.get(p)).filter(p=>!!p&&!!p.file);if(!e.length){this.plugin.clearNoteClipboard(),this.render(),new k.Notice("Those notes no longer exist.");return}let i=this.currentChildren[this.cursorIdx]??null,s=i?.parent??this.focusId??F;if(t.mode==="cut"){let p=new Set(t.ids);for(let h=s;h&&h!==F;h=this.tree.get(h)?.parent??null)if(p.has(h)){new k.Notice("Can't paste cut notes under themselves.");return}let g=i&&!p.has(i.id)?i.id:"";this.plugin.clearNoteClipboard(),await this.moveAcrossThenReorder(e.map(h=>h.id),s,g,"after");return}let n=this.noteFolder,o=[],r=[];for(let p of e){let g=await this.cloneSubtree(p,s,o);g&&r.push(g)}if(!r.length)return;this.tree.rebuild(n),this.pendingFocusIds=r.slice(),this.render();let A=o.map(p=>this.app.vault.getAbstractFileByPath(p)).filter(p=>!!p&&p.extension==="md").map(p=>({id:le(p.basename)??p.basename,parent:null,children:[],file:p,created:new Date().toISOString()})),l=await this.snapshotNotes(A,!1);this.plugin.getUndoStack(n).push({label:`Paste ${r.length} note${r.length===1?"":"s"}`,undo:async()=>{for(let p of[...o].reverse()){let g=this.app.vault.getAbstractFileByPath(p);if(g)try{await this.app.fileManager.trashFile(g)}catch{}}this.tree.rebuild(n),this.render()},redo:async()=>{await this.restoreSnapshots(l,r)}});let d=r.map(p=>this.tree.get(p)).filter(p=>!!p);this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Pasted (duplicated)",nodes:d,suffix:`(${o.length} file${o.length===1?"":"s"} total)`}),kind:"success",category:"clone",affectedIds:r,folder:n,duration:0})}async completeCutIntoComposer(){let t=this.plugin.noteClipboard;if(!t||t.mode!=="cut")return;if(t.folder!==this.noteFolder){let g=t.folder,h=t.ids.slice();this.plugin.clearNoteClipboard();let I=await this.plugin.orderedSubtreeNodes(g,h),u=j().prefixTimestampsOnCopy,f=[];for(let{file:Q,created:E,depth:v}of I)try{let w=this.stripFrontmatter(await this.app.vault.cachedRead(Q)).trim().split(/\r?\n/).join(" "),D=u?`${this.formatTimeInline(E)} `:"";f.push(`${" ".repeat(v)}- ${D}${w}`)}catch{}this.insertIntoComposer(f.length?f.join(` +`):t.text??"");let C=await this.plugin.subtreeFilePaths(g,h),B=await this.plugin.snapshotPaths(C),m=await this.plugin.trashSubtrees(g,h);this.plugin.refreshOpenViewsForFolder(g);let y=m.filter(Q=>Q.extension==="md").length;this.plugin.getUndoStack(g).push({label:`Cut ${h.length} note${h.length===1?"":"s"} into composer (from ${g.split("/").pop()})`,undo:async()=>{await this.plugin.restoreSnapshot(B),this.plugin.refreshOpenViewsForFolder(g)},redo:async()=>{await this.plugin.trashSubtrees(g,h),this.plugin.refreshOpenViewsForFolder(g)}}),this.plugin.notifications.show({message:`Pasted the text of ${h.length} cut note${h.length===1?"":"s"} from "${g.split("/").pop()}" into the composer and removed the original${y===1?"":"s"} (${y} note${y===1?"":"s"}). Undo restores them.`,kind:"warning",category:"delete",affectedIds:h,folder:g,duration:0});return}this.plugin.clearNoteClipboard();let e=t.ids.map(g=>this.tree.get(g)).filter(g=>!!g&&!!g.file);if(!e.length)return;let i=[],s=new Set,n=(g,h)=>{if(!s.has(g.id)){s.add(g.id),i.push({node:g,depth:h});for(let I of this.tree.getChildren(g.id))n(I,h+1)}};for(let g of e)n(g,0);let o=this.noteFolder,r=j().prefixTimestampsOnCopy,A=[];for(let{node:g,depth:h}of i)if(g.file)try{let I=this.stripFrontmatter(await this.app.vault.cachedRead(g.file)).trim().split(/\r?\n/).join(" "),u=r?`${this.formatTimeInline(g.created)} `:"";A.push(`${" ".repeat(h)}- ${u}${I}`)}catch{}this.insertIntoComposer(A.join(` +`));let l=i.map(g=>g.node),d=await this.snapshotNotes(l,!1);for(let g of[...l].reverse())if(g.file)try{await this.app.fileManager.trashFile(g.file)}catch(h){console.warn("[Stashpad] cut-paste delete failed",g.file.path,h)}this.selection.clear(),this.tree.rebuild(o),this.render();let p=e.map(g=>g.id);this.plugin.getUndoStack(o).push({label:`Cut ${e.length} note${e.length===1?"":"s"} into composer`,undo:async()=>{await this.restoreSnapshots(d,p)},redo:async()=>{for(let g of[...d.notes]){let h=this.app.vault.getAbstractFileByPath(g.path);if(h)try{await this.app.fileManager.trashFile(h)}catch{}}this.tree.rebuild(o),this.render()}}),this.plugin.notifications.show({message:`Pasted the text of ${this.titleList(e)} into the composer and deleted the original${e.length===1?"":"s"} (${l.length} note${l.length===1?"":"s"}). Undo (in the list) restores them.`,kind:"warning",category:"delete",affectedIds:p,folder:o,duration:0})}cmdInsertTemplate(){new zt(this.app,this.tree,t=>this.titleForNode(t),{mode:"pick",placeholder:"Insert which note as a template?",allowCreate:!1,onPick:async t=>{if(t.crossFolder){new k.Notice("Cross-Stashpad templates aren't supported yet \u2014 pick a note from this Stashpad.");return}let e=this.tree.get(t.id);if(!e?.file)return;let i=this.noteFolder,s=[],n=await this.cloneSubtree(e,this.focusId,s);if(!n)return;this.tree.rebuild(i),this.pendingFocusIds=[n],this.render();let o=s.map(A=>this.app.vault.getAbstractFileByPath(A)).filter(A=>!!A&&A.extension==="md").map(A=>({id:le(A.basename)??A.basename,parent:null,children:[],file:A,created:new Date().toISOString()})),r=await this.snapshotNotes(o,!1);this.plugin.getUndoStack(i).push({label:"Insert template",undo:async()=>{for(let A of[...s].reverse()){let l=this.app.vault.getAbstractFileByPath(A);if(l)try{await this.app.fileManager.trashFile(l)}catch{}}this.tree.rebuild(i),this.render()},redo:async()=>{await this.restoreSnapshots(r,[n])}}),this.plugin.notifications.show({message:`Inserted template (${s.length} file${s.length===1?"":"s"})`,kind:"success",category:"clone",folder:this.noteFolder})}}).open()}navigateTo(t,e={}){if(e.keepForwardStack||this.recordNavState(),this.selectionGuardKey++,this.listEl&&this.stampSelectedCursor(!0),this.focusId=t,this.persistFocus(),this.defaultCursorToLast(),this.syncComposerDraftForFocus(),this.tagFilter&&this.tagFilter!==ve&&this.tagFilter!==Fe){let n=this.tagFilter.toLowerCase();this.collectFolderTags().some(r=>r.raw.toLowerCase()===n)||(this.tagFilter=null)}if(this.colorFilter){let n=this.colorFilter.toLowerCase();this.collectFolderColors().some(r=>r.hex===n)||(this.colorFilter=null)}let i=this.lastCursorByFocus.get(t),s;i&&this.tree.get(i)?(this.pendingFocusIds=[i],s={kind:"scroll-to-id",id:i,align:"start"}):s={kind:"preserve"},this.render(s),this.refreshHeaderTitle(),this.viewRoot.focus({preventScroll:!0}),this.plugin.notifyStashpadSelectionChanged()}navigateBack(){let t=this.navBackStack.pop();if(!t){this.focusId!==F&&this.navigateUp();return}this.navForwardSnapshots.push(this.captureNavSnapshot()),this.applyNavSnapshot(t)}navigateForward(){let t=this.navForwardSnapshots.pop();t&&(this.navBackStack.push(this.captureNavSnapshot()),this.applyNavSnapshot(t))}async applyNavSnapshot(t){if(this.tagFilter=null,this.colorFilter=null,t.folder!==this.noteFolder){await this.setFolderOverride(t.folder,{skipHistory:!0}),t.focusId!==this.focusId&&this.tree.get(t.focusId)&&(this.focusId=t.focusId,this.render({kind:"preserve"}));return}if(!this.tree.get(t.focusId))return;this.selectionGuardKey++,this.listEl&&this.stampSelectedCursor(!0),this.focusId=t.focusId,this.persistFocus(),this.defaultCursorToLast(),this.syncComposerDraftForFocus();let e=this.lastCursorByFocus.get(t.focusId),i;e&&this.tree.get(e)?(this.pendingFocusIds=[e],i={kind:"scroll-to-id",id:e,align:"start"}):i={kind:"preserve"},this.render(i),this.refreshHeaderTitle(),this.viewRoot.focus({preventScroll:!0})}navigateUp(){this.selectionGuardKey++,this.tagFilter=null,this.colorFilter=null;let t=this.tree.get(this.focusId);if(!t||t.parent==null){if(this.navBackStack.length>0){this.navigateBack();return}return this.navigateTo(F)}let e=this.focusId;if(this.recordNavState(),this.listEl){let o=this.currentChildren[this.cursorIdx]?.id??this.lastSelected;o&&this.plugin.saveLastCursor(this.noteFolder,e,o)}this.focusId=t.parent,this.persistFocus(),this.syncComposerDraftForFocus();let i=this.filterChildren(this.tree.getChildren(this.focusId)),s=i.findIndex(n=>n.id===e);this.selection.clear(),s>=0?(this.cursorIdx=s,this.selection.add(e),this.lastSelected=e):(this.cursorIdx=i.length-1,i.length>0&&(this.selection.add(i[i.length-1].id),this.lastSelected=i[i.length-1].id)),s>=0?this.render({kind:"scroll-to-id",id:e,align:"start"}):this.render({kind:"follow-cursor"}),this.refreshHeaderTitle(),s<0&&this.revealCursorRow()}openBookmarks(){let t=this.app.internalPlugins?.plugins?.bookmarks?.instance?.items??[],e=this.allowedByBases(),i=new k.Menu,s=0;for(let n of t){if(n.type!=="file"||e&&!e.has(n.path))continue;let o=this.tree.idForPath(n.path);o&&(i.addItem(r=>r.setTitle(n.title||n.path).onClick(()=>this.navigateTo(o))),s++)}s||i.addItem(n=>n.setTitle("(no bookmarks in scope)").setDisabled(!0)),i.showAtMouseEvent(new MouseEvent("click",{clientX:200,clientY:400}))}async bootstrapFolder(){if(this.bootstrappedFolders.has(this.noteFolder))return;await this.ensureFolder(this.noteFolder),await this.ensureHomeNote(),await this.migrateNullParents();let t=(this.plugin.settings.importDropFolder||"").trim().replace(/^\/+|\/+$/g,""),e=(this.plugin.settings.exportFolder||"").trim().replace(/^\/+|\/+$/g,"");t&&await this.ensureFolder(`${this.noteFolder}/${t}`),e&&await this.ensureFolder(`${this.noteFolder}/${e}`),await this.order.load(this.noteFolder),await this.sortStore.load(this.noteFolder),this.bootstrappedFolders.add(this.noteFolder)}backfillFrontmatterSync(){let t=[F],e=this.tree.getRoot(),i=s=>{for(let n of this.tree.getChildren(s))t.push(n.id),i(n.id)};for(let s of e.children)i(s);for(let s of t)this.fmSync.wouldWrite(s)&&this.fmSync.schedule(s)}installFmSyncActivityNotice(){this.fmSyncUnsubscribe||(this.fmSyncUnsubscribe=this.fmSync.onError((t,e)=>{this.plugin.notifications.show({message:`Stashpad: couldn't update recovery metadata File: \`${t}\` Error: ${e.message}`,kind:"error",category:"system",duration:0,affectedPaths:[t],folder:this.noteFolder})}))}async ensureHomeNote(){let t=this.noteFolder,e=`${t}/${this.buildHomeFilename(t)}`,i=this.app.vault.getMarkdownFiles().filter(o=>o.path.startsWith(t+"/"));for(let o of i){if(this.app.metadataCache.getFileCache(o)?.frontmatter?.id!==F)continue;if(o.path===e||this.app.vault.getAbstractFileByPath(e))return o;try{await this.app.fileManager.renameFile(o,e);let l=this.app.vault.getAbstractFileByPath(e);if(l instanceof k.TFile)return l}catch(l){console.warn("[Stashpad] home note rename failed; keeping legacy path",l)}return o}let s=new Date().toISOString(),n=["---",`id: ${F}`,"parent: null",`created: ${s}`,"attachments: []","---","","# Home","","This is your Stashpad home note. Edit me freely \u2014 everything else nests below.",""].join(` -`);return this.app.vault.create(e,n)}buildHomeFilename(t){return`Home-${(t.split("/").filter(Boolean).pop()??"Stashpad").replace(/[^A-Za-z0-9_-]+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")||"Stashpad"}.md`}async migrateNullParents(){let t=this.noteFolder,e=this.app.vault.getMarkdownFiles().filter(i=>i.path.startsWith(t+"/"));for(let i of e){let s=this.app.metadataCache.getFileCache(i)?.frontmatter,n=s?.id;if(!n||n===F)continue;let o=s?.parent;(o==null||o===""||o==="null")&&(await this.app.fileManager.processFrontMatter(i,r=>{r.parent=F}),await this.log.append({type:"parent_change",id:n,payload:{from:null,to:F,reason:"migration"}}))}}async openInNewStashpadTab(t){let e=this.app.workspace,i=this.leaf,s=e.getLeaf("tab");await s.setViewState({type:J,active:!0,state:{focusId:t,timeFilter:this.timeFilter,folderOverride:this.folderOverride}}),e.setActiveLeaf(s,{focus:!0}),e.revealLeaf(s);let n=e.on("active-leaf-change",()=>{if((()=>{let A=!1;return e.iterateAllLeaves(l=>{l===s&&(A=!0)}),A})())return;e.offref(n),(()=>{let A=!1;return e.iterateAllLeaves(l=>{l===i&&(A=!0)}),A})()&&(e.setActiveLeaf(i,{focus:!0}),e.revealLeaf(i))})}async openNoteInNewTab(t,e){let i=(t||"").trim().replace(/^\/+|\/+$/g,"");if(!i||!e)return;let s=(this.plugin.settings.folder||"Stashpad").trim().replace(/^\/+|\/+$/g,"")||"Stashpad",n=this.app.workspace,o=n.getLeaf("tab");await o.setViewState({type:J,active:!0,state:{focusId:e,folderOverride:i===s?null:i}}),n.setActiveLeaf(o,{focus:!0}),n.revealLeaf(o)}async openFolderInNewTab(t){let e=(t||"").trim().replace(/^\/+|\/+$/g,"");if(!e)return;let i=(this.plugin.settings.folder||"Stashpad").trim().replace(/^\/+|\/+$/g,"")||"Stashpad",s=this.app.workspace,n=this.leaf,o=s.getLeaf("tab");await o.setViewState({type:J,active:!0,state:{focusId:F,folderOverride:e===i?null:e}}),s.setActiveLeaf(o,{focus:!0}),s.revealLeaf(o);let r=s.on("active-leaf-change",()=>{if((()=>{let d=!1;return s.iterateAllLeaves(g=>{g===o&&(d=!0)}),d})())return;s.offref(r),(()=>{let d=!1;return s.iterateAllLeaves(g=>{g===n&&(d=!0)}),d})()&&(s.setActiveLeaf(n,{focus:!0}),s.revealLeaf(n))})}cmdOpenInEditor(t){if(t){this.openFileAtEnd(t.file);return}let e=this.getActionTargets();if(e.length)for(let i of e)i.file&&this.openFileAtEnd(i.file)}cmdOpenParentInEditor(){let t=this.tree.get(this.focusId);if(!t?.file){new k.Notice("No focused parent to open.");return}this.openFileAtEnd(t.file)}async openFileAtEnd(t){let e=this.app.workspace,i=this.leaf,s=e.getLeaf("tab");await s.openFile(t,{active:!0}),e.setActiveLeaf(s,{focus:!0}),e.revealLeaf(s);let n=e.on("active-leaf-change",()=>{if((()=>{let d=!1;return e.iterateAllLeaves(g=>{g===s&&(d=!0)}),d})())return;e.offref(n),(()=>{let d=!1;return e.iterateAllLeaves(g=>{g===i&&(d=!0)}),d})()&&(e.setActiveLeaf(i,{focus:!0}),e.revealLeaf(i))}),r=s.view?.editor;r&&requestAnimationFrame(()=>{try{let A=r.lastLine(),l=r.getLine(A)?.length??0;r.setCursor({line:A,ch:l}),r.scrollIntoView({from:{line:A,ch:l},to:{line:A,ch:l}},!0),r.focus()}catch{}})}cmdSelectAll(){if(this.currentChildren.length!==0){this.selection.clear();for(let t of this.currentChildren)this.selection.add(t.id);this.firstSelectedId=this.currentChildren[0].id,this.lastSelected=this.currentChildren[this.currentChildren.length-1].id,this.cursorIdx=this.currentChildren.length-1,this.render()}}async cmdTogglePin(){let t=this.getActionTargets();if(t.length===0){let n=this.tree.get(this.focusId);n?.file&&(t=[n])}if(t.length===0){new k.Notice("Nothing to pin.");return}let e=t.some(n=>!this.plugin.isPinned({folder:this.noteFolder,id:n.id})),i=0,s=0;for(let n of t){let o={folder:this.noteFolder,id:n.id};e?this.plugin.isPinned(o)||(await this.plugin.pinNote(o),i++):this.plugin.isPinned(o)&&(await this.plugin.unpinNote(o),s++)}i>0?new k.Notice(`Pinned ${i} note${i===1?"":"s"} to sidebar.`):s>0&&new k.Notice(`Unpinned ${s} note${s===1?"":"s"} from sidebar.`)}async cmdToggleComplete(){let t=this.getActionTargets();if(t.length===0){let r=this.tree.get(this.focusId);r?.file&&(t=[r])}if(t.length===0){new k.Notice("Nothing to toggle.");return}let i=t.some(r=>!this.isCompleted(r)),s=[],n=[];for(let r of t){if(!r.file)continue;let A=this.isCompleted(r);s.push({id:r.id,path:r.file.path,was:A}),A!==i&&(await this.app.fileManager.processFrontMatter(r.file,l=>{i?l.completed=!0:delete l.completed}),this.completedState.set(r.file.path,i),n.push(r.id))}if(this.render(),n.length>0){await this.log.append({type:i?"complete":"uncomplete",id:n[0],payload:{ids:n,count:n.length}});let r=n.map(A=>this.tree.get(A)).filter(A=>!!A);this.plugin.notifications.show({message:this.bulkActionMessage({verb:i?"Marked complete":"Unmarked",nodes:r}),kind:"success",category:i?"complete":"uncomplete",affectedIds:n,folder:this.noteFolder})}let o=this.noteFolder;this.plugin.getUndoStack(o).push({label:`${i?"Mark complete":"Unmark complete"} (${t.length})`,undo:async()=>{let r=[];for(let A of s){let l=this.app.vault.getAbstractFileByPath(A.path);l&&(await this.app.fileManager.processFrontMatter(l,d=>{A.was?d.completed=!0:delete d.completed}),n.includes(A.id)&&r.push(A.id))}r.length>0&&await this.log.append({type:i?"uncomplete":"complete",id:r[0],payload:{ids:r,count:r.length,undo:!0}}),this.tree.rebuild(o),this.render()},redo:async()=>{for(let r of s){let A=this.app.vault.getAbstractFileByPath(r.path);A&&await this.app.fileManager.processFrontMatter(A,l=>{i?l.completed=!0:delete l.completed})}n.length>0&&await this.log.append({type:i?"complete":"uncomplete",id:n[0],payload:{ids:n,count:n.length,redo:!0}}),this.tree.rebuild(o),this.render()}})}isCompleted(t){if(!t.file)return!1;let e=this.completedState.get(t.file.path);return e!==void 0?e:!!this.app.metadataCache.getFileCache(t.file)?.frontmatter?.completed}taggedFromFm(t){return t?be(t,"task")||t.task===!0:!1}cmdSetDue(){let t=this.getActionTargets();if(t.length===0){let r=this.tree.get(this.focusId);r?.file&&(t=[r])}if(t.length===0){new k.Notice("Nothing to schedule.");return}let e=t[0],i=e.file?this.app.metadataCache.getFileCache(e.file)?.frontmatter:null,s=i&&(typeof i.due=="string"||typeof i.due=="number")?String(i.due):null,n=this.plugin.collectKnownAuthors(),o=me(i??{});new li(this.app,s,r=>{this.applyDue(t,r.iso,r.assignees)},{knownAuthors:n,currentAssignees:o}).open()}async applyDue(t,e,i=[]){let s=[],n=[],o=this.authorship.currentAuthorLink();for(let l of i)await this.plugin.ensureAuthorStubFor(this.noteFolder,l.id,l.name);let r=i.map(l=>this.plugin.authorRefFor(this.noteFolder,l.id,l.name));for(let l of t){if(!l.file)continue;let d=this.app.metadataCache.getFileCache(l.file)?.frontmatter,g=this.isTaskTagged(l);s.push({id:l.id,path:l.file.path,due:d?.due,task:d?.task,assignedTo:d?.assignedTo,assignedBy:d?.assignedBy,wasTagged:g}),await this.app.fileManager.processFrontMatter(l.file,h=>{e===null?delete h.due:(h.due=e,h.task=!0),r.length>0?(h.assignedTo=r,o&&(h.assignedBy=o.link),h.task=!0):(delete h.assignedTo,delete h.assignedBy)});let p=e!==null||r.length>0;this.taskTaggedState.set(l.file.path,p||g),n.push(l.id)}if(this.render(),n.length>0){let l=n.map(d=>this.tree.get(d)).filter(d=>!!d);this.plugin.notifications.show({message:this.bulkActionMessage({verb:e===null?"Cleared due date":`Due ${Yt(Date.parse(e),this.plugin.settings)}`,nodes:l}),kind:"success",category:"edit",affectedIds:n,folder:this.noteFolder})}let A=this.noteFolder;this.plugin.getUndoStack(A).push({label:e===null?`Clear due date (${t.length})`:`Set due date (${t.length})`,undo:async()=>{for(let l of s){let d=this.app.vault.getAbstractFileByPath(l.path);d&&(await this.app.fileManager.processFrontMatter(d,g=>{l.due===void 0?delete g.due:g.due=l.due,l.task===void 0?delete g.task:g.task=l.task,l.assignedTo===void 0?delete g.assignedTo:g.assignedTo=l.assignedTo,l.assignedBy===void 0?delete g.assignedBy:g.assignedBy=l.assignedBy}),this.taskTaggedState.set(l.path,l.wasTagged))}this.tree.rebuild(A),this.render()}})}cmdAssign(){let t=this.getActionTargets();if(t.length===0){let o=this.tree.get(this.focusId);o?.file&&(t=[o])}if(t.length===0){new k.Notice("Nothing to assign.");return}let e=t[0],i=e.file?this.app.metadataCache.getFileCache(e.file)?.frontmatter:null,s=this.plugin.collectKnownAuthors(),n=me(i??{});new Ai(this.app,{knownAuthors:s,currentAssignees:n},o=>{this.applyAssignees(t,o)}).open()}async applyAssignees(t,e){let i=this.authorship.currentAuthorLink();for(let A of e)await this.plugin.ensureAuthorStubFor(this.noteFolder,A.id,A.name);let s=e.map(A=>this.plugin.authorRefFor(this.noteFolder,A.id,A.name)),n=[],o=[];for(let A of t){if(!A.file)continue;let l=this.app.metadataCache.getFileCache(A.file)?.frontmatter,d=this.isTaskTagged(A);n.push({path:A.file.path,assignedTo:l?.assignedTo,assignedBy:l?.assignedBy,task:l?.task,wasTagged:d}),await this.app.fileManager.processFrontMatter(A.file,g=>{s.length>0?(g.assignedTo=s,i&&(g.assignedBy=i.link),g.task=!0):(delete g.assignedTo,delete g.assignedBy)}),this.taskTaggedState.set(A.file.path,s.length>0||d),o.push(A.id)}if(this.render(),o.length>0){let A=o.map(d=>this.tree.get(d)).filter(d=>!!d),l=e.map(d=>d.name).join(", ");this.plugin.notifications.show({message:this.bulkActionMessage({verb:s.length>0?`Assigned to ${l}`:"Cleared assignment",nodes:A}),kind:"success",category:"edit",affectedIds:o,folder:this.noteFolder})}let r=this.noteFolder;this.plugin.getUndoStack(r).push({label:s.length>0?`Assign (${t.length})`:`Clear assignment (${t.length})`,undo:async()=>{for(let A of n){let l=this.app.vault.getAbstractFileByPath(A.path);l&&(await this.app.fileManager.processFrontMatter(l,d=>{A.assignedTo===void 0?delete d.assignedTo:d.assignedTo=A.assignedTo,A.assignedBy===void 0?delete d.assignedBy:d.assignedBy=A.assignedBy,A.task===void 0?delete d.task:d.task=A.task}),this.taskTaggedState.set(A.path,A.wasTagged))}this.tree.rebuild(r),this.render()}})}isTask(t){return t.file?this.isTaskTagged(t)?!0:this.app.metadataCache.getFileCache(t.file)?.frontmatter?.completed!==void 0:!1}async cmdToggleTask(){let t=this.getActionTargets();if(t.length===0){let r=this.tree.get(this.focusId);r?.file&&(t=[r])}if(t.length===0){new k.Notice("Nothing to toggle.");return}let e=t.some(r=>!this.isTaskTagged(r)),i=[],s=[];for(let r of t){if(!r.file)continue;let A=this.isTaskTagged(r),l=this.app.metadataCache.getFileCache(r.file)?.frontmatter;if(i.push({id:r.id,path:r.file.path,tags:l?.tags,completed:l?.completed,task:l?.task,wasTagged:A}),A===e)continue;let d=!1;await this.app.fileManager.processFrontMatter(r.file,g=>{e?(Xs(g,"task"),g.completed===void 0&&(g.completed=!1),d=g.completed===!0,delete g.task):(Zs(g,"task"),delete g.completed,delete g.task,d=!1)}),this.completedState.set(r.file.path,d),this.taskTaggedState.set(r.file.path,e),s.push(r.id)}if(this.render(),s.length>0){let r=e?"marked as task":"unmarked as task",A;if(s.length===1){let l=this.tree.get(s[0]);A=`"${l&&this.titleForNode(l).trim()||"(untitled)"}" ${r}`}else A=`${s.length} notes ${r}`;this.plugin.notifications.show({message:A,kind:"success",category:"edit",affectedIds:s,folder:this.noteFolder})}let n=this.noteFolder,o=async()=>{for(let r of i){let A=this.app.vault.getAbstractFileByPath(r.path);A&&(await this.app.fileManager.processFrontMatter(A,l=>{r.tags===void 0?delete l.tags:l.tags=r.tags,r.completed===void 0?delete l.completed:l.completed=r.completed,r.task===void 0?delete l.task:l.task=r.task}),this.completedState.set(r.path,!!r.completed),this.taskTaggedState.set(r.path,r.wasTagged))}this.tree.rebuild(n),this.render()};this.plugin.getUndoStack(n).push({label:`${e?"Mark task":"Unmark task"} (${t.length})`,undo:o,redo:async()=>{for(let r of i){let A=this.app.vault.getAbstractFileByPath(r.path);if(!A)continue;let l=!1;await this.app.fileManager.processFrontMatter(A,d=>{e?(Xs(d,"task"),d.completed===void 0&&(d.completed=!1),l=d.completed===!0,delete d.task):(Zs(d,"task"),delete d.completed,delete d.task,l=!1)}),this.completedState.set(r.path,l),this.taskTaggedState.set(r.path,e)}this.tree.rebuild(n),this.render()}})}async toggleCompletedForNode(t){if(!t.file)return;let e=t.file.path,i=this.isCompleted(t);await this.app.fileManager.processFrontMatter(t.file,n=>{n.completed=!i}),this.completedState.set(e,!i),await this.log.append({type:i?"uncomplete":"complete",id:t.id}),this.render();let s=this.noteFolder;this.plugin.getUndoStack(s).push({label:i?"Mark incomplete":"Mark complete",undo:async()=>{let n=this.app.vault.getAbstractFileByPath(e);n&&(await this.app.fileManager.processFrontMatter(n,o=>{o.completed=i}),this.tree.rebuild(s),this.render())}})}isTaskTagged(t){if(!t.file)return!1;let e=this.taskTaggedState.get(t.file.path);if(e!==void 0)return e;let i=this.app.metadataCache.getFileCache(t.file)?.frontmatter;return this.taggedFromFm(i)}colorForNode(t){if(!t.file)return null;let e=this.app.metadataCache.getFileCache(t.file)?.frontmatter?.color;if(typeof e!="string")return null;let i=e.trim();return/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(i)?i:null}inheritedColorForNode(t){let e=t,i=0,s=new Set;for(;e&&e.id!==F&&!s.has(e.id);){s.add(e.id);let n=this.colorForNode(e);if(n)return{hex:n,depth:i};e=e.parent?this.tree.get(e.parent):void 0,i+=1}return null}isDescendant(t,e){let i=this.tree.get(t),s=new Set;for(;i&&i.parent&&!s.has(i.id);){if(i.parent===e)return!0;s.add(i.id),i=this.tree.get(i.parent)}return!1}async moveAcrossThenReorder(t,e,i,s){let n=[],o=new Set;for(let v of t){let y=this.tree.get(v);y?.file&&(n.push({id:v,path:y.file.path,oldParent:y.parent}),o.add(y.parent??F))}o.add(e);let r=this.authorship.collectAuthorIds(t.map(v=>this.tree.get(v)).filter(v=>!!v)),A=this.noteFolder,l={};for(let v of o)l[v]=this.order.getOrder(A,v).slice();for(let v of n){let y=this.app.vault.getAbstractFileByPath(v.path);y&&(await this.app.fileManager.processFrontMatter(y,b=>{b.parent=e}),this.fmSync.scheduleParentChange(v.id,v.oldParent,e),await this.log.append({type:"parent_change",id:v.id,payload:{from:v.oldParent,to:e,reason:"drag"}}),this.order.removeChild(A,v.id))}this.tree.rebuild(A);let d=this.tree.getChildren(e).map(v=>v.id),g=new Set(t),p=d.filter(v=>!g.has(v)),h=p.indexOf(i);h<0&&(h=p.length),s==="after"&&(h+=1);let I=[...p.slice(0,h),...t.filter(v=>!!this.tree.get(v)),...p.slice(h)];this.order.setOrder(A,e,I),await this.order.save(A),await this.forceManualMode(e),await this.log.append({type:"reorder",id:e,payload:{dir:"drag-cross",parent:e,ids:t,count:t.length}});let u=this.focusId===e,f=u?t[0]:e,C=u?t.slice():[e];u?this.pendingFocusIds=C:(this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=C),this.tree.rebuild(A),this.render({kind:"follow-cursor"});let B=this.selectionGuardKey,m=()=>{if(this.selectionGuardKey!==B||this.selection.has(f))return;let v=this.currentChildren.findIndex(y=>y.id===f);v<0||(this.selection.add(f),this.cursorIdx=v,this.render({kind:"follow-cursor"}))};setTimeout(m,120),setTimeout(m,400);let w=t.map(v=>this.tree.get(v)).filter(v=>!!v),Q=this.tree.get(e),E=Q?this.titleForNode(Q):"(root)";this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Reparented",nodes:w,destination:`\u2192 "${E}"`}),kind:"success",category:"move",affectedIds:t,affectedAuthorIds:r,folder:A,actions:e===F?[]:[{label:"Jump to parent",onClick:()=>this.navigateTo(e)}]}),this.plugin.getUndoStack(A).push({label:`Move + reorder (${t.length})`,undo:async()=>{for(let v of n){let y=this.app.vault.getAbstractFileByPath(v.path);y&&(await this.app.fileManager.processFrontMatter(y,b=>{v.oldParent===null||v.oldParent===void 0?b.parent=F:b.parent=v.oldParent}),await this.log.append({type:"parent_change",id:v.id,payload:{from:e,to:v.oldParent,reason:"drag-undo"}}))}for(let[v,y]of Object.entries(l))if(y.length===0){let b=this.order.cache.get(A)??{};delete b[v],this.order.cache.set(A,b)}else this.order.setOrder(A,v,y);await this.order.save(A),this.pendingFocusIds=t.slice(),this.selection.clear(),this.cursorIdx=-1,this.tree.rebuild(A),this.render()},redo:async()=>{for(let v of n){let y=this.app.vault.getAbstractFileByPath(v.path);y&&(await this.app.fileManager.processFrontMatter(y,b=>{b.parent=e}),this.order.removeChild(A,v.id))}this.order.setOrder(A,e,I),await this.order.save(A),this.pendingFocusIds=t.slice(),this.focusId!==e&&(this.selection.clear(),this.cursorIdx=-1),this.tree.rebuild(A),this.render()}})}async reorderToTarget(t,e,i){let s=this.tree.get(e);if(!s)return;let n=t.map(B=>this.tree.get(B)).filter(B=>!!B&&!!B.file);if(n.length===0)return;if(n.some(B=>B.id===e)){this.plugin.notifications.show({message:"Can't move a note into itself.",kind:"warning",category:"move",folder:this.noteFolder});return}if(i==="into"){for(let B of n)if(this.isDescendant(e,B.id)){this.plugin.notifications.show({message:`Can't nest "${this.titleForNode(B)}" under one of its own descendants \u2014 that would create a cycle.`,kind:"warning",category:"move",folder:this.noteFolder});return}}let o=i==="into"?e:s.parent??F;if(n.some(B=>(B.parent??F)!==o)){let B=j(),m=async()=>{i==="into"?await this.moveAcrossThenReorder(n.map(w=>w.id),o,"","after"):await this.moveAcrossThenReorder(n.map(w=>w.id),o,e,i)};if(B.confirmCrossParentDrag){let w=this.titleForNode(s),Q=n.length,E=i==="into"?"Nest":"Move",v=i==="into"?"as children of":"under";new gt(this.app,i==="into"?"Nest under target?":"Move under different parent?",`${E} ${Q} note${Q===1?"":"s"} ${v} "${w}"? Their parent will change.`,E,y=>{y&&m()}).open()}else await m();return}let A=o,l=n.map(B=>B.id),d=this.tree.getChildren(A).map(B=>B.id),g=new Set(l),p=d.filter(B=>!g.has(B)),h=p.indexOf(e);if(h<0)return;i==="after"&&(h+=1);let I=[...p.slice(0,h),...l,...p.slice(h)];if(js(I,d))return;let u=this.noteFolder,f=this.order.getOrder(u,A).slice();this.order.setOrder(u,A,I),await this.order.save(u),await this.forceManualMode(A),await this.log.append({type:"reorder",id:A,payload:{dir:"drag",parent:A,ids:l,count:l.length}}),this.pendingFocusIds=l.slice(),this.tree.rebuild(u),this.render();let C=l.map(B=>this.tree.get(B)).filter(B=>!!B);this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Reordered",nodes:C}),kind:"success",category:"reorder",affectedIds:l,folder:u}),this.plugin.getUndoStack(u).push({label:`Reorder (drag, ${l.length})`,undo:async()=>{if(f.length===0){let B=this.order.cache.get(u)??{};delete B[A],this.order.cache.set(u,B)}else this.order.setOrder(u,A,f);await this.order.save(u),await this.log.append({type:"reorder",id:A,payload:{dir:"undo",parent:A,ids:l,count:l.length}}),this.pendingFocusIds=l.slice(),this.tree.rebuild(u),this.render()},redo:async()=>{this.order.setOrder(u,A,I),await this.order.save(u),await this.log.append({type:"reorder",id:A,payload:{dir:"redo:drag",parent:A,ids:l,count:l.length}}),this.pendingFocusIds=l.slice(),this.tree.rebuild(u),this.render()}})}cmdMoveUp(){this.reorderSelection("up")}cmdMoveDown(){this.reorderSelection("down")}cmdMoveToTop(){this.reorderSelection("top")}cmdMoveToBottom(){this.reorderSelection("bottom")}async reorderSelection(t){let e=[];if(this.selection.size>0){let g=[...this.selection].map(h=>this.tree.get(h)).filter(h=>!!h&&!!h.file);if(g.length===0)return;if(new Set(g.map(h=>h.parent)).size>1){new k.Notice("Reorder requires a single-parent selection.");return}e=g}else this.cursorIdx>=0&&this.currentChildren[this.cursorIdx]&&(e=[this.currentChildren[this.cursorIdx]]);if(e.length===0){new k.Notice("Nothing to reorder.");return}let i=e[0].parent??F,s=this.tree.getChildren(i).map(g=>g.id);if(s.length===0)return;let n=new Set(e.map(g=>g.id)),o=s.filter(g=>n.has(g));if(o.length===0)return;let r=Bo(s,o,t);if(js(r,s))return;let A=this.noteFolder,l=this.order.getOrder(A,i).slice();this.order.setOrder(A,i,r),await this.order.save(A),await this.forceManualMode(i),await this.log.append({type:"reorder",id:i,payload:{dir:t,parent:i,ids:o,count:o.length}}),this.pendingFocusIds=o.slice(),this.tree.rebuild(A),this.render({kind:"follow-cursor"});let d=o.map(g=>this.tree.get(g)).filter(g=>!!g);this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Moved",nodes:d,destination:t}),kind:"success",category:"reorder",affectedIds:o,folder:A}),this.plugin.getUndoStack(A).push({label:`Reorder (${t})`,undo:async()=>{if(l.length===0){let g=this.order.cache.get(A)??{};delete g[i],this.order.cache.set(A,g)}else this.order.setOrder(A,i,l);await this.order.save(A),await this.log.append({type:"reorder",id:i,payload:{dir:"undo",parent:i,ids:o,count:o.length}}),this.pendingFocusIds=o.slice(),this.tree.rebuild(A),this.render()},redo:async()=>{this.order.setOrder(A,i,r),await this.order.save(A),await this.log.append({type:"reorder",id:i,payload:{dir:`redo:${t}`,parent:i,ids:o,count:o.length}}),this.pendingFocusIds=o.slice(),this.tree.rebuild(A),this.render()}})}async cmdDelete(){let t=this.getActionTargets();if(t.length===0){let I=this.tree.get(this.focusId);I?.file&&(t=[I])}if(t.length===0){new k.Notice("Nothing selected to delete.");return}if((this.plugin.settings.encryptTrash??!1)&&!(this.plugin.settings.encryptTrashFollowObsidian??!1)){if(!this.plugin.encryption?.isConfigured?.()){new k.Notice("\u201CEncrypt items sent to trash\u201D is ON but encryption isn't set up (Settings \u2192 Encryption). Nothing was deleted.");return}await this.secureDeleteSources(t);return}if(t.length===1){await this.deleteNote(t[0]);return}let e=[],i=new Set,s=I=>{if(!i.has(I.id)){i.add(I.id);for(let u of this.tree.getChildren(I.id))s(u);e.push(I)}};for(let I of t)s(I);let n=e.filter(I=>!!I.file),o=await Promise.all(n.map(I=>this.app.vault.read(I.file))),r=[];for(let I=0;I<n.length;I++){let u=n[I];r.push(...this.extractAttachments(this.stripFrontmatter(o[I])));let f=this.app.metadataCache.getFileCache(u.file)?.frontmatter;if(Array.isArray(f?.attachments))for(let C of f.attachments)typeof C=="string"&&C.trim()&&r.push(Be(C))}let A=[...new Set(r)],l=e.length-t.length,d=async I=>{let u=await this.snapshotNotes(e,I),f=0;if(I)for(let H of A){let D=this.app.metadataCache.getFirstLinkpathDest(H,"");if(D)try{await this.app.fileManager.trashFile(D),await this.log.append({type:"attachment_remove",id:F,payload:{path:D.path}}),this.plugin.notifications.show({message:`Deleted attachment "${D.name}"`,kind:"warning",category:"attachment",affectedPaths:[D.path],folder:this.noteFolder}),f+=1}catch{}}let C=new Set;for(let H of e)H.parent&&C.add(H.parent);let B=this.authorship.collectAuthorIds(e),m=new Set(t.map(H=>H.id)),w=this.currentChildren.map((H,D)=>m.has(H.id)?D:-1).filter(H=>H>=0),Q=w.length>0?w[0]:-1,E=null;if(Q>=0){for(let H=Q+1;H<this.currentChildren.length;H++)if(!m.has(this.currentChildren[H].id)){E=this.currentChildren[H].id;break}if(!E){for(let H=Q-1;H>=0;H--)if(!m.has(this.currentChildren[H].id)){E=this.currentChildren[H].id;break}}}for(let H of e)if(H.file){try{await this.app.fileManager.trashFile(H.file)}catch{}await this.log.append({type:"delete",id:H.id,payload:{path:H.file.path,attachmentsRemoved:I?A:[]}})}this.selection.clear(),this.cursorIdx=-1,E&&(this.pendingFocusIds=[E]),this.tree.rebuild(this.noteFolder);for(let H of C)e.some(D=>D.id===H)||this.fmSync.scheduleParentOfDeleted(H);this.render({kind:"follow-cursor"});let v=f>0?` with ${f} attachment${f===1?"":"s"}`:"",y=this.noteFolder,b=t.map(H=>H.id),N=!1,P=async()=>{N||(N=!0,this.selection.clear(),this.cursorIdx=-1,await this.restoreSnapshots(u,b.slice()))};this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Deleted",nodes:t,suffix:v.trim()||void 0}),kind:"warning",category:"delete",duration:0,affectedIds:t.map(H=>H.id),affectedAuthorIds:B,folder:this.noteFolder,actions:[{label:"Undo delete",onClick:()=>void P()}]}),this.plugin.getUndoStack(y).push({label:`Delete ${t.length} note${t.length===1?"":"s"}`,undo:async()=>{await P()},redo:async()=>{this.selection.clear(),this.cursorIdx=-1,N=!1,await this.trashNotesAndAttachments(u)}}),this.focusView()},g=j(),p=g.confirmBulkDelete,h=A.length>0&&g.confirmAttachmentDelete;if(!p&&!h){await d(!1);return}new Me(this.app,`${t.length} selected note${t.length===1?"":"s"}`,l,A.length,h,d).open()}async cmdSplit(t){let e=t??this.resolveActionTarget();if(!e?.file){new k.Notice("Pick a note to split.");return}let i=e.file,s=await this.app.vault.read(i),n=this.stripFrontmatter(s).replace(/\s+$/,""),o=n.split(/\r?\n/);if(n.trim().length<2){new k.Notice("Note is too short to split.");return}let r=s,A=i.path,l=async(g,p,h)=>{if(!g.trim()||!p.trim()){new k.Notice("Split would leave one part empty.");return}try{let I=s.startsWith("---")?s.slice(0,s.indexOf(` +`);return this.app.vault.create(e,n)}buildHomeFilename(t){return`Home-${(t.split("/").filter(Boolean).pop()??"Stashpad").replace(/[^A-Za-z0-9_-]+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")||"Stashpad"}.md`}async migrateNullParents(){let t=this.noteFolder,e=this.app.vault.getMarkdownFiles().filter(i=>i.path.startsWith(t+"/"));for(let i of e){let s=this.app.metadataCache.getFileCache(i)?.frontmatter,n=s?.id;if(!n||n===F)continue;let o=s?.parent;(o==null||o===""||o==="null")&&(await this.app.fileManager.processFrontMatter(i,r=>{r.parent=F}),await this.log.append({type:"parent_change",id:n,payload:{from:null,to:F,reason:"migration"}}))}}async openInNewStashpadTab(t){let e=this.app.workspace,i=this.leaf,s=e.getLeaf("tab");await s.setViewState({type:J,active:!0,state:{focusId:t,timeFilter:this.timeFilter,folderOverride:this.folderOverride}}),e.setActiveLeaf(s,{focus:!0}),e.revealLeaf(s);let n=e.on("active-leaf-change",()=>{if((()=>{let A=!1;return e.iterateAllLeaves(l=>{l===s&&(A=!0)}),A})())return;e.offref(n),(()=>{let A=!1;return e.iterateAllLeaves(l=>{l===i&&(A=!0)}),A})()&&(e.setActiveLeaf(i,{focus:!0}),e.revealLeaf(i))})}async openNoteInNewTab(t,e){let i=(t||"").trim().replace(/^\/+|\/+$/g,"");if(!i||!e)return;let s=(this.plugin.settings.folder||"Stashpad").trim().replace(/^\/+|\/+$/g,"")||"Stashpad",n=this.app.workspace,o=n.getLeaf("tab");await o.setViewState({type:J,active:!0,state:{focusId:e,folderOverride:i===s?null:i}}),n.setActiveLeaf(o,{focus:!0}),n.revealLeaf(o)}async openFolderInNewTab(t){let e=(t||"").trim().replace(/^\/+|\/+$/g,"");if(!e)return;let i=(this.plugin.settings.folder||"Stashpad").trim().replace(/^\/+|\/+$/g,"")||"Stashpad",s=this.app.workspace,n=this.leaf,o=s.getLeaf("tab");await o.setViewState({type:J,active:!0,state:{focusId:F,folderOverride:e===i?null:e}}),s.setActiveLeaf(o,{focus:!0}),s.revealLeaf(o);let r=s.on("active-leaf-change",()=>{if((()=>{let d=!1;return s.iterateAllLeaves(p=>{p===o&&(d=!0)}),d})())return;s.offref(r),(()=>{let d=!1;return s.iterateAllLeaves(p=>{p===n&&(d=!0)}),d})()&&(s.setActiveLeaf(n,{focus:!0}),s.revealLeaf(n))})}cmdOpenInEditor(t){if(t){this.openFileAtEnd(t.file);return}let e=this.getActionTargets();if(e.length)for(let i of e)i.file&&this.openFileAtEnd(i.file)}cmdOpenParentInEditor(){let t=this.tree.get(this.focusId);if(!t?.file){new k.Notice("No focused parent to open.");return}this.openFileAtEnd(t.file)}async openFileAtEnd(t){let e=this.app.workspace,i=this.leaf,s=e.getLeaf("tab");await s.openFile(t,{active:!0}),e.setActiveLeaf(s,{focus:!0}),e.revealLeaf(s);let n=e.on("active-leaf-change",()=>{if((()=>{let d=!1;return e.iterateAllLeaves(p=>{p===s&&(d=!0)}),d})())return;e.offref(n),(()=>{let d=!1;return e.iterateAllLeaves(p=>{p===i&&(d=!0)}),d})()&&(e.setActiveLeaf(i,{focus:!0}),e.revealLeaf(i))}),r=s.view?.editor;r&&requestAnimationFrame(()=>{try{let A=r.lastLine(),l=r.getLine(A)?.length??0;r.setCursor({line:A,ch:l}),r.scrollIntoView({from:{line:A,ch:l},to:{line:A,ch:l}},!0),r.focus()}catch{}})}cmdSelectAll(){if(this.currentChildren.length!==0){this.selection.clear();for(let t of this.currentChildren)this.selection.add(t.id);this.firstSelectedId=this.currentChildren[0].id,this.lastSelected=this.currentChildren[this.currentChildren.length-1].id,this.cursorIdx=this.currentChildren.length-1,this.render()}}async cmdTogglePin(){let t=this.getActionTargets();if(t.length===0){let n=this.tree.get(this.focusId);n?.file&&(t=[n])}if(t.length===0){new k.Notice("Nothing to pin.");return}let e=t.some(n=>!this.plugin.isPinned({folder:this.noteFolder,id:n.id})),i=0,s=0;for(let n of t){let o={folder:this.noteFolder,id:n.id};e?this.plugin.isPinned(o)||(await this.plugin.pinNote(o),i++):this.plugin.isPinned(o)&&(await this.plugin.unpinNote(o),s++)}i>0?new k.Notice(`Pinned ${i} note${i===1?"":"s"} to sidebar.`):s>0&&new k.Notice(`Unpinned ${s} note${s===1?"":"s"} from sidebar.`)}isListPinned(t){let e=this.tree.get(t);if(!e?.file)return!1;let i=this.listPinnedState.get(e.file.path);return i?i.pinned:this.app.metadataCache.getFileCache(e.file)?.frontmatter?.listPinned===!0}listPinnedAt(t){let e=this.tree.get(t);if(!e?.file)return 0;let i=this.listPinnedState.get(e.file.path);if(i)return i.at;let s=this.app.metadataCache.getFileCache(e.file)?.frontmatter?.listPinnedAt,n=typeof s=="string"?Date.parse(s):NaN;return Number.isNaN(n)?0:n}hoistListPinned(t,e){let i=this.tree.getChildren(t).map(A=>A.id);if(!i.some(A=>this.isListPinned(A)))return e;let s=new Set(e),n=[...e,...i.filter(A=>!s.has(A))],o=n.filter(A=>this.isListPinned(A)).sort((A,l)=>this.listPinnedAt(A)-this.listPinnedAt(l)),r=n.filter(A=>!this.isListPinned(A));return[...o,...r]}async cmdToggleListPin(){let t=this.getActionTargets();if(t.length===0){let r=this.tree.get(this.focusId);r?.file&&(t=[r])}if(t.length===0){new k.Notice("Nothing to pin.");return}let e=t.some(r=>!this.isListPinned(r.id)),i=[],s=new Date().toISOString(),n=[];for(let r of t){if(!r.file)continue;let A=this.app.metadataCache.getFileCache(r.file)?.frontmatter;i.push({path:r.file.path,listPinned:A?.listPinned,listPinnedAt:A?.listPinnedAt});let l=e?typeof A?.listPinnedAt=="string"&&Date.parse(A.listPinnedAt)||Date.parse(s):0;this.listPinnedState.set(r.file.path,{pinned:e,at:l}),await this.app.fileManager.processFrontMatter(r.file,d=>{e?(d.listPinned=!0,d.listPinnedAt||(d.listPinnedAt=s)):(delete d.listPinned,delete d.listPinnedAt)}),n.push(r.id)}let o=this.noteFolder;this.tree.rebuild(o),this.render(),this.plugin.notifications.show({message:e?`Pinned ${n.length} to top of list`:`Unpinned ${n.length} from list`,kind:"success",category:"edit",affectedIds:n,folder:o}),this.plugin.getUndoStack(o).push({label:e?`Pin to top (${n.length})`:`Unpin from top (${n.length})`,undo:async()=>{for(let r of i){let A=this.app.vault.getAbstractFileByPath(r.path);if(!A)continue;await this.app.fileManager.processFrontMatter(A,p=>{r.listPinned===void 0?delete p.listPinned:p.listPinned=r.listPinned,r.listPinnedAt===void 0?delete p.listPinnedAt:p.listPinnedAt=r.listPinnedAt});let l=r.listPinned===!0,d=typeof r.listPinnedAt=="string"&&Date.parse(r.listPinnedAt)||0;this.listPinnedState.set(r.path,{pinned:l,at:d})}this.tree.rebuild(o),this.render()}})}async cmdToggleComplete(){let t=this.getActionTargets();if(t.length===0){let r=this.tree.get(this.focusId);r?.file&&(t=[r])}if(t.length===0){new k.Notice("Nothing to toggle.");return}let i=t.some(r=>!this.isCompleted(r)),s=[],n=[];for(let r of t){if(!r.file)continue;let A=this.isCompleted(r);s.push({id:r.id,path:r.file.path,was:A}),A!==i&&(await this.app.fileManager.processFrontMatter(r.file,l=>{i?l.completed=!0:delete l.completed}),this.completedState.set(r.file.path,i),n.push(r.id))}if(this.render(),n.length>0){await this.log.append({type:i?"complete":"uncomplete",id:n[0],payload:{ids:n,count:n.length}});let r=n.map(A=>this.tree.get(A)).filter(A=>!!A);this.plugin.notifications.show({message:this.bulkActionMessage({verb:i?"Marked complete":"Unmarked",nodes:r}),kind:"success",category:i?"complete":"uncomplete",affectedIds:n,folder:this.noteFolder})}let o=this.noteFolder;this.plugin.getUndoStack(o).push({label:`${i?"Mark complete":"Unmark complete"} (${t.length})`,undo:async()=>{let r=[];for(let A of s){let l=this.app.vault.getAbstractFileByPath(A.path);l&&(await this.app.fileManager.processFrontMatter(l,d=>{A.was?d.completed=!0:delete d.completed}),n.includes(A.id)&&r.push(A.id))}r.length>0&&await this.log.append({type:i?"uncomplete":"complete",id:r[0],payload:{ids:r,count:r.length,undo:!0}}),this.tree.rebuild(o),this.render()},redo:async()=>{for(let r of s){let A=this.app.vault.getAbstractFileByPath(r.path);A&&await this.app.fileManager.processFrontMatter(A,l=>{i?l.completed=!0:delete l.completed})}n.length>0&&await this.log.append({type:i?"complete":"uncomplete",id:n[0],payload:{ids:n,count:n.length,redo:!0}}),this.tree.rebuild(o),this.render()}})}isCompleted(t){if(!t.file)return!1;let e=this.completedState.get(t.file.path);return e!==void 0?e:!!this.app.metadataCache.getFileCache(t.file)?.frontmatter?.completed}taggedFromFm(t){return t?Te(t,"task")||t.task===!0:!1}cmdSetDue(){let t=this.getActionTargets();if(t.length===0){let r=this.tree.get(this.focusId);r?.file&&(t=[r])}if(t.length===0){new k.Notice("Nothing to schedule.");return}let e=t[0],i=e.file?this.app.metadataCache.getFileCache(e.file)?.frontmatter:null,s=i&&(typeof i.due=="string"||typeof i.due=="number")?String(i.due):null,n=this.plugin.collectKnownAuthors(),o=we(i??{});new Ge(this.app,s,r=>{this.applyDue(t,r.iso,r.assignees)},{knownAuthors:n,currentAssignees:o}).open()}async applyDue(t,e,i=[]){let s=[],n=[],o=this.authorship.currentAuthorLink();for(let l of i)await this.plugin.ensureAuthorStubFor(this.noteFolder,l.id,l.name);let r=i.map(l=>this.plugin.authorRefFor(this.noteFolder,l.id,l.name));for(let l of t){if(!l.file)continue;let d=this.app.metadataCache.getFileCache(l.file)?.frontmatter,p=this.isTaskTagged(l);s.push({id:l.id,path:l.file.path,due:d?.due,task:d?.task,assignedTo:d?.assignedTo,assignedBy:d?.assignedBy,wasTagged:p}),await this.app.fileManager.processFrontMatter(l.file,h=>{e===null?delete h.due:(h.due=e,h.task=!0),r.length>0?(h.assignedTo=r,o&&(h.assignedBy=o.link),h.task=!0):(delete h.assignedTo,delete h.assignedBy)});let g=e!==null||r.length>0;this.taskTaggedState.set(l.file.path,g||p),n.push(l.id)}if(this.render(),n.length>0){let l=n.map(d=>this.tree.get(d)).filter(d=>!!d);this.plugin.notifications.show({message:this.bulkActionMessage({verb:e===null?"Cleared due date":`Due ${$t(Date.parse(e),this.plugin.settings)}`,nodes:l}),kind:"success",category:"edit",affectedIds:n,folder:this.noteFolder})}let A=this.noteFolder;this.plugin.getUndoStack(A).push({label:e===null?`Clear due date (${t.length})`:`Set due date (${t.length})`,undo:async()=>{for(let l of s){let d=this.app.vault.getAbstractFileByPath(l.path);d&&(await this.app.fileManager.processFrontMatter(d,p=>{l.due===void 0?delete p.due:p.due=l.due,l.task===void 0?delete p.task:p.task=l.task,l.assignedTo===void 0?delete p.assignedTo:p.assignedTo=l.assignedTo,l.assignedBy===void 0?delete p.assignedBy:p.assignedBy=l.assignedBy}),this.taskTaggedState.set(l.path,l.wasTagged))}this.tree.rebuild(A),this.render()}})}cmdAssign(){let t=this.getActionTargets();if(t.length===0){let r=this.tree.get(this.focusId);r?.file&&(t=[r])}if(t.length===0){new k.Notice("Nothing to assign.");return}let e=t[0],i=e.file?this.app.metadataCache.getFileCache(e.file)?.frontmatter:null,s=i&&(typeof i.due=="string"||typeof i.due=="number")?String(i.due):null,n=this.plugin.collectKnownAuthors(),o=we(i??{});new Ge(this.app,s,r=>{this.applyDue(t,r.iso,r.assignees)},{knownAuthors:n,currentAssignees:o,title:"Assign / schedule task"}).open()}isTask(t){return t.file?this.isTaskTagged(t)?!0:this.app.metadataCache.getFileCache(t.file)?.frontmatter?.completed!==void 0:!1}async cmdToggleTask(){let t=this.getActionTargets();if(t.length===0){let r=this.tree.get(this.focusId);r?.file&&(t=[r])}if(t.length===0){new k.Notice("Nothing to toggle.");return}let e=t.some(r=>!this.isTaskTagged(r)),i=[],s=[];for(let r of t){if(!r.file)continue;let A=this.isTaskTagged(r),l=this.app.metadataCache.getFileCache(r.file)?.frontmatter;if(i.push({id:r.id,path:r.file.path,tags:l?.tags,completed:l?.completed,task:l?.task,wasTagged:A}),A===e)continue;let d=!1;await this.app.fileManager.processFrontMatter(r.file,p=>{e?(on(p,"task"),p.completed===void 0&&(p.completed=!1),d=p.completed===!0,delete p.task):(an(p,"task"),delete p.completed,delete p.task,d=!1)}),this.completedState.set(r.file.path,d),this.taskTaggedState.set(r.file.path,e),s.push(r.id)}if(this.render(),s.length>0){let r=e?"marked as task":"unmarked as task",A;if(s.length===1){let l=this.tree.get(s[0]);A=`"${l&&this.titleForNode(l).trim()||"(untitled)"}" ${r}`}else A=`${s.length} notes ${r}`;this.plugin.notifications.show({message:A,kind:"success",category:"edit",affectedIds:s,folder:this.noteFolder})}let n=this.noteFolder,o=async()=>{for(let r of i){let A=this.app.vault.getAbstractFileByPath(r.path);A&&(await this.app.fileManager.processFrontMatter(A,l=>{r.tags===void 0?delete l.tags:l.tags=r.tags,r.completed===void 0?delete l.completed:l.completed=r.completed,r.task===void 0?delete l.task:l.task=r.task}),this.completedState.set(r.path,!!r.completed),this.taskTaggedState.set(r.path,r.wasTagged))}this.tree.rebuild(n),this.render()};this.plugin.getUndoStack(n).push({label:`${e?"Mark task":"Unmark task"} (${t.length})`,undo:o,redo:async()=>{for(let r of i){let A=this.app.vault.getAbstractFileByPath(r.path);if(!A)continue;let l=!1;await this.app.fileManager.processFrontMatter(A,d=>{e?(on(d,"task"),d.completed===void 0&&(d.completed=!1),l=d.completed===!0,delete d.task):(an(d,"task"),delete d.completed,delete d.task,l=!1)}),this.completedState.set(r.path,l),this.taskTaggedState.set(r.path,e)}this.tree.rebuild(n),this.render()}})}async toggleCompletedForNode(t){if(!t.file)return;let e=t.file.path,i=this.isCompleted(t);await this.app.fileManager.processFrontMatter(t.file,n=>{n.completed=!i}),this.completedState.set(e,!i),await this.log.append({type:i?"uncomplete":"complete",id:t.id}),this.render();let s=this.noteFolder;this.plugin.getUndoStack(s).push({label:i?"Mark incomplete":"Mark complete",undo:async()=>{let n=this.app.vault.getAbstractFileByPath(e);n&&(await this.app.fileManager.processFrontMatter(n,o=>{o.completed=i}),this.tree.rebuild(s),this.render())}})}isTaskTagged(t){if(!t.file)return!1;let e=this.taskTaggedState.get(t.file.path);if(e!==void 0)return e;let i=this.app.metadataCache.getFileCache(t.file)?.frontmatter;return this.taggedFromFm(i)}colorForNode(t){if(!t.file)return null;let e=this.app.metadataCache.getFileCache(t.file)?.frontmatter?.color;if(typeof e!="string")return null;let i=e.trim();return/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(i)?i:null}inheritedColorForNode(t){let e=t,i=0,s=new Set;for(;e&&e.id!==F&&!s.has(e.id);){s.add(e.id);let n=this.colorForNode(e);if(n)return{hex:n,depth:i};e=e.parent?this.tree.get(e.parent):void 0,i+=1}return null}isDescendant(t,e){let i=this.tree.get(t),s=new Set;for(;i&&i.parent&&!s.has(i.id);){if(i.parent===e)return!0;s.add(i.id),i=this.tree.get(i.parent)}return!1}async moveAcrossThenReorder(t,e,i,s){let n=[],o=new Set;for(let v of t){let w=this.tree.get(v);w?.file&&(n.push({id:v,path:w.file.path,oldParent:w.parent}),o.add(w.parent??F))}o.add(e);let r=this.authorship.collectAuthorIds(t.map(v=>this.tree.get(v)).filter(v=>!!v)),A=this.noteFolder,l={};for(let v of o)l[v]=this.order.getOrder(A,v).slice();for(let v of n){let w=this.app.vault.getAbstractFileByPath(v.path);w&&(await this.app.fileManager.processFrontMatter(w,D=>{D.parent=e}),this.fmSync.scheduleParentChange(v.id,v.oldParent,e),await this.log.append({type:"parent_change",id:v.id,payload:{from:v.oldParent,to:e,reason:"drag"}}),this.order.removeChild(A,v.id))}this.tree.rebuild(A);let d=this.tree.getChildren(e).map(v=>v.id),p=new Set(t),g=d.filter(v=>!p.has(v)),h=g.indexOf(i);h<0&&(h=g.length),s==="after"&&(h+=1);let I=[...g.slice(0,h),...t.filter(v=>!!this.tree.get(v)),...g.slice(h)];this.order.setOrder(A,e,I),await this.order.save(A),await this.forceManualMode(e),await this.log.append({type:"reorder",id:e,payload:{dir:"drag-cross",parent:e,ids:t,count:t.length}});let u=this.focusId===e,f=u?t[0]:e,C=u?t.slice():[e];u?this.pendingFocusIds=C:(this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=C),this.tree.rebuild(A),this.render({kind:"follow-cursor"});let B=this.selectionGuardKey,m=()=>{if(this.selectionGuardKey!==B||this.selection.has(f))return;let v=this.currentChildren.findIndex(w=>w.id===f);v<0||(this.selection.add(f),this.cursorIdx=v,this.render({kind:"follow-cursor"}))};setTimeout(m,120),setTimeout(m,400);let y=t.map(v=>this.tree.get(v)).filter(v=>!!v),Q=this.tree.get(e),E=Q?this.titleForNode(Q):"(root)";this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Reparented",nodes:y,destination:`\u2192 "${E}"`}),kind:"success",category:"move",affectedIds:t,affectedAuthorIds:r,folder:A,actions:e===F?[]:[{label:"Jump to parent",onClick:()=>this.navigateTo(e)}]}),this.plugin.getUndoStack(A).push({label:`Move + reorder (${t.length})`,undo:async()=>{for(let v of n){let w=this.app.vault.getAbstractFileByPath(v.path);w&&(await this.app.fileManager.processFrontMatter(w,D=>{v.oldParent===null||v.oldParent===void 0?D.parent=F:D.parent=v.oldParent}),await this.log.append({type:"parent_change",id:v.id,payload:{from:e,to:v.oldParent,reason:"drag-undo"}}))}for(let[v,w]of Object.entries(l))if(w.length===0){let D=this.order.cache.get(A)??{};delete D[v],this.order.cache.set(A,D)}else this.order.setOrder(A,v,w);await this.order.save(A),this.pendingFocusIds=t.slice(),this.selection.clear(),this.cursorIdx=-1,this.tree.rebuild(A),this.render()},redo:async()=>{for(let v of n){let w=this.app.vault.getAbstractFileByPath(v.path);w&&(await this.app.fileManager.processFrontMatter(w,D=>{D.parent=e}),this.order.removeChild(A,v.id))}this.order.setOrder(A,e,I),await this.order.save(A),this.pendingFocusIds=t.slice(),this.focusId!==e&&(this.selection.clear(),this.cursorIdx=-1),this.tree.rebuild(A),this.render()}})}async reorderToTarget(t,e,i){let s=this.tree.get(e);if(!s)return;let n=t.map(B=>this.tree.get(B)).filter(B=>!!B&&!!B.file);if(n.length===0)return;if(n.some(B=>B.id===e)){this.plugin.notifications.show({message:"Can't move a note into itself.",kind:"warning",category:"move",folder:this.noteFolder});return}if(i==="into"){for(let B of n)if(this.isDescendant(e,B.id)){this.plugin.notifications.show({message:`Can't nest "${this.titleForNode(B)}" under one of its own descendants \u2014 that would create a cycle.`,kind:"warning",category:"move",folder:this.noteFolder});return}}let o=i==="into"?e:s.parent??F;if(n.some(B=>(B.parent??F)!==o)){let B=j(),m=async()=>{i==="into"?await this.moveAcrossThenReorder(n.map(y=>y.id),o,"","after"):await this.moveAcrossThenReorder(n.map(y=>y.id),o,e,i)};if(B.confirmCrossParentDrag){let y=this.titleForNode(s),Q=n.length,E=i==="into"?"Nest":"Move",v=i==="into"?"as children of":"under";new pt(this.app,i==="into"?"Nest under target?":"Move under different parent?",`${E} ${Q} note${Q===1?"":"s"} ${v} "${y}"? Their parent will change.`,E,w=>{w&&m()}).open()}else await m();return}let A=o,l=n.map(B=>B.id),d=this.tree.getChildren(A).map(B=>B.id),p=new Set(l),g=d.filter(B=>!p.has(B)),h=g.indexOf(e);if(h<0)return;i==="after"&&(h+=1);let I=[...g.slice(0,h),...l,...g.slice(h)];if(rn(I,d))return;let u=this.noteFolder,f=this.order.getOrder(u,A).slice();this.order.setOrder(u,A,I),await this.order.save(u),await this.forceManualMode(A),await this.log.append({type:"reorder",id:A,payload:{dir:"drag",parent:A,ids:l,count:l.length}}),this.pendingFocusIds=l.slice(),this.tree.rebuild(u),this.render();let C=l.map(B=>this.tree.get(B)).filter(B=>!!B);this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Reordered",nodes:C}),kind:"success",category:"reorder",affectedIds:l,folder:u}),this.plugin.getUndoStack(u).push({label:`Reorder (drag, ${l.length})`,undo:async()=>{if(f.length===0){let B=this.order.cache.get(u)??{};delete B[A],this.order.cache.set(u,B)}else this.order.setOrder(u,A,f);await this.order.save(u),await this.log.append({type:"reorder",id:A,payload:{dir:"undo",parent:A,ids:l,count:l.length}}),this.pendingFocusIds=l.slice(),this.tree.rebuild(u),this.render()},redo:async()=>{this.order.setOrder(u,A,I),await this.order.save(u),await this.log.append({type:"reorder",id:A,payload:{dir:"redo:drag",parent:A,ids:l,count:l.length}}),this.pendingFocusIds=l.slice(),this.tree.rebuild(u),this.render()}})}cmdMoveUp(){this.reorderSelection("up")}cmdMoveDown(){this.reorderSelection("down")}cmdMoveToTop(){this.reorderSelection("top")}cmdMoveToBottom(){this.reorderSelection("bottom")}async reorderSelection(t){let e=[];if(this.selection.size>0){let p=[...this.selection].map(h=>this.tree.get(h)).filter(h=>!!h&&!!h.file);if(p.length===0)return;if(new Set(p.map(h=>h.parent)).size>1){new k.Notice("Reorder requires a single-parent selection.");return}e=p}else this.cursorIdx>=0&&this.currentChildren[this.cursorIdx]&&(e=[this.currentChildren[this.cursorIdx]]);if(e.length===0){new k.Notice("Nothing to reorder.");return}let i=e[0].parent??F,s=this.tree.getChildren(i).map(p=>p.id);if(s.length===0)return;let n=new Set(e.map(p=>p.id)),o=s.filter(p=>n.has(p));if(o.length===0)return;let r=So(s,o,t);if(rn(r,s))return;let A=this.noteFolder,l=this.order.getOrder(A,i).slice();this.order.setOrder(A,i,r),await this.order.save(A),await this.forceManualMode(i),await this.log.append({type:"reorder",id:i,payload:{dir:t,parent:i,ids:o,count:o.length}}),this.pendingFocusIds=o.slice(),this.tree.rebuild(A),this.render({kind:"follow-cursor"});let d=o.map(p=>this.tree.get(p)).filter(p=>!!p);this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Moved",nodes:d,destination:t}),kind:"success",category:"reorder",affectedIds:o,folder:A}),this.plugin.getUndoStack(A).push({label:`Reorder (${t})`,undo:async()=>{if(l.length===0){let p=this.order.cache.get(A)??{};delete p[i],this.order.cache.set(A,p)}else this.order.setOrder(A,i,l);await this.order.save(A),await this.log.append({type:"reorder",id:i,payload:{dir:"undo",parent:i,ids:o,count:o.length}}),this.pendingFocusIds=o.slice(),this.tree.rebuild(A),this.render()},redo:async()=>{this.order.setOrder(A,i,r),await this.order.save(A),await this.log.append({type:"reorder",id:i,payload:{dir:`redo:${t}`,parent:i,ids:o,count:o.length}}),this.pendingFocusIds=o.slice(),this.tree.rebuild(A),this.render()}})}async cmdDelete(){let t=this.getActionTargets();if(t.length===0){let I=this.tree.get(this.focusId);I?.file&&(t=[I])}if(t.length===0){new k.Notice("Nothing selected to delete.");return}if((this.plugin.settings.encryptTrash??!1)&&!(this.plugin.settings.encryptTrashFollowObsidian??!1)){if(!this.plugin.encryption?.isConfigured?.()){new k.Notice("\u201CEncrypt items sent to trash\u201D is ON but encryption isn't set up (Settings \u2192 Encryption). Nothing was deleted.");return}await this.secureDeleteSources(t);return}if(t.length===1){await this.deleteNote(t[0]);return}let e=[],i=new Set,s=I=>{if(!i.has(I.id)){i.add(I.id);for(let u of this.tree.getChildren(I.id))s(u);e.push(I)}};for(let I of t)s(I);let n=e.filter(I=>!!I.file),o=await Promise.all(n.map(I=>this.app.vault.read(I.file))),r=[];for(let I=0;I<n.length;I++){let u=n[I];r.push(...this.extractAttachments(this.stripFrontmatter(o[I])));let f=this.app.metadataCache.getFileCache(u.file)?.frontmatter;if(Array.isArray(f?.attachments))for(let C of f.attachments)typeof C=="string"&&C.trim()&&r.push(Ee(C))}let A=[...new Set(r)],l=e.length-t.length,d=async I=>{let u=await this.snapshotNotes(e,I),f=0;if(I)for(let H of A){let b=this.app.metadataCache.getFirstLinkpathDest(H,"");if(b)try{await this.app.fileManager.trashFile(b),await this.log.append({type:"attachment_remove",id:F,payload:{path:b.path}}),this.plugin.notifications.show({message:`Deleted attachment "${b.name}"`,kind:"warning",category:"attachment",affectedPaths:[b.path],folder:this.noteFolder}),f+=1}catch{}}let C=new Set;for(let H of e)H.parent&&C.add(H.parent);let B=this.authorship.collectAuthorIds(e),m=new Set(t.map(H=>H.id)),y=this.currentChildren.map((H,b)=>m.has(H.id)?b:-1).filter(H=>H>=0),Q=y.length>0?y[0]:-1,E=null;if(Q>=0){for(let H=Q+1;H<this.currentChildren.length;H++)if(!m.has(this.currentChildren[H].id)){E=this.currentChildren[H].id;break}if(!E){for(let H=Q-1;H>=0;H--)if(!m.has(this.currentChildren[H].id)){E=this.currentChildren[H].id;break}}}for(let H of e)if(H.file){try{await this.app.fileManager.trashFile(H.file)}catch{}await this.log.append({type:"delete",id:H.id,payload:{path:H.file.path,attachmentsRemoved:I?A:[]}})}this.selection.clear(),this.cursorIdx=-1,E&&(this.pendingFocusIds=[E]),this.tree.rebuild(this.noteFolder);for(let H of C)e.some(b=>b.id===H)||this.fmSync.scheduleParentOfDeleted(H);this.render({kind:"follow-cursor"});let v=f>0?` with ${f} attachment${f===1?"":"s"}`:"",w=this.noteFolder,D=t.map(H=>H.id),N=!1,P=async()=>{N||(N=!0,this.selection.clear(),this.cursorIdx=-1,await this.restoreSnapshots(u,D.slice()))};this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Deleted",nodes:t,suffix:v.trim()||void 0}),kind:"warning",category:"delete",duration:0,affectedIds:t.map(H=>H.id),affectedAuthorIds:B,folder:this.noteFolder,actions:[{label:"Undo delete",onClick:()=>void P()}]}),this.plugin.getUndoStack(w).push({label:`Delete ${t.length} note${t.length===1?"":"s"}`,undo:async()=>{await P()},redo:async()=>{this.selection.clear(),this.cursorIdx=-1,N=!1,await this.trashNotesAndAttachments(u)}}),this.focusView()},p=j(),g=p.confirmBulkDelete,h=A.length>0&&p.confirmAttachmentDelete;if(!g&&!h){await d(!1);return}new Ue(this.app,`${t.length} selected note${t.length===1?"":"s"}`,l,A.length,h,d).open()}async cmdSplit(t){let e=t??this.resolveActionTarget();if(!e?.file){new k.Notice("Pick a note to split.");return}let i=e.file,s=await this.app.vault.read(i),n=this.stripFrontmatter(s).replace(/\s+$/,""),o=n.split(/\r?\n/);if(n.trim().length<2){new k.Notice("Note is too short to split.");return}let r=s,A=i.path,l=async(p,g,h)=>{if(!p.trim()||!g.trim()){new k.Notice("Split would leave one part empty.");return}try{let I=s.startsWith("---")?s.slice(0,s.indexOf(` ---`,3)+4):"",u=I+(I?` -`:"")+g+` -`;await this.app.vault.modify(i,u);let f=e.parent??F,C=Date.parse(e.created||""),B=Number.isFinite(C)?new Date(C+1).toISOString():new Date().toISOString(),m=await this.createNoteUnder(p,f,{record:!1,createdOverride:B});await this.log.append({type:"rename",id:e.id,payload:{action:"split",into:m,...h}}),this.tree.rebuild(this.noteFolder),this.render(),this.suppressComposerFocusUntil=Date.now()+500,this.viewRoot?.focus({preventScroll:!0}),this.plugin.notifications.show({message:`Split "${this.titleForNode(e)}" into two`,kind:"success",category:"split",affectedIds:[e.id],folder:this.noteFolder});let w=m?this.tree.get(m):void 0,Q=w?.file?.path,E=Q?await this.app.vault.read(w.file):null,v=this.noteFolder;this.plugin.getUndoStack(v).push({label:"Split note",undo:async()=>{if(Q){let b=this.app.vault.getAbstractFileByPath(Q);if(b)try{await this.app.fileManager.trashFile(b)}catch{}}let y=this.app.vault.getAbstractFileByPath(A);y&&await this.app.vault.modify(y,r),this.tree.rebuild(v),this.render()},redo:async()=>{let y=this.app.vault.getAbstractFileByPath(A);y&&await this.app.vault.modify(y,u),Q&&E&&!await this.app.vault.adapter.exists(Q)&&await this.app.vault.create(Q,E),this.tree.rebuild(v),this.render()}})}catch(I){new k.Notice(`Stashpad: split failed (${I.message})`),console.error(I)}},d=async g=>{if(!(g.length<2))try{let p=s.startsWith("---")?s.slice(0,s.indexOf(` ----`,3)+4):"",h=g[0].replace(/\s+$/,"");if(!h.trim()){new k.Notice("Split would leave the first part empty.");return}let I=p+(p?` +`:"")+p+` +`;await this.app.vault.modify(i,u);let f=e.parent??F,C=Date.parse(e.created||""),B=Number.isFinite(C)?new Date(C+1).toISOString():new Date().toISOString(),m=await this.createNoteUnder(g,f,{record:!1,createdOverride:B});await this.log.append({type:"rename",id:e.id,payload:{action:"split",into:m,...h}}),this.tree.rebuild(this.noteFolder),this.render(),this.suppressComposerFocusUntil=Date.now()+500,this.viewRoot?.focus({preventScroll:!0}),this.plugin.notifications.show({message:`Split "${this.titleForNode(e)}" into two`,kind:"success",category:"split",affectedIds:[e.id],folder:this.noteFolder});let y=m?this.tree.get(m):void 0,Q=y?.file?.path,E=Q?await this.app.vault.read(y.file):null,v=this.noteFolder;this.plugin.getUndoStack(v).push({label:"Split note",undo:async()=>{if(Q){let D=this.app.vault.getAbstractFileByPath(Q);if(D)try{await this.app.fileManager.trashFile(D)}catch{}}let w=this.app.vault.getAbstractFileByPath(A);w&&await this.app.vault.modify(w,r),this.tree.rebuild(v),this.render()},redo:async()=>{let w=this.app.vault.getAbstractFileByPath(A);w&&await this.app.vault.modify(w,u),Q&&E&&!await this.app.vault.adapter.exists(Q)&&await this.app.vault.create(Q,E),this.tree.rebuild(v),this.render()}})}catch(I){new k.Notice(`Stashpad: split failed (${I.message})`),console.error(I)}},d=async p=>{if(!(p.length<2))try{let g=s.startsWith("---")?s.slice(0,s.indexOf(` +---`,3)+4):"",h=p[0].replace(/\s+$/,"");if(!h.trim()){new k.Notice("Split would leave the first part empty.");return}let I=g+(g?` `:"")+h+` -`;await this.app.vault.modify(i,I);let u=e.parent??F,f=Date.parse(e.created||""),C=Number.isFinite(f)?f:Date.now(),B=[];this.beginBulkRender();try{for(let Q=1;Q<g.length;Q++)await this.createNoteUnder(g[Q],u,{record:!1,createdOverride:new Date(C+Q).toISOString(),deferRender:!0,collectInto:B})}finally{try{await this.fmSync.flush()}catch{}this.endBulkRender()}await this.log.append({type:"rename",id:e.id,payload:{action:"split-many",parts:g.length}}),this.suppressComposerFocusUntil=Date.now()+500,this.viewRoot?.focus({preventScroll:!0}),this.plugin.notifications.show({message:`Split "${this.titleForNode(e)}" into ${g.length}`,kind:"success",category:"split",affectedIds:[e.id],folder:this.noteFolder});let m=B.slice(),w=this.noteFolder;this.plugin.getUndoStack(w).push({label:`Split note into ${g.length}`,undo:async()=>{for(let{path:E}of m){let v=this.app.vault.getAbstractFileByPath(E);if(v)try{await this.app.fileManager.trashFile(v)}catch{}}let Q=this.app.vault.getAbstractFileByPath(A);Q&&await this.app.vault.modify(Q,r),this.tree.rebuild(w),this.render()},redo:async()=>{let Q=this.app.vault.getAbstractFileByPath(A);Q&&await this.app.vault.modify(Q,I);for(let{path:E,content:v}of m)await this.app.vault.adapter.exists(E)||await this.app.vault.create(E,v);this.tree.rebuild(w),this.render()}})}catch(p){new k.Notice(`Stashpad: split failed (${p.message})`),console.error(p)}};new ni(this.app,n,async g=>{let p=o.slice(0,g).join(` -`).replace(/\s+$/,""),h=o.slice(g).join(` -`).replace(/^\s+|\s+$/g,"");await l(p,h,{mode:"line",splitAtLine:g})},async g=>{let p=n.slice(0,g).replace(/\s+$/,""),h=n.slice(g).replace(/^\s+|\s+$/g,"");await l(p,h,{mode:"cursor",splitAtChar:g})},async g=>{await d(g)}).open()}cmdOpenInNewStashpadTab(t){let e=t??this.resolveActionTarget();e?.file&&this.openInNewStashpadTab(e.id)}cmdCloneStashpadTab(){let t=this.tree.get(this.focusId);t?.file?this.cmdOpenInNewStashpadTab(t):this.openInNewStashpadTab(this.focusId)}resolveActionTarget(){if(this.cursorIdx>=0&&this.currentChildren[this.cursorIdx])return this.currentChildren[this.cursorIdx];let t=this.tree.get(this.focusId);return t?.file?t:void 0}cmdExportStash(t){return Ja(this,t)}cmdExportOkf(t){return Ka(this,t)}cmdImportStash(){return za(this)}processStashFile(t){return to(this,t)}async createNoteUnder(t,e,i={record:!0}){let s=(i.targetFolder??this.noteFolder).replace(/\/+$/,""),n=s!==this.noteFolder;await this.ensureFolder(s);let o=tt(),r=null;{let f=(this.plugin.settings.noteTemplates??{})[s];if(f){let C=this.app.vault.getAbstractFileByPath(f);if(C&&C.extension==="md")try{let B=await this.app.vault.cachedRead(C),m=this.stripFrontmatter(B);r=this.app.metadataCache.getFileCache(C)?.frontmatter??{},m.includes("{{body}}")?t=m.replace(/\{\{body\}\}/g,t):t.trim()?m.trim()&&(t=`${t} +`;await this.app.vault.modify(i,I);let u=e.parent??F,f=Date.parse(e.created||""),C=Number.isFinite(f)?f:Date.now(),B=[];this.beginBulkRender();try{for(let Q=1;Q<p.length;Q++)await this.createNoteUnder(p[Q],u,{record:!1,createdOverride:new Date(C+Q).toISOString(),deferRender:!0,collectInto:B})}finally{try{await this.fmSync.flush()}catch{}this.endBulkRender()}await this.log.append({type:"rename",id:e.id,payload:{action:"split-many",parts:p.length}}),this.suppressComposerFocusUntil=Date.now()+500,this.viewRoot?.focus({preventScroll:!0}),this.plugin.notifications.show({message:`Split "${this.titleForNode(e)}" into ${p.length}`,kind:"success",category:"split",affectedIds:[e.id],folder:this.noteFolder});let m=B.slice(),y=this.noteFolder;this.plugin.getUndoStack(y).push({label:`Split note into ${p.length}`,undo:async()=>{for(let{path:E}of m){let v=this.app.vault.getAbstractFileByPath(E);if(v)try{await this.app.fileManager.trashFile(v)}catch{}}let Q=this.app.vault.getAbstractFileByPath(A);Q&&await this.app.vault.modify(Q,r),this.tree.rebuild(y),this.render()},redo:async()=>{let Q=this.app.vault.getAbstractFileByPath(A);Q&&await this.app.vault.modify(Q,I);for(let{path:E,content:v}of m)await this.app.vault.adapter.exists(E)||await this.app.vault.create(E,v);this.tree.rebuild(y),this.render()}})}catch(g){new k.Notice(`Stashpad: split failed (${g.message})`),console.error(g)}};new ci(this.app,n,async p=>{let g=o.slice(0,p).join(` +`).replace(/\s+$/,""),h=o.slice(p).join(` +`).replace(/^\s+|\s+$/g,"");await l(g,h,{mode:"line",splitAtLine:p})},async p=>{let g=n.slice(0,p).replace(/\s+$/,""),h=n.slice(p).replace(/^\s+|\s+$/g,"");await l(g,h,{mode:"cursor",splitAtChar:p})},async p=>{await d(p)}).open()}cmdOpenInNewStashpadTab(t){let e=t??this.resolveActionTarget();e?.file&&this.openInNewStashpadTab(e.id)}cmdCloneStashpadTab(){let t=this.tree.get(this.focusId);t?.file?this.cmdOpenInNewStashpadTab(t):this.openInNewStashpadTab(this.focusId)}resolveActionTarget(){if(this.cursorIdx>=0&&this.currentChildren[this.cursorIdx])return this.currentChildren[this.cursorIdx];let t=this.tree.get(this.focusId);return t?.file?t:void 0}cmdExportStash(t){return ir(this,t)}cmdExportOkf(t){return sr(this,t)}cmdImportStash(){return ar(this)}processStashFile(t){return lo(this,t)}async createNoteUnder(t,e,i={record:!0}){let s=(i.targetFolder??this.noteFolder).replace(/\/+$/,""),n=s!==this.noteFolder;await this.ensureFolder(s);let o=tt(),r=null;{let f=(this.plugin.settings.noteTemplates??{})[s];if(f){let C=this.app.vault.getAbstractFileByPath(f);if(C&&C.extension==="md")try{let B=await this.app.vault.cachedRead(C),m=this.stripFrontmatter(B);r=this.app.metadataCache.getFileCache(C)?.frontmatter??{},m.includes("{{body}}")?t=m.replace(/\{\{body\}\}/g,t):t.trim()?m.trim()&&(t=`${t} -${m}`):t=m}catch(B){console.warn("[Stashpad] template read failed",B)}}}let A=Et(t,this.activeStopwords()),l=wt(A,o),d=`${s}/${l}`,g=e??this.focusId,p=i.createdOverride??new Date().toISOString(),h=this.extractAttachments(t),I=this.authorship.currentAuthorLink();I&&this.authorship.ensureAuthorFile(I);let u=["---",`id: ${o}`,`parent: ${g}`,`created: ${p}`,`modified: ${p}`];if(I&&u.push(`author: "${I.link.replace(/"/g,'\\"')}"`),h.length>0){u.push("attachments:");for(let f of h)u.push(` - "${f.replace(/"/g,'\\"')}"`)}else u.push("attachments: []");u.push("---",t);try{let f=u.join(` -`);this.plugin.importService.suppress(d,6e4),await Qt.timeAsync("write.createNote.file",()=>this.app.vault.create(d,f)),i.collectInto?.push({path:d,content:f});try{let C=this.app.vault.getAbstractFileByPath(d);if(C&&C.extension==="md"){if(!n)this.tree.insertSynthetic({id:o,parent:g,children:[],file:C,created:p}),i.deferRender||this.render(),this.fmSync.scheduleParentChange(o,null,g);else{i.deferRender||this.render();let B=s.split("/").pop()||s,m=(t.split(` -`).find(w=>w.trim())??"note").trim().slice(0,60);i.deferUndo||this.plugin.notifications.show({message:`"${m}" landed in \`${B}\``,kind:"success",category:"create",duration:0,folder:s,affectedIds:[o],actions:[{label:"Jump to note",onClick:()=>{this.switchToFolderAndFocus(s,o)}}]})}if(r)try{await this.app.fileManager.processFrontMatter(C,B=>{for(let[m,w]of Object.entries(r))se.includes(m)||B[m]===void 0&&(B[m]=w)})}catch(B){console.warn("[Stashpad] template fm overlay failed",B)}}}catch{}if(await this.log.append({type:"create",id:o,payload:{path:d,parent:g}}),i.record!==!1&&!i.deferUndo){let C=t;this.plugin.getUndoStack(s).push({label:n?"Send note":"Create note",undo:async()=>{let B=this.app.vault.getAbstractFileByPath(d);if(B)try{await this.app.fileManager.trashFile(B)}catch{}if(this.composerDraft=C,this.saveDraft(C),this.recordLastSubmitted(""),this.composerInputEl){this.composerInputEl.value=C;let m=C.length;this.composerInputEl.setSelectionRange(m,m),this.composerInputEl.focus()}n||this.tree.rebuild(this.noteFolder),this.render()},redo:async()=>{await this.app.vault.adapter.exists(d)||await this.app.vault.create(d,f),this.composerDraft="",this.saveDraft(""),this.recordLastSubmitted(C),this.composerInputEl&&(this.composerInputEl.value=""),n||this.tree.rebuild(this.noteFolder),this.render()}})}return o}catch(f){return new k.Notice(`Stashpad: failed to create note (${f.message})`),null}}async createNotesBatch(t,e,i,s,n){let o=t.length,r=[],A=!!i?.targetFolder&&i.targetFolder!==this.noteFolder,l=8,d=null;if(o>=l){let g=new k.Notice("",0),p=g.messageEl;p.empty(),p.createDiv({cls:"stashpad-split-progress-title",text:`Splitting into ${o} notes\u2026`});let I=p.createDiv({cls:"stashpad-split-progress-bar"}).createDiv({cls:"stashpad-split-progress-fill"}),u=p.createDiv({cls:"stashpad-split-progress-label",text:`0 / ${o}`});d={notice:g,fill:I,label:u}}this.beginBulkRender();try{for(let g=0;g<o;g++)if(await this.createNoteUnder(t[g],e,{...i??{},deferRender:!0,deferUndo:!0,collectInto:r}),d){let p=g+1;d.label.setText(`${p} / ${o}`),d.fill.setCssStyles({width:`${Math.round(p/o*100)}%`}),p%5===0&&await new Promise(h=>window.setTimeout(h,0))}}finally{d?.notice.hide();try{await this.fmSync.flush()}catch{}this.endBulkRender()}if(r.length){let g=r.slice();this.plugin.getUndoStack(n).push({label:`Create ${g.length} notes`,undo:async()=>{for(let{path:p}of g){let h=this.app.vault.getAbstractFileByPath(p);if(h)try{await this.app.fileManager.trashFile(h)}catch{}}if(this.composerDraft=s,this.saveDraft(s),this.recordLastSubmitted(""),this.composerInputEl){this.composerInputEl.value=s;let p=s.length;this.composerInputEl.setSelectionRange(p,p),this.composerInputEl.focus()}A||this.tree.rebuild(this.noteFolder),this.render()},redo:async()=>{for(let{path:p,content:h}of g)await this.app.vault.adapter.exists(p)||await this.app.vault.create(p,h);this.composerDraft="",this.saveDraft(""),this.composerInputEl&&(this.composerInputEl.value=""),A||this.tree.rebuild(this.noteFolder),this.render()}})}o>=l&&this.plugin.notifications.show({message:`Created ${r.length} notes${A?` in \`${n.split("/").pop()}\``:""}.`,kind:"success",category:"create"})}extractAttachments(t){let e=[],i=/!\[\[([^\]\|]+)(?:\|[^\]]+)?\]\]/g,s;for(;(s=i.exec(t))!==null;)e.push(s[1]);return e}async ensureFolder(t){if(await this.app.vault.adapter.exists(t)){let e=this.app.vault.getAbstractFileByPath(t);if(e&&!(e instanceof k.TFolder))throw new Error(`${t} exists and is not a folder`);return}try{await this.app.vault.createFolder(t)}catch(e){let i=e?.message??"";if(!/already exists/i.test(i))throw e}}async importAttachment(t){try{let e=await t.arrayBuffer(),i=`${this.noteFolder}/_attachments`;await this.ensureFolder(i);let s=t.name.replace(/[^\w.\-]+/g,"_"),n=Date.now().toString(36),o=`${i}/${n}-${s}`;return await this.app.vault.createBinary(o,e),await this.log.append({type:"attachment_add",id:F,payload:{path:o,name:t.name,size:t.size}}),this.plugin.notifications.show({message:`Attached ${t.name}`,kind:"success",category:"attachment",affectedPaths:[o],folder:this.noteFolder}),`![[${o}]]`}catch(e){return new k.Notice(`Stashpad: attachment failed (${e.message})`),null}}claimSelectedAsAuthor(){this.authorship.claimSelectedAsAuthor()}claimFolderAsAuthor(){this.authorship.claimFolderAsAuthor()}claimSelectedWithContributor(){this.authorship.claimSelectedWithContributor()}claimFolderWithContributor(){this.authorship.claimFolderWithContributor()}renderAuthorshipFooter(t,e){if(!e.file)return;let i=this.plugin.settings;if(!i.showAuthor&&!i.showContributors&&!i.showLastEdit)return;let s=this.app.metadataCache.getFileCache(e.file)?.frontmatter??{},n=typeof s.author=="string"?s.author:"",o=Array.isArray(s.contributors)?s.contributors.filter(I=>typeof I=="string"&&I.trim()!==""):[],r=typeof s.modified=="string"?s.modified:typeof s.created=="string"?s.created:"",A=i.showAuthor&&!!n,l=i.showContributors&&o.length>0,d=i.showLastEdit&&!!r;if(!A&&!l&&!d)return;let g=t.createDiv({cls:"stashpad-note-authorship"}),p=(I,u)=>{let f=u.replace(/^\[\[/,"").replace(/\]\]$/,""),C=f.indexOf("|"),B=C>=0?f.slice(0,C):f,m=C>=0?f.slice(C+1):f.split("/").pop()??f,w=I.createEl("a",{cls:"internal-link",text:m});w.setAttribute("data-href",B),w.setAttribute("href",B)},h=[];A&&h.push(I=>{I.createSpan({cls:"stashpad-authorship-label",text:"by "}),p(I,n)}),l&&h.push(I=>{I.createSpan({cls:"stashpad-authorship-label",text:"with "}),o.forEach((u,f)=>{f>0&&I.createSpan({text:", "}),p(I,u)})}),d&&h.push(I=>{I.createSpan({cls:"stashpad-authorship-label",text:"edited "}),I.createSpan({text:this.formatTimeInline(r)})}),h.forEach((I,u)=>{u>0&&g.createSpan({cls:"stashpad-authorship-sep",text:"\xB7"});let f=g.createSpan({cls:"stashpad-authorship-piece"});I(f)}),g.addEventListener("click",I=>this.handleRenderedClick(I,e))}activeStopwords(){return this.plugin.settings.slugStopWords??Lt}scheduleSlugRename(t){let e=this.slugDebouncers.get(t.path);e&&e.cancel(),e=(0,k.debounce)(()=>void this.maybeRenameForSlug(t),3e4),this.slugDebouncers.set(t.path,e),e()}async maybeRenameForSlug(t){let e=ve(t.basename);if(!e||e===F)return;let i=await this.app.vault.cachedRead(t),s=this.stripFrontmatter(i),n=Et(s,this.activeStopwords()),o=wt(n,e);if(t.name===o)return;let r=t.parent?`${t.parent.path}/${o}`:o;if(this.app.vault.getAbstractFileByPath(r))return;let A=t.path;try{await this.app.fileManager.renameFile(t,r),await this.log.append({type:"rename",id:e,payload:{from:A,to:r}})}catch{}}scheduleAttachmentSync(t){let e=this.attachmentDebouncers.get(t.path);e&&e.cancel(),e=(0,k.debounce)(()=>void this.syncAttachmentsFrontmatter(t),1500),this.attachmentDebouncers.set(t.path,e),e()}async syncAttachmentsFrontmatter(t){let e=await this.app.vault.cachedRead(t),i=this.stripFrontmatter(e),s=this.extractAttachments(i),n=this.app.metadataCache.getFileCache(t)?.frontmatter,r=(Array.isArray(n?.attachments)?n.attachments:[]).filter(d=>typeof d=="string").map(d=>Be(d));if(r.length===s.length&&r.every((d,g)=>d===s[g]))return;let l=s.map(d=>Rt(d));await this.app.fileManager.processFrontMatter(t,d=>{d.attachments=l})}stripFrontmatter(t){let e=t.replace(/^\uFEFF/,""),i=e.match(/^\s*---\s*\r?\n[\s\S]*?\r?\n---\s*(?:\r?\n|$)/);return i?e.slice(i[0].length):e}formatTime(t){if(!t)return"";let e=(0,k.moment)(t);if(!e.isValid())return"";if(j().useTemplatesFormat){let s=fs(this.app);if(s)return`${e.format(s.dateFormat)} +${m}`):t=m}catch(B){console.warn("[Stashpad] template read failed",B)}}}let A=Qt(t,this.activeStopwords()),l=yt(A,o),d=`${s}/${l}`,p=e??this.focusId,g=i.createdOverride??new Date().toISOString(),h=this.extractAttachments(t),I=this.authorship.currentAuthorLink();I&&this.authorship.ensureAuthorFile(I);let u=["---",`id: ${o}`,`parent: ${p}`,`created: ${g}`,`modified: ${g}`];if(I&&u.push(`author: "${I.link.replace(/"/g,'\\"')}"`),h.length>0){u.push("attachments:");for(let f of h)u.push(` - "${f.replace(/"/g,'\\"')}"`)}else u.push("attachments: []");u.push("---",t);try{let f=u.join(` +`);this.plugin.importService.suppress(d,6e4),await wt.timeAsync("write.createNote.file",()=>this.app.vault.create(d,f)),i.collectInto?.push({path:d,content:f});try{let C=this.app.vault.getAbstractFileByPath(d);if(C&&C.extension==="md"){if(!n)this.tree.insertSynthetic({id:o,parent:p,children:[],file:C,created:g}),i.deferRender||this.render(),this.fmSync.scheduleParentChange(o,null,p);else{i.deferRender||this.render();let B=s.split("/").pop()||s,m=(t.split(` +`).find(y=>y.trim())??"note").trim().slice(0,60);i.deferUndo||this.plugin.notifications.show({message:`"${m}" landed in \`${B}\``,kind:"success",category:"create",duration:0,folder:s,affectedIds:[o],actions:[{label:"Jump to note",onClick:()=>{this.switchToFolderAndFocus(s,o)}}]})}if(r)try{await this.app.fileManager.processFrontMatter(C,B=>{for(let[m,y]of Object.entries(r))ae.includes(m)||B[m]===void 0&&(B[m]=y)})}catch(B){console.warn("[Stashpad] template fm overlay failed",B)}}}catch{}if(await this.log.append({type:"create",id:o,payload:{path:d,parent:p}}),i.record!==!1&&!i.deferUndo){let C=t;this.plugin.getUndoStack(s).push({label:n?"Send note":"Create note",undo:async()=>{let B=this.app.vault.getAbstractFileByPath(d);if(B)try{await this.app.fileManager.trashFile(B)}catch{}if(this.composerDraft=C,this.saveDraft(C),this.recordLastSubmitted(""),this.composerInputEl){this.composerInputEl.value=C;let m=C.length;this.composerInputEl.setSelectionRange(m,m),this.composerInputEl.focus()}n||this.tree.rebuild(this.noteFolder),this.render()},redo:async()=>{await this.app.vault.adapter.exists(d)||await this.app.vault.create(d,f),this.composerDraft="",this.saveDraft(""),this.recordLastSubmitted(C),this.composerInputEl&&(this.composerInputEl.value=""),n||this.tree.rebuild(this.noteFolder),this.render()}})}return o}catch(f){return new k.Notice(`Stashpad: failed to create note (${f.message})`),null}}async createNotesBatch(t,e,i,s,n){let o=t.length,r=[],A=!!i?.targetFolder&&i.targetFolder!==this.noteFolder,l=8,d=null;if(o>=l){let p=new k.Notice("",0),g=p.messageEl;g.empty(),g.createDiv({cls:"stashpad-split-progress-title",text:`Splitting into ${o} notes\u2026`});let I=g.createDiv({cls:"stashpad-split-progress-bar"}).createDiv({cls:"stashpad-split-progress-fill"}),u=g.createDiv({cls:"stashpad-split-progress-label",text:`0 / ${o}`});d={notice:p,fill:I,label:u}}this.beginBulkRender();try{for(let p=0;p<o;p++)if(await this.createNoteUnder(t[p],e,{...i??{},deferRender:!0,deferUndo:!0,collectInto:r}),d){let g=p+1;d.label.setText(`${g} / ${o}`),d.fill.setCssStyles({width:`${Math.round(g/o*100)}%`}),g%5===0&&await new Promise(h=>window.setTimeout(h,0))}}finally{d?.notice.hide();try{await this.fmSync.flush()}catch{}this.endBulkRender()}if(r.length){let p=r.slice();this.plugin.getUndoStack(n).push({label:`Create ${p.length} notes`,undo:async()=>{for(let{path:g}of p){let h=this.app.vault.getAbstractFileByPath(g);if(h)try{await this.app.fileManager.trashFile(h)}catch{}}if(this.composerDraft=s,this.saveDraft(s),this.recordLastSubmitted(""),this.composerInputEl){this.composerInputEl.value=s;let g=s.length;this.composerInputEl.setSelectionRange(g,g),this.composerInputEl.focus()}A||this.tree.rebuild(this.noteFolder),this.render()},redo:async()=>{for(let{path:g,content:h}of p)await this.app.vault.adapter.exists(g)||await this.app.vault.create(g,h);this.composerDraft="",this.saveDraft(""),this.composerInputEl&&(this.composerInputEl.value=""),A||this.tree.rebuild(this.noteFolder),this.render()}})}o>=l&&this.plugin.notifications.show({message:`Created ${r.length} notes${A?` in \`${n.split("/").pop()}\``:""}.`,kind:"success",category:"create"})}extractAttachments(t){let e=[],i=/!\[\[([^\]\|]+)(?:\|[^\]]+)?\]\]/g,s;for(;(s=i.exec(t))!==null;)e.push(s[1]);return e}async ensureFolder(t){if(await this.app.vault.adapter.exists(t)){let e=this.app.vault.getAbstractFileByPath(t);if(e&&!(e instanceof k.TFolder))throw new Error(`${t} exists and is not a folder`);return}try{await this.app.vault.createFolder(t)}catch(e){let i=e?.message??"";if(!/already exists/i.test(i))throw e}}async importAttachment(t){try{let e=await t.arrayBuffer(),i=`${this.noteFolder}/_attachments`;await this.ensureFolder(i);let s=t.name.replace(/[^\w.\-]+/g,"_"),n=Date.now().toString(36),o=`${i}/${n}-${s}`;return await this.app.vault.createBinary(o,e),await this.log.append({type:"attachment_add",id:F,payload:{path:o,name:t.name,size:t.size}}),this.plugin.notifications.show({message:`Attached ${t.name}`,kind:"success",category:"attachment",affectedPaths:[o],folder:this.noteFolder}),`![[${o}]]`}catch(e){return new k.Notice(`Stashpad: attachment failed (${e.message})`),null}}claimSelectedAsAuthor(){this.authorship.claimSelectedAsAuthor()}claimFolderAsAuthor(){this.authorship.claimFolderAsAuthor()}claimSelectedWithContributor(){this.authorship.claimSelectedWithContributor()}claimFolderWithContributor(){this.authorship.claimFolderWithContributor()}renderAuthorshipFooter(t,e){if(!e.file)return;let i=this.plugin.settings;if(!i.showAuthor&&!i.showContributors&&!i.showLastEdit)return;let s=this.app.metadataCache.getFileCache(e.file)?.frontmatter??{},n=typeof s.author=="string"?s.author:"",o=Array.isArray(s.contributors)?s.contributors.filter(I=>typeof I=="string"&&I.trim()!==""):[],r=typeof s.modified=="string"?s.modified:typeof s.created=="string"?s.created:"",A=i.showAuthor&&!!n,l=i.showContributors&&o.length>0,d=i.showLastEdit&&!!r;if(!A&&!l&&!d)return;let p=t.createDiv({cls:"stashpad-note-authorship"}),g=(I,u)=>{let f=u.replace(/^\[\[/,"").replace(/\]\]$/,""),C=f.indexOf("|"),B=C>=0?f.slice(0,C):f,m=C>=0?f.slice(C+1):f.split("/").pop()??f,y=I.createEl("a",{cls:"internal-link",text:m});y.setAttribute("data-href",B),y.setAttribute("href",B)},h=[];A&&h.push(I=>{I.createSpan({cls:"stashpad-authorship-label",text:"by "}),g(I,n)}),l&&h.push(I=>{I.createSpan({cls:"stashpad-authorship-label",text:"with "}),o.forEach((u,f)=>{f>0&&I.createSpan({text:", "}),g(I,u)})}),d&&h.push(I=>{I.createSpan({cls:"stashpad-authorship-label",text:"edited "}),I.createSpan({text:this.formatTimeInline(r)})}),h.forEach((I,u)=>{u>0&&p.createSpan({cls:"stashpad-authorship-sep",text:"\xB7"});let f=p.createSpan({cls:"stashpad-authorship-piece"});I(f)}),p.addEventListener("click",I=>this.handleRenderedClick(I,e))}activeStopwords(){return this.plugin.settings.slugStopWords??Jt}scheduleSlugRename(t){let e=this.slugDebouncers.get(t.path);e&&e.cancel(),e=(0,k.debounce)(()=>void this.maybeRenameForSlug(t),3e4),this.slugDebouncers.set(t.path,e),e()}async maybeRenameForSlug(t){let e=le(t.basename);if(!e||e===F)return;let i=await this.app.vault.cachedRead(t),s=this.stripFrontmatter(i),n=Qt(s,this.activeStopwords()),o=yt(n,e);if(t.name===o)return;let r=t.parent?`${t.parent.path}/${o}`:o;if(this.app.vault.getAbstractFileByPath(r))return;let A=t.path;try{await this.app.fileManager.renameFile(t,r),await this.log.append({type:"rename",id:e,payload:{from:A,to:r}})}catch{}}scheduleAttachmentSync(t){let e=this.attachmentDebouncers.get(t.path);e&&e.cancel(),e=(0,k.debounce)(()=>void this.syncAttachmentsFrontmatter(t),1500),this.attachmentDebouncers.set(t.path,e),e()}async syncAttachmentsFrontmatter(t){let e=await this.app.vault.cachedRead(t),i=this.stripFrontmatter(e),s=this.extractAttachments(i),n=this.app.metadataCache.getFileCache(t)?.frontmatter,r=(Array.isArray(n?.attachments)?n.attachments:[]).filter(d=>typeof d=="string").map(d=>Ee(d));if(r.length===s.length&&r.every((d,p)=>d===s[p]))return;let l=s.map(d=>qt(d));await this.app.fileManager.processFrontMatter(t,d=>{d.attachments=l})}stripFrontmatter(t){let e=t.replace(/^\uFEFF/,""),i=e.match(/^\s*---\s*\r?\n[\s\S]*?\r?\n---\s*(?:\r?\n|$)/);return i?e.slice(i[0].length):e}formatTime(t){if(!t)return"";let e=(0,k.moment)(t);if(!e.isValid())return"";if(j().useTemplatesFormat){let s=ws(this.app);if(s)return`${e.format(s.dateFormat)} ${e.format(s.timeFormat)}`}return`${e.format("YYYY.MM.DD")} -${e.format("HH:mm A")}`}formatTimeInline(t){if(!t)return"";let e=(0,k.moment)(t);if(!e.isValid())return"";if(j().useTemplatesFormat){let s=fs(this.app);if(s){let n=/:ss/.test(s.timeFormat)?s.timeFormat:s.timeFormat.replace(/(:mm)/,"$1:ss");return`${e.format(s.dateFormat)} ${e.format(n)}`}}return`${e.format("YYYY.MM.DD")} ${e.format("HH:mm:ss A")}`}scrollListToBottom(){let t=this.listEl;if(!t)return;if(this.stickToListBottom=!0,t.scrollTop=t.scrollHeight,k.Platform.isMobile){let r=0,A=()=>{!this.stickToListBottom||r>=8||(r++,Date.now()>=this.keyboardTransitionUntil&&(t.scrollTop=t.scrollHeight),window.setTimeout(A,120))};window.setTimeout(A,60);return}this.stickyRowObserver?.disconnect();let e=()=>{if(!this.stickToListBottom){this.stickyRowObserver?.disconnect(),this.stickyRowObserver=null;return}t.scrollTop=t.scrollHeight},i=new ResizeObserver(e);for(let r of Array.from(t.children))r instanceof HTMLElement&&i.observe(r);this.stickyRowObserver=i;let s=performance.now(),n=t.scrollHeight,o=()=>{if(!this.stickToListBottom)return;let r=t.scrollHeight;r!==n&&(t.scrollTop=r,n=r),performance.now()-s<3e4?requestAnimationFrame(o):(this.stickToListBottom=!1,this.stickyRowObserver?.disconnect(),this.stickyRowObserver=null)};requestAnimationFrame(o)}openNoteMenu(t,e){if(!e.file)return;let i=e.file,s=new k.Menu;s.addItem(A=>A.setTitle("Open in new Stashpad tab").setIcon("layout-grid").onClick(()=>{this.openInNewStashpadTab(e.id)})),s.addItem(A=>A.setTitle("Open in editor").setIcon("file-text").onClick(()=>{this.openFileAtEnd(i)})),s.addItem(A=>A.setTitle("Focus in Stashpad").setIcon("arrow-right").onClick(()=>this.navigateTo(e.id))),s.addSeparator(),s.addItem(A=>A.setTitle("Split note\u2026").setIcon("split").onClick(()=>void this.cmdSplit(e))),s.addItem(A=>A.setTitle("Clone (duplicate / copy)").setIcon("files").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdClone()})),s.addItem(A=>A.setTitle("Insert template\u2026").setIcon("file-plus-2").onClick(()=>this.cmdInsertTemplate())),s.addItem(A=>A.setTitle("Export to .stash").setIcon("package").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdExportStash()})),this.plugin.settings.okfEnabled&&s.addItem(A=>A.setTitle("Export as OKF\u2026").setIcon("book-marked").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdExportOkf()})),this.plugin.encryption?.isConfigured?.()&&s.addItem(A=>A.setTitle("Encrypt (lock) note + children").setIcon("lock").onClick(async()=>{let l=this.order.getOrder(this.noteFolder,e.parent??F),d=l.indexOf(e.id),g=d>0?l[d-1]:null;await this.plugin.lockNoteSubtree(this.noteFolder,e.id,g)&&this.render()})),s.addSeparator(),s.addItem(A=>A.setTitle("Move to\u2026").setIcon("move").onClick(()=>this.cmdMovePicker())),s.addItem(A=>A.setTitle("Move to Home").setIcon("home").onClick(async()=>{await this.changeParent(e,F),this.plugin.settings.autoNavOnMoveOut&&this.focusId!==F&&this.navigateTo(F)}));let n={folder:this.noteFolder,id:e.id},o=this.plugin.isPinned(n);s.addItem(A=>A.setTitle(o?"Unpin from sidebar":"Pin to sidebar").setIcon(o?"pin-off":"pin").onClick(async()=>{o?await this.plugin.unpinNote(n):await this.plugin.pinNote(n)})),s.addItem(A=>A.setTitle("Set color\u2026").setIcon("palette").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdSetColor()}));let r=this.isCompleted(e);s.addItem(A=>A.setTitle(r?"Mark incomplete":"Mark complete").setIcon(r?"circle":"check-circle").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdToggleComplete()})),s.addSeparator(),s.addItem(A=>A.setTitle("Delete").setIcon("trash").onClick(async()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),await this.cmdDelete()})),s.addSeparator(),s.addItem(A=>A.setTitle("More commands\u2026").setIcon("terminal").onClick(()=>this.openCommandPalette())),s.showAtMouseEvent(t)}async deleteNote(t){if(!t.file)return;let e=[],i=I=>{for(let u of this.tree.getChildren(I.id))i(u),e.push(u)};i(t);let s=[...e,t],n=s.filter(I=>!!I.file),o=await Promise.all(n.map(I=>this.app.vault.cachedRead(I.file))),r=[];for(let I=0;I<n.length;I++){let u=n[I];r.push(...this.extractAttachments(this.stripFrontmatter(o[I])));let f=this.app.metadataCache.getFileCache(u.file)?.frontmatter;if(Array.isArray(f?.attachments))for(let C of f.attachments)typeof C=="string"&&C.trim()&&r.push(Be(C))}let A=[...new Set(r)],l=this.authorship.collectAuthorIds(s),d=async I=>{let u=await this.snapshotNotes(s,I),f=0;if(I)for(let N of A){let P=this.app.metadataCache.getFirstLinkpathDest(N,"");if(P)try{await this.app.fileManager.trashFile(P),await this.log.append({type:"attachment_remove",id:F,payload:{path:P.path}}),this.plugin.notifications.show({message:`Deleted attachment "${P.name}"`,kind:"warning",category:"attachment",affectedPaths:[P.path],folder:this.noteFolder}),f+=1}catch{}}let C=new Set;for(let N of s)N.parent&&C.add(N.parent);let B=this.currentChildren.findIndex(N=>N.id===t.id),m=null;if(B>=0){for(let N=B+1;N<this.currentChildren.length;N++)if(this.currentChildren[N].id!==t.id){m=this.currentChildren[N].id;break}if(!m){for(let N=B-1;N>=0;N--)if(this.currentChildren[N].id!==t.id){m=this.currentChildren[N].id;break}}}for(let N of s)if(N.file){try{await this.app.fileManager.trashFile(N.file)}catch{}await this.log.append({type:"delete",id:N.id,payload:{path:N.file.path,attachmentsRemoved:I?A:[]}})}this.selection.clear(),this.cursorIdx=-1,m&&(this.pendingFocusIds=[m]),this.tree.rebuild(this.noteFolder),this.render({kind:"follow-cursor"});for(let N of C)s.some(P=>P.id===N)||this.fmSync.scheduleParentOfDeleted(N);let w=this.noteFolder,Q=`Delete "${this.titleForNode(t)}"`,E=t.id,v=f>0?` with ${f} attachment${f===1?"":"s"}`:"",y=!1,b=async()=>{y||(y=!0,this.selection.clear(),this.cursorIdx=-1,await this.restoreSnapshots(u,[E]))};this.plugin.notifications.show({message:`Deleted "${this.titleForNode(t)}"${v}`,kind:"warning",category:"delete",duration:0,affectedIds:[t.id],affectedAuthorIds:l,folder:this.noteFolder,actions:[{label:"Undo delete",onClick:()=>void b()}]}),this.plugin.getUndoStack(w).push({label:Q,undo:async()=>{await b()},redo:async()=>{this.selection.clear(),this.cursorIdx=-1,y=!1,await this.trashNotesAndAttachments(u)}})},g=j(),p=e.length>0&&g.confirmBulkDelete,h=A.length>0&&g.confirmAttachmentDelete;if(!p&&!h){await d(!1),this.focusView();return}new Me(this.app,this.titleForNode(t),e.length,A.length,h,async I=>{await d(I),this.focusView()}).open()}async cmdSwapWithParent(){let t=this.cursorIdx>=0?this.currentChildren[this.cursorIdx]:null;if(!t?.file){new k.Notice("Pick a note first (move the cursor onto it).");return}if(!t.parent||t.parent===F){new k.Notice("Already at Home \u2014 no parent to swap with.");return}let e=this.tree.get(t.parent);if(!e?.file){new k.Notice("Couldn't find the parent note.");return}let i=e.parent??F,s=this.titleForNode(t),n=this.titleForNode(e),o=this.tree.getChildren(e.id).filter(A=>A.id!==t.id).length,r=[`"${n}" becomes a child of "${s}".`];o>0&&r.push(`${o} sibling${o===1?"":"s"} move with it.`),new gt(this.app,"Swap notes?",r.join(` -`),"Swap",async A=>{A&&await this.swapParentChild(e,t,i)}).open()}offerSwapForDescendantMove(t,e){let i=this.tree.get(e);if(!i?.file){this.plugin.notifications.show({message:`Can't nest "${this.titleForNode(t)}" under one of its own descendants \u2014 that would create a cycle.`,kind:"warning",category:"move",affectedIds:[t.id],folder:this.noteFolder});return}if(i.parent!==t.id){this.plugin.notifications.show({message:`Can't nest "${this.titleForNode(t)}" under "${this.titleForNode(i)}" \u2014 it's a deeper descendant. Only direct parent \u2194 child swaps are supported (try moving "${this.titleForNode(i)}" up first, then swap).`,kind:"warning",category:"move",affectedIds:[t.id,i.id],folder:this.noteFolder});return}let s=this.titleForNode(t),n=this.titleForNode(i),o=this.tree.getChildren(t.id).filter(A=>A.id!==i.id).length,r=[`"${s}" becomes a child of "${n}".`];o>0&&r.push(`${o} sibling${o===1?"":"s"} move with it.`),new gt(this.app,"Confirm Note Swap",r.join(` -`),"Swap",async A=>{if(!A)return;let l=t.parent??F;await this.swapParentChild(t,i,l)}).open()}async swapParentChild(t,e,i){if(!t.file||!e.file)return;if(e.parent!==t.id){new k.Notice("Swap aborted: parent/child relationship changed.");return}let s=this.noteFolder,n=t.parent,o=this.tree.getChildren(t.id).filter(h=>h.id!==e.id).filter(h=>!!h.file),r=o.map(h=>({id:h.id,path:h.file.path,was:h.parent})),A=this.order.getOrder(s,i).slice(),l=this.order.getOrder(s,e.id).slice(),d=this.order.getOrder(s,t.id).slice();await this.app.fileManager.processFrontMatter(e.file,h=>{h.parent=i}),this.fmSync.scheduleParentChange(e.id,t.id,i),await this.app.fileManager.processFrontMatter(t.file,h=>{h.parent=e.id}),this.fmSync.scheduleParentChange(t.id,n,e.id);for(let h of o)await this.app.fileManager.processFrontMatter(h.file,I=>{I.parent=e.id}),this.fmSync.scheduleParentChange(h.id,t.id,e.id);if(A.length>0){let h=A.includes(t.id)?A.map(I=>I===t.id?e.id:I):[...A.filter(I=>I!==e.id),e.id];this.order.setOrder(s,i,h)}let g=o.map(h=>h.id),p=[t.id,...l.filter(h=>h!==t.id&&!g.includes(h)),...g];this.order.setOrder(s,e.id,p),this.order.setOrder(s,t.id,[]),await this.order.save(s),await this.log.append({type:"parent_change",id:e.id,payload:{from:t.id,to:i,reason:"swap"}}),await this.log.append({type:"parent_change",id:t.id,payload:{from:n,to:e.id,reason:"swap"}});for(let h of r)await this.log.append({type:"parent_change",id:h.id,payload:{from:h.was,to:e.id,reason:"swap"}});this.tree.rebuild(s),this.pendingFocusIds=[e.id],this.render({kind:"follow-cursor"}),this.plugin.notifications.show({message:`Swapped "${this.titleForNode(e)}" \u2194 "${this.titleForNode(t)}".`,kind:"success",category:"move",affectedIds:[e.id,t.id,...g],folder:s}),this.plugin.getUndoStack(s).push({label:`Swap "${this.titleForNode(e)}" \u2194 parent`,undo:async()=>{let h=this.tree.get(t.id),I=this.tree.get(e.id);h?.file&&await this.app.fileManager.processFrontMatter(h.file,u=>{n==null||n===F?(delete u.parent,u.parent=F):u.parent=n}),I?.file&&await this.app.fileManager.processFrontMatter(I.file,u=>{u.parent=t.id});for(let u of r){let f=this.app.vault.getAbstractFileByPath(u.path);f&&await this.app.fileManager.processFrontMatter(f,C=>{u.was==null?C.parent=F:C.parent=u.was})}this.order.setOrder(s,i,A),this.order.setOrder(s,e.id,l),this.order.setOrder(s,t.id,d),await this.order.save(s),this.tree.rebuild(s),this.pendingFocusIds=[t.id],this.render({kind:"follow-cursor"})},redo:async()=>{await this.swapParentChild(t,e,i)}})}async changeParent(t,e,i={record:!0}){if(!t.file)return!1;let s=t.file,n=t.parent,o=A=>A??F;if(o(n)===o(e)){if(!i.quiet){let A=this.titleForNode(t),l=e===F?"Home":`"${this.titleForNode(this.tree.get(e)??t)}"`;this.plugin.notifications.show({message:`"${A}" is already under ${l}.`,kind:"info",category:"move",affectedIds:[t.id],folder:this.noteFolder})}return!1}if(e===t.id)return i.quiet||this.plugin.notifications.show({message:`Can't move "${this.titleForNode(t)}" into itself.`,kind:"warning",category:"move",affectedIds:[t.id],folder:this.noteFolder}),!1;if(e!==F&&this.isDescendant(e,t.id))return i.quiet||this.offerSwapForDescendantMove(t,e),!1;let r=this.authorship.collectAuthorIds([t]);if(await this.app.fileManager.processFrontMatter(s,A=>{A.parent=e}),this.fmSync.scheduleParentChange(t.id,n,e),await this.log.append({type:"parent_change",id:t.id,payload:{from:n,to:e}}),this.pendingFocusIds=[t.id],this.focusId!==e&&this.focusId!==n?(this.selection.clear(),this.cursorIdx=-1):this.focusId===n&&(this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=null),!i.quiet&&!i.silentSuccess){let A=this.tree.get(e),l=A?this.titleForNode(A):"(root)";this.plugin.notifications.show({message:`Reparented "${this.titleForNode(t)}" \u2192 "${l}"`,kind:"success",category:"move",affectedIds:[t.id],affectedAuthorIds:r,folder:this.noteFolder,actions:e===F?[]:[{label:"Jump to parent",onClick:()=>this.navigateTo(e)}]})}if(i.record!==!1){let A=this.noteFolder,l=s.path,d=t.id;this.plugin.getUndoStack(A).push({label:"Move note",undo:async()=>{let g=this.app.vault.getAbstractFileByPath(l);if(g){await this.app.fileManager.processFrontMatter(g,p=>{p.parent=n}),this.pendingFocusIds=[d],this.focusId!==n&&this.focusId!==e?(this.selection.clear(),this.cursorIdx=-1):this.focusId===e&&(this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=null),this.tree.rebuild(A),this.render({kind:"follow-cursor"});{let p=this.selectionGuardKey,h=()=>{if(this.selectionGuardKey!==p||this.selection.has(d))return;let I=this.currentChildren.findIndex(u=>u.id===d);I<0||(this.selection.add(d),this.cursorIdx=I,this.render({kind:"follow-cursor"}))};setTimeout(h,120),setTimeout(h,400)}}},redo:async()=>{let g=this.app.vault.getAbstractFileByPath(l);if(g){await this.app.fileManager.processFrontMatter(g,p=>{p.parent=e}),this.pendingFocusIds=[d],this.focusId!==e&&this.focusId!==n?(this.selection.clear(),this.cursorIdx=-1):this.focusId===n&&(this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=null),this.tree.rebuild(A),this.render({kind:"follow-cursor"});{let p=this.selectionGuardKey,h=()=>{if(this.selectionGuardKey!==p||this.selection.has(d))return;let I=this.currentChildren.findIndex(u=>u.id===d);I<0||(this.selection.add(d),this.cursorIdx=I,this.render({kind:"follow-cursor"}))};setTimeout(h,120),setTimeout(h,400)}}}})}return!0}notifyBatchMove(t,e,i){if(!t.length)return;let s=this.tree.get(e),n=e===F?"Home":`"${s?this.titleForNode(s):"the destination"}"`,o=A=>i.get(A.id)??0,r;if(t.length===1){let A=this.titleForNode(t[0]),l=o(t[0]);r=l>0?`Moved "${A}" and its ${l} ${l===1?"child":"children"} \u2192 ${n}`:`Moved "${A}" \u2192 ${n}`}else{let A=t.reduce((l,d)=>l+o(d),0);r=A>0?`Moved ${t.length} notes (${A} nested) \u2192 ${n}`:`Moved ${t.length} notes \u2192 ${n}`}this.plugin.notifications.show({message:r,kind:"success",category:"move",duration:e===F?void 0:0,affectedIds:t.map(A=>A.id),affectedAuthorIds:this.authorship.collectAuthorIds(t),folder:this.noteFolder,actions:e===F?[]:[{label:"Jump to destination",onClick:()=>this.navigateTo(e)}]})}},eo=class extends k.SuggestModal{constructor(t,e,i){super(t);this.folders=e;this.onPick=i;this.setPlaceholder("Move to which archive folder?")}getSuggestions(t){let e=t.toLowerCase();return this.folders.filter(i=>i.toLowerCase().includes(e))}renderSuggestion(t,e){e.createDiv({text:t.split("/").pop()||t}),e.createEl("small",{text:t,cls:"stashpad-suggest-path"})}onChooseSuggestion(t){this.onPick(t)}},Ms=class extends k.SuggestModal{constructor(t,e,i){super(t);this.entries=e;this.onPick=i;this.setPlaceholder("Restore which deleted note?")}getSuggestions(t){let e=t.toLowerCase();return this.entries.filter(i=>`${i.label} ${i.folder}`.toLowerCase().includes(e))}renderSuggestion(t,e){e.createDiv({text:t.label}),e.createEl("small",{text:`from ${t.folder}`,cls:"stashpad-suggest-path"})}onChooseSuggestion(t){this.onPick(t.blob)}};var ee=require("obsidian");rt();var JA=ee.moment,Ts=class extends ee.ItemView{constructor(t,e){super(t);this.plugin=e;this.renderPending=!1;this.renderGen=0}getViewType(){return De}getDisplayText(){return"Encrypted trash"}getIcon(){return"trash-2"}async onOpen(){this.containerEl.addClass("stashpad-trash-view"),this.registerEvent(this.app.vault.on("create",t=>{t.path.startsWith("_deleted/")&&this.scheduleRender()})),this.registerEvent(this.app.vault.on("delete",t=>{t.path.startsWith("_deleted/")&&this.scheduleRender()})),await this.render()}scheduleRender(){this.renderPending||(this.renderPending=!0,window.setTimeout(()=>{this.renderPending=!1,this.render()},150))}async render(){let t=++this.renderGen,e=this.contentEl;e.empty(),e.addClass("stashpad-trash-view-body");let i=e.createDiv({cls:"stashpad-trash-view-header"});i.createEl("h3",{text:"Encrypted trash"});let s=i.createEl("button",{cls:"stashpad-trash-iconbtn"});if((0,ee.setIcon)(s,"refresh-cw"),s.setAttr("aria-label","Refresh"),s.onclick=()=>void this.render(),!this.plugin.encryption?.isConfigured?.()){e.createDiv({cls:"stashpad-trash-empty",text:"Encryption isn't set up."});return}let n=await this.plugin.listDeletedTrash();if(t!==this.renderGen)return;if(n.length===0){e.createDiv({cls:"stashpad-trash-empty",text:"Nothing in the encrypted trash. Notes you securely delete land here, recoverable with your password."});return}let o=i.createEl("button",{cls:"stashpad-trash-restore",text:"Restore all"});(0,ee.setIcon)(o.createSpan({cls:"stashpad-btn-icon"}),"rotate-ccw"),o.onclick=async()=>{o.disabled=!0,await this.plugin.restoreAllTrash(),await this.render()};let r=new Map;for(let l of n){let d=l.meta?.title?l.meta.originalFolder||"(unknown folder)":" hidden";(r.get(d)??r.set(d,[]).get(d)).push(l)}let A=[...r.keys()].sort((l,d)=>l===" hidden"?1:d===" hidden"?-1:l.localeCompare(d));for(let l of A){let d=l===" hidden",g=e.createDiv({cls:"stashpad-trash-group"}),p=g.createDiv({cls:"stashpad-trash-group-head"});(0,ee.setIcon)(p.createSpan({cls:"stashpad-trash-group-icon"}),d?"lock":"folder"),p.createSpan({text:d?"Hidden (title obscured)":l.split("/").pop()||l}),p.createSpan({cls:"stashpad-trash-group-count",text:String(r.get(l).length)});for(let h of r.get(l)){let I=g.createDiv({cls:"stashpad-trash-row"}),u=I.createDiv({cls:"stashpad-trash-row-main"});u.createSpan({cls:"stashpad-trash-title",text:d?"Locked note":h.meta?.title||"Locked note"});let f=h.meta?.deletedAt?`deleted ${JA(h.meta.deletedAt).fromNow()}`:"deleted",C=h.meta&&h.meta.count>1?` \xB7 ${h.meta.count} ${h.meta.kind==="rawtrash"?"files":"notes"}`:"";u.createSpan({cls:"stashpad-trash-sub",text:f+C});let B=I.createEl("button",{cls:"stashpad-trash-restore",text:"Restore"});(0,ee.setIcon)(B.createSpan({cls:"stashpad-btn-icon"}),"rotate-ccw"),B.onclick=async()=>{B.disabled=!0,await this.plugin.restoreDeletedAt(h.blob)?await this.render():B.disabled=!1}}}}async onClose(){this.contentEl.empty()}};async function $a(c){let{workspace:a}=c.app,t=a.getLeavesOfType(De);if(t.length>0){a.revealLeaf(t[0]);return}let e=a.getLeaf("tab");await e.setViewState({type:De,active:!0}),a.revealLeaf(e)}rt();var $=require("obsidian");rt();vt();var Hs=class c extends $.ItemView{constructor(t,e){super(t);this.plugin=e;this.renderTimer=null;this.pinExpanded=new Set;this.homeColorByFolder=new Map}getViewType(){return fe}getDisplayText(){return"Stashpad folders"}getIcon(){return"folders"}async onOpen(){this.render(),this.registerEvent(this.app.workspace.on("active-leaf-change",()=>this.scheduleRender())),this.registerEvent(this.app.workspace.on("layout-change",()=>this.scheduleRender())),this.registerEvent(this.app.vault.on("create",()=>this.scheduleRender())),this.registerEvent(this.app.vault.on("delete",()=>this.scheduleRender())),this.registerEvent(this.app.vault.on("rename",()=>this.scheduleRender())),this.registerEvent(this.app.metadataCache.on("changed",()=>this.scheduleRender()))}scheduleRender(){this.renderTimer==null&&(this.renderTimer=window.setTimeout(()=>{this.renderTimer=null,this.containerEl.isConnected&&this.render()},100))}render(){let t=this.contentEl;t.empty(),t.addClass("stashpad-folderpanel-root");let e=this.clampFrac(this.plugin.settings.folderPanelPinnedFraction??.5),i=t.createDiv({cls:"stashpad-folderpanel-section stashpad-folderpanel-pinned"});i.style.flex=`0 0 ${(e*100).toFixed(2)}%`;let s=i.createDiv({cls:"stashpad-folderpanel-heading stashpad-folderpanel-heading-row"});s.createSpan({cls:"stashpad-folderpanel-heading-title",text:"Pinned"});let n=s.createEl("button",{cls:"stashpad-folderpanel-iconbtn"});(0,$.setIcon)(n,"list"),n.setAttr("aria-label","Pinned view options"),n.onclick=d=>{d.stopPropagation(),this.openPinnedOptionsMenu(d)},this.renderPinned(i.createDiv({cls:"stashpad-folderpanel-list stashpad-folderpanel-pins"}));let o=t.createDiv({cls:"stashpad-folderpanel-divider"});o.createDiv({cls:"stashpad-folderpanel-divider-grip"}),this.attachDividerDrag(t,i,o);let r=t.createDiv({cls:"stashpad-folderpanel-section stashpad-folderpanel-folders"});r.setCssStyles({flex:"1 1 0"});let A=r.createDiv({cls:"stashpad-folderpanel-heading stashpad-folderpanel-heading-row"}),l=A.createSpan({cls:"stashpad-folderpanel-heading-title stashpad-folderpanel-heading-switch",text:"Folders"});if(l.setAttr("aria-label","Open folder switcher"),l.onmousedown=d=>{d.button===0&&(d.preventDefault(),this.plugin.openFolderPicker())},this.plugin.encryption?.isConfigured?.()){let d=A.createEl("button",{cls:"stashpad-folderpanel-iconbtn stashpad-folderpanel-heading-trash"});(0,$.setIcon)(d,"trash-2"),d.setAttr("aria-label","Open encrypted trash"),d.onmousedown=g=>{g.button===0&&(g.preventDefault(),g.stopPropagation(),this.plugin.openEncryptedTrash())}}this.renderFolders(r.createDiv({cls:"stashpad-folderpanel-list"}))}clampFrac(t){return Number.isFinite(t)?Math.max(.15,Math.min(.85,t)):.5}attachDividerDrag(t,e,i){let s=null,n=r=>{let A=t.getBoundingClientRect();if(A.height<=0)return;let l=this.clampFrac((r.clientY-A.top)/A.height);s=l,e.style.flex=`0 0 ${(l*100).toFixed(2)}%`},o=r=>{document.removeEventListener("pointermove",n),document.removeEventListener("pointerup",o),document.body.removeClass("stashpad-folderpanel-resizing");try{i.releasePointerCapture(r.pointerId)}catch{}s!=null&&(this.plugin.settings.folderPanelPinnedFraction=s,this.plugin.saveSettings())};i.addEventListener("pointerdown",r=>{r.preventDefault(),document.body.addClass("stashpad-folderpanel-resizing");try{i.setPointerCapture(r.pointerId)}catch{}document.addEventListener("pointermove",n),document.addEventListener("pointerup",o)})}openPinnedOptionsMenu(t){let e=this.plugin.settings.folderPanelPinnedGrouping??"pin-order",i=new $.Menu;i.addItem(s=>s.setTitle("Sort by pin order").setChecked(e==="pin-order").onClick(()=>void this.setPinnedGrouping("pin-order"))),i.addItem(s=>s.setTitle("Group by folder").setChecked(e==="folder").onClick(()=>void this.setPinnedGrouping("folder"))),i.showAtMouseEvent(t)}async setPinnedGrouping(t){(this.plugin.settings.folderPanelPinnedGrouping??"pin-order")!==t&&(this.plugin.settings.folderPanelPinnedGrouping=t,await this.plugin.saveSettings(),this.render())}renderPinned(t){let e=this.plugin.discoverStashpadFolders().filter(n=>this.folderState(n)==="pinned"),i=this.plugin.listPinnedNotes();if(e.length===0&&i.length===0){t.createDiv({cls:"stashpad-folderpanel-empty",text:"Nothing pinned yet \u2014 pin a note or folder from its right-click menu."});return}if(e.length>0){let n=this.openFolders();for(let o of e)this.renderFolderRow(t,o,n)}if(i.length===0)return;if((this.plugin.settings.folderPanelPinnedGrouping??"pin-order")==="folder"){let n=new Map;i.forEach((A,l)=>{let d=n.get(A.folder);d||(d=[],n.set(A.folder,d)),d.push({...A,idx:l})});let o=this.plugin.lastActiveStashpadLeaf?.view?.noteFolder,r=Array.from(n.keys());o&&n.has(o)&&(r.splice(r.indexOf(o),1),r.unshift(o));for(let A of r){let l=t.createDiv({cls:"stashpad-pinned-group-header"});A===o&&l.addClass("is-active-folder"),l.createSpan({cls:"stashpad-pinned-group-name",text:A.split("/").pop()||A});for(let d of n.get(A)??[])this.renderPinNote(t,d.folder,d.id,d.file,d.idx)}}else i.forEach((n,o)=>this.renderPinNote(t,n.folder,n.id,n.file,o))}async reorderPin(t,e){let i=this.plugin.listPinnedNotes();if(t<0||t>=i.length)return;let s=i[t],n=i.filter((d,g)=>g!==t),o=Math.max(0,Math.min(e>t?e-1:e,n.length)),r=n[o-1],A=n[o],l;!r&&!A?l=Date.now():r?A?l=(r.pinnedAt+A.pinnedAt)/2:l=r.pinnedAt+1e3:l=A.pinnedAt-1e3;try{await this.app.fileManager.processFrontMatter(s.file,d=>{d.pinnedAt=l})}catch(d){console.warn("[Stashpad] pin reorder failed",d)}this.render()}renderPinNote(t,e,i,s,n){let o=this.app.metadataCache.getFileCache(s)?.frontmatter??{},r=typeof o.color=="string"?o.color:null,A=o.completed===!0,l=this.childrenOf(e,i),d=l.length>0,g=`${e}|${i}`,p=this.pinExpanded.has(g),h=t.createDiv({cls:"stashpad-pinned-row"});r&&(h.addClass("has-color"),h.style.setProperty("--stashpad-note-color",r)),A&&h.addClass("is-completed"),h.draggable=!0,h.dataset.pinIdx=String(n),h.addEventListener("dragstart",C=>{C.dataTransfer?.setData("text/plain",String(n)),C.dataTransfer&&(C.dataTransfer.effectAllowed="move"),h.addClass("is-dragging")}),h.addEventListener("dragend",()=>h.removeClass("is-dragging")),h.addEventListener("dragover",C=>{C.preventDefault(),C.dataTransfer&&(C.dataTransfer.dropEffect="move");let B=h.getBoundingClientRect(),m=C.clientY-B.top<B.height/2;h.toggleClass("drop-before",m),h.toggleClass("drop-after",!m)}),h.addEventListener("dragleave",()=>{h.removeClass("drop-before"),h.removeClass("drop-after")}),h.addEventListener("drop",C=>{C.preventDefault(),h.removeClass("drop-before"),h.removeClass("drop-after");let B=parseInt(C.dataTransfer?.getData("text/plain")??"",10);if(!Number.isFinite(B)||B===n)return;let m=h.getBoundingClientRect(),w=C.clientY-m.top<m.height/2;this.reorderPin(B,w?n:n+1)});let I=h.createSpan({cls:"stashpad-pinned-toggle"});d&&(we(I,l.length,p),I.onclick=C=>{C.stopPropagation(),this.pinExpanded.has(g)?this.pinExpanded.delete(g):this.pinExpanded.add(g),this.render()});let u=h.createSpan({cls:"stashpad-pinned-icon"});(0,$.setIcon)(u,d?"folder-tree":"file-text"),r&&(u.style.color=r);let f=h.createSpan({cls:"stashpad-pinned-label",text:this.titleFromFile(s)});if(f.onclick=()=>{this.onNavigateAway(),this.plugin.revealNoteInStashpad(s)},h.createSpan({cls:"stashpad-pinned-folder",text:e.split("/").pop()||e}),h.oncontextmenu=C=>{C.preventDefault();let B=new $.Menu;B.addItem(m=>m.setTitle("Unpin from sidebar").setIcon("pin-off").onClick(()=>void this.plugin.unpinNote({folder:e,id:i}))),B.showAtMouseEvent(C)},d&&p){let C=t.createDiv({cls:"stashpad-pinned-children"});this.renderPinSubtree(C,e,i,1)}}renderPinSubtree(t,e,i,s){for(let n of this.childrenOf(e,i)){let o=this.app.metadataCache.getFileCache(n)?.frontmatter??{},r=typeof o.id=="string"?o.id:null;if(!r)continue;let A=typeof o.color=="string"?o.color:null,l=o.completed===!0,d=this.childrenOf(e,r),g=d.length>0,p=`${e}|${r}`,h=this.pinExpanded.has(p),I=t.createDiv({cls:"stashpad-pinned-subrow"});l&&I.addClass("is-completed"),I.style.paddingLeft=`${s*16}px`;let u=I.createSpan({cls:"stashpad-pinned-toggle"});g&&(we(u,d.length,h),u.onclick=B=>{B.stopPropagation(),this.pinExpanded.has(p)?this.pinExpanded.delete(p):this.pinExpanded.add(p),this.render()});let f=I.createSpan({cls:"stashpad-pinned-icon"});(0,$.setIcon)(f,"file-text"),A&&(f.style.color=A);let C=I.createSpan({cls:"stashpad-pinned-label",text:this.titleFromFile(n)});C.onclick=()=>{this.onNavigateAway(),this.plugin.revealNoteInStashpad(n)},g&&h&&this.renderPinSubtree(t,e,r,s+1)}}childrenOf(t,e){let i=[];for(let s of this.app.vault.getMarkdownFiles()){if((s.parent?.path?.replace(/\/+$/,"")??"")!==t)continue;let o=this.app.metadataCache.getFileCache(s)?.frontmatter;if(!o||typeof o.id!="string")continue;let r=o.parent;if(r===e||e===F&&(r==null||r===F)){if(o.id===F)continue;i.push(s)}}return i.sort((s,n)=>{let o=this.app.metadataCache.getFileCache(s)?.frontmatter?.created??"",r=this.app.metadataCache.getFileCache(n)?.frontmatter?.created??"";return String(o).localeCompare(String(r))}),i}onNavigateAway(){$.Platform.isMobile&&(this.plugin.suppressComposerAutofocusUntil=Date.now()+1500,this.app.workspace.leftSplit?.collapse?.())}titleFromFile(t){return t.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||t.basename}openFolders(){let t=new Set,e=(this.plugin.settings.folder||"Stashpad").replace(/\/+$/,"");for(let i of this.app.workspace.getLeavesOfType(J)){let s=(i.view?.noteFolder??"").replace(/\/+$/,"");s||(s=(((i.getViewState?.()?.state??{}).folderOverride??"")||e).replace(/\/+$/,"")),s&&t.add(s)}return t}static clean(t){return t.replace(/\/+$/,"")}folderState(t){let e=c.clean(t),i=this.plugin.settings;return(i.folderPanelPinned??[]).includes(e)?"pinned":(i.folderPanelDownranked??[]).includes(e)?"downranked":(i.folderPanelHidden??[]).includes(e)?"hidden":"normal"}async setFolderState(t,e){let i=c.clean(t),s=this.plugin.settings;s.folderPanelPinned=(s.folderPanelPinned??[]).filter(n=>n!==i),s.folderPanelDownranked=(s.folderPanelDownranked??[]).filter(n=>n!==i),s.folderPanelHidden=(s.folderPanelHidden??[]).filter(n=>n!==i),e==="pinned"?s.folderPanelPinned.push(i):e==="downranked"?s.folderPanelDownranked.push(i):e==="hidden"&&s.folderPanelHidden.push(i),await this.plugin.saveSettings(),this.render()}folderHomeColor(t){return this.homeColorByFolder.get(c.clean(t))??null}rebuildHomeColors(){this.homeColorByFolder.clear();for(let t of this.app.vault.getMarkdownFiles()){let e=this.app.metadataCache.getFileCache(t)?.frontmatter;if(!e||e.id!==F||typeof e.color!="string"||!e.color.trim())continue;let i=(t.parent?.path??"").replace(/\/+$/,"");i&&this.homeColorByFolder.set(i,e.color)}}renderFolders(t){let e=this.plugin.discoverStashpadFolders();if(e.length===0){t.createDiv({cls:"stashpad-folderpanel-empty",text:"No Stashpad folders yet."});return}this.rebuildHomeColors();let i=this.openFolders(),s=[],n=[],o=[],r=[];for(let l of e)switch(this.folderState(l)){case"pinned":s.push(l);break;case"downranked":o.push(l);break;case"hidden":r.push(l);break;default:n.push(l)}let A=[...s,...n,...o];if(A.length===0&&r.length===0){t.createDiv({cls:"stashpad-folderpanel-empty",text:"No Stashpad folders yet."});return}for(let l of A)this.renderFolderRow(t,l,i);r.length>0&&this.renderHiddenSection(t,r)}renderFolderRow(t,e,i){let s=this.folderState(e),n=i.has(c.clean(e)),o=t.createDiv({cls:"stashpad-folderpanel-row stashpad-folderpanel-folder-row"});n&&o.addClass("is-open"),s==="downranked"&&o.addClass("is-downranked"),s==="pinned"&&o.addClass("is-pinned");let r=o.createSpan({cls:"stashpad-folderpanel-dot"});if(r.setAttr("aria-label",n?"Open in a tab":"Not open"),n&&r.setAttr("title","Open in a tab"),s==="pinned"){let I=o.createSpan({cls:"stashpad-folderpanel-pinmark"});(0,$.setIcon)(I,"pin"),I.setAttr("aria-label","Pinned")}let A=this.plugin.isArchiveFolder(e),l=o.createSpan({cls:"stashpad-folderpanel-folder-icon"});(0,$.setIcon)(l,A?"archive":"folder"),A&&l.setAttr("aria-label","Archive folder \u2014 notes moved in are auto-encrypted");let d=this.folderHomeColor(e);d&&(l.style.color=d);let g=e.split("/").pop()||e;o.createSpan({cls:"stashpad-folderpanel-row-label",text:g});let h=o.createDiv({cls:"stashpad-folderpanel-actions"}).createEl("button",{cls:"stashpad-folderpanel-iconbtn"});(0,$.setIcon)(h,"plus-square"),h.setAttr("aria-label","Open in new tab"),h.onmousedown=I=>{I.button===0&&(I.preventDefault(),I.stopPropagation(),this.onNavigateAway(),this.plugin.activateViewForFolder(e))},o.addEventListener("mousedown",I=>{I.button===0&&(I.target?.closest?.(".stashpad-folderpanel-actions")||(this.onNavigateAway(),this.jumpToFolder(e)))}),o.oncontextmenu=I=>{I.preventDefault(),this.openFolderMenu(I,e)}}renderHiddenSection(t,e){let i=t.createDiv({cls:"stashpad-folderpanel-hidden"}),s=i.createDiv({cls:"stashpad-folderpanel-hidden-header"}),n=s.createSpan({cls:"stashpad-folderpanel-hidden-caret"});(0,$.setIcon)(n,"chevron-right"),s.createSpan({cls:"stashpad-folderpanel-hidden-title",text:`Hidden (${e.length})`});let o=i.createDiv({cls:"stashpad-folderpanel-hidden-body"});o.setCssStyles({display:"none"}),s.onclick=()=>{let r=o.style.display!=="none";o.setCssStyles({display:r?"none":""}),(0,$.setIcon)(n,r?"chevron-right":"chevron-down")};for(let r of e){let A=o.createDiv({cls:"stashpad-folderpanel-row stashpad-folderpanel-hidden-row"}),l=r.split("/").pop()||r;A.createSpan({cls:"stashpad-folderpanel-row-label",text:l});let d=A.createEl("button",{cls:"stashpad-folderpanel-iconbtn"});(0,$.setIcon)(d,"eye"),d.setAttr("aria-label","Unhide"),d.onclick=g=>{g.stopPropagation(),this.setFolderState(r,"normal")}}}jumpToFolder(t){this.plugin.openFolderInStashpad(t)}revealFolder(t){let e=this.app.vault.getAbstractFileByPath(t.replace(/\/+$/,""));if(!(e instanceof $.TFolder)){new $.Notice("Couldn't find that folder.");return}let i=this.app.workspace.getLeavesOfType("file-explorer")[0];if(!i){new $.Notice("File explorer isn't available.");return}this.app.workspace.revealLeaf(i),i.view?.revealInFolder?.(e)}openFolderMenu(t,e){let i=new $.Menu;i.addItem(n=>n.setTitle("Open in new tab").setIcon("plus-square").onClick(()=>void this.plugin.activateViewForFolder(e))),i.addItem(n=>n.setTitle("Reveal in file explorer").setIcon("folder-search").onClick(()=>this.revealFolder(e))),i.addSeparator();let s=this.folderState(e);if(i.addItem(n=>n.setTitle(s==="pinned"?"Unpin":"Pin to top").setIcon("pin").onClick(()=>void this.setFolderState(e,s==="pinned"?"normal":"pinned"))),i.addItem(n=>n.setTitle(s==="downranked"?"Remove downrank":"Downrank").setIcon("arrow-down").onClick(()=>void this.setFolderState(e,s==="downranked"?"normal":"downranked"))),i.addItem(n=>n.setTitle("Hide from list").setIcon("eye-off").onClick(()=>void this.setFolderState(e,"hidden"))),i.addSeparator(),i.addItem(n=>n.setTitle("Rename\u2026").setIcon("pencil").onClick(()=>this.renameFolder(e))),this.plugin.encryption?.isConfigured?.()){i.addSeparator(),i.addItem(r=>r.setTitle("Encrypt (lock) all notes in folder").setIcon("lock").onClick(()=>void this.plugin.lockFolder(e))),this.app.vault.getFiles().some(r=>r.extension==="stashenc"&&(r.parent?.path?.replace(/\/+$/,"")??"")===e.replace(/\/+$/,""))&&i.addItem(r=>r.setTitle("Decrypt (unlock) all notes in folder").setIcon("unlock").onClick(()=>void this.plugin.unlockFolder(e)));let n=e.replace(/\/+$/,""),o=this.plugin.isArchiveFolder(n);i.addItem(r=>r.setTitle(o?"Unmark archive folder":"Mark as archive folder\u2026").setIcon("archive").onClick(async()=>{if(o){this.plugin.settings.archiveFolders=(this.plugin.settings.archiveFolders??[]).filter(A=>A!==n),await this.plugin.saveSettings(),new $.Notice(`"${n.split("/").pop()}" is no longer an archive folder. Existing locked notes stay locked.`,0),this.render();return}new gt(this.app,`Make "${n.split("/").pop()}" an archive folder?`,["An archive folder automatically LOCKS (encrypts) any note you move into it.","","What that means in plain terms:",`\u2022 "Encrypting" scrambles the note with your encryption password so its text can't be read by anyone \u2014 or any app \u2014 without that password.`,"\u2022 The normal, readable copy is permanently removed from your vault. What's left is an unreadable, locked \u{1F512} placeholder.","\u2022 To read or edit the note again, you unlock it with your encryption password (one click on the placeholder). Then you can re-archive it later.","\u2022 If you ever lose your encryption password, the locked notes are gone for good \u2014 there is no backdoor or recovery, on purpose.",'\u2022 Notes ALREADY in this folder are not touched \u2014 only notes moved in from now on. (To lock the ones already here, use "Encrypt all notes in folder".)',"","Good for folders of things you want kept private at rest: finished or sensitive material you'd rather not have readable if someone opened your vault."].join(` -`),"Make it an archive folder",async A=>{A&&(this.plugin.settings.archiveFolders=[...this.plugin.settings.archiveFolders??[],n],await this.plugin.saveSettings(),new $.Notice(`"${n.split("/").pop()}" is now an archive folder \u2014 notes moved in will be encrypted.`,0),this.render())}).open()})),i.addItem(r=>r.setTitle("Open encrypted trash").setIcon("rotate-ccw").onClick(()=>this.plugin.openEncryptedTrash()))}i.addSeparator(),i.addItem(n=>{n.setTitle("Delete folder\u2026").setIcon("trash").onClick(()=>this.deleteFolder(e)),n.setWarning?.(!0)}),i.showAtMouseEvent(t)}renameFolder(t){let e=t.replace(/\/+$/,""),i=this.app.vault.getAbstractFileByPath(e);if(!(i instanceof $.TFolder)){new $.Notice("Couldn't find that folder.");return}let s=i.name;new io(this.app,s,async n=>{let o=n.trim().replace(/[\\/:]+/g,"").trim();if(!o||o===s)return;let A=`${i.parent?.path&&i.parent.path!=="/"?`${i.parent.path}/`:""}${o}`;if(this.app.vault.getAbstractFileByPath(A)){new $.Notice(`"${o}" already exists.`);return}try{await this.app.fileManager.renameFile(i,A),(this.plugin.settings.folder||"").replace(/\/+$/,"")===e&&(this.plugin.settings.folder=A,await this.plugin.saveSettings()),new $.Notice(`Renamed to "${o}".`)}catch(l){console.warn("[Stashpad] folder rename failed",l),new $.Notice("Rename failed (see console).")}}).open()}deleteFolder(t){let e=t.replace(/\/+$/,""),i=this.app.vault.getAbstractFileByPath(e);if(!(i instanceof $.TFolder)){new $.Notice("Couldn't find that folder.");return}let s=this.app.vault.getMarkdownFiles().filter(o=>(o.parent?.path?.replace(/\/+$/,"")??"")===e||o.path.startsWith(e+"/")).length,n=i.name;new gt(this.app,`Delete "${n}"?`,`This moves the entire folder \u2014 about ${s} note${s===1?"":"s"} plus its attachments and exports \u2014 to the trash. -You can restore it from your system/Obsidian trash.`,"Delete folder",async o=>{o&&await this.plugin.deleteStashpadFolderWithUndo(i)}).open()}},io=class extends $.Modal{constructor(t,e,i){super(t);this.current=e;this.onSubmit=i;this.delivered=!1}onOpen(){this.modalEl.addClass("stashpad-compact-modal"),this.contentEl.empty(),this.titleEl.setText("Rename folder");let t=this.contentEl.createEl("input",{type:"text"});t.addClass("stashpad-folderpanel-rename-input"),t.value=this.current;let e=this.contentEl.createDiv({cls:"stashpad-folderpanel-rename-footer"});e.createEl("button",{text:"Cancel"}).onclick=()=>this.close();let i=e.createEl("button",{cls:"mod-cta",text:"Rename"}),s=()=>{this.delivered=!0;let n=t.value;this.close(),this.onSubmit(n)};i.onclick=s,this.scope.register([],"Enter",n=>{n.preventDefault(),t.value.trim()&&s()}),requestAnimationFrame(()=>{t.focus(),t.select()})}onClose(){this.contentEl.empty()}};async function Ps(c){let a=c.workspace.getLeavesOfType(fe);if(a.length>0){c.workspace.revealLeaf(a[0]);return}let t=c.workspace.getLeftLeaf(!1);if(!t){new $.Notice("Stashpad: couldn't open the folder panel.");return}await t.setViewState({type:fe,active:!0}),c.workspace.revealLeaf(t)}vt();Te();rt();var so="OKF Template.md",KA=`--- +${e.format("HH:mm A")}`}formatTimeInline(t){if(!t)return"";let e=(0,k.moment)(t);if(!e.isValid())return"";if(j().useTemplatesFormat){let s=ws(this.app);if(s){let n=/:ss/.test(s.timeFormat)?s.timeFormat:s.timeFormat.replace(/(:mm)/,"$1:ss");return`${e.format(s.dateFormat)} ${e.format(n)}`}}return`${e.format("YYYY.MM.DD")} ${e.format("HH:mm:ss A")}`}scrollListToBottom(){let t=this.listEl;if(!t)return;if(this.stickToListBottom=!0,t.scrollTop=t.scrollHeight,k.Platform.isMobile){let r=0,A=()=>{!this.stickToListBottom||r>=8||(r++,Date.now()>=this.keyboardTransitionUntil&&(t.scrollTop=t.scrollHeight),window.setTimeout(A,120))};window.setTimeout(A,60);return}this.stickyRowObserver?.disconnect();let e=()=>{if(!this.stickToListBottom){this.stickyRowObserver?.disconnect(),this.stickyRowObserver=null;return}t.scrollTop=t.scrollHeight},i=new ResizeObserver(e);for(let r of Array.from(t.children))r instanceof HTMLElement&&i.observe(r);this.stickyRowObserver=i;let s=performance.now(),n=t.scrollHeight,o=()=>{if(!this.stickToListBottom)return;let r=t.scrollHeight;r!==n&&(t.scrollTop=r,n=r),performance.now()-s<3e4?requestAnimationFrame(o):(this.stickToListBottom=!1,this.stickyRowObserver?.disconnect(),this.stickyRowObserver=null)};requestAnimationFrame(o)}openNoteMenu(t,e){if(!e.file)return;let i=e.file,s=new k.Menu;s.addItem(d=>d.setTitle("Open in new Stashpad tab").setIcon("layout-grid").onClick(()=>{this.openInNewStashpadTab(e.id)})),s.addItem(d=>d.setTitle("Open in editor").setIcon("file-text").onClick(()=>{this.openFileAtEnd(i)})),s.addItem(d=>d.setTitle("Focus in Stashpad").setIcon("arrow-right").onClick(()=>this.navigateTo(e.id))),s.addSeparator(),s.addItem(d=>d.setTitle("Split note\u2026").setIcon("split").onClick(()=>void this.cmdSplit(e))),s.addItem(d=>d.setTitle("Clone (duplicate / copy)").setIcon("files").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdClone()})),s.addItem(d=>d.setTitle("Fork (copy under another parent)\u2026").setIcon("git-branch").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdForkNote()})),s.addItem(d=>d.setTitle("Insert template\u2026").setIcon("file-plus-2").onClick(()=>this.cmdInsertTemplate())),s.addItem(d=>d.setTitle("Export to .stash").setIcon("package").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdExportStash()})),this.plugin.settings.okfEnabled&&s.addItem(d=>d.setTitle("Export as OKF\u2026").setIcon("book-marked").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdExportOkf()})),this.plugin.encryption?.isConfigured?.()&&s.addItem(d=>d.setTitle("Encrypt (lock) note + children").setIcon("lock").onClick(async()=>{let p=this.order.getOrder(this.noteFolder,e.parent??F),g=p.indexOf(e.id),h=g>0?p[g-1]:null;await this.plugin.lockNoteSubtree(this.noteFolder,e.id,h)&&this.render()})),s.addSeparator(),s.addItem(d=>d.setTitle("Move to\u2026").setIcon("move").onClick(()=>this.cmdMovePicker())),s.addItem(d=>d.setTitle("Move to Home").setIcon("home").onClick(async()=>{await this.changeParent(e,F),this.plugin.settings.autoNavOnMoveOut&&this.focusId!==F&&this.navigateTo(F)}));let n={folder:this.noteFolder,id:e.id},o=this.plugin.isPinned(n);s.addItem(d=>d.setTitle(o?"Unpin from sidebar":"Pin to sidebar").setIcon(o?"pin-off":"pin").onClick(async()=>{o?await this.plugin.unpinNote(n):await this.plugin.pinNote(n)}));let r=this.isListPinned(e.id);s.addItem(d=>d.setTitle(r?"Unpin from top of list":"Pin to top of list").setIcon(r?"pin-off":"arrow-up-to-line").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdToggleListPin()})),s.addItem(d=>d.setTitle("Set color\u2026").setIcon("palette").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdSetColor()}));let A=()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id)},l=d=>{let p=this.isTask(e);if(p){let g=this.isCompleted(e);d.addItem(h=>h.setTitle(g?"Mark incomplete":"Mark complete").setIcon(g?"circle":"check-circle").onClick(()=>{A(),this.cmdToggleComplete()}))}else d.addItem(g=>g.setTitle("Turn into task").setIcon("check-square").onClick(()=>{A(),this.cmdToggleTask()}));d.addItem(g=>g.setTitle("Assign / schedule\u2026").setIcon("user-plus").onClick(()=>{A(),this.cmdAssign()})),p&&d.addItem(g=>g.setTitle("Remove from tasks").setIcon("square").onClick(()=>{A(),this.cmdToggleTask()}))};s.addItem(d=>{d.setTitle("Task").setIcon("check-square");let p=typeof d.setSubmenu=="function"?d.setSubmenu():null;p&&typeof p.addItem=="function"?l(p):d.onClick(()=>this.openCommandPalette())}),s.addSeparator(),s.addItem(d=>d.setTitle("Delete").setIcon("trash").onClick(async()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),await this.cmdDelete()})),s.addSeparator(),s.addItem(d=>d.setTitle("More commands\u2026").setIcon("terminal").onClick(()=>this.openCommandPalette())),s.showAtMouseEvent(t)}async deleteNote(t){if(!t.file)return;let e=[],i=I=>{for(let u of this.tree.getChildren(I.id))i(u),e.push(u)};i(t);let s=[...e,t],n=s.filter(I=>!!I.file),o=await Promise.all(n.map(I=>this.app.vault.cachedRead(I.file))),r=[];for(let I=0;I<n.length;I++){let u=n[I];r.push(...this.extractAttachments(this.stripFrontmatter(o[I])));let f=this.app.metadataCache.getFileCache(u.file)?.frontmatter;if(Array.isArray(f?.attachments))for(let C of f.attachments)typeof C=="string"&&C.trim()&&r.push(Ee(C))}let A=[...new Set(r)],l=this.authorship.collectAuthorIds(s),d=async I=>{let u=await this.snapshotNotes(s,I),f=0;if(I)for(let N of A){let P=this.app.metadataCache.getFirstLinkpathDest(N,"");if(P)try{await this.app.fileManager.trashFile(P),await this.log.append({type:"attachment_remove",id:F,payload:{path:P.path}}),this.plugin.notifications.show({message:`Deleted attachment "${P.name}"`,kind:"warning",category:"attachment",affectedPaths:[P.path],folder:this.noteFolder}),f+=1}catch{}}let C=new Set;for(let N of s)N.parent&&C.add(N.parent);let B=this.currentChildren.findIndex(N=>N.id===t.id),m=null;if(B>=0){for(let N=B+1;N<this.currentChildren.length;N++)if(this.currentChildren[N].id!==t.id){m=this.currentChildren[N].id;break}if(!m){for(let N=B-1;N>=0;N--)if(this.currentChildren[N].id!==t.id){m=this.currentChildren[N].id;break}}}for(let N of s)if(N.file){try{await this.app.fileManager.trashFile(N.file)}catch{}await this.log.append({type:"delete",id:N.id,payload:{path:N.file.path,attachmentsRemoved:I?A:[]}})}this.selection.clear(),this.cursorIdx=-1,m&&(this.pendingFocusIds=[m]),this.tree.rebuild(this.noteFolder),this.render({kind:"follow-cursor"});for(let N of C)s.some(P=>P.id===N)||this.fmSync.scheduleParentOfDeleted(N);let y=this.noteFolder,Q=`Delete "${this.titleForNode(t)}"`,E=t.id,v=f>0?` with ${f} attachment${f===1?"":"s"}`:"",w=!1,D=async()=>{w||(w=!0,this.selection.clear(),this.cursorIdx=-1,await this.restoreSnapshots(u,[E]))};this.plugin.notifications.show({message:`Deleted "${this.titleForNode(t)}"${v}`,kind:"warning",category:"delete",duration:0,affectedIds:[t.id],affectedAuthorIds:l,folder:this.noteFolder,actions:[{label:"Undo delete",onClick:()=>void D()}]}),this.plugin.getUndoStack(y).push({label:Q,undo:async()=>{await D()},redo:async()=>{this.selection.clear(),this.cursorIdx=-1,w=!1,await this.trashNotesAndAttachments(u)}})},p=j(),g=e.length>0&&p.confirmBulkDelete,h=A.length>0&&p.confirmAttachmentDelete;if(!g&&!h){await d(!1),this.focusView();return}new Ue(this.app,this.titleForNode(t),e.length,A.length,h,async I=>{await d(I),this.focusView()}).open()}async cmdSwapWithParent(){let t=this.cursorIdx>=0?this.currentChildren[this.cursorIdx]:null;if(!t?.file){new k.Notice("Pick a note first (move the cursor onto it).");return}if(!t.parent||t.parent===F){new k.Notice("Already at Home \u2014 no parent to swap with.");return}let e=this.tree.get(t.parent);if(!e?.file){new k.Notice("Couldn't find the parent note.");return}let i=e.parent??F,s=this.titleForNode(t),n=this.titleForNode(e),o=this.tree.getChildren(e.id).filter(A=>A.id!==t.id).length,r=[`"${n}" becomes a child of "${s}".`];o>0&&r.push(`${o} sibling${o===1?"":"s"} move with it.`),new pt(this.app,"Swap notes?",r.join(` +`),"Swap",async A=>{A&&await this.swapParentChild(e,t,i)}).open()}offerSwapForDescendantMove(t,e){let i=this.tree.get(e);if(!i?.file){this.plugin.notifications.show({message:`Can't nest "${this.titleForNode(t)}" under one of its own descendants \u2014 that would create a cycle.`,kind:"warning",category:"move",affectedIds:[t.id],folder:this.noteFolder});return}if(i.parent!==t.id){this.plugin.notifications.show({message:`Can't nest "${this.titleForNode(t)}" under "${this.titleForNode(i)}" \u2014 it's a deeper descendant. Only direct parent \u2194 child swaps are supported (try moving "${this.titleForNode(i)}" up first, then swap).`,kind:"warning",category:"move",affectedIds:[t.id,i.id],folder:this.noteFolder});return}let s=this.titleForNode(t),n=this.titleForNode(i),o=this.tree.getChildren(t.id).filter(A=>A.id!==i.id).length,r=[`"${s}" becomes a child of "${n}".`];o>0&&r.push(`${o} sibling${o===1?"":"s"} move with it.`),new pt(this.app,"Confirm Note Swap",r.join(` +`),"Swap",async A=>{if(!A)return;let l=t.parent??F;await this.swapParentChild(t,i,l)}).open()}async swapParentChild(t,e,i){if(!t.file||!e.file)return;if(e.parent!==t.id){new k.Notice("Swap aborted: parent/child relationship changed.");return}let s=this.noteFolder,n=t.parent,o=this.tree.getChildren(t.id).filter(h=>h.id!==e.id).filter(h=>!!h.file),r=o.map(h=>({id:h.id,path:h.file.path,was:h.parent})),A=this.order.getOrder(s,i).slice(),l=this.order.getOrder(s,e.id).slice(),d=this.order.getOrder(s,t.id).slice();await this.app.fileManager.processFrontMatter(e.file,h=>{h.parent=i}),this.fmSync.scheduleParentChange(e.id,t.id,i),await this.app.fileManager.processFrontMatter(t.file,h=>{h.parent=e.id}),this.fmSync.scheduleParentChange(t.id,n,e.id);for(let h of o)await this.app.fileManager.processFrontMatter(h.file,I=>{I.parent=e.id}),this.fmSync.scheduleParentChange(h.id,t.id,e.id);if(A.length>0){let h=A.includes(t.id)?A.map(I=>I===t.id?e.id:I):[...A.filter(I=>I!==e.id),e.id];this.order.setOrder(s,i,h)}let p=o.map(h=>h.id),g=[t.id,...l.filter(h=>h!==t.id&&!p.includes(h)),...p];this.order.setOrder(s,e.id,g),this.order.setOrder(s,t.id,[]),await this.order.save(s),await this.log.append({type:"parent_change",id:e.id,payload:{from:t.id,to:i,reason:"swap"}}),await this.log.append({type:"parent_change",id:t.id,payload:{from:n,to:e.id,reason:"swap"}});for(let h of r)await this.log.append({type:"parent_change",id:h.id,payload:{from:h.was,to:e.id,reason:"swap"}});this.tree.rebuild(s),this.pendingFocusIds=[e.id],this.render({kind:"follow-cursor"}),this.plugin.notifications.show({message:`Swapped "${this.titleForNode(e)}" \u2194 "${this.titleForNode(t)}".`,kind:"success",category:"move",affectedIds:[e.id,t.id,...p],folder:s}),this.plugin.getUndoStack(s).push({label:`Swap "${this.titleForNode(e)}" \u2194 parent`,undo:async()=>{let h=this.tree.get(t.id),I=this.tree.get(e.id);h?.file&&await this.app.fileManager.processFrontMatter(h.file,u=>{n==null||n===F?(delete u.parent,u.parent=F):u.parent=n}),I?.file&&await this.app.fileManager.processFrontMatter(I.file,u=>{u.parent=t.id});for(let u of r){let f=this.app.vault.getAbstractFileByPath(u.path);f&&await this.app.fileManager.processFrontMatter(f,C=>{u.was==null?C.parent=F:C.parent=u.was})}this.order.setOrder(s,i,A),this.order.setOrder(s,e.id,l),this.order.setOrder(s,t.id,d),await this.order.save(s),this.tree.rebuild(s),this.pendingFocusIds=[t.id],this.render({kind:"follow-cursor"})},redo:async()=>{await this.swapParentChild(t,e,i)}})}async changeParent(t,e,i={record:!0}){if(!t.file)return!1;let s=t.file,n=t.parent,o=A=>A??F;if(o(n)===o(e)){if(!i.quiet){let A=this.titleForNode(t),l=e===F?"Home":`"${this.titleForNode(this.tree.get(e)??t)}"`;this.plugin.notifications.show({message:`"${A}" is already under ${l}.`,kind:"info",category:"move",affectedIds:[t.id],folder:this.noteFolder})}return!1}if(e===t.id)return i.quiet||this.plugin.notifications.show({message:`Can't move "${this.titleForNode(t)}" into itself.`,kind:"warning",category:"move",affectedIds:[t.id],folder:this.noteFolder}),!1;if(e!==F&&this.isDescendant(e,t.id))return i.quiet||this.offerSwapForDescendantMove(t,e),!1;let r=this.authorship.collectAuthorIds([t]);if(await this.app.fileManager.processFrontMatter(s,A=>{A.parent=e}),this.fmSync.scheduleParentChange(t.id,n,e),await this.log.append({type:"parent_change",id:t.id,payload:{from:n,to:e}}),this.pendingFocusIds=[t.id],this.focusId!==e&&this.focusId!==n?(this.selection.clear(),this.cursorIdx=-1):this.focusId===n&&(this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=null),!i.quiet&&!i.silentSuccess){let A=this.tree.get(e),l=A?this.titleForNode(A):"(root)";this.plugin.notifications.show({message:`Reparented "${this.titleForNode(t)}" \u2192 "${l}"`,kind:"success",category:"move",affectedIds:[t.id],affectedAuthorIds:r,folder:this.noteFolder,actions:e===F?[]:[{label:"Jump to parent",onClick:()=>this.navigateTo(e)}]})}if(i.record!==!1){let A=this.noteFolder,l=s.path,d=t.id;this.plugin.getUndoStack(A).push({label:"Move note",undo:async()=>{let p=this.app.vault.getAbstractFileByPath(l);if(p){await this.app.fileManager.processFrontMatter(p,g=>{g.parent=n}),this.pendingFocusIds=[d],this.focusId!==n&&this.focusId!==e?(this.selection.clear(),this.cursorIdx=-1):this.focusId===e&&(this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=null),this.tree.rebuild(A),this.render({kind:"follow-cursor"});{let g=this.selectionGuardKey,h=()=>{if(this.selectionGuardKey!==g||this.selection.has(d))return;let I=this.currentChildren.findIndex(u=>u.id===d);I<0||(this.selection.add(d),this.cursorIdx=I,this.render({kind:"follow-cursor"}))};setTimeout(h,120),setTimeout(h,400)}}},redo:async()=>{let p=this.app.vault.getAbstractFileByPath(l);if(p){await this.app.fileManager.processFrontMatter(p,g=>{g.parent=e}),this.pendingFocusIds=[d],this.focusId!==e&&this.focusId!==n?(this.selection.clear(),this.cursorIdx=-1):this.focusId===n&&(this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=null),this.tree.rebuild(A),this.render({kind:"follow-cursor"});{let g=this.selectionGuardKey,h=()=>{if(this.selectionGuardKey!==g||this.selection.has(d))return;let I=this.currentChildren.findIndex(u=>u.id===d);I<0||(this.selection.add(d),this.cursorIdx=I,this.render({kind:"follow-cursor"}))};setTimeout(h,120),setTimeout(h,400)}}}})}return!0}notifyBatchMove(t,e,i){if(!t.length)return;let s=this.tree.get(e),n=e===F?"Home":`"${s?this.titleForNode(s):"the destination"}"`,o=A=>i.get(A.id)??0,r;if(t.length===1){let A=this.titleForNode(t[0]),l=o(t[0]);r=l>0?`Moved "${A}" and its ${l} ${l===1?"child":"children"} \u2192 ${n}`:`Moved "${A}" \u2192 ${n}`}else{let A=t.reduce((l,d)=>l+o(d),0);r=A>0?`Moved ${t.length} notes (${A} nested) \u2192 ${n}`:`Moved ${t.length} notes \u2192 ${n}`}this.plugin.notifications.show({message:r,kind:"success",category:"move",duration:e===F?void 0:0,affectedIds:t.map(A=>A.id),affectedAuthorIds:this.authorship.collectAuthorIds(t),folder:this.noteFolder,actions:e===F?[]:[{label:"Jump to destination",onClick:()=>this.navigateTo(e)}]})}},co=class extends k.SuggestModal{constructor(t,e,i){super(t);this.folders=e;this.onPick=i;this.setPlaceholder("Move to which archive folder?")}getSuggestions(t){let e=t.toLowerCase();return this.folders.filter(i=>i.toLowerCase().includes(e))}renderSuggestion(t,e){e.createDiv({text:t.split("/").pop()||t}),e.createEl("small",{text:t,cls:"stashpad-suggest-path"})}onChooseSuggestion(t){this.onPick(t)}},qs=class extends k.SuggestModal{constructor(t,e,i){super(t);this.entries=e;this.onPick=i;this.setPlaceholder("Restore which deleted note?")}getSuggestions(t){let e=t.toLowerCase();return this.entries.filter(i=>`${i.label} ${i.folder}`.toLowerCase().includes(e))}renderSuggestion(t,e){e.createDiv({text:t.label}),e.createEl("small",{text:`from ${t.folder}`,cls:"stashpad-suggest-path"})}onChooseSuggestion(t){this.onPick(t.blob)}};var ne=require("obsidian");rt();var ol=ne.moment,Js=class extends ne.ItemView{constructor(t,e){super(t);this.plugin=e;this.renderPending=!1;this.renderGen=0}getViewType(){return Me}getDisplayText(){return"Encrypted trash"}getIcon(){return"trash-2"}async onOpen(){this.containerEl.addClass("stashpad-trash-view"),this.registerEvent(this.app.vault.on("create",t=>{t.path.startsWith("_deleted/")&&this.scheduleRender()})),this.registerEvent(this.app.vault.on("delete",t=>{t.path.startsWith("_deleted/")&&this.scheduleRender()})),await this.render()}scheduleRender(){this.renderPending||(this.renderPending=!0,window.setTimeout(()=>{this.renderPending=!1,this.render()},150))}async render(){let t=++this.renderGen,e=this.contentEl;e.empty(),e.addClass("stashpad-trash-view-body");let i=e.createDiv({cls:"stashpad-trash-view-header"});i.createEl("h3",{text:"Encrypted trash"});let s=i.createEl("button",{cls:"stashpad-trash-iconbtn"});if((0,ne.setIcon)(s,"refresh-cw"),s.setAttr("aria-label","Refresh"),s.onclick=()=>void this.render(),!this.plugin.encryption?.isConfigured?.()){e.createDiv({cls:"stashpad-trash-empty",text:"Encryption isn't set up."});return}let n=await this.plugin.listDeletedTrash();if(t!==this.renderGen)return;if(n.length===0){e.createDiv({cls:"stashpad-trash-empty",text:"Nothing in the encrypted trash. Notes you securely delete land here, recoverable with your password."});return}let o=i.createEl("button",{cls:"stashpad-trash-restore",text:"Restore all"});(0,ne.setIcon)(o.createSpan({cls:"stashpad-btn-icon"}),"rotate-ccw"),o.onclick=async()=>{o.disabled=!0,await this.plugin.restoreAllTrash(),await this.render()};let r=new Map;for(let l of n){let d=l.meta?.title?l.meta.originalFolder||"(unknown folder)":" hidden";(r.get(d)??r.set(d,[]).get(d)).push(l)}let A=[...r.keys()].sort((l,d)=>l===" hidden"?1:d===" hidden"?-1:l.localeCompare(d));for(let l of A){let d=l===" hidden",p=e.createDiv({cls:"stashpad-trash-group"}),g=p.createDiv({cls:"stashpad-trash-group-head"});(0,ne.setIcon)(g.createSpan({cls:"stashpad-trash-group-icon"}),d?"lock":"folder"),g.createSpan({text:d?"Hidden (title obscured)":l.split("/").pop()||l}),g.createSpan({cls:"stashpad-trash-group-count",text:String(r.get(l).length)});for(let h of r.get(l)){let I=p.createDiv({cls:"stashpad-trash-row"}),u=I.createDiv({cls:"stashpad-trash-row-main"});u.createSpan({cls:"stashpad-trash-title",text:d?"Locked note":h.meta?.title||"Locked note"});let f=h.meta?.deletedAt?`deleted ${ol(h.meta.deletedAt).fromNow()}`:"deleted",C=h.meta&&h.meta.count>1?` \xB7 ${h.meta.count} ${h.meta.kind==="rawtrash"?"files":"notes"}`:"";u.createSpan({cls:"stashpad-trash-sub",text:f+C});let B=I.createEl("button",{cls:"stashpad-trash-restore",text:"Restore"});(0,ne.setIcon)(B.createSpan({cls:"stashpad-btn-icon"}),"rotate-ccw"),B.onclick=async()=>{B.disabled=!0,await this.plugin.restoreDeletedAt(h.blob)?await this.render():B.disabled=!1}}}}async onClose(){this.contentEl.empty()}};async function rr(c){let{workspace:a}=c.app,t=a.getLeavesOfType(Me);if(t.length>0){a.revealLeaf(t[0]);return}let e=a.getLeaf("tab");await e.setViewState({type:Me,active:!0}),a.revealLeaf(e)}rt();var Y=require("obsidian");rt();Ft();var Ks=class c extends Y.ItemView{constructor(t,e){super(t);this.plugin=e;this.renderTimer=null;this.pinExpanded=new Set;this.folderPinExpanded=new Set;this.homeColorByFolder=new Map}getViewType(){return Qe}getDisplayText(){return"Stashpad folders"}getIcon(){return"folders"}async onOpen(){this.render(),this.registerEvent(this.app.workspace.on("active-leaf-change",()=>this.scheduleRender())),this.registerEvent(this.app.workspace.on("layout-change",()=>this.scheduleRender())),this.registerEvent(this.app.vault.on("create",()=>this.scheduleRender())),this.registerEvent(this.app.vault.on("delete",()=>this.scheduleRender())),this.registerEvent(this.app.vault.on("rename",()=>this.scheduleRender())),this.registerEvent(this.app.metadataCache.on("changed",()=>this.scheduleRender()))}scheduleRender(){this.renderTimer==null&&(this.renderTimer=window.setTimeout(()=>{this.renderTimer=null,this.containerEl.isConnected&&this.render()},100))}render(){let t=this.contentEl;t.empty(),t.addClass("stashpad-folderpanel-root");let e=this.clampFrac(this.plugin.settings.folderPanelPinnedFraction??.5),i=t.createDiv({cls:"stashpad-folderpanel-section stashpad-folderpanel-pinned"});i.style.flex=`0 0 ${(e*100).toFixed(2)}%`;let s=i.createDiv({cls:"stashpad-folderpanel-heading stashpad-folderpanel-heading-row"});s.createSpan({cls:"stashpad-folderpanel-heading-title",text:"Pinned"});let n=s.createEl("button",{cls:"stashpad-folderpanel-iconbtn"});(0,Y.setIcon)(n,"list"),n.setAttr("aria-label","Pinned view options"),n.onclick=d=>{d.stopPropagation(),this.openPinnedOptionsMenu(d)},this.renderPinned(i.createDiv({cls:"stashpad-folderpanel-list stashpad-folderpanel-pins"}));let o=t.createDiv({cls:"stashpad-folderpanel-divider"});o.createDiv({cls:"stashpad-folderpanel-divider-grip"}),this.attachDividerDrag(t,i,o);let r=t.createDiv({cls:"stashpad-folderpanel-section stashpad-folderpanel-folders"});r.setCssStyles({flex:"1 1 0"});let A=r.createDiv({cls:"stashpad-folderpanel-heading stashpad-folderpanel-heading-row"}),l=A.createSpan({cls:"stashpad-folderpanel-heading-title stashpad-folderpanel-heading-switch",text:"Folders"});if(l.setAttr("aria-label","Open folder switcher"),l.onmousedown=d=>{d.button===0&&(d.preventDefault(),this.plugin.openFolderPicker())},this.plugin.encryption?.isConfigured?.()){let d=A.createEl("button",{cls:"stashpad-folderpanel-iconbtn stashpad-folderpanel-heading-trash"});(0,Y.setIcon)(d,"trash-2"),d.setAttr("aria-label","Open encrypted trash"),d.onmousedown=p=>{p.button===0&&(p.preventDefault(),p.stopPropagation(),this.plugin.openEncryptedTrash())}}this.renderFolders(r.createDiv({cls:"stashpad-folderpanel-list"}))}clampFrac(t){return Number.isFinite(t)?Math.max(.15,Math.min(.85,t)):.5}attachDividerDrag(t,e,i){let s=null,n=r=>{let A=t.getBoundingClientRect();if(A.height<=0)return;let l=this.clampFrac((r.clientY-A.top)/A.height);s=l,e.style.flex=`0 0 ${(l*100).toFixed(2)}%`},o=r=>{document.removeEventListener("pointermove",n),document.removeEventListener("pointerup",o),document.body.removeClass("stashpad-folderpanel-resizing");try{i.releasePointerCapture(r.pointerId)}catch{}s!=null&&(this.plugin.settings.folderPanelPinnedFraction=s,this.plugin.saveSettings())};i.addEventListener("pointerdown",r=>{r.preventDefault(),document.body.addClass("stashpad-folderpanel-resizing");try{i.setPointerCapture(r.pointerId)}catch{}document.addEventListener("pointermove",n),document.addEventListener("pointerup",o)})}openPinnedOptionsMenu(t){let e=this.plugin.settings.folderPanelPinnedGrouping??"pin-order",i=new Y.Menu;i.addItem(s=>s.setTitle("Sort by pin order").setChecked(e==="pin-order").onClick(()=>void this.setPinnedGrouping("pin-order"))),i.addItem(s=>s.setTitle("Group by folder").setChecked(e==="folder").onClick(()=>void this.setPinnedGrouping("folder"))),i.showAtMouseEvent(t)}async setPinnedGrouping(t){(this.plugin.settings.folderPanelPinnedGrouping??"pin-order")!==t&&(this.plugin.settings.folderPanelPinnedGrouping=t,await this.plugin.saveSettings(),this.render())}renderPinned(t){let e=this.plugin.discoverStashpadFolders().filter(n=>this.folderState(n)==="pinned"),i=this.plugin.listPinnedNotes();if(e.length===0&&i.length===0){t.createDiv({cls:"stashpad-folderpanel-empty",text:"Nothing pinned yet \u2014 pin a note or folder from its right-click menu."});return}if(e.length>0){let n=this.openFolders();for(let o of e)this.renderFolderRow(t,o,n)}if(i.length===0)return;if((this.plugin.settings.folderPanelPinnedGrouping??"pin-order")==="folder"){let n=new Map;i.forEach((A,l)=>{let d=n.get(A.folder);d||(d=[],n.set(A.folder,d)),d.push({...A,idx:l})});let o=this.plugin.lastActiveStashpadLeaf?.view?.noteFolder,r=Array.from(n.keys());o&&n.has(o)&&(r.splice(r.indexOf(o),1),r.unshift(o));for(let A of r){let l=t.createDiv({cls:"stashpad-pinned-group-header"});A===o&&l.addClass("is-active-folder"),l.createSpan({cls:"stashpad-pinned-group-name",text:A.split("/").pop()||A});for(let d of n.get(A)??[])this.renderPinNote(t,d.folder,d.id,d.file,d.idx)}}else i.forEach((n,o)=>this.renderPinNote(t,n.folder,n.id,n.file,o))}async reorderPin(t,e){let i=this.plugin.listPinnedNotes();if(t<0||t>=i.length)return;let s=i[t],n=i.filter((d,p)=>p!==t),o=Math.max(0,Math.min(e>t?e-1:e,n.length)),r=n[o-1],A=n[o],l;!r&&!A?l=Date.now():r?A?l=(r.pinnedAt+A.pinnedAt)/2:l=r.pinnedAt+1e3:l=A.pinnedAt-1e3;try{await this.app.fileManager.processFrontMatter(s.file,d=>{d.pinnedAt=l})}catch(d){console.warn("[Stashpad] pin reorder failed",d)}this.render()}renderPinNote(t,e,i,s,n){let o=this.app.metadataCache.getFileCache(s)?.frontmatter??{},r=typeof o.color=="string"?o.color:null,A=o.completed===!0,l=this.childrenOf(e,i),d=l.length>0,p=`${e}|${i}`,g=this.pinExpanded.has(p),h=t.createDiv({cls:"stashpad-pinned-row"});r&&(h.addClass("has-color"),h.style.setProperty("--stashpad-note-color",r)),A&&h.addClass("is-completed"),h.draggable=!0,h.dataset.pinIdx=String(n),h.addEventListener("dragstart",C=>{C.dataTransfer?.setData("text/plain",String(n)),C.dataTransfer&&(C.dataTransfer.effectAllowed="move"),h.addClass("is-dragging")}),h.addEventListener("dragend",()=>h.removeClass("is-dragging")),h.addEventListener("dragover",C=>{C.preventDefault(),C.dataTransfer&&(C.dataTransfer.dropEffect="move");let B=h.getBoundingClientRect(),m=C.clientY-B.top<B.height/2;h.toggleClass("drop-before",m),h.toggleClass("drop-after",!m)}),h.addEventListener("dragleave",()=>{h.removeClass("drop-before"),h.removeClass("drop-after")}),h.addEventListener("drop",C=>{C.preventDefault(),h.removeClass("drop-before"),h.removeClass("drop-after");let B=parseInt(C.dataTransfer?.getData("text/plain")??"",10);if(!Number.isFinite(B)||B===n)return;let m=h.getBoundingClientRect(),y=C.clientY-m.top<m.height/2;this.reorderPin(B,y?n:n+1)});let I=h.createSpan({cls:"stashpad-pinned-toggle"});d&&(Ae(I,l.length,g),I.onclick=C=>{C.stopPropagation(),this.pinExpanded.has(p)?this.pinExpanded.delete(p):this.pinExpanded.add(p),this.render()});let u=h.createSpan({cls:"stashpad-pinned-icon"});(0,Y.setIcon)(u,d?"folder-tree":"file-text"),r&&(u.style.color=r);let f=h.createSpan({cls:"stashpad-pinned-label",text:this.titleFromFile(s)});if(f.onclick=()=>{this.onNavigateAway(),this.plugin.revealNoteInStashpad(s)},h.createSpan({cls:"stashpad-pinned-folder",text:e.split("/").pop()||e}),h.oncontextmenu=C=>{C.preventDefault();let B=new Y.Menu;B.addItem(m=>m.setTitle("Unpin from sidebar").setIcon("pin-off").onClick(()=>void this.plugin.unpinNote({folder:e,id:i}))),B.showAtMouseEvent(C)},d&&g){let C=t.createDiv({cls:"stashpad-pinned-children"});this.renderPinSubtree(C,e,i,1)}}renderPinSubtree(t,e,i,s){for(let n of this.childrenOf(e,i)){let o=this.app.metadataCache.getFileCache(n)?.frontmatter??{},r=typeof o.id=="string"?o.id:null;if(!r)continue;let A=typeof o.color=="string"?o.color:null,l=o.completed===!0,d=this.childrenOf(e,r),p=d.length>0,g=`${e}|${r}`,h=this.pinExpanded.has(g),I=t.createDiv({cls:"stashpad-pinned-subrow"});l&&I.addClass("is-completed"),I.style.paddingLeft=`${s*16}px`;let u=I.createSpan({cls:"stashpad-pinned-toggle"});p&&(Ae(u,d.length,h),u.onclick=B=>{B.stopPropagation(),this.pinExpanded.has(g)?this.pinExpanded.delete(g):this.pinExpanded.add(g),this.render()});let f=I.createSpan({cls:"stashpad-pinned-icon"});(0,Y.setIcon)(f,"file-text"),A&&(f.style.color=A);let C=I.createSpan({cls:"stashpad-pinned-label",text:this.titleFromFile(n)});C.onclick=()=>{this.onNavigateAway(),this.plugin.revealNoteInStashpad(n)},p&&h&&this.renderPinSubtree(t,e,r,s+1)}}childrenOf(t,e){let i=[];for(let s of this.app.vault.getMarkdownFiles()){if((s.parent?.path?.replace(/\/+$/,"")??"")!==t)continue;let o=this.app.metadataCache.getFileCache(s)?.frontmatter;if(!o||typeof o.id!="string")continue;let r=o.parent;if(r===e||e===F&&(r==null||r===F)){if(o.id===F)continue;i.push(s)}}return i.sort((s,n)=>{let o=this.app.metadataCache.getFileCache(s)?.frontmatter?.created??"",r=this.app.metadataCache.getFileCache(n)?.frontmatter?.created??"";return String(o).localeCompare(String(r))}),i}onNavigateAway(){Y.Platform.isMobile&&(this.plugin.suppressComposerAutofocusUntil=Date.now()+1500,this.app.workspace.leftSplit?.collapse?.())}titleFromFile(t){return t.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||t.basename}openFolders(){let t=new Set,e=(this.plugin.settings.folder||"Stashpad").replace(/\/+$/,"");for(let i of this.app.workspace.getLeavesOfType(J)){let s=(i.view?.noteFolder??"").replace(/\/+$/,"");s||(s=(((i.getViewState?.()?.state??{}).folderOverride??"")||e).replace(/\/+$/,"")),s&&t.add(s)}return t}static clean(t){return t.replace(/\/+$/,"")}folderState(t){let e=c.clean(t),i=this.plugin.settings;return(i.folderPanelPinned??[]).includes(e)?"pinned":(i.folderPanelDownranked??[]).includes(e)?"downranked":(i.folderPanelHidden??[]).includes(e)?"hidden":"normal"}async setFolderState(t,e){let i=c.clean(t),s=this.plugin.settings;s.folderPanelPinned=(s.folderPanelPinned??[]).filter(n=>n!==i),s.folderPanelDownranked=(s.folderPanelDownranked??[]).filter(n=>n!==i),s.folderPanelHidden=(s.folderPanelHidden??[]).filter(n=>n!==i),e==="pinned"?s.folderPanelPinned.push(i):e==="downranked"?s.folderPanelDownranked.push(i):e==="hidden"&&s.folderPanelHidden.push(i),await this.plugin.saveSettings(),this.render()}folderHomeColor(t){return this.homeColorByFolder.get(c.clean(t))??null}rebuildHomeColors(){this.homeColorByFolder.clear();for(let t of this.app.vault.getMarkdownFiles()){let e=this.app.metadataCache.getFileCache(t)?.frontmatter;if(!e||e.id!==F||typeof e.color!="string"||!e.color.trim())continue;let i=(t.parent?.path??"").replace(/\/+$/,"");i&&this.homeColorByFolder.set(i,e.color)}}renderFolders(t){let e=this.plugin.discoverStashpadFolders();if(e.length===0){t.createDiv({cls:"stashpad-folderpanel-empty",text:"No Stashpad folders yet."});return}this.rebuildHomeColors();let i=this.openFolders(),s=[],n=[],o=[],r=[];for(let l of e)switch(this.folderState(l)){case"pinned":s.push(l);break;case"downranked":o.push(l);break;case"hidden":r.push(l);break;default:n.push(l)}let A=[...s,...n,...o];if(A.length===0&&r.length===0){t.createDiv({cls:"stashpad-folderpanel-empty",text:"No Stashpad folders yet."});return}for(let l of A)this.renderFolderRow(t,l,i);r.length>0&&this.renderHiddenSection(t,r)}renderFolderRow(t,e,i){let s=this.folderState(e),n=i.has(c.clean(e)),o=t.createDiv({cls:"stashpad-folderpanel-row stashpad-folderpanel-folder-row"});n&&o.addClass("is-open"),s==="downranked"&&o.addClass("is-downranked"),s==="pinned"&&o.addClass("is-pinned");let r=o.createSpan({cls:"stashpad-folderpanel-dot"});if(r.setAttr("aria-label",n?"Open in a tab":"Not open"),n&&r.setAttr("title","Open in a tab"),s==="pinned"){let C=o.createSpan({cls:"stashpad-folderpanel-pinmark"});(0,Y.setIcon)(C,"pin"),C.setAttr("aria-label","Pinned")}let A=this.folderHomePinnedNotes(e),l=c.clean(e),d=this.folderPinExpanded.has(l);if(A.length>0){let C=o.createSpan({cls:"stashpad-folderpanel-pinreveal"});Ae(C,A.length,d),C.setAttr("aria-label",d?"Hide pinned notes":`${A.length} pinned note${A.length===1?"":"s"}`),C.addEventListener("mousedown",B=>{B.stopPropagation(),B.preventDefault()}),C.onclick=B=>{B.stopPropagation(),this.folderPinExpanded.has(l)?this.folderPinExpanded.delete(l):this.folderPinExpanded.add(l),this.render()}}let p=this.plugin.isArchiveFolder(e),g=o.createSpan({cls:"stashpad-folderpanel-folder-icon"});(0,Y.setIcon)(g,p?"archive":"folder"),p&&g.setAttr("aria-label","Archive folder \u2014 notes moved in are auto-encrypted");let h=this.folderHomeColor(e);h&&(g.style.color=h);let I=e.split("/").pop()||e;o.createSpan({cls:"stashpad-folderpanel-row-label",text:I});let f=o.createDiv({cls:"stashpad-folderpanel-actions"}).createEl("button",{cls:"stashpad-folderpanel-iconbtn"});if((0,Y.setIcon)(f,"plus-square"),f.setAttr("aria-label","Open in new tab"),f.onmousedown=C=>{C.button===0&&(C.preventDefault(),C.stopPropagation(),this.onNavigateAway(),this.plugin.activateViewForFolder(e))},o.addEventListener("mousedown",C=>{C.button===0&&(C.target?.closest?.(".stashpad-folderpanel-actions")||(this.onNavigateAway(),this.jumpToFolder(e)))}),o.oncontextmenu=C=>{C.preventDefault(),this.openFolderMenu(C,e)},A.length>0&&d){let C=t.createDiv({cls:"stashpad-folderpanel-pinlist"});for(let B of A){let m=C.createDiv({cls:"stashpad-folderpanel-pinrow"}),y=this.app.metadataCache.getFileCache(B)?.frontmatter??{},Q=m.createSpan({cls:"stashpad-folderpanel-pinrow-icon"});(0,Y.setIcon)(Q,"arrow-up-to-line"),typeof y.color=="string"&&(Q.style.color=y.color),m.createSpan({cls:"stashpad-folderpanel-pinrow-label",text:this.titleFromFile(B)}),m.onclick=()=>{this.onNavigateAway(),this.plugin.revealNoteInStashpad(B)}}}}folderHomePinnedNotes(t){return this.childrenOf(t,F).filter(e=>this.app.metadataCache.getFileCache(e)?.frontmatter?.listPinned===!0)}renderHiddenSection(t,e){let i=t.createDiv({cls:"stashpad-folderpanel-hidden"}),s=i.createDiv({cls:"stashpad-folderpanel-hidden-header"}),n=s.createSpan({cls:"stashpad-folderpanel-hidden-caret"});(0,Y.setIcon)(n,"chevron-right"),s.createSpan({cls:"stashpad-folderpanel-hidden-title",text:`Hidden (${e.length})`});let o=i.createDiv({cls:"stashpad-folderpanel-hidden-body"});o.setCssStyles({display:"none"}),s.onclick=()=>{let r=o.style.display!=="none";o.setCssStyles({display:r?"none":""}),(0,Y.setIcon)(n,r?"chevron-right":"chevron-down")};for(let r of e){let A=o.createDiv({cls:"stashpad-folderpanel-row stashpad-folderpanel-hidden-row"}),l=r.split("/").pop()||r;A.createSpan({cls:"stashpad-folderpanel-row-label",text:l});let d=A.createEl("button",{cls:"stashpad-folderpanel-iconbtn"});(0,Y.setIcon)(d,"eye"),d.setAttr("aria-label","Unhide"),d.onclick=p=>{p.stopPropagation(),this.setFolderState(r,"normal")}}}jumpToFolder(t){this.plugin.openFolderInStashpad(t)}revealFolder(t){let e=this.app.vault.getAbstractFileByPath(t.replace(/\/+$/,""));if(!(e instanceof Y.TFolder)){new Y.Notice("Couldn't find that folder.");return}let i=this.app.workspace.getLeavesOfType("file-explorer")[0];if(!i){new Y.Notice("File explorer isn't available.");return}this.app.workspace.revealLeaf(i),i.view?.revealInFolder?.(e)}openFolderMenu(t,e){let i=new Y.Menu;i.addItem(n=>n.setTitle("Open in new tab").setIcon("plus-square").onClick(()=>void this.plugin.activateViewForFolder(e))),i.addItem(n=>n.setTitle("Reveal in file explorer").setIcon("folder-search").onClick(()=>this.revealFolder(e))),i.addSeparator();let s=this.folderState(e);if(i.addItem(n=>n.setTitle(s==="pinned"?"Unpin":"Pin to top").setIcon("pin").onClick(()=>void this.setFolderState(e,s==="pinned"?"normal":"pinned"))),i.addItem(n=>n.setTitle(s==="downranked"?"Remove downrank":"Downrank").setIcon("arrow-down").onClick(()=>void this.setFolderState(e,s==="downranked"?"normal":"downranked"))),i.addItem(n=>n.setTitle("Hide from list").setIcon("eye-off").onClick(()=>void this.setFolderState(e,"hidden"))),i.addSeparator(),i.addItem(n=>n.setTitle("Rename\u2026").setIcon("pencil").onClick(()=>this.renameFolder(e))),this.plugin.encryption?.isConfigured?.()){i.addSeparator(),i.addItem(r=>r.setTitle("Encrypt (lock) all notes in folder").setIcon("lock").onClick(()=>void this.plugin.lockFolder(e))),this.app.vault.getFiles().some(r=>r.extension==="stashenc"&&(r.parent?.path?.replace(/\/+$/,"")??"")===e.replace(/\/+$/,""))&&i.addItem(r=>r.setTitle("Decrypt (unlock) all notes in folder").setIcon("unlock").onClick(()=>void this.plugin.unlockFolder(e)));let n=e.replace(/\/+$/,""),o=this.plugin.isArchiveFolder(n);i.addItem(r=>r.setTitle(o?"Unmark archive folder":"Mark as archive folder\u2026").setIcon("archive").onClick(async()=>{if(o){this.plugin.settings.archiveFolders=(this.plugin.settings.archiveFolders??[]).filter(A=>A!==n),await this.plugin.saveSettings(),new Y.Notice(`"${n.split("/").pop()}" is no longer an archive folder. Existing locked notes stay locked.`,0),this.render();return}new pt(this.app,`Make "${n.split("/").pop()}" an archive folder?`,["An archive folder automatically LOCKS (encrypts) any note you move into it.","","What that means in plain terms:",`\u2022 "Encrypting" scrambles the note with your encryption password so its text can't be read by anyone \u2014 or any app \u2014 without that password.`,"\u2022 The normal, readable copy is permanently removed from your vault. What's left is an unreadable, locked \u{1F512} placeholder.","\u2022 To read or edit the note again, you unlock it with your encryption password (one click on the placeholder). Then you can re-archive it later.","\u2022 If you ever lose your encryption password, the locked notes are gone for good \u2014 there is no backdoor or recovery, on purpose.",'\u2022 Notes ALREADY in this folder are not touched \u2014 only notes moved in from now on. (To lock the ones already here, use "Encrypt all notes in folder".)',"","Good for folders of things you want kept private at rest: finished or sensitive material you'd rather not have readable if someone opened your vault."].join(` +`),"Make it an archive folder",async A=>{A&&(this.plugin.settings.archiveFolders=[...this.plugin.settings.archiveFolders??[],n],await this.plugin.saveSettings(),new Y.Notice(`"${n.split("/").pop()}" is now an archive folder \u2014 notes moved in will be encrypted.`,0),this.render())}).open()})),i.addItem(r=>r.setTitle("Open encrypted trash").setIcon("rotate-ccw").onClick(()=>this.plugin.openEncryptedTrash()))}i.addSeparator(),i.addItem(n=>{n.setTitle("Delete folder\u2026").setIcon("trash").onClick(()=>this.deleteFolder(e)),n.setWarning?.(!0)}),i.showAtMouseEvent(t)}renameFolder(t){let e=t.replace(/\/+$/,""),i=this.app.vault.getAbstractFileByPath(e);if(!(i instanceof Y.TFolder)){new Y.Notice("Couldn't find that folder.");return}let s=i.name;new ho(this.app,s,async n=>{let o=n.trim().replace(/[\\/:]+/g,"").trim();if(!o||o===s)return;let A=`${i.parent?.path&&i.parent.path!=="/"?`${i.parent.path}/`:""}${o}`;if(this.app.vault.getAbstractFileByPath(A)){new Y.Notice(`"${o}" already exists.`);return}try{await this.app.fileManager.renameFile(i,A),(this.plugin.settings.folder||"").replace(/\/+$/,"")===e&&(this.plugin.settings.folder=A,await this.plugin.saveSettings()),new Y.Notice(`Renamed to "${o}".`)}catch(l){console.warn("[Stashpad] folder rename failed",l),new Y.Notice("Rename failed (see console).")}}).open()}deleteFolder(t){let e=t.replace(/\/+$/,""),i=this.app.vault.getAbstractFileByPath(e);if(!(i instanceof Y.TFolder)){new Y.Notice("Couldn't find that folder.");return}let s=this.app.vault.getMarkdownFiles().filter(o=>(o.parent?.path?.replace(/\/+$/,"")??"")===e||o.path.startsWith(e+"/")).length,n=i.name;new pt(this.app,`Delete "${n}"?`,`This moves the entire folder \u2014 about ${s} note${s===1?"":"s"} plus its attachments and exports \u2014 to the trash. +You can restore it from your system/Obsidian trash.`,"Delete folder",async o=>{o&&await this.plugin.deleteStashpadFolderWithUndo(i)}).open()}},ho=class extends Y.Modal{constructor(t,e,i){super(t);this.current=e;this.onSubmit=i;this.delivered=!1}onOpen(){this.modalEl.addClass("stashpad-compact-modal"),this.contentEl.empty(),this.titleEl.setText("Rename folder");let t=this.contentEl.createEl("input",{type:"text"});t.addClass("stashpad-folderpanel-rename-input"),t.value=this.current;let e=this.contentEl.createDiv({cls:"stashpad-folderpanel-rename-footer"});e.createEl("button",{text:"Cancel"}).onclick=()=>this.close();let i=e.createEl("button",{cls:"mod-cta",text:"Rename"}),s=()=>{this.delivered=!0;let n=t.value;this.close(),this.onSubmit(n)};i.onclick=s,this.scope.register([],"Enter",n=>{n.preventDefault(),t.value.trim()&&s()}),requestAnimationFrame(()=>{t.focus(),t.select()})}onClose(){this.contentEl.empty()}};async function Os(c){let a=c.workspace.getLeavesOfType(Qe);if(a.length>0){c.workspace.revealLeaf(a[0]);return}let t=c.workspace.getLeftLeaf(!1);if(!t){new Y.Notice("Stashpad: couldn't open the folder panel.");return}await t.setViewState({type:Qe,active:!0}),c.workspace.revealLeaf(t)}Ft();Re();rt();var po="OKF Template.md",al=`--- okfType: concept --- {{body}} -`,no=["> Generated by Stashpad \u2014 this folder is an Open Knowledge Format (OKF) bundle.","> Field legend: `okfType`\u2192`type`, `okfTitle`\u2192`title`, `okfDescription`\u2192`description`, `okfTags`\u2192`tags`, `okfTimestamp`\u2192`timestamp`; `okfParent`/`okfChildren` are relative-markdown cross-links. Stashpad's own `id`/`parent` are extensions \u2014 ignore them for OKF."].join(` -`);function Mi(c){return c.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||c.basename}function Va(c){return`[${Mi(c)}](${encodeURI(c.name)})`}async function Wa(c,a=so){try{await c.vault.adapter.exists(a)||await c.vault.create(a,KA)}catch{}return a}function Xa(c,a){if(!a)return[];let t=a.replace(/^\/+/,"");return Object.entries(c??{}).filter(([,e])=>(e??"").replace(/^\/+/,"")===t).map(([e])=>e.replace(/\/+$/,""))}async function oo(c,a){let t=a.replace(/\/+$/,""),e=new Map,i=new Map;for(let o of c.vault.getMarkdownFiles()){if((o.parent?.path?.replace(/\/+$/,"")??"")!==t)continue;let r;try{r=lt(await c.vault.read(o)).fm}catch{continue}let A=typeof r.id=="string"?r.id:null;if(!A)continue;let l=typeof r.parent=="string"?r.parent:F;e.set(A,{file:o,id:A,parent:l,modified:typeof r.modified=="string"?r.modified:"",created:typeof r.created=="string"?r.created:""});let d=i.get(l)??[];d.push(A),i.set(l,d)}let s=0,n=0;for(let o of e.values()){if(o.id===F)continue;s+=1;let r=o.parent&&o.parent!==F&&e.get(o.parent)?Va(e.get(o.parent).file):null,A=(i.get(o.id)??[]).map(l=>e.get(l)).filter(l=>!!l).map(l=>Va(l.file));try{let l=!1;await c.fileManager.processFrontMatter(o.file,d=>{r?d.okfParent!==r&&(d.okfParent=r,l=!0):d.okfParent!==void 0&&(delete d.okfParent,l=!0);let g=Array.isArray(d.okfChildren)?d.okfChildren:[],p=g.length===A.length&&g.every((h,I)=>h===A[I]);if(A.length?p||(d.okfChildren=A,l=!0):d.okfChildren!==void 0&&(delete d.okfChildren,l=!0),d.okfType===void 0&&(d.okfType="concept",l=!0),d.okfTitle===void 0&&(d.okfTitle=Mi(o.file),l=!0),d.okfTimestamp===void 0){let h=o.modified||o.created;h&&(d.okfTimestamp=h,l=!0)}}),l&&(n+=1,await new Promise(d=>setTimeout(d,50)))}catch(l){console.warn("[Stashpad] OKF rebuild failed",o.file.path,l)}}try{await c.vault.adapter.write(`${t}/index.md`,await ao(c,t))}catch(o){console.warn("[Stashpad] OKF index.md write failed",t,o)}return{checked:s,written:n}}async function ao(c,a,t){let e=a.replace(/\/+$/,""),i=new Map,s=new Map;for(let d of c.vault.getMarkdownFiles()){if((d.parent?.path?.replace(/\/+$/,"")??"")!==e||d.name==="index.md")continue;let g;try{g=lt(await c.vault.read(d)).fm}catch{continue}let p=typeof g.id=="string"?g.id:null;!p||p===F||t&&!t.has(p)||i.set(p,{id:p,file:d,parent:typeof g.parent=="string"?g.parent:F,title:typeof g.okfTitle=="string"&&g.okfTitle?g.okfTitle:Mi(d),type:typeof g.okfType=="string"&&g.okfType?g.okfType:"concept",position:typeof g.position=="number"?g.position:Number.MAX_SAFE_INTEGER,created:typeof g.created=="string"?g.created:""})}for(let d of i.values()){let g=s.get(d.parent)??[];g.push(d),s.set(d.parent,g)}for(let d of s.values())d.sort((g,p)=>g.position-p.position||g.created.localeCompare(p.created));let n=[],o=(d,g,p)=>{if(!p.has(d.id)){p.add(d.id),n.push(`${" ".repeat(g)}- [${d.title}](${encodeURI(d.file.name)}) \u2014 ${d.type}`);for(let h of s.get(d.id)??[])o(h,g+1,p)}},r=new Set,A=[...i.values()].filter(d=>d.parent===F||!i.has(d.parent)).sort((d,g)=>d.position-g.position||d.created.localeCompare(g.created));for(let d of A)o(d,0,r);let l=e.split("/").pop()||e;return["---","type: index",`title: ${l} (OKF index)`,"---","",`# ${l}`,"",no,"","## Concepts",n.length?n.join(` +`,go=["> Generated by Stashpad \u2014 this folder is an Open Knowledge Format (OKF) bundle.","> Field legend: `okfType`\u2192`type`, `okfTitle`\u2192`title`, `okfDescription`\u2192`description`, `okfTags`\u2192`tags`, `okfTimestamp`\u2192`timestamp`; `okfParent`/`okfChildren` are relative-markdown cross-links. Stashpad's own `id`/`parent` are extensions \u2014 ignore them for OKF."].join(` +`);function Li(c){return c.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||c.basename}function Ar(c){return`[${Li(c)}](${encodeURI(c.name)})`}async function lr(c,a=po){try{await c.vault.adapter.exists(a)||await c.vault.create(a,al)}catch{}return a}function cr(c,a){if(!a)return[];let t=a.replace(/^\/+/,"");return Object.entries(c??{}).filter(([,e])=>(e??"").replace(/^\/+/,"")===t).map(([e])=>e.replace(/\/+$/,""))}async function Io(c,a){let t=a.replace(/\/+$/,""),e=new Map,i=new Map;for(let o of c.vault.getMarkdownFiles()){if((o.parent?.path?.replace(/\/+$/,"")??"")!==t)continue;let r;try{r=lt(await c.vault.read(o)).fm}catch{continue}let A=typeof r.id=="string"?r.id:null;if(!A)continue;let l=typeof r.parent=="string"?r.parent:F;e.set(A,{file:o,id:A,parent:l,modified:typeof r.modified=="string"?r.modified:"",created:typeof r.created=="string"?r.created:""});let d=i.get(l)??[];d.push(A),i.set(l,d)}let s=0,n=0;for(let o of e.values()){if(o.id===F)continue;s+=1;let r=o.parent&&o.parent!==F&&e.get(o.parent)?Ar(e.get(o.parent).file):null,A=(i.get(o.id)??[]).map(l=>e.get(l)).filter(l=>!!l).map(l=>Ar(l.file));try{let l=!1;await c.fileManager.processFrontMatter(o.file,d=>{r?d.okfParent!==r&&(d.okfParent=r,l=!0):d.okfParent!==void 0&&(delete d.okfParent,l=!0);let p=Array.isArray(d.okfChildren)?d.okfChildren:[],g=p.length===A.length&&p.every((h,I)=>h===A[I]);if(A.length?g||(d.okfChildren=A,l=!0):d.okfChildren!==void 0&&(delete d.okfChildren,l=!0),d.okfType===void 0&&(d.okfType="concept",l=!0),d.okfTitle===void 0&&(d.okfTitle=Li(o.file),l=!0),d.okfTimestamp===void 0){let h=o.modified||o.created;h&&(d.okfTimestamp=h,l=!0)}}),l&&(n+=1,await new Promise(d=>setTimeout(d,50)))}catch(l){console.warn("[Stashpad] OKF rebuild failed",o.file.path,l)}}try{await c.vault.adapter.write(`${t}/index.md`,await uo(c,t))}catch(o){console.warn("[Stashpad] OKF index.md write failed",t,o)}return{checked:s,written:n}}async function uo(c,a,t){let e=a.replace(/\/+$/,""),i=new Map,s=new Map;for(let d of c.vault.getMarkdownFiles()){if((d.parent?.path?.replace(/\/+$/,"")??"")!==e||d.name==="index.md")continue;let p;try{p=lt(await c.vault.read(d)).fm}catch{continue}let g=typeof p.id=="string"?p.id:null;!g||g===F||t&&!t.has(g)||i.set(g,{id:g,file:d,parent:typeof p.parent=="string"?p.parent:F,title:typeof p.okfTitle=="string"&&p.okfTitle?p.okfTitle:Li(d),type:typeof p.okfType=="string"&&p.okfType?p.okfType:"concept",position:typeof p.position=="number"?p.position:Number.MAX_SAFE_INTEGER,created:typeof p.created=="string"?p.created:""})}for(let d of i.values()){let p=s.get(d.parent)??[];p.push(d),s.set(d.parent,p)}for(let d of s.values())d.sort((p,g)=>p.position-g.position||p.created.localeCompare(g.created));let n=[],o=(d,p,g)=>{if(!g.has(d.id)){g.add(d.id),n.push(`${" ".repeat(p)}- [${d.title}](${encodeURI(d.file.name)}) \u2014 ${d.type}`);for(let h of s.get(d.id)??[])o(h,p+1,g)}},r=new Set,A=[...i.values()].filter(d=>d.parent===F||!i.has(d.parent)).sort((d,p)=>d.position-p.position||d.created.localeCompare(p.created));for(let d of A)o(d,0,r);let l=e.split("/").pop()||e;return["---","type: index",`title: ${l} (OKF index)`,"---","",`# ${l}`,"",go,"","## Concepts",n.length?n.join(` `):"_No concepts yet._",""].join(` -`)}var OA=new TextEncoder,Us=c=>OA.encode(c);function Ti(c){if(typeof c=="number"||typeof c=="boolean")return String(c);let a=String(c??"");return/[:#[\]{}",&*!|>%@`]|^\s|\s$|^$/.test(a)?JSON.stringify(a):a}function YA(c,a){let{fm:t}=lt(c),e=[];e.push(`type: ${Ti(typeof t.okfType=="string"&&t.okfType?t.okfType:"concept")}`),e.push(`title: ${Ti(typeof t.okfTitle=="string"&&t.okfTitle?t.okfTitle:Mi(a))}`),typeof t.okfDescription=="string"&&t.okfDescription&&e.push(`description: ${Ti(t.okfDescription)}`);let i=t.okfTags;if(Array.isArray(i)&&i.length){e.push("tags:");for(let r of i)e.push(` - ${Ti(r)}`)}let s=typeof t.okfTimestamp=="string"&&t.okfTimestamp||typeof t.modified=="string"&&t.modified||typeof t.created=="string"&&t.created||"";s&&e.push(`timestamp: ${Ti(s)}`);let n=e.join(` +`)}var rl=new TextEncoder,Ys=c=>rl.encode(c);function qi(c){if(typeof c=="number"||typeof c=="boolean")return String(c);let a=String(c??"");return/[:#[\]{}",&*!|>%@`]|^\s|\s$|^$/.test(a)?JSON.stringify(a):a}function Al(c,a){let{fm:t}=lt(c),e=[];e.push(`type: ${qi(typeof t.okfType=="string"&&t.okfType?t.okfType:"concept")}`),e.push(`title: ${qi(typeof t.okfTitle=="string"&&t.okfTitle?t.okfTitle:Li(a))}`),typeof t.okfDescription=="string"&&t.okfDescription&&e.push(`description: ${qi(t.okfDescription)}`);let i=t.okfTags;if(Array.isArray(i)&&i.length){e.push("tags:");for(let r of i)e.push(` - ${qi(r)}`)}let s=typeof t.okfTimestamp=="string"&&t.okfTimestamp||typeof t.modified=="string"&&t.modified||typeof t.created=="string"&&t.created||"";s&&e.push(`timestamp: ${qi(s)}`);let n=e.join(` `),o=c.match(/^---\r?\n/);return o?c.slice(0,o[0].length)+n+` `+c.slice(o[0].length):`--- ${n} --- -${c}`}async function Za(c,a,t,e){let i=[],s=new Map;for(let n of a){let o=await c.vault.read(n);i.push({name:n.name,data:Us(YA(o,n))});for(let r of o.match(/!\[\[([^\]]+?)\]\]/g)??[]){let A=r.slice(3,-2).split("|")[0].split("#")[0].trim(),l=c.metadataCache.getFirstLinkpathDest(A,n.path);l&&!s.has(l.name)&&s.set(l.name,l)}}for(let[n,o]of s)i.push({name:`_attachments/${n}`,data:new Uint8Array(await c.vault.readBinary(o))});return i.push({name:"index.md",data:Us(await ao(c,t,e))}),i.push({name:"_okf.md",data:Us(`# About this bundle +${c}`}async function dr(c,a,t,e){let i=[],s=new Map;for(let n of a){let o=await c.vault.read(n);i.push({name:n.name,data:Ys(Al(o,n))});for(let r of o.match(/!\[\[([^\]]+?)\]\]/g)??[]){let A=r.slice(3,-2).split("|")[0].split("#")[0].trim(),l=c.metadataCache.getFirstLinkpathDest(A,n.path);l&&!s.has(l.name)&&s.set(l.name,l)}}for(let[n,o]of s)i.push({name:`_attachments/${n}`,data:new Uint8Array(await c.vault.readBinary(o))});return i.push({name:"index.md",data:Ys(await uo(c,t,e))}),i.push({name:"_okf.md",data:Ys(`# About this bundle -${no.replace(/^> /gm,"")} -`)}),i}async function ja(c){let{zipFiles:a}=await Promise.resolve().then(()=>(As(),ha));return a(c.map(t=>({name:t.name,data:t.data})))}function Ve(c,a){return c.toString(8).padStart(a-1,"0")+"\0"}function zA(c,a){let t=new Uint8Array(512),e=(s,n,o)=>{let r=Us(s);t.set(r.subarray(0,o),n)};e(c.slice(0,100),0,100),e(Ve(420,8),100,8),e(Ve(0,8),108,8),e(Ve(0,8),116,8),e(Ve(a,12),124,12),e(Ve(0,12),136,12),e(" ",148,8),t[156]=48,e("ustar\0",257,6),e("00",263,2);let i=0;for(let s=0;s<512;s++)i+=t[s];return e(Ve(i,8),148,8),t}function $A(c){let a=[],t=0;for(let s of c){let n=zA(s.name,s.data.length);a.push(n,s.data),t+=512+s.data.length;let o=(512-s.data.length%512)%512;o&&(a.push(new Uint8Array(o)),t+=o)}a.push(new Uint8Array(1024)),t+=1024;let e=new Uint8Array(t),i=0;for(let s of a)e.set(s,i),i+=s.length;return e}async function VA(c){let a=new CompressionStream("gzip"),t=new Response(c).body.pipeThrough(a);return new Uint8Array(await new Response(t).arrayBuffer())}async function _a(c){return VA($A(c))}var Gs=class{constructor(a,t,e){this.app=a;this.dirOk=!1;this.writeChain=Promise.resolve();this.baseDir=t.replace(/\/+$/,""),this.logPath=`${this.baseDir}/log.jsonl`,this.statePath=`${this.baseDir}/state.json`,this.getAuthor=e??(()=>"")}getLogPath(){return this.logPath}getDir(){return this.baseDir}async ensureDir(){if(this.dirOk)return;let a=this.app.vault.adapter,t=this.baseDir.split("/").filter(Boolean),e="";for(let i of t)e=e?`${e}/${i}`:i,await a.exists(e)||await a.mkdir(e);this.dirOk=!0}append(a){let t=a.author??this.getAuthor()??"",e={ts:new Date().toISOString(),...a};t?e.author=t:delete e.author;let i=JSON.stringify(e)+` -`;return this.writeChain=this.writeChain.then(async()=>{try{await this.ensureDir();let s=this.app.vault.adapter;if(typeof s.append=="function")await s.append(this.logPath,i);else{let n=await s.exists(this.logPath)?await s.read(this.logPath):"";await s.write(this.logPath,n+i)}}catch(s){console.warn("Stashpad: log append failed",s)}}),Promise.resolve()}async readState(){let a=this.app.vault.adapter;if(!await a.exists(this.statePath))return{};try{return JSON.parse(await a.read(this.statePath))}catch{return{}}}async writeState(a){await this.ensureDir(),await this.app.vault.adapter.write(this.statePath,JSON.stringify(a,null,2))}};rt();var Rs=class{constructor(){this.undoStack=[];this.redoStack=[];this.cap=30}push(a){for(this.undoStack.push(a),this.redoStack.length=0;this.undoStack.length>this.cap;)this.undoStack.shift()}async undo(){let a=this.undoStack.pop();if(!a)return null;try{await a.undo()}catch(t){throw console.error("Stashpad: undo failed",t),t}return this.redoStack.push(a),a}async redo(){let a=this.redoStack.pop();if(!a)return null;if(a.redo)try{await a.redo()}catch(t){throw console.error("Stashpad: redo failed",t),t}return this.undoStack.push(a),a}peekUndoLabel(){return this.undoStack[this.undoStack.length-1]?.label??null}peekRedoLabel(){return this.redoStack[this.redoStack.length-1]?.label??null}canUndo(){return this.undoStack.length>0}canRedo(){return this.redoStack.length>0}clear(){this.undoStack=[],this.redoStack=[]}};var Ls=class{constructor(a,t){this.app=a;this.data={version:1,authors:{}};this.loaded=!1;this.dirOk=!1;this.writeChain=Promise.resolve();this.path=`${t.replace(/\/+$/,"")}/authors.json`}getPath(){return this.path}async load(){if(!this.loaded){this.loaded=!0;try{let a=this.app.vault.adapter;if(await a.exists(this.path)){let t=JSON.parse(await a.read(this.path));t&&typeof t=="object"&&t.authors&&(this.data={version:typeof t.version=="number"?t.version:1,authors:t.authors})}}catch(a){console.warn("[Stashpad] author registry load failed; starting empty",a),this.data={version:1,authors:{}}}}}all(){return Object.values(this.data.authors).sort((a,t)=>(t.lastSeen??"").localeCompare(a.lastSeen??""))}get(a){return this.data.authors[a]??null}record(a){let t=(a.id??"").trim();if(!t)return!1;let e=a.at??new Date().toISOString(),i=(a.name??"").trim(),s=this.data.authors[t],n=!1;if(!s)this.data.authors[t]={id:t,name:i,role:a.role?.trim()||void 0,department:a.department?.trim()||void 0,firstSeen:e,lastSeen:e,renames:[]},n=!0;else{if(i&&i!==s.name&&(s.renames.push({from:s.name,to:i,at:e}),s.name=i,n=!0),a.role!==void 0){let o=a.role.trim()||void 0;o!==s.role&&(s.role=o,n=!0)}if(a.department!==void 0){let o=a.department.trim()||void 0;o!==s.department&&(s.department=o,n=!0)}s.lastSeen=e}return n&&this.save(),n}replaceAll(a,t){let e=t??new Date().toISOString(),i={};for(let s of a){let n=(s.id??"").trim();if(!n)continue;let o=this.data.authors[n],r=(s.name??"").trim()||o?.name||"",A=o?.renames?[...o.renames]:[];o&&r&&r!==o.name&&A.push({from:o.name,to:r,at:e}),i[n]={id:n,name:r,role:s.role?.trim()||o?.role||void 0,department:s.department?.trim()||o?.department||void 0,firstSeen:o?.firstSeen??e,lastSeen:e,renames:A}}this.data={version:1,authors:i},this.save()}async ensureDir(){if(this.dirOk)return;let a=this.app.vault.adapter,e=this.path.slice(0,this.path.lastIndexOf("/")).split("/").filter(Boolean),i="";for(let s of e)i=i?`${i}/${s}`:s,await a.exists(i)||await a.mkdir(i);this.dirOk=!0}save(){return this.writeChain=this.writeChain.then(async()=>{try{await this.ensureDir(),await this.app.vault.adapter.write(this.path,JSON.stringify(this.data,null,2))}catch(a){console.warn("[Stashpad] author registry save failed",a)}}),this.writeChain}};var et=require("obsidian");rt();xt();Te();Gi();vt();var qs=new Set(["_attachments","_authors","_exports","_imports","_processed","_archive",".archive"]),tr="_archive",er=new Set([jt,"edtz","stashenc","stashmeta"]),We=class We{constructor(a){this.plugin=a;this.pending=new Map;this.pendingFolders=new Map;this.suppressed=new Set;this.armed=!1;this.drainTimer=null;this.draining=!1;this.pendingEncryptedStashes=new Set;this.encryptedNotifySnoozeUntil=0}setArmed(a){this.armed=a}isArmed(){return this.armed}get app(){return this.plugin.app}enqueue(a){this.armed&&this.plugin.settings.autoImport&&this.isEligiblePath(a)&&(this.pending.set(a.path,Date.now()),this.arm())}enqueueFolder(a){if(!this.armed||!this.plugin.settings.autoImport||this.suppressed.has(a.path))return;let t=a.parent?.path?.replace(/\/+$/,"")??"";this.plugin.discoverStashpadFolders().includes(t)&&(qs.has(a.name)||(this.pendingFolders.set(a.path,Date.now()),this.arm()))}arm(){this.drainTimer!=null&&window.clearTimeout(this.drainTimer),this.drainTimer=window.setTimeout(()=>void this.drain(),We.DEBOUNCE_MS)}suppress(a,t=4e3){this.suppressed.add(a),window.setTimeout(()=>this.suppressed.delete(a),t)}async createNote(a,t){this.suppress(a,6e4),await this.app.vault.create(a,t)}isEligiblePath(a){if(this.suppressed.has(a.path)||er.has(a.extension))return!1;let t=a.parent?.path?.replace(/\/+$/,"")??"",e=t.split("/").pop()??"";return qs.has(e)?!1:this.plugin.discoverStashpadFolders().includes(t)}async isStillImportable(a){if(!this.isEligiblePath(a))return!1;if(a.extension==="md")try{let{fm:t}=lt(await this.app.vault.read(a));if(t&&typeof t.id=="string"&&t.id)return!1}catch{}return!0}async drain(){if(this.drainTimer=null,!this.draining){this.draining=!0;try{let a=[...this.pending.keys()];this.pending.clear();let t=a.map(g=>this.app.vault.getAbstractFileByPath(g)).filter(g=>g instanceof et.TFile),e=[];for(let g of t)await this.isStillImportable(g)&&e.push(g);let i=[...this.pendingFolders.keys()];this.pendingFolders.clear();let s=i.map(g=>this.app.vault.getAbstractFileByPath(g)).filter(g=>g instanceof et.TFolder).map(g=>({folder:g,files:this.filesUnder(g.path)})).filter(g=>g.files.length>0),n=s.reduce((g,p)=>g+p.files.length,0),o=e.length+n;if(o===0)return;await this.plugin.importLog.load();let r=e,A=[],l=e.filter(g=>this.plugin.importLog.findDuplicate(g.name,g.stat?.size??null));if(l.length>0){let g=l.slice(0,5).map(I=>`\u2022 ${I.name}`).join(` -`),p=l.length>5?` +${go.replace(/^> /gm,"")} +`)}),i}async function hr(c){let{zipFiles:a}=await Promise.resolve().then(()=>(Is(),Ea));return a(c.map(t=>({name:t.name,data:t.data})))}function ti(c,a){return c.toString(8).padStart(a-1,"0")+"\0"}function ll(c,a){let t=new Uint8Array(512),e=(s,n,o)=>{let r=Ys(s);t.set(r.subarray(0,o),n)};e(c.slice(0,100),0,100),e(ti(420,8),100,8),e(ti(0,8),108,8),e(ti(0,8),116,8),e(ti(a,12),124,12),e(ti(0,12),136,12),e(" ",148,8),t[156]=48,e("ustar\0",257,6),e("00",263,2);let i=0;for(let s=0;s<512;s++)i+=t[s];return e(ti(i,8),148,8),t}function cl(c){let a=[],t=0;for(let s of c){let n=ll(s.name,s.data.length);a.push(n,s.data),t+=512+s.data.length;let o=(512-s.data.length%512)%512;o&&(a.push(new Uint8Array(o)),t+=o)}a.push(new Uint8Array(1024)),t+=1024;let e=new Uint8Array(t),i=0;for(let s of a)e.set(s,i),i+=s.length;return e}async function dl(c){let a=new CompressionStream("gzip"),t=new Response(c).body.pipeThrough(a);return new Uint8Array(await new Response(t).arrayBuffer())}async function pr(c){return dl(cl(c))}var zs=class{constructor(a,t,e){this.app=a;this.dirOk=!1;this.writeChain=Promise.resolve();this.baseDir=t.replace(/\/+$/,""),this.logPath=`${this.baseDir}/log.jsonl`,this.statePath=`${this.baseDir}/state.json`,this.getAuthor=e??(()=>"")}getLogPath(){return this.logPath}getDir(){return this.baseDir}async ensureDir(){if(this.dirOk)return;let a=this.app.vault.adapter,t=this.baseDir.split("/").filter(Boolean),e="";for(let i of t)e=e?`${e}/${i}`:i,await a.exists(e)||await a.mkdir(e);this.dirOk=!0}append(a){let t=a.author??this.getAuthor()??"",e={ts:new Date().toISOString(),...a};t?e.author=t:delete e.author;let i=JSON.stringify(e)+` +`;return this.writeChain=this.writeChain.then(async()=>{try{await this.ensureDir();let s=this.app.vault.adapter;if(typeof s.append=="function")await s.append(this.logPath,i);else{let n=await s.exists(this.logPath)?await s.read(this.logPath):"";await s.write(this.logPath,n+i)}}catch(s){console.warn("Stashpad: log append failed",s)}}),Promise.resolve()}async readState(){let a=this.app.vault.adapter;if(!await a.exists(this.statePath))return{};try{return JSON.parse(await a.read(this.statePath))}catch{return{}}}async writeState(a){await this.ensureDir(),await this.app.vault.adapter.write(this.statePath,JSON.stringify(a,null,2))}};rt();var Vs=class{constructor(){this.undoStack=[];this.redoStack=[];this.cap=30}push(a){for(this.undoStack.push(a),this.redoStack.length=0;this.undoStack.length>this.cap;)this.undoStack.shift()}async undo(){let a=this.undoStack.pop();if(!a)return null;try{await a.undo()}catch(t){throw console.error("Stashpad: undo failed",t),t}return this.redoStack.push(a),a}async redo(){let a=this.redoStack.pop();if(!a)return null;if(a.redo)try{await a.redo()}catch(t){throw console.error("Stashpad: redo failed",t),t}return this.undoStack.push(a),a}peekUndoLabel(){return this.undoStack[this.undoStack.length-1]?.label??null}peekRedoLabel(){return this.redoStack[this.redoStack.length-1]?.label??null}canUndo(){return this.undoStack.length>0}canRedo(){return this.redoStack.length>0}clear(){this.undoStack=[],this.redoStack=[]}};var $s=class{constructor(a,t){this.app=a;this.data={version:1,authors:{}};this.loaded=!1;this.dirOk=!1;this.writeChain=Promise.resolve();this.path=`${t.replace(/\/+$/,"")}/authors.json`}getPath(){return this.path}async load(){if(!this.loaded){this.loaded=!0;try{let a=this.app.vault.adapter;if(await a.exists(this.path)){let t=JSON.parse(await a.read(this.path));t&&typeof t=="object"&&t.authors&&(this.data={version:typeof t.version=="number"?t.version:1,authors:t.authors})}}catch(a){console.warn("[Stashpad] author registry load failed; starting empty",a),this.data={version:1,authors:{}}}}}all(){return Object.values(this.data.authors).sort((a,t)=>(t.lastSeen??"").localeCompare(a.lastSeen??""))}get(a){return this.data.authors[a]??null}record(a){let t=(a.id??"").trim();if(!t)return!1;let e=a.at??new Date().toISOString(),i=(a.name??"").trim(),s=this.data.authors[t],n=!1;if(!s)this.data.authors[t]={id:t,name:i,role:a.role?.trim()||void 0,department:a.department?.trim()||void 0,firstSeen:e,lastSeen:e,renames:[]},n=!0;else{if(i&&i!==s.name&&(s.renames.push({from:s.name,to:i,at:e}),s.name=i,n=!0),a.role!==void 0){let o=a.role.trim()||void 0;o!==s.role&&(s.role=o,n=!0)}if(a.department!==void 0){let o=a.department.trim()||void 0;o!==s.department&&(s.department=o,n=!0)}s.lastSeen=e}return n&&this.save(),n}replaceAll(a,t){let e=t??new Date().toISOString(),i={};for(let s of a){let n=(s.id??"").trim();if(!n)continue;let o=this.data.authors[n],r=(s.name??"").trim()||o?.name||"",A=o?.renames?[...o.renames]:[];o&&r&&r!==o.name&&A.push({from:o.name,to:r,at:e}),i[n]={id:n,name:r,role:s.role?.trim()||o?.role||void 0,department:s.department?.trim()||o?.department||void 0,firstSeen:o?.firstSeen??e,lastSeen:e,renames:A}}this.data={version:1,authors:i},this.save()}async ensureDir(){if(this.dirOk)return;let a=this.app.vault.adapter,e=this.path.slice(0,this.path.lastIndexOf("/")).split("/").filter(Boolean),i="";for(let s of e)i=i?`${i}/${s}`:s,await a.exists(i)||await a.mkdir(i);this.dirOk=!0}save(){return this.writeChain=this.writeChain.then(async()=>{try{await this.ensureDir(),await this.app.vault.adapter.write(this.path,JSON.stringify(this.data,null,2))}catch(a){console.warn("[Stashpad] author registry save failed",a)}}),this.writeChain}};var et=require("obsidian");rt();Tt();Re();Yi();Ft();var Ws=new Set(["_attachments","_authors","_exports","_imports","_processed","_archive",".archive"]),gr="_archive",Ir=new Set([ee,"edtz","stashenc","stashmeta"]),ei=class ei{constructor(a){this.plugin=a;this.pending=new Map;this.pendingFolders=new Map;this.suppressed=new Set;this.armed=!1;this.drainTimer=null;this.draining=!1;this.pendingEncryptedStashes=new Set;this.encryptedNotifySnoozeUntil=0}setArmed(a){this.armed=a}isArmed(){return this.armed}get app(){return this.plugin.app}enqueue(a){this.armed&&this.plugin.settings.autoImport&&this.isEligiblePath(a)&&(this.pending.set(a.path,Date.now()),this.arm())}enqueueFolder(a){if(!this.armed||!this.plugin.settings.autoImport||this.suppressed.has(a.path))return;let t=a.parent?.path?.replace(/\/+$/,"")??"";this.plugin.discoverStashpadFolders().includes(t)&&(Ws.has(a.name)||(this.pendingFolders.set(a.path,Date.now()),this.arm()))}arm(){this.drainTimer!=null&&window.clearTimeout(this.drainTimer),this.drainTimer=window.setTimeout(()=>void this.drain(),ei.DEBOUNCE_MS)}suppress(a,t=4e3){this.suppressed.add(a),window.setTimeout(()=>this.suppressed.delete(a),t)}async createNote(a,t){this.suppress(a,6e4),await this.app.vault.create(a,t)}isEligiblePath(a){if(this.suppressed.has(a.path)||Ir.has(a.extension))return!1;let t=a.parent?.path?.replace(/\/+$/,"")??"",e=t.split("/").pop()??"";return Ws.has(e)?!1:this.plugin.discoverStashpadFolders().includes(t)}async isStillImportable(a){if(!this.isEligiblePath(a))return!1;if(a.extension==="md")try{let{fm:t}=lt(await this.app.vault.read(a));if(t&&typeof t.id=="string"&&t.id)return!1}catch{}return!0}async drain(){if(this.drainTimer=null,!this.draining){this.draining=!0;try{let a=[...this.pending.keys()];this.pending.clear();let t=a.map(p=>this.app.vault.getAbstractFileByPath(p)).filter(p=>p instanceof et.TFile),e=[];for(let p of t)await this.isStillImportable(p)&&e.push(p);let i=[...this.pendingFolders.keys()];this.pendingFolders.clear();let s=i.map(p=>this.app.vault.getAbstractFileByPath(p)).filter(p=>p instanceof et.TFolder).map(p=>({folder:p,files:this.filesUnder(p.path)})).filter(p=>p.files.length>0),n=s.reduce((p,g)=>p+g.files.length,0),o=e.length+n;if(o===0)return;await this.plugin.importLog.load();let r=e,A=[],l=e.filter(p=>this.plugin.importLog.findDuplicate(p.name,p.stat?.size??null));if(l.length>0){let p=l.slice(0,5).map(I=>`\u2022 ${I.name}`).join(` +`),g=l.length>5?` \u2026and ${l.length-5} more`:"",h=await this.dupChoice(`${l.length} of these look like files you've imported before: -${g}${p} +${p}${g} -Replace the existing notes, skip the duplicates, or import them anyway as new notes?`);if(h==="skip"){let I=new Set(l.map(u=>u.path));if(r=e.filter(u=>!I.has(u.path)),r.length===0&&s.length===0){new et.Notice(`Skipped ${l.length} duplicate file(s) \u2014 nothing new to import.`);return}}else if(h==="replace")for(let I of l){let u=this.plugin.importLog.findDuplicate(I.name,I.stat?.size??null);for(let f of u?.notePaths??[]){let C=this.app.vault.getAbstractFileByPath(f);if(C instanceof et.TFile)try{A.push({path:f,content:await this.app.vault.read(C)}),await this.app.fileManager.trashFile(C)}catch(B){console.warn("[Stashpad] replace: couldn't remove prior note",f,B)}}}}if(o=r.length+n,o>=We.BATCH_CONFIRM_AT){let g=s.length?` (incl. ${s.length} folder${s.length===1?"":"s"})`:"";if(!await this.confirm("Import many files?",`You're about to auto-import ${o} files into Stashpad${g}. Proceed? -Markdown becomes notes (originals archived); other files move to _attachments with a linking note. Dropped folders move to _archive.`,"Import all")){new et.Notice(`Import cancelled \u2014 ${o} file(s) left as-is.`);return}}let d=[];for(let g of r)try{let p=g.stat?.size??null,h=g.extension==="md"?await this.importMarkdown(g):await this.importOtherFile(g);h&&(d.push(h),this.plugin.importLog.append({ts:new Date().toISOString(),folder:h.folder,kind:h.kind,originalName:g.name,size:p,sourcePath:g.path,notePaths:h.kind==="folder"?h.notePaths:[h.notePath]}))}catch(p){console.warn("[Stashpad] import failed",g.path,p)}for(let{folder:g}of s)try{let p=await this.importFolder(g);p&&p.kind==="folder"&&(d.push(p),this.plugin.importLog.append({ts:new Date().toISOString(),folder:p.folder,kind:"folder",originalName:p.originalName,size:null,sourcePath:g.path,notePaths:p.notePaths}))}catch(p){console.warn("[Stashpad] folder import failed",g.path,p)}(d.length>0||A.length>0)&&this.announce(d,A)}finally{this.draining=!1}}}async importMarkdown(a){let t=a.parent.path.replace(/\/+$/,""),e=await this.app.vault.read(a),{fm:i,body:s}=lt(e),n=`${t}/${tr}`;await this.ensureFolder(n);let o=await this.uniquePath(n,a.name);if(await this.app.fileManager.renameFile(a,o),!(this.app.vault.getAbstractFileByPath(o)instanceof et.TFile))throw new Error(`archive move failed for ${a.path} \u2014 import aborted to avoid data loss`);let r={};for(let[g,p]of Object.entries(i))se.includes(g)||(r[g]=p);r.id=tt(),r.parent=F;let A=this.preservedTimes(i,a);r.created=A.created,A.modified&&(r.modified=A.modified),r.attachments=Array.isArray(i.attachments)?i.attachments:[],i.author!==void 0&&(r.author=i.author),i.contributors!==void 0&&(r.contributors=i.contributors),r.imported=!0;let l=Et(s)||a.basename,d=await this.uniquePath(t,wt(l,r.id));return await this.createNote(d,le(r,s)),{kind:"md",folder:t,archivePath:o,notePath:d,originalName:a.name}}async importOtherFile(a){let t=a.parent.path.replace(/\/+$/,""),e=`${t}/_attachments`;await this.ensureFolder(e);let i=await this.uniquePath(e,a.name);await this.app.fileManager.renameFile(a,i);let s=a.basename,n=tt(),o={id:n,parent:F,created:new Date().toISOString(),attachments:[Rt(i)],imported:!0},r=`${s} +Replace the existing notes, skip the duplicates, or import them anyway as new notes?`);if(h==="skip"){let I=new Set(l.map(u=>u.path));if(r=e.filter(u=>!I.has(u.path)),r.length===0&&s.length===0){new et.Notice(`Skipped ${l.length} duplicate file(s) \u2014 nothing new to import.`);return}}else if(h==="replace")for(let I of l){let u=this.plugin.importLog.findDuplicate(I.name,I.stat?.size??null);for(let f of u?.notePaths??[]){let C=this.app.vault.getAbstractFileByPath(f);if(C instanceof et.TFile)try{A.push({path:f,content:await this.app.vault.read(C)}),await this.app.fileManager.trashFile(C)}catch(B){console.warn("[Stashpad] replace: couldn't remove prior note",f,B)}}}}if(o=r.length+n,o>=ei.BATCH_CONFIRM_AT){let p=s.length?` (incl. ${s.length} folder${s.length===1?"":"s"})`:"";if(!await this.confirm("Import many files?",`You're about to auto-import ${o} files into Stashpad${p}. Proceed? +Markdown becomes notes (originals archived); other files move to _attachments with a linking note. Dropped folders move to _archive.`,"Import all")){new et.Notice(`Import cancelled \u2014 ${o} file(s) left as-is.`);return}}let d=[];for(let p of r)try{let g=p.stat?.size??null,h=p.extension==="md"?await this.importMarkdown(p):await this.importOtherFile(p);h&&(d.push(h),this.plugin.importLog.append({ts:new Date().toISOString(),folder:h.folder,kind:h.kind,originalName:p.name,size:g,sourcePath:p.path,notePaths:h.kind==="folder"?h.notePaths:[h.notePath]}))}catch(g){console.warn("[Stashpad] import failed",p.path,g)}for(let{folder:p}of s)try{let g=await this.importFolder(p);g&&g.kind==="folder"&&(d.push(g),this.plugin.importLog.append({ts:new Date().toISOString(),folder:g.folder,kind:"folder",originalName:g.originalName,size:null,sourcePath:p.path,notePaths:g.notePaths}))}catch(g){console.warn("[Stashpad] folder import failed",p.path,g)}(d.length>0||A.length>0)&&this.announce(d,A)}finally{this.draining=!1}}}async importMarkdown(a){let t=a.parent.path.replace(/\/+$/,""),e=await this.app.vault.read(a),{fm:i,body:s}=lt(e),n=`${t}/${gr}`;await this.ensureFolder(n);let o=await this.uniquePath(n,a.name);if(await this.app.fileManager.renameFile(a,o),!(this.app.vault.getAbstractFileByPath(o)instanceof et.TFile))throw new Error(`archive move failed for ${a.path} \u2014 import aborted to avoid data loss`);let r={};for(let[p,g]of Object.entries(i))ae.includes(p)||(r[p]=g);r.id=tt(),r.parent=F;let A=this.preservedTimes(i,a);r.created=A.created,A.modified&&(r.modified=A.modified),r.attachments=Array.isArray(i.attachments)?i.attachments:[],i.author!==void 0&&(r.author=i.author),i.contributors!==void 0&&(r.contributors=i.contributors),r.imported=!0;let l=Qt(s)||a.basename,d=await this.uniquePath(t,yt(l,r.id));return await this.createNote(d,pe(r,s)),{kind:"md",folder:t,archivePath:o,notePath:d,originalName:a.name}}async importOtherFile(a){let t=a.parent.path.replace(/\/+$/,""),e=`${t}/_attachments`;await this.ensureFolder(e);let i=await this.uniquePath(e,a.name);await this.app.fileManager.renameFile(a,i);let s=a.basename,n=tt(),o={id:n,parent:F,created:new Date().toISOString(),attachments:[qt(i)],imported:!0},r=`${s} ![[${i}]] -`,A=Et(s)||s,l=await this.uniquePath(t,wt(A,n));return await this.createNote(l,le(o,r)),{kind:"file",folder:t,attachmentPath:i,notePath:l,originalName:a.name}}preservedTimes(a,t){let e=n=>typeof n=="string"&&n.trim().length>0&&!Number.isNaN(Date.parse(n)),i=e(a.created)?a.created:t.stat?.ctime?new Date(t.stat.ctime).toISOString():new Date().toISOString(),s=e(a.modified)?a.modified:t.stat?.mtime?new Date(t.stat.mtime).toISOString():null;return{created:i,modified:s}}filesUnder(a){let t=a.replace(/\/+$/,"")+"/";return this.app.vault.getFiles().filter(e=>e.path.startsWith(t))}async importFolder(a){let t=a.parent.path.replace(/\/+$/,""),e=a.name,i=`${t}/${tr}`;await this.ensureFolder(i);let s=await this.uniquePath(i,e);await this.app.fileManager.renameFile(a,s);let n=this.app.vault.getAbstractFileByPath(s),o=new Set;for(let d of this.app.vault.getMarkdownFiles()){if((d.parent?.path?.replace(/\/+$/,"")??"")!==t)continue;let g=this.app.metadataCache.getFileCache(d)?.frontmatter?.id;typeof g=="string"&&g&&o.add(g)}let r=[],A=[],l=await this.createFolderNote(t,e,F,A,o);return n instanceof et.TFolder&&await this.buildNotesFromArchive(n,t,l,A,o,r),r.length&&new et.Notice(`Stashpad: ${r.length} attachment name collision(s) renamed on import \u2014 check ![[links]] in the imported notes.`),{kind:"folder",folder:t,archivePath:s,notePaths:A,attachmentPaths:[],originalName:e}}async createFolderNote(a,t,e,i,s){let n=tt();s.add(n);let o={id:n,parent:e,created:new Date().toISOString(),attachments:[]},r=Et(t)||t,A=await this.uniquePath(a,wt(r,n));return await this.createNote(A,le(o,`${t} -`)),i.push(A),n}async mergeReservedFolder(a,t,e){await this.ensureFolder(t);for(let i of[...a.children])if(i instanceof et.TFolder)await this.mergeReservedFolder(i,`${t}/${i.name}`,e);else if(i instanceof et.TFile){let s=`${t}/${i.name}`;await this.app.vault.adapter.exists(s)&&(s=await this.uniquePath(t,i.name),e.push(`${i.name} \u2192 ${s.split("/").pop()}`)),await this.app.fileManager.renameFile(i,s)}}async buildNotesFromArchive(a,t,e,i,s,n){for(let o of[...a.children])if(o instanceof et.TFolder)if(qs.has(o.name))await this.mergeReservedFolder(o,`${t}/${o.name}`,n);else{let r=await this.createFolderNote(t,o.name,e,i,s);await this.buildNotesFromArchive(o,t,r,i,s,n)}else if(o instanceof et.TFile)if(o.extension==="md"){let r=await this.app.vault.read(o),{fm:A,body:l}=lt(r),d={};for(let[f,C]of Object.entries(A))se.includes(f)||(d[f]=C);let g=typeof A.id=="string"&&A.id?A.id:null,p=g&&!s.has(g)?g:tt();s.add(p),d.id=p,d.parent=e;let h=this.preservedTimes(A,o);d.created=h.created,h.modified&&(d.modified=h.modified),d.attachments=Array.isArray(A.attachments)?A.attachments:[];let I=Et(l)||o.basename,u=await this.uniquePath(t,wt(I,d.id));await this.createNote(u,le(d,l)),i.push(u)}else{if(er.has(o.extension))continue;{let r=tt(),A={id:r,parent:e,created:new Date().toISOString(),attachments:[Rt(o.path)]},l=`${o.basename} +`,A=Qt(s)||s,l=await this.uniquePath(t,yt(A,n));return await this.createNote(l,pe(o,r)),{kind:"file",folder:t,attachmentPath:i,notePath:l,originalName:a.name}}preservedTimes(a,t){let e=n=>typeof n=="string"&&n.trim().length>0&&!Number.isNaN(Date.parse(n)),i=e(a.created)?a.created:t.stat?.ctime?new Date(t.stat.ctime).toISOString():new Date().toISOString(),s=e(a.modified)?a.modified:t.stat?.mtime?new Date(t.stat.mtime).toISOString():null;return{created:i,modified:s}}filesUnder(a){let t=a.replace(/\/+$/,"")+"/";return this.app.vault.getFiles().filter(e=>e.path.startsWith(t))}async importFolder(a){let t=a.parent.path.replace(/\/+$/,""),e=a.name,i=`${t}/${gr}`;await this.ensureFolder(i);let s=await this.uniquePath(i,e);await this.app.fileManager.renameFile(a,s);let n=this.app.vault.getAbstractFileByPath(s),o=new Set;for(let d of this.app.vault.getMarkdownFiles()){if((d.parent?.path?.replace(/\/+$/,"")??"")!==t)continue;let p=this.app.metadataCache.getFileCache(d)?.frontmatter?.id;typeof p=="string"&&p&&o.add(p)}let r=[],A=[],l=await this.createFolderNote(t,e,F,A,o);return n instanceof et.TFolder&&await this.buildNotesFromArchive(n,t,l,A,o,r),r.length&&new et.Notice(`Stashpad: ${r.length} attachment name collision(s) renamed on import \u2014 check ![[links]] in the imported notes.`),{kind:"folder",folder:t,archivePath:s,notePaths:A,attachmentPaths:[],originalName:e}}async createFolderNote(a,t,e,i,s){let n=tt();s.add(n);let o={id:n,parent:e,created:new Date().toISOString(),attachments:[]},r=Qt(t)||t,A=await this.uniquePath(a,yt(r,n));return await this.createNote(A,pe(o,`${t} +`)),i.push(A),n}async mergeReservedFolder(a,t,e){await this.ensureFolder(t);for(let i of[...a.children])if(i instanceof et.TFolder)await this.mergeReservedFolder(i,`${t}/${i.name}`,e);else if(i instanceof et.TFile){let s=`${t}/${i.name}`;await this.app.vault.adapter.exists(s)&&(s=await this.uniquePath(t,i.name),e.push(`${i.name} \u2192 ${s.split("/").pop()}`)),await this.app.fileManager.renameFile(i,s)}}async buildNotesFromArchive(a,t,e,i,s,n){for(let o of[...a.children])if(o instanceof et.TFolder)if(Ws.has(o.name))await this.mergeReservedFolder(o,`${t}/${o.name}`,n);else{let r=await this.createFolderNote(t,o.name,e,i,s);await this.buildNotesFromArchive(o,t,r,i,s,n)}else if(o instanceof et.TFile)if(o.extension==="md"){let r=await this.app.vault.read(o),{fm:A,body:l}=lt(r),d={};for(let[f,C]of Object.entries(A))ae.includes(f)||(d[f]=C);let p=typeof A.id=="string"&&A.id?A.id:null,g=p&&!s.has(p)?p:tt();s.add(g),d.id=g,d.parent=e;let h=this.preservedTimes(A,o);d.created=h.created,h.modified&&(d.modified=h.modified),d.attachments=Array.isArray(A.attachments)?A.attachments:[];let I=Qt(l)||o.basename,u=await this.uniquePath(t,yt(I,d.id));await this.createNote(u,pe(d,l)),i.push(u)}else{if(Ir.has(o.extension))continue;{let r=tt(),A={id:r,parent:e,created:new Date().toISOString(),attachments:[qt(o.path)]},l=`${o.basename} ![[${o.path}]] -`,d=Et(o.basename)||o.basename,g=await this.uniquePath(t,wt(d,r));await this.createNote(g,le(A,l)),i.push(g)}}}recordNotePaths(a){return a.kind==="folder"?a.notePaths:[a.notePath]}announce(a,t=[]){let e=a[0]?.folder??"",i=a.length,s=t.length?`, replaced ${t.length}`:"",n=!1,o=async()=>{n||(n=!0,await this.undo(a,t))};this.plugin.notifications.show({message:`Imported ${i} file${i===1?"":"s"}${s} into \`${e.split("/").pop()}\`.`,kind:"success",category:"import",duration:0,folder:e,affectedPaths:a.flatMap(r=>this.recordNotePaths(r)),actions:[{label:"Undo import",onClick:()=>void o()}]}),e&&this.plugin.getUndoStack(e).push({label:`Import ${i} file${i===1?"":"s"}`,undo:async()=>{await o()},redo:async()=>{}})}async undo(a,t=[]){for(let e of a)try{if(e.kind==="md"){let i=this.app.vault.getAbstractFileByPath(e.notePath);i instanceof et.TFile&&await this.app.fileManager.trashFile(i);let s=this.app.vault.getAbstractFileByPath(e.archivePath);if(s instanceof et.TFile){let n=await this.uniquePath(e.folder,e.originalName);this.suppress(n),await this.app.fileManager.renameFile(s,n)}}else if(e.kind==="file"){let i=this.app.vault.getAbstractFileByPath(e.notePath);i instanceof et.TFile&&await this.app.fileManager.trashFile(i);let s=this.app.vault.getAbstractFileByPath(e.attachmentPath);if(s instanceof et.TFile){let n=await this.uniquePath(e.folder,e.originalName);this.suppress(n),await this.app.fileManager.renameFile(s,n)}}else{for(let s of e.notePaths){let n=this.app.vault.getAbstractFileByPath(s);n instanceof et.TFile&&await this.app.fileManager.trashFile(n)}for(let s of e.attachmentPaths){let n=this.app.vault.getAbstractFileByPath(s);n instanceof et.TFile&&await this.app.fileManager.trashFile(n)}let i=this.app.vault.getAbstractFileByPath(e.archivePath);if(i instanceof et.TFolder){let s=await this.uniquePath(e.folder,e.originalName);this.suppress(s),await this.app.fileManager.renameFile(i,s)}}}catch(i){console.warn("[Stashpad] import undo failed",e,i)}for(let e of t)try{await this.app.vault.adapter.exists(e.path)||await this.app.vault.create(e.path,e.content)}catch(i){console.warn("[Stashpad] import undo: couldn't restore replaced note",e.path,i)}new et.Notice(`Undid import of ${a.length} file(s).`)}pickFilesInto(a){let t=document.createElement("input");t.type="file",t.multiple=!0,t.setCssStyles({display:"none"}),t.onchange=async()=>{let e=Array.from(t.files??[]);if(t.remove(),e.length===0)return;let i=[];for(let n of e)try{let o=await n.arrayBuffer(),r=await this.uniquePath(a,n.name);this.suppress(r,6e4),await this.app.vault.createBinary(r,o);let A=this.app.vault.getAbstractFileByPath(r);A instanceof et.TFile&&i.push(A)}catch(o){console.warn("[Stashpad] file-picker write failed",n.name,o)}if(i.length===0)return;await this.plugin.importLog.load();let s=[];for(let n of i)try{let o=n.stat?.size??null,r=n.extension==="md"?await this.importMarkdown(n):await this.importOtherFile(n);r&&(s.push(r),this.plugin.importLog.append({ts:new Date().toISOString(),folder:r.folder,kind:r.kind,originalName:n.name,size:o,sourcePath:n.path,notePaths:r.kind==="folder"?r.notePaths:[r.notePath]}))}catch(o){console.warn("[Stashpad] file-picker import failed",n.path,o)}s.length>0&&this.announce(s,[])},document.body.appendChild(t),t.click()}async importLooseFilesIn(a){let t=a.replace(/\/+$/,""),e=this.app.vault.getFiles().filter(n=>(n.parent?.path?.replace(/\/+$/,"")??"")===t),i=[];for(let n of e)await this.isStillImportable(n)&&i.push(n);if(i.length===0)return 0;await this.plugin.importLog.load();let s=0;for(let n of i)try{let o=n.stat?.size??null,r=n.extension==="md"?await this.importMarkdown(n):await this.importOtherFile(n);r&&(s++,this.plugin.importLog.append({ts:new Date().toISOString(),folder:r.folder,kind:r.kind,originalName:n.name,size:o,sourcePath:n.path,notePaths:r.kind==="folder"?r.notePaths:[r.notePath]}))}catch(o){console.warn("[Stashpad] loose-file import failed",n.path,o)}return s}async importLooseFoldersIn(a){let t=a.replace(/\/+$/,""),e=this.app.vault.getAbstractFileByPath(t);if(!(e instanceof et.TFolder))return 0;let i=e.children.filter(n=>n instanceof et.TFolder&&!qs.has(n.name));if(i.length===0)return 0;await this.plugin.importLog.load();let s=0;for(let n of i){let o=n.path;try{let r=await this.importFolder(n);r&&r.kind==="folder"&&(s++,this.plugin.importLog.append({ts:new Date().toISOString(),folder:r.folder,kind:r.kind,originalName:n.name,size:null,sourcePath:o,notePaths:r.notePaths}))}catch(r){console.warn("[Stashpad] loose-folder import failed",o,r)}}return s}pendingEncryptedPaths(){for(let a of[...this.pendingEncryptedStashes])this.app.vault.getAbstractFileByPath(a)instanceof et.TFile||this.pendingEncryptedStashes.delete(a);return[...this.pendingEncryptedStashes]}clearPendingEncrypted(a){this.pendingEncryptedStashes.delete(a)}shouldNotifyEncrypted(){return Date.now()>=this.encryptedNotifySnoozeUntil}snoozeEncryptedNotify(a){this.encryptedNotifySnoozeUntil=a===1/0?Number.MAX_SAFE_INTEGER:Date.now()+a}parkEncrypted(a){return this.pendingEncryptedStashes.has(a)?!1:(this.pendingEncryptedStashes.add(a),this.encryptedNotifySnoozeUntil=0,!0)}async importPendingEncrypted(){let a=0,t=!1;for(let e of this.pendingEncryptedPaths()){let i=this.app.vault.getAbstractFileByPath(e);if(!(i instanceof et.TFile))continue;let s=i.parent?.path?.replace(/\/+$/,"")??"";if(await this.importOneStash(i,s,this.liveRootIds(s),!1,{allowLater:!0,onLater:()=>{t=!0,this.snoozeEncryptedNotify(60*60*1e3)}})&&a++,t)break}return{imported:a,rescheduled:t}}liveRootIds(a){let t=new Set;for(let e of this.app.vault.getMarkdownFiles()){if((e.parent?.path?.replace(/\/+$/,"")??"")!==a)continue;let i=this.app.metadataCache.getFileCache(e)?.frontmatter?.id;typeof i=="string"&&i&&t.add(i)}return t}async importOneStash(a,t,e,i,s={}){try{let n=new Uint8Array(await this.app.vault.readBinary(a));if(i&&Ht(n))return this.pendingEncryptedStashes.add(a.path),!1;let o=await Re(this.app,n,{...s,secretId:ii(a.basename)});if(!o)return!1;let r=await Kt(this.app,o,t,e);if(r.colorAliases)for(let[A,l]of Object.entries(r.colorAliases))try{await this.plugin.setColorAlias(t,A,l)}catch{}try{await this.app.fileManager.trashFile(a)}catch{}this.pendingEncryptedStashes.delete(a.path);try{await this.plugin.newLog().append({type:"stash_import",id:F,payload:{from:a.path,into:t,noteCount:r.notesWritten,attachmentsWritten:r.attachmentsWritten,collisionsRenamed:r.collisionsRenamed,loose:!0}})}catch{}return!0}catch(n){return console.warn("[Stashpad] loose .stash import failed",a.path,n),!1}}async importLooseStashesIn(a,t={}){let e=a.replace(/\/+$/,""),i=this.app.vault.getFiles().filter(o=>(o.parent?.path?.replace(/\/+$/,"")??"")===e&&o.extension===jt);if(i.length===0)return 0;let s=this.liveRootIds(e),n=0;for(let o of i)await this.importOneStash(o,e,s,!!t.auto)&&n++;return n}async importLooseInto(a,t={}){let e=await this.importLooseFilesIn(a),i=await this.importLooseFoldersIn(a),s=await this.importLooseStashesIn(a,t);return{files:e,folders:i,stashes:s}}defaultDestination(){let t=this.plugin.lastActiveStashpadLeaf?.view?.noteFolder;return t&&this.plugin.discoverStashpadFolders().includes(t)?t:this.plugin.discoverStashpadFolders()[0]??null}confirm(a,t,e){return new Promise(i=>{new gt(this.app,a,t,e,i).open()})}dupChoice(a){return new Promise(t=>{new di(this.app,a,t).open()})}async ensureFolder(a){let t=this.app.vault.adapter,e=a.split("/").filter(Boolean),i="";for(let s of e){i=i?`${i}/${s}`:s;try{await t.exists(i)||await t.mkdir(i)}catch(n){if(!/already exists/i.test(n.message))throw n}}}async uniquePath(a,t){let e=this.app.vault.adapter,i=t.lastIndexOf("."),s=i>0?t.slice(0,i):t,n=i>0?t.slice(i):"",o=`${a}/${t}`,r=0;for(;await e.exists(o);)r+=1,o=`${a}/${s}-${r}${n}`;return o}};We.DEBOUNCE_MS=900,We.BATCH_CONFIRM_AT=8;var Js=We;var Ks=class{constructor(a,t){this.app=a;this.entries=[];this.loaded=!1;this.dirOk=!1;this.writeChain=Promise.resolve();this.path=`${t.replace(/\/+$/,"")}/import-log.jsonl`}getPath(){return this.path}async load(){if(!this.loaded){this.loaded=!0;try{let a=this.app.vault.adapter;if(await a.exists(this.path)){let t=await a.read(this.path);for(let e of t.split(/\r?\n/))if(e.trim())try{this.entries.push(JSON.parse(e))}catch{}}}catch(a){console.warn("[Stashpad] import log load failed",a)}}}recent(){return[...this.entries].reverse()}findDuplicate(a,t){for(let e=this.entries.length-1;e>=0;e--){let i=this.entries[e];if(i.originalName===a&&(t==null||i.size==null||i.size===t))return i}return null}append(a){this.entries.push(a),this.writeChain=this.writeChain.then(async()=>{try{await this.ensureDir(),await this.app.vault.adapter.append(this.path,JSON.stringify(a)+` -`)}catch(t){console.warn("[Stashpad] import log append failed",t)}})}async ensureDir(){if(this.dirOk)return;let a=this.app.vault.adapter,e=this.path.slice(0,this.path.lastIndexOf("/")).split("/").filter(Boolean),i="";for(let s of e)i=i?`${i}/${s}`:s,await a.exists(i)||await a.mkdir(i);this.dirOk=!0}};var Ys=class Ys{constructor(a,t){this.app=a;this.map=new Map;this.loaded=!1;this.dirty=!1;this.saveTimer=null;this.dirOk=!1;this.writeChain=Promise.resolve();this.path=`${t.replace(/\/+$/,"")}/render-cache.json`}async load(){if(!this.loaded){this.loaded=!0;try{let a=this.app.vault.adapter;if(await a.exists(this.path)){let t=JSON.parse(await a.read(this.path));if(t?.schema===1&&t.entries){for(let[e,i]of Object.entries(t.entries))this.map.set(e,i);for(let e of[...this.map.keys()])this.app.vault.getAbstractFileByPath(e)||(this.map.delete(e),this.dirty=!0)}}}catch(a){console.warn("[Stashpad] render cache load failed; starting empty",a),this.map.clear()}}}evict(a){this.map.delete(a)&&(this.dirty=!0,this.save())}get(a){return this.map.get(a)}has(a){return this.map.has(a)}set(a,t){this.map.set(a,t),this.dirty=!0,this.scheduleSave()}scheduleSave(){this.saveTimer==null&&(this.saveTimer=window.setTimeout(()=>{this.saveTimer=null,this.save()},Ys.SAVE_DEBOUNCE_MS))}save(){return this.saveTimer!=null&&(window.clearTimeout(this.saveTimer),this.saveTimer=null),this.dirty?(this.dirty=!1,this.writeChain=this.writeChain.then(async()=>{try{await this.ensureDir();let a={schema:1,entries:Object.fromEntries(this.map)};await this.app.vault.adapter.write(this.path,JSON.stringify(a))}catch(a){console.warn("[Stashpad] render cache save failed",a)}}),this.writeChain):this.writeChain}async ensureDir(){if(this.dirOk)return;let a=this.app.vault.adapter,e=this.path.slice(0,this.path.lastIndexOf("/")).split("/").filter(Boolean),i="";for(let s of e)i=i?`${i}/${s}`:s,await a.exists(i)||await a.mkdir(i);this.dirOk=!0}};Ys.SAVE_DEBOUNCE_MS=8e3;var Os=Ys;var ro="stashpad:unghost-after-reload",zs=class extends T.Plugin{constructor(){super(...arguments);this.settings={...ge};this.undoStacks=new Map;this.lastActiveStashpadLeaf=null;this.rebootstrapInProgress=!1;this.suppressComposerAutofocusUntil=0;this.settingTab=null;this.stashpadSelectionListeners=new Set;this.stashpadContentListeners=new Set;this._notifications=null;this._authorRegistry=null;this._importService=null;this._importLog=null;this.noteClipboard=null;this.noteClipboardNotice=null;this._renderCacheStore=null;this.knownStashpadFolders=new Set;this.suppressedFolderDeletes=new Set;this.sweptFolders=new Set;this.notifiedBuildVersion=null;this.authorRenameInFlight=new Set;this.reHomePending=new Set;this.okfRebuildTimers=new Map;this.okfRebuildingFolders=new Set;this.archivePending=new Map;this.autoSweepInProgress=!1;this.notifPersistenceWired=!1;this.notifSaveTimer=null;this.LAST_CURSOR_LS_KEY="stashpad:last-cursor";this.LAST_SELECTION_LS_KEY="stashpad:last-selection";this.writeChain=Promise.resolve()}get notifications(){return this._notifications||(this._notifications=new $i(this.app)),this._notifications}get authorRegistry(){return this._authorRegistry||(this._authorRegistry=new Ls(this.app,this.pluginPrivatePath())),this._authorRegistry}get importService(){return this._importService||(this._importService=new Js(this)),this._importService}get importLog(){return this._importLog||(this._importLog=new Ks(this.app,this.pluginPrivatePath())),this._importLog}clearNoteClipboard(){try{this.noteClipboardNotice?.hide()}catch{}this.noteClipboardNotice=null,this.noteClipboard=null}get renderCacheStore(){return this._renderCacheStore||(this._renderCacheStore=new Os(this.app,this.pluginPrivatePath())),this._renderCacheStore}async onunload(){try{this.encryption?.dispose()}catch{}try{for(let t of this.archivePending.values())window.clearTimeout(t.timer);this.archivePending.clear()}catch{}try{await this._renderCacheStore?.save()}catch{}}pluginPrivatePath(t=""){let i=`${this.manifest.dir.replace(/\/+$/,"")}/.stashpad`;return t?`${i}/${t.replace(/^\/+/,"")}`:i}newLog(){return new Gs(this.app,this.pluginPrivatePath(),()=>(this.settings?.authorName??"").trim())}async migrateLegacyPaths(){let t=this.app.vault.adapter,e=this.pluginPrivatePath(),i=async()=>{let r=e.split("/").filter(Boolean),A="";for(let l of r)A=A?`${A}/${l}`:l,await t.exists(A)||await t.mkdir(A)},s=`${this.manifest.dir.replace(/\/+$/,"")}/data.json`,n=this.pluginPrivatePath("data.json");if(await t.exists(s)&&!await t.exists(n))try{await i();let r=await t.read(s);await t.write(n,r),console.debug("[Stashpad] migrated data.json \u2192",n)}catch(r){console.warn("Stashpad: data.json migration failed",r)}let o=".stashpad";if(await t.exists(o))try{await i();let r=await t.list(o);for(let A of r.files){let l=A.replace(/^.*\//,""),d=this.pluginPrivatePath(l);if(!await t.exists(d))try{let g=await t.read(A);await t.write(d,g),console.debug("[Stashpad] migrated",A,"\u2192",d)}catch(g){console.warn(`Stashpad: failed to migrate ${A}`,g)}}}catch(r){console.warn("Stashpad: .stashpad migration scan failed",r)}}async loadData(){let t=this.app.vault.adapter,e=this.pluginPrivatePath("data.json");if(!await t.exists(e))return null;try{return JSON.parse(await t.read(e))}catch(i){return console.warn("Stashpad: data.json parse failed",i),null}}async saveData(t){let e=this.app.vault.adapter,i=this.pluginPrivatePath();if(!await e.exists(i)){let s=i.split("/").filter(Boolean),n="";for(let o of s)n=n?`${n}/${o}`:o,await e.exists(n)||await e.mkdir(n)}await e.write(this.pluginPrivatePath("data.json"),JSON.stringify(t,null,2))}async createNewStashpad(t){let e=t.trim().replace(/^\/+|\/+$/g,"");if(!e)throw new Error("Folder name is empty");let i=this.app.vault.adapter,s=e.split("/").filter(Boolean),n="";for(let l of s)n=n?`${n}/${l}`:l,await i.exists(n)||await i.mkdir(n);let o=`${e}/Home.md`;if(await i.exists(o)){let l=this.app.vault.getAbstractFileByPath(o);l&&await this.app.fileManager.processFrontMatter(l,d=>{(typeof d.id!="string"||!d.id)&&(d.id=F),"parent"in d||(d.parent=null),(typeof d.created!="string"||!d.created)&&(d.created=new Date().toISOString())});return}let r=new Date().toISOString(),A=["---",`id: ${F}`,"parent: null",`created: ${r}`,"---","Home"].join(` -`);await this.app.vault.create(o,A);try{await this.seedLocalAuthorStub(e)}catch{}try{await this.seedKnownAuthorsInFolder(e)}catch{}}collectColorsInFolder(t){let e=new Map,i=t.replace(/\/+$/,"");for(let n of this.app.vault.getMarkdownFiles()){let o=n.parent?.path?.replace(/\/+$/,"")??"";if(o!==i&&!o.startsWith(i+"/"))continue;let r=this.app.metadataCache.getFileCache(n)?.frontmatter,A=typeof r?.color=="string"?r.color.trim():"";if(!A||!/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(A))continue;let l=A.toLowerCase();e.set(l,(e.get(l)??0)+1)}let s=[...e.entries()].map(([n,o])=>({hex:n,count:o}));return s.sort((n,o)=>o.count-n.count||n.hex.localeCompare(o.hex)),s}async recolorAllInFolder(t,e,i){let s=t.replace(/\/+$/,""),n=e.toLowerCase(),o=0;for(let A of this.app.vault.getMarkdownFiles()){let l=A.parent?.path?.replace(/\/+$/,"")??"";if(l!==s&&!l.startsWith(s+"/"))continue;let d=this.app.metadataCache.getFileCache(A)?.frontmatter;if((typeof d?.color=="string"?d.color.trim().toLowerCase():"")===n)try{await this.app.fileManager.processFrontMatter(A,p=>{i?p.color=i:delete p.color}),o++}catch(p){console.warn(`Stashpad: recolor failed for ${A.path}`,p)}}let r=this.settings.colorAliases?.[s];if(r){let A=r[n];A&&(delete r[n],i&&(r[i.toLowerCase()]=A),Object.keys(r).length===0&&delete this.settings.colorAliases[s],await this.saveSettings())}return o}getColorAlias(t,e){let i=t.replace(/\/+$/,""),s=this.settings.colorAliases?.[i];if(!s)return;let n=s[e.toLowerCase()];return n&&n.trim()?n:void 0}async setColorAlias(t,e,i){let s=t.replace(/\/+$/,""),n=e.toLowerCase();this.settings.colorAliases||(this.settings.colorAliases={}),this.settings.colorAliases[s]||(this.settings.colorAliases[s]={});let o=this.settings.colorAliases[s],r=i.trim();r?o[n]=r:delete o[n],Object.keys(o).length===0&&delete this.settings.colorAliases[s],await this.saveSettings()}async waitForStashpadFolder(t,e=2e3){let i=t.trim().replace(/^\/+|\/+$/g,"");if(!i)return;let s=Date.now();for(;Date.now()-s<e;){if(this.discoverStashpadFolders().includes(i))return;await new Promise(n=>setTimeout(n,80))}}discoverStashpadFolders(){let t=new Set;for(let i of this.app.vault.getMarkdownFiles()){let s=this.app.metadataCache.getFileCache(i)?.frontmatter;if(typeof s?.id!="string"||!s.id.trim()||!s||!("parent"in s))continue;let n=i.parent?.path?.replace(/\/+$/,"")??"";n&&t.add(n)}let e=[...t].sort();return this.knownStashpadFolders=new Set(e),e}closeStashpadTabsFor(t){let e=0;for(let i of this.app.workspace.getLeavesOfType(J)){let s=i.view?.noteFolder??"";s||(s=((i.getViewState?.()?.state??{}).folderOverride??"")||this.settings.folder||"Stashpad"),s=(s||"").replace(/\/+$/,""),(s===t||s.startsWith(t+"/"))&&(i.detach(),e++)}return e}async prunePlacementFor(t){let e=this.settings,i=o=>(o??[]).filter(r=>r!==t&&!r.startsWith(t+"/")),s=(e.folderPanelPinned?.length??0)+(e.folderPanelDownranked?.length??0)+(e.folderPanelHidden?.length??0);e.folderPanelPinned=i(e.folderPanelPinned),e.folderPanelDownranked=i(e.folderPanelDownranked),e.folderPanelHidden=i(e.folderPanelHidden),e.folderPanelPinned.length+e.folderPanelDownranked.length+e.folderPanelHidden.length!==s&&await this.saveSettings()}async deleteStashpadFolderWithUndo(t){let e=t.path.replace(/\/+$/,""),i=t.name,s=this.app.vault.adapter,n=".trash";try{await s.exists(n)||await s.mkdir(n)}catch(l){console.warn("[Stashpad] couldn't ensure .trash",l)}let o=`${n}/${i}`;for(let l=1;await s.exists(o);l++)o=`${n}/${i} (${l})`;this.suppressedFolderDeletes.add(e),window.setTimeout(()=>this.suppressedFolderDeletes.delete(e),5e3);let r=this.closeStashpadTabsFor(e);await this.prunePlacementFor(e),this.knownStashpadFolders.delete(e);try{await s.rename(e,o)}catch(l){console.warn("[Stashpad] folder delete failed",l),this.suppressedFolderDeletes.delete(e),new T.Notice("Delete failed (see console).");return}let A=r>0?`Deleted \u201C${i}\u201D \u2014 closed ${r} open tab${r===1?"":"s"}.`:`Deleted \u201C${i}\u201D.`;this.notifications.show({message:A,kind:"warning",category:"delete",duration:0,folder:e,actions:[{label:"Undo",onClick:async()=>{try{if(await s.exists(e)){new T.Notice(`Can't undo \u2014 \u201C${i}\u201D already exists.`);return}this.suppressedFolderDeletes.add(e),window.setTimeout(()=>this.suppressedFolderDeletes.delete(e),5e3),await s.rename(o,e),new T.Notice(`Restored \u201C${i}\u201D.`),this.activateViewForFolder(e)}catch(l){console.warn("[Stashpad] folder undo failed",l),new T.Notice("Undo failed (see console).")}}}]})}async handleStashpadFolderDeleted(t){let e=t.replace(/\/+$/,"");if(!e||this.suppressedFolderDeletes.has(e))return;let i=this.closeStashpadTabsFor(e);await this.prunePlacementFor(e),this.knownStashpadFolders.delete(e);let s=e.split("/").pop()||e;this.notifications.show({message:i>0?`Stashpad \u201C${s}\u201D was deleted \u2014 closed ${i} open tab${i===1?"":"s"}.`:`Stashpad \u201C${s}\u201D was deleted.`,kind:"warning",category:"delete",folder:e})}searchableFolders(t){let e=new Set(this.settings.searchIncludedFolders),i=new Set(this.settings.searchExcludedFolders),s=new Set((this.settings.archiveFolders??[]).map(l=>(l??"").replace(/\/+$/,""))),o=this.discoverStashpadFolders().filter(l=>s.has(l)?!1:e.size>0?e.has(l):!i.has(l)),r=(t||"").trim().replace(/\/+$/,""),A=o.filter(l=>l!==r);return r&&A.unshift(r),A}async maybeSweepFolder(t){let e=(t||"").trim().replace(/\/+$/,"");!e||this.sweptFolders.has(e)||(this.sweptFolders.add(e),setTimeout(()=>{this.runSweep(e,{silent:!0})},3e3))}async runIntegrityCheckOnFolder(t){let e=(t||"").trim().replace(/\/+$/,"");e&&await this.runSweep(e,{silent:!1})}async runSweep(t,e){try{let i=this.newLog(),s={},n=this.app.vault.getMarkdownFiles().filter(l=>l.path===t||l.path.startsWith(t+"/"));for(let l of n){let d=this.app.metadataCache.getFileCache(l)?.frontmatter,g=typeof d?.id=="string"?d.id.trim():"";if(!g)continue;let p=d&&"parent"in d?d.parent??null:null;s[g]={parent:p,path:l.path}}let o=await i.readState(),r=l=>l===t||l.startsWith(t+"/");if(!e.silent){for(let[l,d]of Object.entries(s)){let g=o[l];g?g.parent!==d.parent?await i.append({type:"parent_change",id:l,payload:{from:g.parent,to:d.parent}}):g.path!==d.path&&await i.append({type:"rename",id:l,payload:{from:g.path,to:d.path}}):await i.append({type:"create",id:l,payload:{path:d.path,parent:d.parent}})}for(let[l,d]of Object.entries(o))!s[l]&&r(d.path)&&await i.append({type:"missing",id:l,payload:{lastPath:d.path}})}let A={};for(let[l,d]of Object.entries(o))r(d.path)||(A[l]=d);for(let[l,d]of Object.entries(s))A[l]=d;await i.writeState(A)}catch(i){console.warn("Stashpad: integrity sweep failed",i)}}getUndoStack(t){let e=this.undoStacks.get(t);return e||(e=new Rs,this.undoStacks.set(t,e)),e}async onload(){await this.migrateLegacyPaths(),await this.loadSettings(),Qt.enabled=!!this.settings.enablePerfProfiling,this.encryption=new ss(this.app,()=>({...Ei(),...this.settings.encryption??{}}),async h=>{this.settings.encryption=h,await this.saveSettings()},()=>this.settings.encryptionIdleLockMinutes??0),this.encryption.init().then(()=>this.encryption.tryAutoUnlock()),this.settingTab=new us(this.app,this),this.addSettingTab(this.settingTab),await this.renderCacheStore.load(),this.registerEvent(this.app.vault.on("delete",h=>this.renderCacheStore.evict(h.path))),this.registerEvent(this.app.vault.on("rename",(h,I)=>this.renderCacheStore.evict(I))),this.registerEvent(this.app.vault.on("create",h=>this.onOkfFileEvent(h.path))),this.registerEvent(this.app.vault.on("delete",h=>this.onOkfFileEvent(h.path))),this.registerEvent(this.app.vault.on("rename",(h,I)=>{this.onOkfFileEvent(h.path),this.onOkfFileEvent(I)})),await this.authorRegistry.load();{let h=(this.settings.authorId??"").trim();h&&this.authorRegistry.record({id:h,name:this.settings.authorName,role:this.settings.authorRole,department:this.settings.authorDepartment})}this.app.workspace.onLayoutReady(()=>{this.reconcileLockedRegistry(),window.setTimeout(()=>void this.checkDueReminders(),6e3),this.registerInterval(window.setInterval(()=>void this.checkDueReminders(),5*60*1e3)),window.setTimeout(()=>{this.seedLocalAuthorStubsEverywhere()},4e3),window.setTimeout(()=>this.syncObsidianExcludedArchives(),4500),window.setTimeout(()=>this.importService.setArmed(!0),2500),window.setTimeout(()=>void this.runAutoImportSweep(),5e3),this.registerInterval(window.setInterval(()=>void this.runAutoImportSweep(),5*60*1e3)),window.setTimeout(()=>void this.migratePinnedNotesToFrontmatter(),3e3),window.setTimeout(()=>void this.unghostStashpadTabsIfFlagged(),1200)}),this.registerView(J,h=>new xs(h,this)),this.registerView(Ce,h=>new Cs(h,this)),this.registerView(ie,h=>new qi(h,this)),this.registerView(De,h=>new Ts(h,this)),this.registerView(fe,h=>new Hs(h,this)),this.registerEvent(this.app.workspace.on("active-leaf-change",h=>{h&&h.view.getViewType()===J&&(this.lastActiveStashpadLeaf=h,this.settings.autoOpenDetailPanel&&this.app.workspace.getLeavesOfType(Ce).length===0&&setTimeout(()=>{Bs(this.app)},0),this.notifyStashpadSelectionChanged())}));let t=()=>{let h=_t(),I=!!h&&this.app.workspace.activeLeaf&&this.app.workspace.activeLeaf.view===h,u=!!I&&this.settings.hideMobileToolbarInStashpad;document.body.classList.toggle("stashpad-hide-mobile-toolbar",u),document.body.classList.toggle("stashpad-active",!!I)};this.register(Sa(t)),this.registerEvent(this.app.workspace.on("active-leaf-change",t));let e=h=>{try{let I=Array.from(document.querySelectorAll("style")).filter(u=>(u.textContent??"").includes(".stashpad-"));for(let u of I){let f=u.id||"",C=f?`style[data-stashpad-source="${f}"]`:null;if(C&&h.head.querySelector(C))continue;let B=h.createElement("style");f?B.setAttribute("data-stashpad-source",f):B.setAttribute("data-stashpad-source","anon"),B.textContent=u.textContent??"",h.head.appendChild(B)}}catch(I){console.warn("[Stashpad] inject popout styles failed",I)}};this.registerEvent(this.app.workspace.on("window-open",h=>{let I=h?.doc??h?.win?.document??null;I&&e(I)})),this.registerEvent(this.app.workspace.on("file-menu",(h,I)=>{if(!(I instanceof T.TFolder))return;let u=I.path.replace(/\/+$/,"");this.discoverStashpadFolders().includes(u)&&h.addItem(f=>{f.setTitle("Open folder in Stashpad").setIcon("layout-list").onClick(()=>void this.openFolderInStashpad(u))})})),setTimeout(()=>{try{let h=this.app.workspace;typeof h.iterateAllLeaves=="function"&&h.iterateAllLeaves(I=>{let u=I?.view?.containerEl?.ownerDocument;u&&u!==document&&e(u)})}catch{}},200),t(),this.register(()=>document.body.classList.remove("stashpad-hide-mobile-toolbar","stashpad-active"));let i=window.visualViewport,s=()=>{let h=document.querySelector(".mobile-toolbar, .mobile-toolbar-container"),I=h&&h.isConnected?h.offsetHeight:0;document.body.style.setProperty("--stashpad-toolbar-h",`${I}px`);let u=0;i&&(u=Math.max(0,window.innerHeight-i.height-i.offsetTop)),document.body.style.setProperty("--stashpad-vv-bottom-gap",`${u}px`),document.body.classList.toggle("stashpad-keyboard-open",u>100)};s(),i&&(i.addEventListener("resize",s),i.addEventListener("scroll",s),this.register(()=>{i.removeEventListener("resize",s),i.removeEventListener("scroll",s)})),window.addEventListener("resize",s),this.register(()=>window.removeEventListener("resize",s)),requestAnimationFrame(s),setTimeout(s,250),setTimeout(s,1e3),this.addRibbonIcon("list-tree","Open Stashpad",()=>{if(this.discoverStashpadFolders().length===0){this.activateView({reveal:!0});return}this.openFolderPicker()}).addEventListener("contextmenu",h=>{h.preventDefault(),this.openFolderPicker()}),this.addRibbonIcon("panel-left","Open Stashpad panels (sidebar)",()=>{Ji(this.app)}),this.addRibbonIcon("folders","Open Stashpad folder panel (sidebar)",()=>{Ps(this.app)}),this.addRibbonIcon("panel-right","Open Stashpad detail panel (right sidebar)",()=>{Bs(this.app)}),this.addCommand({id:"stashpad-open",name:"Open Stashpad in new tab",callback:()=>{if(this.discoverStashpadFolders().length>=2){this.openFolderPicker();return}this.activateView({reveal:!1})}}),this.addCommand({id:"stashpad-reveal",name:"Reveal or open Stashpad",callback:()=>void this.activateView({reveal:!0})}),this.addCommand({id:"stashpad-focus-last-tab",name:"Focus last Stashpad tab",callback:()=>void this.focusLastStashpadTab()}),this.addCommand({id:"stashpad-focus-folder-panel",name:"Focus folder panel",callback:()=>void this.focusFolderPanel()}),this.addCommand({id:"stashpad-lock-encryption",name:"Lock encryption (forget password)",callback:()=>{if(!this.encryption.isConfigured()){new T.Notice("Encryption isn't set up.");return}this.encryption.lock(),new T.Notice("Encryption locked.")}});let o=h=>{let I=_t();I&&typeof I[h]=="function"&&I[h]()};this.addCommand({id:"stashpad-toggle-split",name:"Toggle split-on-newlines",callback:()=>o("toggleSplit")}),this.addCommand({id:"stashpad-command-palette",name:"Command palette (Stashpad only)",callback:()=>o("openStashpadCommandPalette")}),this.addCommand({id:"stashpad-lock-selection",name:"Encrypt (lock) selection (notes + children)",callback:()=>o("cmdLockSelection")}),this.addCommand({id:"stashpad-unlock-all",name:"Decrypt (unlock) locked notes in view",callback:()=>o("cmdUnlockAll")}),this.addCommand({id:"stashpad-unlock-all-vault",name:"Decrypt (unlock) ALL locked notes in the vault",callback:()=>void this.unlockAllInVault()}),this.addCommand({id:"stashpad-copy-notes",name:"Copy notes (note clipboard \u2014 paste to duplicate)",callback:()=>o("cmdCopyNotes")}),this.addCommand({id:"stashpad-cut-notes",name:"Cut notes (paste in list to move, in composer to extract text)",callback:()=>o("cmdCutNotes")}),this.addCommand({id:"stashpad-paste-notes",name:"Paste notes (from the note clipboard)",callback:()=>o("cmdPasteNotes")}),this.addCommand({id:"stashpad-move-to-archive",name:"Move selection to archive (encrypt)",callback:()=>o("cmdMoveToArchive")}),this.addCommand({id:"stashpad-encrypt-delete",name:"Encrypt & delete selection (to encrypted trash)",callback:()=>o("cmdEncryptDelete")}),this.addCommand({id:"stashpad-restore-trash",name:"Open encrypted trash (restore deleted)\u2026",callback:()=>this.openEncryptedTrash()}),this.addCommand({id:"stashpad-encrypt-existing-trash",name:"Encrypt existing Obsidian trash (backfill .trash into encrypted trash)",callback:()=>void this.encryptExistingTrash()}),this.addCommand({id:"stashpad-close-duplicate-tabs",name:"Close duplicate & orphaned Stashpad tabs (tidy up)",callback:()=>void this.closeDuplicateStashpadTabs()}),this.addCommand({id:"stashpad-claim-selected-author",name:"Claim authorship of selected notes",callback:()=>o("claimSelectedAsAuthor")}),this.addCommand({id:"stashpad-claim-folder-author",name:"Claim authorship of all unauthored notes in this folder",callback:()=>o("claimFolderAsAuthor")}),this.addCommand({id:"stashpad-claim-selected-contributor",name:"Claim selected notes (author if unowned, else add me as contributor)",callback:()=>o("claimSelectedWithContributor")}),this.addCommand({id:"stashpad-claim-folder-contributor",name:"Claim all notes in this folder (author if unowned, else add me as contributor)",callback:()=>o("claimFolderWithContributor")}),this.addCommand({id:"stashpad-pick-destination",name:"Pick destination for next note",callback:()=>o("openDestinationPicker")}),this.addCommand({id:"stashpad-search",name:"Search Stashpad notes",callback:()=>o("openSearchModal")}),this.addCommand({id:"stashpad-search-in-parent",name:"Search in current parent",callback:()=>o("openSearchInParentModal")}),this.addCommand({id:"stashpad-move-picker",name:"Move selection (picker)",callback:()=>o("cmdMovePicker")}),this.addCommand({id:"stashpad-merge",name:"Merge selection",callback:()=>o("cmdMerge")}),this.addCommand({id:"stashpad-copy",name:"Copy selection",callback:()=>o("cmdCopy")}),this.addCommand({id:"stashpad-copy-tree",name:"Copy focused subtree",callback:()=>o("cmdCopyTree")}),this.addCommand({id:"stashpad-copy-outline",name:"Copy as outline (nested embeds)",callback:()=>o("cmdCopyOutline")}),this.addCommand({id:"stashpad-split",name:"Split note\u2026",callback:()=>o("cmdSplit")}),this.addCommand({id:"stashpad-edit-note",name:"Edit note in new tab (selection)",callback:()=>o("cmdOpenInEditor")}),this.addCommand({id:"stashpad-edit-parent",name:"Edit parent note in new tab",callback:()=>o("cmdOpenParentInEditor")}),this.addCommand({id:"stashpad-delete",name:"Delete selection",callback:()=>o("cmdDelete")}),this.addCommand({id:"stashpad-move-up",name:"Move note up",callback:()=>o("cmdMoveUp")}),this.addCommand({id:"stashpad-move-down",name:"Move note down",callback:()=>o("cmdMoveDown")}),this.addCommand({id:"stashpad-move-to-top",name:"Move note to top",callback:()=>o("cmdMoveToTop")}),this.addCommand({id:"stashpad-move-to-bottom",name:"Move note to bottom",callback:()=>o("cmdMoveToBottom")}),this.addCommand({id:"stashpad-outdent",name:"Outdent (move to grandparent)",callback:()=>o("cmdOutdent")}),this.addCommand({id:"stashpad-set-color",name:"Set note color\u2026",callback:()=>o("cmdSetColor")}),this.addCommand({id:"stashpad-clone",name:"Clone selection (duplicate / copy notes)",callback:()=>o("cmdClone")}),this.addCommand({id:"stashpad-insert-template",name:"Insert template (clone an existing note)",callback:()=>o("cmdInsertTemplate")}),this.addCommand({id:"stashpad-toggle-expand",name:"Show more / show less (expand toggle)",callback:()=>o("cmdToggleExpand")}),this.addCommand({id:"stashpad-pick-move",name:"Move (in-list, arrow + Enter)",callback:()=>o("cmdInListPicker")}),this.addCommand({id:"stashpad-open-in-new-tab",name:"Open in new Stashpad tab",callback:()=>o("cmdOpenInNewStashpadTab")}),this.addCommand({id:"stashpad-toggle-complete",name:"Toggle complete (strikethrough)",callback:()=>o("cmdToggleComplete")}),this.addCommand({id:"stashpad-toggle-task",name:"Toggle task (todo)",callback:()=>o("cmdToggleTask")}),this.addCommand({id:"stashpad-set-due",name:"Set due date\u2026",callback:()=>o("cmdSetDue")}),this.addCommand({id:"stashpad-dump-perf",name:"Dump performance profile (copy to clipboard)",callback:async()=>{if(!this.settings.enablePerfProfiling){new T.Notice("Enable \u201CPerformance profiling\u201D in Stashpad settings first, then use the app and run this again.");return}let h=Qt.report();console.log(h);try{await navigator.clipboard.writeText(h)}catch{}new T.Notice("Performance profile copied to clipboard (also in the console).")}}),this.addCommand({id:"stashpad-reset-perf",name:"Reset performance profile",callback:()=>{Qt.reset(),new T.Notice("Performance profile reset.")}}),this.addCommand({id:"stashpad-jump-to-top",name:"Jump to top of list",callback:()=>o("jumpToTop")}),this.addCommand({id:"stashpad-jump-to-bottom",name:"Jump to bottom of list",callback:()=>o("jumpToBottom")}),this.addCommand({id:"stashpad-assign",name:"Assign task to\u2026",callback:()=>o("cmdAssign")}),this.addCommand({id:"stashpad-open-import-log",name:"Open import log",callback:async()=>{await this.importLog.load();let{ImportLogModal:h}=await Promise.resolve().then(()=>(vt(),gi));new h(this.app,this.importLog.recent()).open()}}),this.addCommand({id:"stashpad-import-files",name:"Import file(s) into Stashpad\u2026",callback:()=>this.openImportPicker()}),this.addCommand({id:"stashpad-import-loose-files",name:"Import loose files & folders in this folder (scan for moved-in / unprocessed items)",checkCallback:h=>{let I=this.importService.defaultDestination();return h?!!I:(I&&this.runImportLooseFiles(I),!0)}}),this.addCommand({id:"stashpad-rerun-slug-pass",name:"Re-run filename (slug) pass on this folder",checkCallback:h=>{let I=this.importService.defaultDestination();return h?!!I:(I&&this.runFolderSlugPass(I),!0)}}),this.addCommand({id:"stashpad-rerun-frontmatter-backfill",name:"Re-run frontmatter backfill (recovery links) on this folder",checkCallback:h=>{let I=this.importService.defaultDestination();return h?!!I:(I&&this.runFolderFrontmatterBackfill(I),!0)}}),this.addCommand({id:"stashpad-select-all",name:"Select all visible notes",callback:()=>o("cmdSelectAll")}),this.addCommand({id:"stashpad-copy-codeblock",name:"Copy code from codeblock",callback:()=>o("cmdCopyCodeBlock")}),this.addCommand({id:"stashpad-open-panels",name:"Open Stashpad panels (sidebar)",callback:()=>void Ji(this.app)}),this.addCommand({id:"stashpad-open-folder-panel",name:"Open folder panel (sidebar)",callback:()=>void Ps(this.app)}),this.addCommand({id:"stashpad-open-detail",name:"Open Stashpad detail panel (right sidebar)",callback:()=>void Bs(this.app)}),this.addCommand({id:"stashpad-reveal-active-note",name:"Open this note in Stashpad",checkCallback:h=>{let I=this.app.workspace.getActiveFile(),u=!!I&&I.extension==="md"&&this.isStashpadNoteFile(I);return h||u&&I&&this.revealNoteInStashpad(I),u}});let r=Object.keys(pi);for(let h of r){let I=pi[h];this.addCommand({id:`stashpad-open-panels-${h}`,name:`Open Stashpad panel: ${I.label}`,callback:async()=>{await Ji(this.app),this.app.workspace.getLeavesOfType(ie)[0]?.view?.setActivePanel?.(h)}})}this.addCommand({id:"stashpad-swap-with-parent",name:"Swap with parent (ouroboros)",callback:()=>o("cmdSwapWithParent")}),this.addCommand({id:"stashpad-toggle-pin",name:"Pin / unpin selected note (sidebar)",callback:()=>o("cmdTogglePin")}),this.addCommand({id:"stashpad-open-tiny",name:"Open Stashpad in tiny window",callback:()=>void this.openTinyWindow()}),this.addCommand({id:"stashpad-clone-tab",name:"Clone (duplicate / copy) this Stashpad tab",callback:()=>o("cmdCloneStashpadTab")}),this.addCommand({id:"stashpad-undo",name:"Undo last Stashpad action",callback:()=>o("cmdUndo")}),this.addCommand({id:"stashpad-redo",name:"Redo last undone Stashpad action",callback:()=>o("cmdRedo")}),this.addCommand({id:"stashpad-export-stash",name:"Export selection to .stash",callback:()=>o("cmdExportStash")}),this.addCommand({id:"stashpad-export-okf",name:"Export selection as OKF bundle (.zip / .tar.gz / .stash)",callback:()=>o("cmdExportOkf")}),this.addCommand({id:"stashpad-import-stash",name:"Import .stash file\u2026",callback:()=>o("cmdImportStash")}),this.addCommand({id:"stashpad-pick-folder",name:"Stashpad: open / switch / create folder\u2026",callback:()=>this.openFolderPicker()}),this.addCommand({id:"stashpad-run-integrity-check",name:"Run integrity check on active Stashpad folder",checkCallback:h=>{let I=_t(),u=I&&I.noteFolder;return u?(h||(new T.Notice(`Running integrity check on "${u}"\u2026`),this.runIntegrityCheckOnFolder(u).then(()=>{new T.Notice("Integrity check complete \u2014 see Stashpad log.")})),!0):!1}}),this.addCommand({id:"stashpad-fix-orphans",name:"Set missing parents to Home (orphan fix)",callback:()=>void this.fixOrphanParents()}),this.addCommand({id:"stashpad-rebuild-author-registry",name:"Rebuild author registry (scan authors + note frontmatter)",callback:async()=>{new T.Notice("Stashpad: rebuilding author registry\u2026");try{let h=await this.rebuildAuthorRegistry();this.notifications.show({message:`Author registry rebuilt: ${h.total} author(s) \u2014 ${h.fromStubs} from stubs, ${h.fromNotes} from note links.`,kind:"success",category:"system"})}catch(h){new T.Notice(`Author registry rebuild failed: ${h.message}`)}}}),this.addCommand({id:"stashpad-restore-author-stubs",name:"Restore missing author stubs (from registry)",callback:async()=>{new T.Notice("Stashpad: restoring author stubs\u2026");try{let h=await this.restoreMissingAuthorStubs();this.notifications.show({message:h.created>0?`Restored ${h.created} author stub(s) across ${h.folders} folder(s).`:`No missing author stubs \u2014 all present across ${h.folders} folder(s).`,kind:"success",category:"system"})}catch(h){new T.Notice(`Restore author stubs failed: ${h.message}`)}}}),this.addCommand({id:"stashpad-sync-authors",name:"Sync authors across all folders (multiplayer)",callback:()=>void this.syncAuthorsAcrossFolders()}),this.addCommand({id:"stashpad-rebootstrap-all",name:"Rebootstrap all Stashpad folders (backfill metadata + rename stale titles)",callback:async()=>{new T.Notice("Stashpad: rebootstrapping\u2026");try{let{touched:h,fmChecked:I,fmWritten:u,slugsRenamed:f,authors:C,imported:B,attachmentsLinked:m}=await this.rebootstrapAllFolders(),w=[];w.push(`rebootstrapped ${h.length} folder${h.length===1?"":"s"}`),B>0&&w.push(`imported ${B} loose file${B===1?"":"s"}`),m>0&&w.push(`linked attachments on ${m} note${m===1?"":"s"}`),u>0&&w.push(`updated ${u} note${u===1?"":"s"}' metadata`),f>0&&w.push(`renamed ${f} note${f===1?"":"s"}`),C>0&&w.push(`${C} author${C===1?"":"s"} in registry`),w.push(`(checked ${I} total)`),new T.Notice(`Stashpad: ${w.join(" \xB7 ")}`)}catch(h){new T.Notice(`Stashpad: rebootstrap failed (${h.message})`)}}}),this.addCommand({id:"stashpad-adopt-note",name:"Adopt active note into Stashpad (fill missing frontmatter)",checkCallback:h=>{let I=this.app.workspace.getActiveFile();return!I||I.extension!=="md"?!1:(h||this.adoptNote(I),!0)}}),this.addCommand({id:"stashpad-open-notification-history",name:"Open notification history",callback:()=>{Promise.resolve().then(()=>(vt(),gi)).then(({NotificationHistoryModal:h,LogModal:I})=>{new h(this.app,this.notifications,async()=>{let u=this.app.vault.adapter,f=this.pluginPrivatePath("log.jsonl");if(!await u.exists(f)){new T.Notice("No log yet \u2014 make some changes first.");return}let C=await u.read(f);new I(this.app,C,f).open()},this.settings.authorId||null,u=>this.lookupNoteAuthorIds(u)).open()})}});let A=[{key:"prefixTimestampsOnCopy",label:"Prefix timestamps when copying"},{key:"useTemplatesFormat",label:"Use Templates plugin date/time formats"},{key:"autoNavOnMoveIn",label:"Auto-navigate into parent on move IN"},{key:"autoNavOnMoveOut",label:"Auto-navigate to destination on move OUT"},{key:"confirmCrossParentDrag",label:"Confirm cross-parent drag-and-drop"},{key:"confirmBulkDelete",label:"Confirm bulk deletes"},{key:"confirmAttachmentDelete",label:"Offer to delete attachments with note"},{key:"autofocusComposerAfterSend",label:"Autofocus composer after sending"},{key:"popoutDuplicates",label:"Open in new window \u2014 duplicate tab"},{key:"autoExpandCursorRow",label:"Expand the cursor row's body automatically"},{key:"autoOpenDetailPanel",label:"Auto-open the detail panel"},{key:"doubleClickToFocus",label:"Double-click a note to open it"}];for(let h of A){let I=`stashpad-toggle-${String(h.key).replace(/[A-Z]/g,u=>`-${u.toLowerCase()}`)}`;this.addCommand({id:I,name:`Toggle: ${h.label}`,callback:async()=>{let u=!this.settings[h.key];this.settings[h.key]=u,await this.saveSettings(),new T.Notice(`${h.label}: ${u?"ON":"OFF"}`)}})}this.addCommand({id:"stashpad-open-settings",name:"Open Stashpad settings",callback:()=>{let h=this.app.setting;!h?.open||!h?.openTabById||(h.open(),h.openTabById(this.manifest.id))}}),this.addCommand({id:"stashpad-search-settings",name:"Search Stashpad settings\u2026",callback:()=>{let h=this.app.setting;!h?.open||!h?.openTabById||(h.open(),h.openTabById(this.manifest.id),setTimeout(()=>{h?.modalEl?.querySelector?.("input[type='search']")?.focus()},0))}});for(let h of Is)this.addCommand({id:`stashpad-open-settings-${h.id}`,name:`Open Stashpad settings: ${h.label}`,callback:()=>{let I=this.app.setting;!I?.open||!I?.openTabById||(I.open(),I.openTabById(this.manifest.id))}});let l=()=>{let h=this.app.setting;!h?.open||!h?.openTabById||(h.open(),h.openTabById(this.manifest.id),setTimeout(()=>{document.getElementById("stashpad-jd-index-section")?.scrollIntoView({behavior:"smooth",block:"start"})},100))};this.addCommand({id:"stashpad-preview-jd-index",name:"Preview JD index (overwrites home note body)",callback:async()=>{try{let{buildJdIndexPreview:h}=await Promise.resolve().then(()=>(ui(),Yi)),I=await h(this.app,this,this.settings);if(I.error==="no-dest"){new T.Notice("Set a Designated Stashpad folder for Index in settings first.",6e3),l();return}if(I.error==="no-home"){new T.Notice(`"${this.settings.jdIndexStashpadFolder}" has no Stashpad home note. Open the folder in Stashpad first to create one.`,7e3);return}let{buildJdPreviewNotice:u}=await Promise.resolve().then(()=>(ui(),Yi));u(this.app,I)}catch(h){console.error("[stashpad] preview failed",h),new T.Notice(`Preview failed: ${h?.message??h}`,8e3)}}}),this.addCommand({id:"stashpad-build-jd-index",name:"Build JD index notes (creates Stashpad-note hierarchy)",callback:async()=>{try{let{buildJdIndexNotes:h,scanForJdNotes:I,JdBuildConfirmModal:u}=await Promise.resolve().then(()=>(ui(),Yi));if(!(this.settings.jdIndexStashpadFolder??"").trim().replace(/^\/+|\/+$/g,"")){new T.Notice("Set a Designated Stashpad folder for Index in settings first.",6e3),l();return}let C=I(this.app,this,this.settings);new u(this.app,this,this.settings,C.indexed.length,async()=>{try{let m=await h(this.app,this,this.settings);if(m.error==="no-dest"){new T.Notice("Set a Designated Stashpad folder for Index in settings first.",6e3),l();return}if(m.error==="dest-not-stashpad"){new T.Notice(`"${m.destFolder}" isn't a known Stashpad folder. Pick a real Stashpad folder in settings.`,7e3),l();return}this.settings.jdIndexHasBuilt=!0,await this.saveSettings(),new T.Notice(`Index built: ${m.created} created, ${m.updated} updated, ${m.skipped} skipped \u2192 ${m.destFolder}`,6e3)}catch(m){console.error("[stashpad] build failed",m),new T.Notice(`Build failed: ${m?.message??m}`,8e3)}}).open()}catch(h){console.error("[stashpad] build failed",h),new T.Notice(`Build failed: ${h?.message??h}`,8e3)}}});let d=h=>{if(h.extension!==jt)return;let I=(this.settings.importDropFolder||"").trim().replace(/^\/+|\/+$/g,""),u=(this.settings.exportFolder||"").trim().replace(/^\/+|\/+$/g,""),f=h.parent?.path||"",C=f.split("/").pop()??"";if(I&&C===I){if(u&&f.endsWith(`/${u}`))return;let B=f.slice(0,f.length-I.length).replace(/\/+$/,"")||this.settings.folder;this.autoImportStash(h,B);return}this.settings.autoImport&&this.importService.isArmed()&&(Ne(h.path)||this.discoverStashpadFolders().includes(f)&&this.autoImportStash(h,f))};this.registerEvent(this.app.vault.on("create",h=>{h instanceof T.TFile&&d(h)})),this.registerEvent(this.app.vault.on("rename",h=>{h instanceof T.TFile&&d(h)}));let g=h=>{if(h.extension!=="md")return;let I=h.parent?.path?.replace(/\/+$/,"")??"";this.discoverStashpadFolders().includes(I)&&setTimeout(()=>{this.fixOrphanParentForFile(h)},800)},p=h=>{if(h.extension!=="md")return;let I=(this.settings.importDropFolder||"").trim().replace(/^\/+|\/+$/g,"");if(!I)return;let u=h.parent?.path?.replace(/\/+$/,"")??"";if((u.split("/").pop()??"")!==I)return;let C=u.slice(0,u.length-I.length).replace(/\/+$/,"");!C||!this.discoverStashpadFolders().includes(C)||setTimeout(()=>{this.adoptMarkdownDrop(h,C)},200)};this.registerEvent(this.app.vault.on("create",h=>{h instanceof T.TFile&&(g(h),p(h))})),this.registerEvent(this.app.vault.on("rename",h=>{h instanceof T.TFile&&(g(h),p(h))})),this.registerEvent(this.app.vault.on("delete",h=>{if(!(h instanceof T.TFolder))return;let I=h.path.replace(/\/+$/,"");this.knownStashpadFolders.has(I)&&this.handleStashpadFolderDeleted(I)})),this.registerEvent(this.app.vault.on("rename",(h,I)=>{h instanceof T.TFile&&this.maybeReHomeOnCrossFolderMove(h,I)})),this.registerEvent(this.app.vault.on("rename",(h,I)=>{h instanceof T.TFile&&this.maybeArchiveOnMoveIn(h,I)})),this.registerEvent(this.app.vault.on("create",h=>{h instanceof T.TFile?this.importService.enqueue(h):h instanceof T.TFolder&&this.importService.enqueueFolder(h)})),this.registerEvent(this.app.vault.on("rename",h=>{h instanceof T.TFile?this.importService.enqueue(h):h instanceof T.TFolder&&this.importService.enqueueFolder(h)})),this.registerEvent(this.app.vault.on("rename",(h,I)=>{h instanceof T.TFile&&this.maybeAdoptAuthorRename(h,I)})),this.registerDomEvent(window,"focus",()=>void this.checkForSyncedBuild()),setTimeout(()=>void this.checkForSyncedBuild(),5e3),this.registerInterval(window.setInterval(()=>void this.checkForSyncedBuild(),45e3))}async checkForSyncedBuild(){try{let t=this.manifest.dir;if(!t)return;let e=`${t.replace(/\/+$/,"")}/manifest.json`,i=this.app.vault.adapter;if(!await i.exists(e))return;let s=JSON.parse(await i.read(e))?.version,n=this.manifest.version;if(typeof s!="string"||!s||s===n||!this.isSemverGreater(s,n)||this.notifiedBuildVersion===s)return;this.notifiedBuildVersion=s,this.notifications.show({message:`A newer Stashpad build synced in (\`${n}\` \u2192 \`${s}\`). Reload the app to apply it.`,kind:"info",category:"system",duration:0,actions:[{label:"Reload app",onClick:()=>this.reloadAppForUpdate()}]})}catch(t){console.debug("[Stashpad] synced-build check failed",t)}}reloadAppForUpdate(){try{window.localStorage?.setItem(ro,"1")}catch{}try{if(this.app.commands?.executeCommandById?.("app:reload"))return}catch(t){console.warn("[Stashpad] app:reload command failed",t)}try{window.location.reload()}catch{new T.Notice("Reload Obsidian (close + reopen) to apply the Stashpad update.")}}async unghostStashpadTabsIfFlagged(){let t=!1;try{t=window.localStorage?.getItem(ro)==="1"}catch{}if(t){try{window.localStorage?.removeItem(ro)}catch{}for(let e of this.app.workspace.getLeavesOfType(J))try{let i=e;i.isDeferred&&typeof i.loadIfDeferred=="function"&&await i.loadIfDeferred()}catch(i){console.warn("[Stashpad] un-ghost leaf failed",i)}}}isSemverGreater(t,e){let i=t.split(".").map(o=>parseInt(o,10)||0),s=e.split(".").map(o=>parseInt(o,10)||0),n=Math.max(i.length,s.length);for(let o=0;o<n;o++){let r=i[o]??0,A=s[o]??0;if(r!==A)return r>A}return!1}parseAuthorFilePath(t){let e=t.match(/\/_authors\/([^/]+?)-([a-z0-9]{4,12})\.md$/i);return e?{name:e[1].replace(/-/g," "),id:e[2]}:null}authorNameToSafe(t){return t.replace(/[^\w\- ]+/g,"").trim().replace(/\s+/g,"-")||"author"}async syncAuthorFilesToName(){let t=(this.settings.authorId??"").trim(),e=(this.settings.authorName??"").trim();if(!t||!e)return;let i=this.authorNameToSafe(e);for(let s of this.discoverStashpadFolders()){let n=`${s}/_authors`;if(await this.app.vault.adapter.exists(n))for(let o of this.app.vault.getMarkdownFiles()){if(!o.path.startsWith(n+"/"))continue;let r=this.parseAuthorFilePath(o.path);if(!r||r.id!==t)continue;let A=`${n}/${i}-${t}.md`,l=o;if(o.path!==A)try{this.authorRenameInFlight.add(o.path),this.authorRenameInFlight.add(A),await this.app.fileManager.renameFile(o,A);let d=this.app.vault.getAbstractFileByPath(A);d&&(l=d)}catch(d){console.warn("[Stashpad] author file rename failed",d);continue}try{await this.refreshAuthorStub(l)}catch{}}}}async refreshAuthorStub(t){let e=(this.settings.authorName??"").trim(),i=(this.settings.authorRole??"").trim(),s=(this.settings.authorDepartment??"").trim();if(e)try{let n=await this.app.vault.read(t),o=n.replace(/^# .*$/m,`# ${e}`);o!==n&&await this.app.vault.modify(t,o),await this.app.fileManager.processFrontMatter(t,r=>{r.aliases=[e],delete r.name,i?r.role=i:delete r.role,s?r.department=s:delete r.department})}catch(n){console.warn("[Stashpad] refreshAuthorStub failed",n)}}async maybeAdoptAuthorRename(t,e){if(this.authorRenameInFlight.delete(t.path)||this.authorRenameInFlight.delete(e))return;let i=this.parseAuthorFilePath(t.path);if(!i)return;let s=(this.settings.authorId??"").trim();if(!s||i.id!==s)return;let n=i.name.trim();!n||n===(this.settings.authorName??"").trim()||(this.settings.authorName=n,await this.saveSettings(),await this.syncAuthorFilesToName())}async adoptMarkdownDrop(t,e){try{let i=this.app.vault.adapter,s=t.name,n=s.lastIndexOf("."),o=n>0?s.slice(0,n):s,r=n>0?s.slice(n):"",A=0;for(;await i.exists(`${e}/${s}`);)A+=1,s=`${o}-${A}${r}`;let l=`${e}/${s}`;await this.app.fileManager.renameFile(t,l);let d=this.app.vault.getAbstractFileByPath(l);d instanceof T.TFile&&setTimeout(()=>{this.fixOrphanParentForFile(d)},500),this.notifications.show({message:`Imported \`${t.name}\` \u2192 \`${e}\``,kind:"success",category:"import",folder:e,affectedPaths:[l]})}catch(i){console.warn("Stashpad: markdown drop adoption failed",i),this.notifications.show({message:`Couldn't import \`${t.name}\`: ${i.message}`,kind:"error",category:"import"})}}async fixOrphanParentForFile(t){try{let e=this.app.metadataCache.getFileCache(t)?.frontmatter,i=typeof e?.id=="string"?e.id.trim():"",s=e?.parent,n=typeof s=="string"?s.trim()!=="":s!=null,o=typeof e?.created=="string"&&e.created.trim()!=="",r=!i,A=!n,l=!o;if(!r&&!A&&!l)return;let{newId:d}=await Promise.resolve().then(()=>(xt(),Ri)),g,p=!1,h=!1;if(await this.app.fileManager.processFrontMatter(t,f=>{if(r&&(typeof f.id=="string"&&f.id.trim()||(g=d(),f.id=g)),A){let C=f.parent;(typeof C=="string"?C.trim()!=="":C!=null)||(f.parent=F,p=!0)}l&&(typeof f.created=="string"&&f.created.trim()||(f.created=new Date(t.stat.ctime).toISOString(),h=!0))}),!g&&!p&&!h)return;let I=this.newLog(),u=g||i;u&&await I.append({type:"parent_change",id:u,payload:{from:null,to:F,reason:"orphan_auto_fix",path:t.path,addedId:!!g,addedParent:p,addedCreated:h}}),new T.Notice(`Adopted ${t.basename} \u2192 Home`)}catch(e){console.warn("Stashpad: orphan auto-fix failed",e)}}maybeReHomeOnCrossFolderMove(t,e){if(t.extension!=="md")return;let i=t.parent?.path?.replace(/\/+$/,"")??"",s=e.lastIndexOf("/"),n=(s>=0?e.slice(0,s):"").replace(/\/+$/,"");i!==n&&this.discoverStashpadFolders().includes(i)&&(this.reHomePending.has(t.path)||(this.reHomePending.add(t.path),setTimeout(()=>{this.reHomePending.delete(t.path),this.reHomeDanglingParent(t,i)},900)))}async reHomeDanglingParent(t,e){try{let i=this.app.metadataCache.getFileCache(t)?.frontmatter,s=typeof i?.id=="string"?i.id.trim():"",n=typeof i?.parent=="string"?i.parent.trim():"";if(!s||!n||n===F||this.app.vault.getMarkdownFiles().some(r=>(r.parent?.path?.replace(/\/+$/,"")??"")===e&&this.app.metadataCache.getFileCache(r)?.frontmatter?.id===n))return;await this.app.fileManager.processFrontMatter(t,r=>{let A=typeof r.parent=="string"?r.parent.trim():"";A&&A!==F&&(r.parent=F)}),await this.newLog().append({type:"parent_change",id:s,payload:{from:n,to:F,reason:"rehome_cross_folder_move",path:t.path}}),new T.Notice(`Re-homed ${t.basename} \u2192 Home (its parent isn't in this folder)`)}catch(i){console.warn("[Stashpad] re-home on cross-folder move failed",i)}}async autoImportStash(t,e){try{let i=new Uint8Array(await this.app.vault.readBinary(t));if(Ht(i)){this.importService.parkEncrypted(t.path),this.notifyPendingEncrypted();return}let s=await Re(this.app,i);if(!s)return;let n=_t(),o=new Set;if(n&&typeof n.collectExistingIds=="function"&&n.noteFolder===e)for(let l of n.collectExistingIds())o.add(l);else for(let l of this.app.vault.getMarkdownFiles()){if(!l.path.startsWith(e+"/"))continue;let d=this.app.metadataCache.getFileCache(l)?.frontmatter?.id;typeof d=="string"&&o.add(d)}let r=await Kt(this.app,s,e,o);try{await this.newLog().append({type:"stash_import",id:F,payload:{from:t.path,into:e,noteCount:r.notesWritten,attachmentsWritten:r.attachmentsWritten,collisionsRenamed:r.collisionsRenamed,auto:!0}})}catch{}try{await this.app.fileManager.trashFile(t)}catch{}let A=[`Auto-imported ${r.notesWritten} note${r.notesWritten===1?"":"s"} from ${t.name}`];r.attachmentsWritten&&A.push(`+ ${r.attachmentsWritten} attachment${r.attachmentsWritten===1?"":"s"}`),r.collisionsRenamed&&A.push(`(${r.collisionsRenamed} renamed)`),this.notifications.show({message:A.join(" "),kind:"success",category:"import",folder:e}),n&&typeof n.debouncedRender=="function"&&n.debouncedRender()}catch(i){this.notifications.show({message:`Stashpad: auto-import failed +`,d=Qt(o.basename)||o.basename,p=await this.uniquePath(t,yt(d,r));await this.createNote(p,pe(A,l)),i.push(p)}}}recordNotePaths(a){return a.kind==="folder"?a.notePaths:[a.notePath]}announce(a,t=[]){let e=a[0]?.folder??"",i=a.length,s=t.length?`, replaced ${t.length}`:"",n=!1,o=async()=>{n||(n=!0,await this.undo(a,t))};this.plugin.notifications.show({message:`Imported ${i} file${i===1?"":"s"}${s} into \`${e.split("/").pop()}\`.`,kind:"success",category:"import",duration:0,folder:e,affectedPaths:a.flatMap(r=>this.recordNotePaths(r)),actions:[{label:"Undo import",onClick:()=>void o()}]}),e&&this.plugin.getUndoStack(e).push({label:`Import ${i} file${i===1?"":"s"}`,undo:async()=>{await o()},redo:async()=>{}})}async undo(a,t=[]){for(let e of a)try{if(e.kind==="md"){let i=this.app.vault.getAbstractFileByPath(e.notePath);i instanceof et.TFile&&await this.app.fileManager.trashFile(i);let s=this.app.vault.getAbstractFileByPath(e.archivePath);if(s instanceof et.TFile){let n=await this.uniquePath(e.folder,e.originalName);this.suppress(n),await this.app.fileManager.renameFile(s,n)}}else if(e.kind==="file"){let i=this.app.vault.getAbstractFileByPath(e.notePath);i instanceof et.TFile&&await this.app.fileManager.trashFile(i);let s=this.app.vault.getAbstractFileByPath(e.attachmentPath);if(s instanceof et.TFile){let n=await this.uniquePath(e.folder,e.originalName);this.suppress(n),await this.app.fileManager.renameFile(s,n)}}else{for(let s of e.notePaths){let n=this.app.vault.getAbstractFileByPath(s);n instanceof et.TFile&&await this.app.fileManager.trashFile(n)}for(let s of e.attachmentPaths){let n=this.app.vault.getAbstractFileByPath(s);n instanceof et.TFile&&await this.app.fileManager.trashFile(n)}let i=this.app.vault.getAbstractFileByPath(e.archivePath);if(i instanceof et.TFolder){let s=await this.uniquePath(e.folder,e.originalName);this.suppress(s),await this.app.fileManager.renameFile(i,s)}}}catch(i){console.warn("[Stashpad] import undo failed",e,i)}for(let e of t)try{await this.app.vault.adapter.exists(e.path)||await this.app.vault.create(e.path,e.content)}catch(i){console.warn("[Stashpad] import undo: couldn't restore replaced note",e.path,i)}new et.Notice(`Undid import of ${a.length} file(s).`)}pickFilesInto(a){let t=document.createElement("input");t.type="file",t.multiple=!0,t.setCssStyles({display:"none"}),t.onchange=async()=>{let e=Array.from(t.files??[]);if(t.remove(),e.length===0)return;let i=[];for(let n of e)try{let o=await n.arrayBuffer(),r=await this.uniquePath(a,n.name);this.suppress(r,6e4),await this.app.vault.createBinary(r,o);let A=this.app.vault.getAbstractFileByPath(r);A instanceof et.TFile&&i.push(A)}catch(o){console.warn("[Stashpad] file-picker write failed",n.name,o)}if(i.length===0)return;await this.plugin.importLog.load();let s=[];for(let n of i)try{let o=n.stat?.size??null,r=n.extension==="md"?await this.importMarkdown(n):await this.importOtherFile(n);r&&(s.push(r),this.plugin.importLog.append({ts:new Date().toISOString(),folder:r.folder,kind:r.kind,originalName:n.name,size:o,sourcePath:n.path,notePaths:r.kind==="folder"?r.notePaths:[r.notePath]}))}catch(o){console.warn("[Stashpad] file-picker import failed",n.path,o)}s.length>0&&this.announce(s,[])},document.body.appendChild(t),t.click()}async importLooseFilesIn(a){let t=a.replace(/\/+$/,""),e=this.app.vault.getFiles().filter(n=>(n.parent?.path?.replace(/\/+$/,"")??"")===t),i=[];for(let n of e)await this.isStillImportable(n)&&i.push(n);if(i.length===0)return 0;await this.plugin.importLog.load();let s=0;for(let n of i)try{let o=n.stat?.size??null,r=n.extension==="md"?await this.importMarkdown(n):await this.importOtherFile(n);r&&(s++,this.plugin.importLog.append({ts:new Date().toISOString(),folder:r.folder,kind:r.kind,originalName:n.name,size:o,sourcePath:n.path,notePaths:r.kind==="folder"?r.notePaths:[r.notePath]}))}catch(o){console.warn("[Stashpad] loose-file import failed",n.path,o)}return s}async importLooseFoldersIn(a){let t=a.replace(/\/+$/,""),e=this.app.vault.getAbstractFileByPath(t);if(!(e instanceof et.TFolder))return 0;let i=e.children.filter(n=>n instanceof et.TFolder&&!Ws.has(n.name));if(i.length===0)return 0;await this.plugin.importLog.load();let s=0;for(let n of i){let o=n.path;try{let r=await this.importFolder(n);r&&r.kind==="folder"&&(s++,this.plugin.importLog.append({ts:new Date().toISOString(),folder:r.folder,kind:r.kind,originalName:n.name,size:null,sourcePath:o,notePaths:r.notePaths}))}catch(r){console.warn("[Stashpad] loose-folder import failed",o,r)}}return s}pendingEncryptedPaths(){for(let a of[...this.pendingEncryptedStashes])this.app.vault.getAbstractFileByPath(a)instanceof et.TFile||this.pendingEncryptedStashes.delete(a);return[...this.pendingEncryptedStashes]}clearPendingEncrypted(a){this.pendingEncryptedStashes.delete(a)}shouldNotifyEncrypted(){return Date.now()>=this.encryptedNotifySnoozeUntil}snoozeEncryptedNotify(a){this.encryptedNotifySnoozeUntil=a===1/0?Number.MAX_SAFE_INTEGER:Date.now()+a}parkEncrypted(a){return this.pendingEncryptedStashes.has(a)?!1:(this.pendingEncryptedStashes.add(a),this.encryptedNotifySnoozeUntil=0,!0)}async importPendingEncrypted(){let a=0,t=!1;for(let e of this.pendingEncryptedPaths()){let i=this.app.vault.getAbstractFileByPath(e);if(!(i instanceof et.TFile))continue;let s=i.parent?.path?.replace(/\/+$/,"")??"";if(await this.importOneStash(i,s,this.liveRootIds(s),!1,{allowLater:!0,onLater:()=>{t=!0,this.snoozeEncryptedNotify(60*60*1e3)}})&&a++,t)break}return{imported:a,rescheduled:t}}liveRootIds(a){let t=new Set;for(let e of this.app.vault.getMarkdownFiles()){if((e.parent?.path?.replace(/\/+$/,"")??"")!==a)continue;let i=this.app.metadataCache.getFileCache(e)?.frontmatter?.id;typeof i=="string"&&i&&t.add(i)}return t}async importOneStash(a,t,e,i,s={}){try{let n=new Uint8Array(await this.app.vault.readBinary(a));if(i&&Ut(n))return this.pendingEncryptedStashes.add(a.path),!1;let o=await Oe(this.app,n,{...s,secretId:Ai(a.basename)});if(!o)return!1;let r=await Yt(this.app,o,t,e);if(r.colorAliases)for(let[A,l]of Object.entries(r.colorAliases))try{await this.plugin.setColorAlias(t,A,l)}catch{}try{await this.app.fileManager.trashFile(a)}catch{}this.pendingEncryptedStashes.delete(a.path);try{await this.plugin.newLog().append({type:"stash_import",id:F,payload:{from:a.path,into:t,noteCount:r.notesWritten,attachmentsWritten:r.attachmentsWritten,collisionsRenamed:r.collisionsRenamed,loose:!0}})}catch{}return!0}catch(n){return console.warn("[Stashpad] loose .stash import failed",a.path,n),!1}}async importLooseStashesIn(a,t={}){let e=a.replace(/\/+$/,""),i=this.app.vault.getFiles().filter(o=>(o.parent?.path?.replace(/\/+$/,"")??"")===e&&o.extension===ee);if(i.length===0)return 0;let s=this.liveRootIds(e),n=0;for(let o of i)await this.importOneStash(o,e,s,!!t.auto)&&n++;return n}async importLooseInto(a,t={}){let e=await this.importLooseFilesIn(a),i=await this.importLooseFoldersIn(a),s=await this.importLooseStashesIn(a,t);return{files:e,folders:i,stashes:s}}defaultDestination(){let t=this.plugin.lastActiveStashpadLeaf?.view?.noteFolder;return t&&this.plugin.discoverStashpadFolders().includes(t)?t:this.plugin.discoverStashpadFolders()[0]??null}confirm(a,t,e){return new Promise(i=>{new pt(this.app,a,t,e,i).open()})}dupChoice(a){return new Promise(t=>{new Ii(this.app,a,t).open()})}async ensureFolder(a){let t=this.app.vault.adapter,e=a.split("/").filter(Boolean),i="";for(let s of e){i=i?`${i}/${s}`:s;try{await t.exists(i)||await t.mkdir(i)}catch(n){if(!/already exists/i.test(n.message))throw n}}}async uniquePath(a,t){let e=this.app.vault.adapter,i=t.lastIndexOf("."),s=i>0?t.slice(0,i):t,n=i>0?t.slice(i):"",o=`${a}/${t}`,r=0;for(;await e.exists(o);)r+=1,o=`${a}/${s}-${r}${n}`;return o}};ei.DEBOUNCE_MS=900,ei.BATCH_CONFIRM_AT=8;var Xs=ei;var Zs=class{constructor(a,t){this.app=a;this.entries=[];this.loaded=!1;this.dirOk=!1;this.writeChain=Promise.resolve();this.path=`${t.replace(/\/+$/,"")}/import-log.jsonl`}getPath(){return this.path}async load(){if(!this.loaded){this.loaded=!0;try{let a=this.app.vault.adapter;if(await a.exists(this.path)){let t=await a.read(this.path);for(let e of t.split(/\r?\n/))if(e.trim())try{this.entries.push(JSON.parse(e))}catch{}}}catch(a){console.warn("[Stashpad] import log load failed",a)}}}recent(){return[...this.entries].reverse()}findDuplicate(a,t){for(let e=this.entries.length-1;e>=0;e--){let i=this.entries[e];if(i.originalName===a&&(t==null||i.size==null||i.size===t))return i}return null}append(a){this.entries.push(a),this.writeChain=this.writeChain.then(async()=>{try{await this.ensureDir(),await this.app.vault.adapter.append(this.path,JSON.stringify(a)+` +`)}catch(t){console.warn("[Stashpad] import log append failed",t)}})}async ensureDir(){if(this.dirOk)return;let a=this.app.vault.adapter,e=this.path.slice(0,this.path.lastIndexOf("/")).split("/").filter(Boolean),i="";for(let s of e)i=i?`${i}/${s}`:s,await a.exists(i)||await a.mkdir(i);this.dirOk=!0}};var _s=class _s{constructor(a,t){this.app=a;this.map=new Map;this.loaded=!1;this.dirty=!1;this.saveTimer=null;this.dirOk=!1;this.writeChain=Promise.resolve();this.path=`${t.replace(/\/+$/,"")}/render-cache.json`}async load(){if(!this.loaded){this.loaded=!0;try{let a=this.app.vault.adapter;if(await a.exists(this.path)){let t=JSON.parse(await a.read(this.path));if(t?.schema===1&&t.entries){for(let[e,i]of Object.entries(t.entries))this.map.set(e,i);for(let e of[...this.map.keys()])this.app.vault.getAbstractFileByPath(e)||(this.map.delete(e),this.dirty=!0)}}}catch(a){console.warn("[Stashpad] render cache load failed; starting empty",a),this.map.clear()}}}evict(a){this.map.delete(a)&&(this.dirty=!0,this.save())}get(a){return this.map.get(a)}has(a){return this.map.has(a)}set(a,t){this.map.set(a,t),this.dirty=!0,this.scheduleSave()}scheduleSave(){this.saveTimer==null&&(this.saveTimer=window.setTimeout(()=>{this.saveTimer=null,this.save()},_s.SAVE_DEBOUNCE_MS))}save(){return this.saveTimer!=null&&(window.clearTimeout(this.saveTimer),this.saveTimer=null),this.dirty?(this.dirty=!1,this.writeChain=this.writeChain.then(async()=>{try{await this.ensureDir();let a={schema:1,entries:Object.fromEntries(this.map)};await this.app.vault.adapter.write(this.path,JSON.stringify(a))}catch(a){console.warn("[Stashpad] render cache save failed",a)}}),this.writeChain):this.writeChain}async ensureDir(){if(this.dirOk)return;let a=this.app.vault.adapter,e=this.path.slice(0,this.path.lastIndexOf("/")).split("/").filter(Boolean),i="";for(let s of e)i=i?`${i}/${s}`:s,await a.exists(i)||await a.mkdir(i);this.dirOk=!0}};_s.SAVE_DEBOUNCE_MS=8e3;var js=_s;var fo="stashpad:unghost-after-reload",tn=class extends T.Plugin{constructor(){super(...arguments);this.settings={...fe};this.undoStacks=new Map;this.lastActiveStashpadLeaf=null;this.rebootstrapInProgress=!1;this.suppressComposerAutofocusUntil=0;this.settingTab=null;this.stashpadSelectionListeners=new Set;this.stashpadContentListeners=new Set;this._notifications=null;this._authorRegistry=null;this._importService=null;this._importLog=null;this.noteClipboard=null;this.noteClipboardNotice=null;this._renderCacheStore=null;this.knownStashpadFolders=new Set;this.suppressedFolderDeletes=new Set;this.sweptFolders=new Set;this.notifiedBuildVersion=null;this.authorRenameInFlight=new Set;this.reHomePending=new Set;this.okfRebuildTimers=new Map;this.okfRebuildingFolders=new Set;this.archivePending=new Map;this.autoSweepInProgress=!1;this.notifPersistenceWired=!1;this.notifSaveTimer=null;this.LAST_CURSOR_LS_KEY="stashpad:last-cursor";this.LAST_SELECTION_LS_KEY="stashpad:last-selection";this.ACTIVE_VERSIONS_LS_KEY="stashpad:active-versions";this.writeChain=Promise.resolve()}get notifications(){return this._notifications||(this._notifications=new ts(this.app)),this._notifications}get authorRegistry(){return this._authorRegistry||(this._authorRegistry=new $s(this.app,this.pluginPrivatePath())),this._authorRegistry}get importService(){return this._importService||(this._importService=new Xs(this)),this._importService}get importLog(){return this._importLog||(this._importLog=new Zs(this.app,this.pluginPrivatePath())),this._importLog}clearNoteClipboard(){try{this.noteClipboardNotice?.hide()}catch{}this.noteClipboardNotice=null,this.noteClipboard=null}get renderCacheStore(){return this._renderCacheStore||(this._renderCacheStore=new js(this.app,this.pluginPrivatePath())),this._renderCacheStore}async onunload(){try{this.encryption?.dispose()}catch{}try{for(let t of this.archivePending.values())window.clearTimeout(t.timer);this.archivePending.clear()}catch{}try{await this._renderCacheStore?.save()}catch{}}pluginPrivatePath(t=""){let i=`${this.manifest.dir.replace(/\/+$/,"")}/.stashpad`;return t?`${i}/${t.replace(/^\/+/,"")}`:i}newLog(){return new zs(this.app,this.pluginPrivatePath(),()=>(this.settings?.authorName??"").trim())}async migrateLegacyPaths(){let t=this.app.vault.adapter,e=this.pluginPrivatePath(),i=async()=>{let r=e.split("/").filter(Boolean),A="";for(let l of r)A=A?`${A}/${l}`:l,await t.exists(A)||await t.mkdir(A)},s=`${this.manifest.dir.replace(/\/+$/,"")}/data.json`,n=this.pluginPrivatePath("data.json");if(await t.exists(s)&&!await t.exists(n))try{await i();let r=await t.read(s);await t.write(n,r),console.debug("[Stashpad] migrated data.json \u2192",n)}catch(r){console.warn("Stashpad: data.json migration failed",r)}let o=".stashpad";if(await t.exists(o))try{await i();let r=await t.list(o);for(let A of r.files){let l=A.replace(/^.*\//,""),d=this.pluginPrivatePath(l);if(!await t.exists(d))try{let p=await t.read(A);await t.write(d,p),console.debug("[Stashpad] migrated",A,"\u2192",d)}catch(p){console.warn(`Stashpad: failed to migrate ${A}`,p)}}}catch(r){console.warn("Stashpad: .stashpad migration scan failed",r)}}async loadData(){let t=this.app.vault.adapter,e=this.pluginPrivatePath("data.json");if(!await t.exists(e))return null;try{return JSON.parse(await t.read(e))}catch(i){return console.warn("Stashpad: data.json parse failed",i),null}}async saveData(t){let e=this.app.vault.adapter,i=this.pluginPrivatePath();if(!await e.exists(i)){let s=i.split("/").filter(Boolean),n="";for(let o of s)n=n?`${n}/${o}`:o,await e.exists(n)||await e.mkdir(n)}await e.write(this.pluginPrivatePath("data.json"),JSON.stringify(t,null,2))}async createNewStashpad(t){let e=t.trim().replace(/^\/+|\/+$/g,"");if(!e)throw new Error("Folder name is empty");let i=this.app.vault.adapter,s=e.split("/").filter(Boolean),n="";for(let l of s)n=n?`${n}/${l}`:l,await i.exists(n)||await i.mkdir(n);let o=`${e}/Home.md`;if(await i.exists(o)){let l=this.app.vault.getAbstractFileByPath(o);l&&await this.app.fileManager.processFrontMatter(l,d=>{(typeof d.id!="string"||!d.id)&&(d.id=F),"parent"in d||(d.parent=null),(typeof d.created!="string"||!d.created)&&(d.created=new Date().toISOString())});return}let r=new Date().toISOString(),A=["---",`id: ${F}`,"parent: null",`created: ${r}`,"---","Home"].join(` +`);await this.app.vault.create(o,A);try{await this.seedLocalAuthorStub(e)}catch{}try{await this.seedKnownAuthorsInFolder(e)}catch{}}collectColorsInFolder(t){let e=new Map,i=t.replace(/\/+$/,"");for(let n of this.app.vault.getMarkdownFiles()){let o=n.parent?.path?.replace(/\/+$/,"")??"";if(o!==i&&!o.startsWith(i+"/"))continue;let r=this.app.metadataCache.getFileCache(n)?.frontmatter,A=typeof r?.color=="string"?r.color.trim():"";if(!A||!/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(A))continue;let l=A.toLowerCase();e.set(l,(e.get(l)??0)+1)}let s=[...e.entries()].map(([n,o])=>({hex:n,count:o}));return s.sort((n,o)=>o.count-n.count||n.hex.localeCompare(o.hex)),s}async recolorAllInFolder(t,e,i){let s=t.replace(/\/+$/,""),n=e.toLowerCase(),o=0;for(let A of this.app.vault.getMarkdownFiles()){let l=A.parent?.path?.replace(/\/+$/,"")??"";if(l!==s&&!l.startsWith(s+"/"))continue;let d=this.app.metadataCache.getFileCache(A)?.frontmatter;if((typeof d?.color=="string"?d.color.trim().toLowerCase():"")===n)try{await this.app.fileManager.processFrontMatter(A,g=>{i?g.color=i:delete g.color}),o++}catch(g){console.warn(`Stashpad: recolor failed for ${A.path}`,g)}}let r=this.settings.colorAliases?.[s];if(r){let A=r[n];A&&(delete r[n],i&&(r[i.toLowerCase()]=A),Object.keys(r).length===0&&delete this.settings.colorAliases[s],await this.saveSettings())}return o}getColorAlias(t,e){let i=t.replace(/\/+$/,""),s=this.settings.colorAliases?.[i];if(!s)return;let n=s[e.toLowerCase()];return n&&n.trim()?n:void 0}async setColorAlias(t,e,i){let s=t.replace(/\/+$/,""),n=e.toLowerCase();this.settings.colorAliases||(this.settings.colorAliases={}),this.settings.colorAliases[s]||(this.settings.colorAliases[s]={});let o=this.settings.colorAliases[s],r=i.trim();r?o[n]=r:delete o[n],Object.keys(o).length===0&&delete this.settings.colorAliases[s],await this.saveSettings()}async waitForStashpadFolder(t,e=2e3){let i=t.trim().replace(/^\/+|\/+$/g,"");if(!i)return;let s=Date.now();for(;Date.now()-s<e;){if(this.discoverStashpadFolders().includes(i))return;await new Promise(n=>setTimeout(n,80))}}discoverStashpadFolders(){let t=new Set;for(let i of this.app.vault.getMarkdownFiles()){let s=this.app.metadataCache.getFileCache(i)?.frontmatter;if(typeof s?.id!="string"||!s.id.trim()||!s||!("parent"in s))continue;let n=i.parent?.path?.replace(/\/+$/,"")??"";n&&t.add(n)}let e=[...t].sort();return this.knownStashpadFolders=new Set(e),e}closeStashpadTabsFor(t){let e=0;for(let i of this.app.workspace.getLeavesOfType(J)){let s=i.view?.noteFolder??"";s||(s=((i.getViewState?.()?.state??{}).folderOverride??"")||this.settings.folder||"Stashpad"),s=(s||"").replace(/\/+$/,""),(s===t||s.startsWith(t+"/"))&&(i.detach(),e++)}return e}async prunePlacementFor(t){let e=this.settings,i=o=>(o??[]).filter(r=>r!==t&&!r.startsWith(t+"/")),s=(e.folderPanelPinned?.length??0)+(e.folderPanelDownranked?.length??0)+(e.folderPanelHidden?.length??0);e.folderPanelPinned=i(e.folderPanelPinned),e.folderPanelDownranked=i(e.folderPanelDownranked),e.folderPanelHidden=i(e.folderPanelHidden),e.folderPanelPinned.length+e.folderPanelDownranked.length+e.folderPanelHidden.length!==s&&await this.saveSettings()}async deleteStashpadFolderWithUndo(t){let e=t.path.replace(/\/+$/,""),i=t.name,s=this.app.vault.adapter,n=".trash";try{await s.exists(n)||await s.mkdir(n)}catch(l){console.warn("[Stashpad] couldn't ensure .trash",l)}let o=`${n}/${i}`;for(let l=1;await s.exists(o);l++)o=`${n}/${i} (${l})`;this.suppressedFolderDeletes.add(e),window.setTimeout(()=>this.suppressedFolderDeletes.delete(e),5e3);let r=this.closeStashpadTabsFor(e);await this.prunePlacementFor(e),this.knownStashpadFolders.delete(e);try{await s.rename(e,o)}catch(l){console.warn("[Stashpad] folder delete failed",l),this.suppressedFolderDeletes.delete(e),new T.Notice("Delete failed (see console).");return}let A=r>0?`Deleted \u201C${i}\u201D \u2014 closed ${r} open tab${r===1?"":"s"}.`:`Deleted \u201C${i}\u201D.`;this.notifications.show({message:A,kind:"warning",category:"delete",duration:0,folder:e,actions:[{label:"Undo",onClick:async()=>{try{if(await s.exists(e)){new T.Notice(`Can't undo \u2014 \u201C${i}\u201D already exists.`);return}this.suppressedFolderDeletes.add(e),window.setTimeout(()=>this.suppressedFolderDeletes.delete(e),5e3),await s.rename(o,e),new T.Notice(`Restored \u201C${i}\u201D.`),this.activateViewForFolder(e)}catch(l){console.warn("[Stashpad] folder undo failed",l),new T.Notice("Undo failed (see console).")}}}]})}async handleStashpadFolderDeleted(t){let e=t.replace(/\/+$/,"");if(!e||this.suppressedFolderDeletes.has(e))return;let i=this.closeStashpadTabsFor(e);await this.prunePlacementFor(e),this.knownStashpadFolders.delete(e);let s=e.split("/").pop()||e;this.notifications.show({message:i>0?`Stashpad \u201C${s}\u201D was deleted \u2014 closed ${i} open tab${i===1?"":"s"}.`:`Stashpad \u201C${s}\u201D was deleted.`,kind:"warning",category:"delete",folder:e})}searchableFolders(t){let e=new Set(this.settings.searchIncludedFolders),i=new Set(this.settings.searchExcludedFolders),s=new Set((this.settings.archiveFolders??[]).map(l=>(l??"").replace(/\/+$/,""))),o=this.discoverStashpadFolders().filter(l=>s.has(l)?!1:e.size>0?e.has(l):!i.has(l)),r=(t||"").trim().replace(/\/+$/,""),A=o.filter(l=>l!==r);return r&&A.unshift(r),A}async maybeSweepFolder(t){let e=(t||"").trim().replace(/\/+$/,"");!e||this.sweptFolders.has(e)||(this.sweptFolders.add(e),setTimeout(()=>{this.runSweep(e,{silent:!0})},3e3))}async runIntegrityCheckOnFolder(t){let e=(t||"").trim().replace(/\/+$/,"");e&&await this.runSweep(e,{silent:!1})}async runSweep(t,e){try{let i=this.newLog(),s={},n=this.app.vault.getMarkdownFiles().filter(l=>l.path===t||l.path.startsWith(t+"/"));for(let l of n){let d=this.app.metadataCache.getFileCache(l)?.frontmatter,p=typeof d?.id=="string"?d.id.trim():"";if(!p)continue;let g=d&&"parent"in d?d.parent??null:null;s[p]={parent:g,path:l.path}}let o=await i.readState(),r=l=>l===t||l.startsWith(t+"/");if(!e.silent){for(let[l,d]of Object.entries(s)){let p=o[l];p?p.parent!==d.parent?await i.append({type:"parent_change",id:l,payload:{from:p.parent,to:d.parent}}):p.path!==d.path&&await i.append({type:"rename",id:l,payload:{from:p.path,to:d.path}}):await i.append({type:"create",id:l,payload:{path:d.path,parent:d.parent}})}for(let[l,d]of Object.entries(o))!s[l]&&r(d.path)&&await i.append({type:"missing",id:l,payload:{lastPath:d.path}})}let A={};for(let[l,d]of Object.entries(o))r(d.path)||(A[l]=d);for(let[l,d]of Object.entries(s))A[l]=d;await i.writeState(A)}catch(i){console.warn("Stashpad: integrity sweep failed",i)}}getUndoStack(t){let e=this.undoStacks.get(t);return e||(e=new Vs,this.undoStacks.set(t,e)),e}async onload(){await this.migrateLegacyPaths(),await this.loadSettings(),wt.enabled=!!this.settings.enablePerfProfiling,this.encryption=new cs(this.app,()=>({...ki(),...this.settings.encryption??{}}),async h=>{this.settings.encryption=h,await this.saveSettings()},()=>this.settings.encryptionIdleLockMinutes??0),this.encryption.init().then(()=>this.encryption.tryAutoUnlock()),this.settingTab=new Es(this.app,this),this.addSettingTab(this.settingTab),await this.renderCacheStore.load(),this.registerEvent(this.app.vault.on("delete",h=>this.renderCacheStore.evict(h.path))),this.registerEvent(this.app.vault.on("rename",(h,I)=>this.renderCacheStore.evict(I))),this.registerEvent(this.app.vault.on("create",h=>this.onOkfFileEvent(h.path))),this.registerEvent(this.app.vault.on("delete",h=>this.onOkfFileEvent(h.path))),this.registerEvent(this.app.vault.on("rename",(h,I)=>{this.onOkfFileEvent(h.path),this.onOkfFileEvent(I)})),await this.authorRegistry.load();{let h=(this.settings.authorId??"").trim();h&&this.authorRegistry.record({id:h,name:this.settings.authorName,role:this.settings.authorRole,department:this.settings.authorDepartment})}this.app.workspace.onLayoutReady(()=>{this.reconcileLockedRegistry(),window.setTimeout(()=>void this.checkDueReminders(),6e3),this.registerInterval(window.setInterval(()=>void this.checkDueReminders(),5*60*1e3)),window.setTimeout(()=>{this.seedLocalAuthorStubsEverywhere()},4e3),window.setTimeout(()=>this.syncObsidianExcludedArchives(),4500),window.setTimeout(()=>this.importService.setArmed(!0),2500),window.setTimeout(()=>void this.runAutoImportSweep(),5e3),this.registerInterval(window.setInterval(()=>void this.runAutoImportSweep(),5*60*1e3)),window.setTimeout(()=>void this.migratePinnedNotesToFrontmatter(),3e3),window.setTimeout(()=>void this.unghostStashpadTabsIfFlagged(),1200)}),this.registerView(J,h=>new Ls(h,this)),this.registerView(ye,h=>new vs(h,this)),this.registerView(oe,h=>new $i(h,this)),this.registerView(Me,h=>new Js(h,this)),this.registerView(Qe,h=>new Ks(h,this)),this.registerEvent(this.app.workspace.on("active-leaf-change",h=>{h&&h.view.getViewType()===J&&(this.lastActiveStashpadLeaf=h,this.settings.autoOpenDetailPanel&&this.app.workspace.getLeavesOfType(ye).length===0&&setTimeout(()=>{Fs(this.app)},0),this.notifyStashpadSelectionChanged())}));let t=()=>{let h=ie(),I=!!h&&this.app.workspace.activeLeaf&&this.app.workspace.activeLeaf.view===h,u=!!I&&this.settings.hideMobileToolbarInStashpad;document.body.classList.toggle("stashpad-hide-mobile-toolbar",u),document.body.classList.toggle("stashpad-active",!!I)};this.register(Ra(t)),this.registerEvent(this.app.workspace.on("active-leaf-change",t));let e=h=>{try{let I=Array.from(document.querySelectorAll("style")).filter(u=>(u.textContent??"").includes(".stashpad-"));for(let u of I){let f=u.id||"",C=f?`style[data-stashpad-source="${f}"]`:null;if(C&&h.head.querySelector(C))continue;let B=h.createElement("style");f?B.setAttribute("data-stashpad-source",f):B.setAttribute("data-stashpad-source","anon"),B.textContent=u.textContent??"",h.head.appendChild(B)}}catch(I){console.warn("[Stashpad] inject popout styles failed",I)}};this.registerEvent(this.app.workspace.on("window-open",h=>{let I=h?.doc??h?.win?.document??null;I&&e(I)})),this.registerEvent(this.app.workspace.on("file-menu",(h,I)=>{if(!(I instanceof T.TFolder))return;let u=I.path.replace(/\/+$/,"");this.discoverStashpadFolders().includes(u)&&h.addItem(f=>{f.setTitle("Open folder in Stashpad").setIcon("layout-list").onClick(()=>void this.openFolderInStashpad(u))})})),setTimeout(()=>{try{let h=this.app.workspace;typeof h.iterateAllLeaves=="function"&&h.iterateAllLeaves(I=>{let u=I?.view?.containerEl?.ownerDocument;u&&u!==document&&e(u)})}catch{}},200),t(),this.register(()=>document.body.classList.remove("stashpad-hide-mobile-toolbar","stashpad-active"));let i=window.visualViewport,s=()=>{let h=document.querySelector(".mobile-toolbar, .mobile-toolbar-container"),I=h&&h.isConnected?h.offsetHeight:0;document.body.style.setProperty("--stashpad-toolbar-h",`${I}px`);let u=0;i&&(u=Math.max(0,window.innerHeight-i.height-i.offsetTop)),document.body.style.setProperty("--stashpad-vv-bottom-gap",`${u}px`),document.body.classList.toggle("stashpad-keyboard-open",u>100)};s(),i&&(i.addEventListener("resize",s),i.addEventListener("scroll",s),this.register(()=>{i.removeEventListener("resize",s),i.removeEventListener("scroll",s)})),window.addEventListener("resize",s),this.register(()=>window.removeEventListener("resize",s)),requestAnimationFrame(s),setTimeout(s,250),setTimeout(s,1e3),this.addRibbonIcon("list-tree","Open Stashpad",()=>{if(this.discoverStashpadFolders().length===0){this.activateView({reveal:!0});return}this.openFolderPicker()}).addEventListener("contextmenu",h=>{h.preventDefault(),this.openFolderPicker()}),this.addRibbonIcon("panel-left","Open Stashpad panels (sidebar)",()=>{Wi(this.app)}),this.addRibbonIcon("folders","Open Stashpad folder panel (sidebar)",()=>{Os(this.app)}),this.addRibbonIcon("panel-right","Open Stashpad detail panel (right sidebar)",()=>{Fs(this.app)}),this.addCommand({id:"stashpad-open",name:"Open Stashpad in new tab",callback:()=>{if(this.discoverStashpadFolders().length>=2){this.openFolderPicker();return}this.activateView({reveal:!1})}}),this.addCommand({id:"stashpad-reveal",name:"Reveal or open Stashpad",callback:()=>void this.activateView({reveal:!0})}),this.addCommand({id:"stashpad-focus-last-tab",name:"Focus last Stashpad tab",callback:()=>void this.focusLastStashpadTab()}),this.addCommand({id:"stashpad-focus-folder-panel",name:"Focus folder panel",callback:()=>void this.focusFolderPanel()}),this.addCommand({id:"stashpad-lock-encryption",name:"Lock encryption (forget password)",callback:()=>{if(!this.encryption.isConfigured()){new T.Notice("Encryption isn't set up.");return}this.encryption.lock(),new T.Notice("Encryption locked.")}});let o=h=>{let I=ie();I&&typeof I[h]=="function"&&I[h]()};this.addCommand({id:"stashpad-toggle-split",name:"Toggle split-on-newlines",callback:()=>o("toggleSplit")}),this.addCommand({id:"stashpad-fork-version",name:"Fork as version (alternate draft / sheet)",callback:()=>o("cmdForkVersion")}),this.addCommand({id:"stashpad-mark-version-final",name:"Mark version as final (sheet)",callback:()=>o("cmdMarkVersionFinal")}),this.addCommand({id:"stashpad-command-palette",name:"Command palette (Stashpad only)",callback:()=>o("openStashpadCommandPalette")}),this.addCommand({id:"stashpad-lock-selection",name:"Encrypt (lock) selection (notes + children)",callback:()=>o("cmdLockSelection")}),this.addCommand({id:"stashpad-unlock-all",name:"Decrypt (unlock) locked notes in view",callback:()=>o("cmdUnlockAll")}),this.addCommand({id:"stashpad-unlock-all-vault",name:"Decrypt (unlock) ALL locked notes in the vault",callback:()=>void this.unlockAllInVault()}),this.addCommand({id:"stashpad-copy-notes",name:"Copy notes (note clipboard \u2014 paste to duplicate)",callback:()=>o("cmdCopyNotes")}),this.addCommand({id:"stashpad-cut-notes",name:"Cut notes (paste in list to move, in composer to extract text)",callback:()=>o("cmdCutNotes")}),this.addCommand({id:"stashpad-paste-notes",name:"Paste notes (from the note clipboard)",callback:()=>o("cmdPasteNotes")}),this.addCommand({id:"stashpad-move-to-archive",name:"Move selection to archive (encrypt)",callback:()=>o("cmdMoveToArchive")}),this.addCommand({id:"stashpad-encrypt-delete",name:"Encrypt & delete selection (to encrypted trash)",callback:()=>o("cmdEncryptDelete")}),this.addCommand({id:"stashpad-restore-trash",name:"Open encrypted trash (restore deleted)\u2026",callback:()=>this.openEncryptedTrash()}),this.addCommand({id:"stashpad-encrypt-existing-trash",name:"Encrypt existing Obsidian trash (backfill .trash into encrypted trash)",callback:()=>void this.encryptExistingTrash()}),this.addCommand({id:"stashpad-close-duplicate-tabs",name:"Close duplicate & orphaned Stashpad tabs (tidy up)",callback:()=>void this.closeDuplicateStashpadTabs()}),this.addCommand({id:"stashpad-claim-selected-author",name:"Claim authorship of selected notes",callback:()=>o("claimSelectedAsAuthor")}),this.addCommand({id:"stashpad-claim-folder-author",name:"Claim authorship of all unauthored notes in this folder",callback:()=>o("claimFolderAsAuthor")}),this.addCommand({id:"stashpad-claim-selected-contributor",name:"Claim selected notes (author if unowned, else add me as contributor)",callback:()=>o("claimSelectedWithContributor")}),this.addCommand({id:"stashpad-claim-folder-contributor",name:"Claim all notes in this folder (author if unowned, else add me as contributor)",callback:()=>o("claimFolderWithContributor")}),this.addCommand({id:"stashpad-pick-destination",name:"Pick destination for next note",callback:()=>o("openDestinationPicker")}),this.addCommand({id:"stashpad-search",name:"Search Stashpad notes",callback:()=>o("openSearchModal")}),this.addCommand({id:"stashpad-search-in-parent",name:"Search in current parent",callback:()=>o("openSearchInParentModal")}),this.addCommand({id:"stashpad-move-picker",name:"Move selection (picker)",callback:()=>o("cmdMovePicker")}),this.addCommand({id:"stashpad-merge",name:"Merge selection",callback:()=>o("cmdMerge")}),this.addCommand({id:"stashpad-copy",name:"Copy selection",callback:()=>o("cmdCopy")}),this.addCommand({id:"stashpad-copy-tree",name:"Copy focused subtree",callback:()=>o("cmdCopyTree")}),this.addCommand({id:"stashpad-copy-outline",name:"Copy as outline (nested embeds)",callback:()=>o("cmdCopyOutline")}),this.addCommand({id:"stashpad-split",name:"Split note\u2026",callback:()=>o("cmdSplit")}),this.addCommand({id:"stashpad-edit-note",name:"Edit note in new tab (selection)",callback:()=>o("cmdOpenInEditor")}),this.addCommand({id:"stashpad-edit-parent",name:"Edit parent note in new tab",callback:()=>o("cmdOpenParentInEditor")}),this.addCommand({id:"stashpad-delete",name:"Delete selection",callback:()=>o("cmdDelete")}),this.addCommand({id:"stashpad-move-up",name:"Move note up",callback:()=>o("cmdMoveUp")}),this.addCommand({id:"stashpad-move-down",name:"Move note down",callback:()=>o("cmdMoveDown")}),this.addCommand({id:"stashpad-move-to-top",name:"Move note to top",callback:()=>o("cmdMoveToTop")}),this.addCommand({id:"stashpad-move-to-bottom",name:"Move note to bottom",callback:()=>o("cmdMoveToBottom")}),this.addCommand({id:"stashpad-outdent",name:"Outdent (move to grandparent)",callback:()=>o("cmdOutdent")}),this.addCommand({id:"stashpad-set-color",name:"Set note color\u2026",callback:()=>o("cmdSetColor")}),this.addCommand({id:"stashpad-clone",name:"Clone selection (duplicate / copy notes)",callback:()=>o("cmdClone")}),this.addCommand({id:"stashpad-fork-note",name:"Fork note (copy as a variant under a chosen parent)",callback:()=>o("cmdForkNote")}),this.addCommand({id:"stashpad-insert-template",name:"Insert template (clone an existing note)",callback:()=>o("cmdInsertTemplate")}),this.addCommand({id:"stashpad-toggle-expand",name:"Show more / show less (expand toggle)",callback:()=>o("cmdToggleExpand")}),this.addCommand({id:"stashpad-expand-all",name:"Expand all (show every note's full body)",callback:()=>o("cmdExpandAll")}),this.addCommand({id:"stashpad-collapse-all",name:"Collapse all (clamp every note's body)",callback:()=>o("cmdCollapseAll")}),this.addCommand({id:"stashpad-pick-move",name:"Move (in-list, arrow + Enter)",callback:()=>o("cmdInListPicker")}),this.addCommand({id:"stashpad-open-in-new-tab",name:"Open in new Stashpad tab",callback:()=>o("cmdOpenInNewStashpadTab")}),this.addCommand({id:"stashpad-toggle-complete",name:"Toggle complete (strikethrough)",callback:()=>o("cmdToggleComplete")}),this.addCommand({id:"stashpad-toggle-task",name:"Toggle task (todo)",callback:()=>o("cmdToggleTask")}),this.addCommand({id:"stashpad-set-due",name:"Set due date\u2026",callback:()=>o("cmdSetDue")}),this.addCommand({id:"stashpad-dump-perf",name:"Dump performance profile (copy to clipboard)",callback:async()=>{if(!this.settings.enablePerfProfiling){new T.Notice("Enable \u201CPerformance profiling\u201D in Stashpad settings first, then use the app and run this again.");return}let h=wt.report();console.log(h);try{await navigator.clipboard.writeText(h)}catch{}new T.Notice("Performance profile copied to clipboard (also in the console).")}}),this.addCommand({id:"stashpad-reset-perf",name:"Reset performance profile",callback:()=>{wt.reset(),new T.Notice("Performance profile reset.")}}),this.addCommand({id:"stashpad-jump-to-top",name:"Jump to top of list",callback:()=>o("jumpToTop")}),this.addCommand({id:"stashpad-jump-to-bottom",name:"Jump to bottom of list",callback:()=>o("jumpToBottom")}),this.addCommand({id:"stashpad-assign",name:"Assign task to\u2026",callback:()=>o("cmdAssign")}),this.addCommand({id:"stashpad-open-import-log",name:"Open import log",callback:async()=>{await this.importLog.load();let{ImportLogModal:h}=await Promise.resolve().then(()=>(Ft(),fi));new h(this.app,this.importLog.recent()).open()}}),this.addCommand({id:"stashpad-import-files",name:"Import file(s) into Stashpad\u2026",callback:()=>this.openImportPicker()}),this.addCommand({id:"stashpad-import-loose-files",name:"Import loose files & folders in this folder (scan for moved-in / unprocessed items)",checkCallback:h=>{let I=this.importService.defaultDestination();return h?!!I:(I&&this.runImportLooseFiles(I),!0)}}),this.addCommand({id:"stashpad-rerun-slug-pass",name:"Re-run filename (slug) pass on this folder",checkCallback:h=>{let I=this.importService.defaultDestination();return h?!!I:(I&&this.runFolderSlugPass(I),!0)}}),this.addCommand({id:"stashpad-rerun-frontmatter-backfill",name:"Re-run frontmatter backfill (recovery links) on this folder",checkCallback:h=>{let I=this.importService.defaultDestination();return h?!!I:(I&&this.runFolderFrontmatterBackfill(I),!0)}}),this.addCommand({id:"stashpad-select-all",name:"Select all visible notes",callback:()=>o("cmdSelectAll")}),this.addCommand({id:"stashpad-copy-codeblock",name:"Copy code from codeblock",callback:()=>o("cmdCopyCodeBlock")}),this.addCommand({id:"stashpad-open-panels",name:"Open Stashpad panels (sidebar)",callback:()=>void Wi(this.app)}),this.addCommand({id:"stashpad-open-folder-panel",name:"Open folder panel (sidebar)",callback:()=>void Os(this.app)}),this.addCommand({id:"stashpad-open-detail",name:"Open Stashpad detail panel (right sidebar)",callback:()=>void Fs(this.app)}),this.addCommand({id:"stashpad-reveal-active-note",name:"Open this note in Stashpad",checkCallback:h=>{let I=this.app.workspace.getActiveFile(),u=!!I&&I.extension==="md"&&this.isStashpadNoteFile(I);return h||u&&I&&this.revealNoteInStashpad(I),u}});let r=Object.keys(Ci);for(let h of r){let I=Ci[h];this.addCommand({id:`stashpad-open-panels-${h}`,name:`Open Stashpad panel: ${I.label}`,callback:async()=>{await Wi(this.app),this.app.workspace.getLeavesOfType(oe)[0]?.view?.setActivePanel?.(h)}})}this.addCommand({id:"stashpad-swap-with-parent",name:"Swap with parent (ouroboros)",callback:()=>o("cmdSwapWithParent")}),this.addCommand({id:"stashpad-toggle-pin",name:"Pin / unpin selected note (sidebar)",callback:()=>o("cmdTogglePin")}),this.addCommand({id:"stashpad-list-pin",name:"Pin / unpin to top of list",callback:()=>o("cmdToggleListPin")}),this.addCommand({id:"stashpad-open-tiny",name:"Open Stashpad in tiny window",callback:()=>void this.openTinyWindow()}),this.addCommand({id:"stashpad-clone-tab",name:"Clone (duplicate / copy) this Stashpad tab",callback:()=>o("cmdCloneStashpadTab")}),this.addCommand({id:"stashpad-undo",name:"Undo last Stashpad action",callback:()=>o("cmdUndo")}),this.addCommand({id:"stashpad-redo",name:"Redo last undone Stashpad action",callback:()=>o("cmdRedo")}),this.addCommand({id:"stashpad-export-stash",name:"Export selection to .stash",callback:()=>o("cmdExportStash")}),this.addCommand({id:"stashpad-export-okf",name:"Export selection as OKF bundle (.zip / .tar.gz / .stash)",callback:()=>o("cmdExportOkf")}),this.addCommand({id:"stashpad-import-stash",name:"Import .stash file\u2026",callback:()=>o("cmdImportStash")}),this.addCommand({id:"stashpad-pick-folder",name:"Stashpad: open / switch / create folder\u2026",callback:()=>this.openFolderPicker()}),this.addCommand({id:"stashpad-run-integrity-check",name:"Run integrity check on active Stashpad folder",checkCallback:h=>{let I=ie(),u=I&&I.noteFolder;return u?(h||(new T.Notice(`Running integrity check on "${u}"\u2026`),this.runIntegrityCheckOnFolder(u).then(()=>{new T.Notice("Integrity check complete \u2014 see Stashpad log.")})),!0):!1}}),this.addCommand({id:"stashpad-fix-orphans",name:"Set missing parents to Home (orphan fix)",callback:()=>void this.fixOrphanParents()}),this.addCommand({id:"stashpad-rebuild-author-registry",name:"Rebuild author registry (scan authors + note frontmatter)",callback:async()=>{new T.Notice("Stashpad: rebuilding author registry\u2026");try{let h=await this.rebuildAuthorRegistry();this.notifications.show({message:`Author registry rebuilt: ${h.total} author(s) \u2014 ${h.fromStubs} from stubs, ${h.fromNotes} from note links.`,kind:"success",category:"system"})}catch(h){new T.Notice(`Author registry rebuild failed: ${h.message}`)}}}),this.addCommand({id:"stashpad-restore-author-stubs",name:"Restore missing author stubs (from registry)",callback:async()=>{new T.Notice("Stashpad: restoring author stubs\u2026");try{let h=await this.restoreMissingAuthorStubs();this.notifications.show({message:h.created>0?`Restored ${h.created} author stub(s) across ${h.folders} folder(s).`:`No missing author stubs \u2014 all present across ${h.folders} folder(s).`,kind:"success",category:"system"})}catch(h){new T.Notice(`Restore author stubs failed: ${h.message}`)}}}),this.addCommand({id:"stashpad-sync-authors",name:"Sync authors across all folders (multiplayer)",callback:()=>void this.syncAuthorsAcrossFolders()}),this.addCommand({id:"stashpad-rebootstrap-all",name:"Rebootstrap all Stashpad folders (backfill metadata + rename stale titles)",callback:async()=>{new T.Notice("Stashpad: rebootstrapping\u2026");try{let{touched:h,fmChecked:I,fmWritten:u,slugsRenamed:f,authors:C,imported:B,attachmentsLinked:m}=await this.rebootstrapAllFolders(),y=[];y.push(`rebootstrapped ${h.length} folder${h.length===1?"":"s"}`),B>0&&y.push(`imported ${B} loose file${B===1?"":"s"}`),m>0&&y.push(`linked attachments on ${m} note${m===1?"":"s"}`),u>0&&y.push(`updated ${u} note${u===1?"":"s"}' metadata`),f>0&&y.push(`renamed ${f} note${f===1?"":"s"}`),C>0&&y.push(`${C} author${C===1?"":"s"} in registry`),y.push(`(checked ${I} total)`),new T.Notice(`Stashpad: ${y.join(" \xB7 ")}`)}catch(h){new T.Notice(`Stashpad: rebootstrap failed (${h.message})`)}}}),this.addCommand({id:"stashpad-adopt-note",name:"Adopt active note into Stashpad (fill missing frontmatter)",checkCallback:h=>{let I=this.app.workspace.getActiveFile();return!I||I.extension!=="md"?!1:(h||this.adoptNote(I),!0)}}),this.addCommand({id:"stashpad-open-notification-history",name:"Open notification history",callback:()=>{Promise.resolve().then(()=>(Ft(),fi)).then(({NotificationHistoryModal:h,LogModal:I})=>{new h(this.app,this.notifications,async()=>{let u=this.app.vault.adapter,f=this.pluginPrivatePath("log.jsonl");if(!await u.exists(f)){new T.Notice("No log yet \u2014 make some changes first.");return}let C=await u.read(f);new I(this.app,C,f).open()},this.settings.authorId||null,u=>this.lookupNoteAuthorIds(u)).open()})}});let A=[{key:"prefixTimestampsOnCopy",label:"Prefix timestamps when copying"},{key:"useTemplatesFormat",label:"Use Templates plugin date/time formats"},{key:"autoNavOnMoveIn",label:"Auto-navigate into parent on move IN"},{key:"autoNavOnMoveOut",label:"Auto-navigate to destination on move OUT"},{key:"confirmCrossParentDrag",label:"Confirm cross-parent drag-and-drop"},{key:"confirmBulkDelete",label:"Confirm bulk deletes"},{key:"confirmAttachmentDelete",label:"Offer to delete attachments with note"},{key:"autofocusComposerAfterSend",label:"Autofocus composer after sending"},{key:"popoutDuplicates",label:"Open in new window \u2014 duplicate tab"},{key:"autoExpandCursorRow",label:"Expand the cursor row's body automatically"},{key:"autoOpenDetailPanel",label:"Auto-open the detail panel"},{key:"doubleClickToFocus",label:"Double-click a note to open it"}];for(let h of A){let I=`stashpad-toggle-${String(h.key).replace(/[A-Z]/g,u=>`-${u.toLowerCase()}`)}`;this.addCommand({id:I,name:`Toggle: ${h.label}`,callback:async()=>{let u=!this.settings[h.key];this.settings[h.key]=u,await this.saveSettings(),new T.Notice(`${h.label}: ${u?"ON":"OFF"}`)}})}this.addCommand({id:"stashpad-open-settings",name:"Open Stashpad settings",callback:()=>{let h=this.app.setting;!h?.open||!h?.openTabById||(h.open(),h.openTabById(this.manifest.id))}}),this.addCommand({id:"stashpad-search-settings",name:"Search Stashpad settings\u2026",callback:()=>{let h=this.app.setting;!h?.open||!h?.openTabById||(h.open(),h.openTabById(this.manifest.id),setTimeout(()=>{h?.modalEl?.querySelector?.("input[type='search']")?.focus()},0))}});for(let h of ys)this.addCommand({id:`stashpad-open-settings-${h.id}`,name:`Open Stashpad settings: ${h.label}`,callback:()=>{let I=this.app.setting;!I?.open||!I?.openTabById||(I.open(),I.openTabById(this.manifest.id))}});let l=()=>{let h=this.app.setting;!h?.open||!h?.openTabById||(h.open(),h.openTabById(this.manifest.id),setTimeout(()=>{document.getElementById("stashpad-jd-index-section")?.scrollIntoView({behavior:"smooth",block:"start"})},100))};this.addCommand({id:"stashpad-preview-jd-index",name:"Preview JD index (overwrites home note body)",callback:async()=>{try{let{buildJdIndexPreview:h}=await Promise.resolve().then(()=>(mi(),ji)),I=await h(this.app,this,this.settings);if(I.error==="no-dest"){new T.Notice("Set a Designated Stashpad folder for Index in settings first.",6e3),l();return}if(I.error==="no-home"){new T.Notice(`"${this.settings.jdIndexStashpadFolder}" has no Stashpad home note. Open the folder in Stashpad first to create one.`,7e3);return}let{buildJdPreviewNotice:u}=await Promise.resolve().then(()=>(mi(),ji));u(this.app,I)}catch(h){console.error("[stashpad] preview failed",h),new T.Notice(`Preview failed: ${h?.message??h}`,8e3)}}}),this.addCommand({id:"stashpad-build-jd-index",name:"Build JD index notes (creates Stashpad-note hierarchy)",callback:async()=>{try{let{buildJdIndexNotes:h,scanForJdNotes:I,JdBuildConfirmModal:u}=await Promise.resolve().then(()=>(mi(),ji));if(!(this.settings.jdIndexStashpadFolder??"").trim().replace(/^\/+|\/+$/g,"")){new T.Notice("Set a Designated Stashpad folder for Index in settings first.",6e3),l();return}let C=I(this.app,this,this.settings);new u(this.app,this,this.settings,C.indexed.length,async()=>{try{let m=await h(this.app,this,this.settings);if(m.error==="no-dest"){new T.Notice("Set a Designated Stashpad folder for Index in settings first.",6e3),l();return}if(m.error==="dest-not-stashpad"){new T.Notice(`"${m.destFolder}" isn't a known Stashpad folder. Pick a real Stashpad folder in settings.`,7e3),l();return}this.settings.jdIndexHasBuilt=!0,await this.saveSettings(),new T.Notice(`Index built: ${m.created} created, ${m.updated} updated, ${m.skipped} skipped \u2192 ${m.destFolder}`,6e3)}catch(m){console.error("[stashpad] build failed",m),new T.Notice(`Build failed: ${m?.message??m}`,8e3)}}).open()}catch(h){console.error("[stashpad] build failed",h),new T.Notice(`Build failed: ${h?.message??h}`,8e3)}}});let d=h=>{if(h.extension!==ee)return;let I=(this.settings.importDropFolder||"").trim().replace(/^\/+|\/+$/g,""),u=(this.settings.exportFolder||"").trim().replace(/^\/+|\/+$/g,""),f=h.parent?.path||"",C=f.split("/").pop()??"";if(I&&C===I){if(u&&f.endsWith(`/${u}`))return;let B=f.slice(0,f.length-I.length).replace(/\/+$/,"")||this.settings.folder;this.autoImportStash(h,B);return}this.settings.autoImport&&this.importService.isArmed()&&(He(h.path)||this.discoverStashpadFolders().includes(f)&&this.autoImportStash(h,f))};this.registerEvent(this.app.vault.on("create",h=>{h instanceof T.TFile&&d(h)})),this.registerEvent(this.app.vault.on("rename",h=>{h instanceof T.TFile&&d(h)}));let p=h=>{if(h.extension!=="md")return;let I=h.parent?.path?.replace(/\/+$/,"")??"";this.discoverStashpadFolders().includes(I)&&setTimeout(()=>{this.fixOrphanParentForFile(h)},800)},g=h=>{if(h.extension!=="md")return;let I=(this.settings.importDropFolder||"").trim().replace(/^\/+|\/+$/g,"");if(!I)return;let u=h.parent?.path?.replace(/\/+$/,"")??"";if((u.split("/").pop()??"")!==I)return;let C=u.slice(0,u.length-I.length).replace(/\/+$/,"");!C||!this.discoverStashpadFolders().includes(C)||setTimeout(()=>{this.adoptMarkdownDrop(h,C)},200)};this.registerEvent(this.app.vault.on("create",h=>{h instanceof T.TFile&&(p(h),g(h))})),this.registerEvent(this.app.vault.on("rename",h=>{h instanceof T.TFile&&(p(h),g(h))})),this.registerEvent(this.app.vault.on("delete",h=>{if(!(h instanceof T.TFolder))return;let I=h.path.replace(/\/+$/,"");this.knownStashpadFolders.has(I)&&this.handleStashpadFolderDeleted(I)})),this.registerEvent(this.app.vault.on("rename",(h,I)=>{h instanceof T.TFile&&this.maybeReHomeOnCrossFolderMove(h,I)})),this.registerEvent(this.app.vault.on("rename",(h,I)=>{h instanceof T.TFile&&this.maybeArchiveOnMoveIn(h,I)})),this.registerEvent(this.app.vault.on("create",h=>{h instanceof T.TFile?this.importService.enqueue(h):h instanceof T.TFolder&&this.importService.enqueueFolder(h)})),this.registerEvent(this.app.vault.on("rename",h=>{h instanceof T.TFile?this.importService.enqueue(h):h instanceof T.TFolder&&this.importService.enqueueFolder(h)})),this.registerEvent(this.app.vault.on("rename",(h,I)=>{h instanceof T.TFile&&this.maybeAdoptAuthorRename(h,I)})),this.registerDomEvent(window,"focus",()=>void this.checkForSyncedBuild()),setTimeout(()=>void this.checkForSyncedBuild(),5e3),this.registerInterval(window.setInterval(()=>void this.checkForSyncedBuild(),45e3))}async checkForSyncedBuild(){try{let t=this.manifest.dir;if(!t)return;let e=`${t.replace(/\/+$/,"")}/manifest.json`,i=this.app.vault.adapter;if(!await i.exists(e))return;let s=JSON.parse(await i.read(e))?.version,n=this.manifest.version;if(typeof s!="string"||!s||s===n||!this.isSemverGreater(s,n)||this.notifiedBuildVersion===s)return;this.notifiedBuildVersion=s,this.notifications.show({message:`A newer Stashpad build synced in (\`${n}\` \u2192 \`${s}\`). Reload the app to apply it.`,kind:"info",category:"system",duration:0,actions:[{label:"Reload app",onClick:()=>this.reloadAppForUpdate()}]})}catch(t){console.debug("[Stashpad] synced-build check failed",t)}}reloadAppForUpdate(){try{window.localStorage?.setItem(fo,"1")}catch{}try{if(this.app.commands?.executeCommandById?.("app:reload"))return}catch(t){console.warn("[Stashpad] app:reload command failed",t)}try{window.location.reload()}catch{new T.Notice("Reload Obsidian (close + reopen) to apply the Stashpad update.")}}async unghostStashpadTabsIfFlagged(){let t=!1;try{t=window.localStorage?.getItem(fo)==="1"}catch{}if(t){try{window.localStorage?.removeItem(fo)}catch{}for(let e of this.app.workspace.getLeavesOfType(J))try{let i=e;i.isDeferred&&typeof i.loadIfDeferred=="function"&&await i.loadIfDeferred()}catch(i){console.warn("[Stashpad] un-ghost leaf failed",i)}}}isSemverGreater(t,e){let i=t.split(".").map(o=>parseInt(o,10)||0),s=e.split(".").map(o=>parseInt(o,10)||0),n=Math.max(i.length,s.length);for(let o=0;o<n;o++){let r=i[o]??0,A=s[o]??0;if(r!==A)return r>A}return!1}parseAuthorFilePath(t){let e=t.match(/\/_authors\/([^/]+?)-([a-z0-9]{4,12})\.md$/i);return e?{name:e[1].replace(/-/g," "),id:e[2]}:null}authorNameToSafe(t){return t.replace(/[^\w\- ]+/g,"").trim().replace(/\s+/g,"-")||"author"}async syncAuthorFilesToName(){let t=(this.settings.authorId??"").trim(),e=(this.settings.authorName??"").trim();if(!t||!e)return;let i=this.authorNameToSafe(e);for(let s of this.discoverStashpadFolders()){let n=`${s}/_authors`;if(await this.app.vault.adapter.exists(n))for(let o of this.app.vault.getMarkdownFiles()){if(!o.path.startsWith(n+"/"))continue;let r=this.parseAuthorFilePath(o.path);if(!r||r.id!==t)continue;let A=`${n}/${i}-${t}.md`,l=o;if(o.path!==A)try{this.authorRenameInFlight.add(o.path),this.authorRenameInFlight.add(A),await this.app.fileManager.renameFile(o,A);let d=this.app.vault.getAbstractFileByPath(A);d&&(l=d)}catch(d){console.warn("[Stashpad] author file rename failed",d);continue}try{await this.refreshAuthorStub(l)}catch{}}}}async refreshAuthorStub(t){let e=(this.settings.authorName??"").trim(),i=(this.settings.authorRole??"").trim(),s=(this.settings.authorDepartment??"").trim();if(e)try{let n=await this.app.vault.read(t),o=n.replace(/^# .*$/m,`# ${e}`);o!==n&&await this.app.vault.modify(t,o),await this.app.fileManager.processFrontMatter(t,r=>{r.aliases=[e],delete r.name,i?r.role=i:delete r.role,s?r.department=s:delete r.department})}catch(n){console.warn("[Stashpad] refreshAuthorStub failed",n)}}async maybeAdoptAuthorRename(t,e){if(this.authorRenameInFlight.delete(t.path)||this.authorRenameInFlight.delete(e))return;let i=this.parseAuthorFilePath(t.path);if(!i)return;let s=(this.settings.authorId??"").trim();if(!s||i.id!==s)return;let n=i.name.trim();!n||n===(this.settings.authorName??"").trim()||(this.settings.authorName=n,await this.saveSettings(),await this.syncAuthorFilesToName())}async adoptMarkdownDrop(t,e){try{let i=this.app.vault.adapter,s=t.name,n=s.lastIndexOf("."),o=n>0?s.slice(0,n):s,r=n>0?s.slice(n):"",A=0;for(;await i.exists(`${e}/${s}`);)A+=1,s=`${o}-${A}${r}`;let l=`${e}/${s}`;await this.app.fileManager.renameFile(t,l);let d=this.app.vault.getAbstractFileByPath(l);d instanceof T.TFile&&setTimeout(()=>{this.fixOrphanParentForFile(d)},500),this.notifications.show({message:`Imported \`${t.name}\` \u2192 \`${e}\``,kind:"success",category:"import",folder:e,affectedPaths:[l]})}catch(i){console.warn("Stashpad: markdown drop adoption failed",i),this.notifications.show({message:`Couldn't import \`${t.name}\`: ${i.message}`,kind:"error",category:"import"})}}async fixOrphanParentForFile(t){try{let e=this.app.metadataCache.getFileCache(t)?.frontmatter,i=typeof e?.id=="string"?e.id.trim():"",s=e?.parent,n=typeof s=="string"?s.trim()!=="":s!=null,o=typeof e?.created=="string"&&e.created.trim()!=="",r=!i,A=!n,l=!o;if(!r&&!A&&!l)return;let{newId:d}=await Promise.resolve().then(()=>(Tt(),zi)),p,g=!1,h=!1;if(await this.app.fileManager.processFrontMatter(t,f=>{if(r&&(typeof f.id=="string"&&f.id.trim()||(p=d(),f.id=p)),A){let C=f.parent;(typeof C=="string"?C.trim()!=="":C!=null)||(f.parent=F,g=!0)}l&&(typeof f.created=="string"&&f.created.trim()||(f.created=new Date(t.stat.ctime).toISOString(),h=!0))}),!p&&!g&&!h)return;let I=this.newLog(),u=p||i;u&&await I.append({type:"parent_change",id:u,payload:{from:null,to:F,reason:"orphan_auto_fix",path:t.path,addedId:!!p,addedParent:g,addedCreated:h}}),new T.Notice(`Adopted ${t.basename} \u2192 Home`)}catch(e){console.warn("Stashpad: orphan auto-fix failed",e)}}maybeReHomeOnCrossFolderMove(t,e){if(t.extension!=="md")return;let i=t.parent?.path?.replace(/\/+$/,"")??"",s=e.lastIndexOf("/"),n=(s>=0?e.slice(0,s):"").replace(/\/+$/,"");i!==n&&this.discoverStashpadFolders().includes(i)&&(this.reHomePending.has(t.path)||(this.reHomePending.add(t.path),setTimeout(()=>{this.reHomePending.delete(t.path),this.reHomeDanglingParent(t,i)},900)))}async reHomeDanglingParent(t,e){try{let i=this.app.metadataCache.getFileCache(t)?.frontmatter,s=typeof i?.id=="string"?i.id.trim():"",n=typeof i?.parent=="string"?i.parent.trim():"";if(!s||!n||n===F||this.app.vault.getMarkdownFiles().some(r=>(r.parent?.path?.replace(/\/+$/,"")??"")===e&&this.app.metadataCache.getFileCache(r)?.frontmatter?.id===n))return;await this.app.fileManager.processFrontMatter(t,r=>{let A=typeof r.parent=="string"?r.parent.trim():"";A&&A!==F&&(r.parent=F)}),await this.newLog().append({type:"parent_change",id:s,payload:{from:n,to:F,reason:"rehome_cross_folder_move",path:t.path}}),new T.Notice(`Re-homed ${t.basename} \u2192 Home (its parent isn't in this folder)`)}catch(i){console.warn("[Stashpad] re-home on cross-folder move failed",i)}}async autoImportStash(t,e){try{let i=new Uint8Array(await this.app.vault.readBinary(t));if(Ut(i)){this.importService.parkEncrypted(t.path),this.notifyPendingEncrypted();return}let s=await Oe(this.app,i);if(!s)return;let n=ie(),o=new Set;if(n&&typeof n.collectExistingIds=="function"&&n.noteFolder===e)for(let l of n.collectExistingIds())o.add(l);else for(let l of this.app.vault.getMarkdownFiles()){if(!l.path.startsWith(e+"/"))continue;let d=this.app.metadataCache.getFileCache(l)?.frontmatter?.id;typeof d=="string"&&o.add(d)}let r=await Yt(this.app,s,e,o);try{await this.newLog().append({type:"stash_import",id:F,payload:{from:t.path,into:e,noteCount:r.notesWritten,attachmentsWritten:r.attachmentsWritten,collisionsRenamed:r.collisionsRenamed,auto:!0}})}catch{}try{await this.app.fileManager.trashFile(t)}catch{}let A=[`Auto-imported ${r.notesWritten} note${r.notesWritten===1?"":"s"} from ${t.name}`];r.attachmentsWritten&&A.push(`+ ${r.attachmentsWritten} attachment${r.attachmentsWritten===1?"":"s"}`),r.collisionsRenamed&&A.push(`(${r.collisionsRenamed} renamed)`),this.notifications.show({message:A.join(" "),kind:"success",category:"import",folder:e}),n&&typeof n.debouncedRender=="function"&&n.debouncedRender()}catch(i){this.notifications.show({message:`Stashpad: auto-import failed File: \`${t.name}\` Error: ${i.message} -Inspect with the buttons below \u2014 rename to .zip to crack it open in an archive tool.`,kind:"error",category:"import",affectedPaths:[t.path],actions:Vi(this.app,t.path,T.Platform.isMobile)}),console.error(i)}}lookupNoteAuthorIds(t){let e=new Set,i=s=>{if(typeof s!="string")return null;let n=s.match(/-([a-z0-9]{4,12})(?:\.md)?(?:\||\]\])/i);return n?n[1]:null};for(let s of this.app.vault.getMarkdownFiles()){let n=this.app.metadataCache.getFileCache(s)?.frontmatter;if(n?.id!==t)continue;let o=i(n?.author);o&&e.add(o);let r=n?.contributors;if(Array.isArray(r))for(let A of r){let l=i(A);l&&e.add(l)}break}return Array.from(e)}lookupNoteAuthorId(t){return this.lookupNoteAuthorIds(t)[0]??null}async rebootstrapAllFolders(){this.rebootstrapInProgress=!0;try{return await this.rebootstrapAllFoldersInner()}finally{window.setTimeout(()=>{this.rebootstrapInProgress=!1;for(let t of this.app.workspace.getLeavesOfType(J))t.view?.forceReconcileRender?.()},2500)}}async rebootstrapAllFoldersInner(){let t="__root__",e=new Set;for(let I of this.app.vault.getMarkdownFiles()){if(this.app.metadataCache.getFileCache(I)?.frontmatter?.id!==t)continue;let f=I.parent?.path;f&&e.add(f)}let i=(this.settings.importDropFolder||"").trim().replace(/^\/+|\/+$/g,""),s=(this.settings.exportFolder||"").trim().replace(/^\/+|\/+$/g,""),n=[],o=async I=>{if(I&&!await this.app.vault.adapter.exists(I))try{await this.app.vault.createFolder(I)}catch(u){let f=u?.message??"";if(!/already exists/i.test(f))throw u}},r=0,A=0,l=0,d=0,g=new Set(this.okfActiveFolders());for(let I of e)try{if(i&&await o(`${I}/${i}`),s&&await o(`${I}/${s}`),this.settings.autoImport)try{let f=await this.importService.importLooseInto(I);d+=f.files+f.folders+f.stashes}catch(f){console.warn("Stashpad: loose sweep failed",I,f)}let u=await Ye(this.app,I);if(r+=u.checked,A+=u.written,l+=await this.rebootstrapFolderSlugs(I),g.has(I.replace(/\/+$/,"")))try{await oo(this.app,I)}catch(f){console.warn("Stashpad: OKF rebuild during rebootstrap failed",I,f)}n.push(I)}catch(u){console.warn(`Stashpad: rebootstrap skipped ${I}`,u)}let p=0;try{p=(await this.rebuildAuthorRegistry()).total}catch(I){console.warn("Stashpad: rebootstrap author-registry rebuild failed",I)}let h=0;try{h=await this.convertAttachmentsToLinks()}catch(I){console.warn("Stashpad: attachment-link conversion failed",I)}return{touched:n,fmChecked:r,fmWritten:A,slugsRenamed:l,authors:p,imported:d,attachmentsLinked:h}}async rebootstrapFolderSlugs(t){let e="__root__",i=t.replace(/\/+$/,""),s=this.settings.slugStopWords??Lt,n=0,o=this.app.vault.getMarkdownFiles().filter(r=>(r.parent?.path?.replace(/\/+$/,"")??"")===i);for(let r of o){let A=ve(r.basename);if(!(!A||A===e||this.app.metadataCache.getFileCache(r)?.frontmatter?.id!==A))try{let d=await this.app.vault.cachedRead(r),g=d.startsWith("---")?d.slice(d.indexOf(` ----`,3)+4).replace(/^\r?\n/,""):d,p=Et(g,s),h=wt(p,A);if(r.name===h)continue;let I=r.parent?`${r.parent.path}/${h}`:h;if(this.app.vault.getAbstractFileByPath(I))continue;await this.app.fileManager.renameFile(r,I),n+=1}catch(d){console.warn(`Stashpad: slug rebootstrap skipped ${r.path}`,d)}}return n}onStashpadSelectionChange(t){return this.stashpadSelectionListeners.add(t),()=>this.stashpadSelectionListeners.delete(t)}notifyStashpadSelectionChanged(){for(let t of this.stashpadSelectionListeners)try{t()}catch(e){console.warn("[Stashpad] selection listener failed",e)}}onStashpadContentChange(t){return this.stashpadContentListeners.add(t),()=>this.stashpadContentListeners.delete(t)}notifyStashpadContentChanged(){for(let t of this.stashpadContentListeners)try{t()}catch(e){console.warn("[Stashpad] content listener failed",e)}}getActiveStashpadSelection(){let e=this.lastActiveStashpadLeaf?.view;if(!e||e.getViewType?.()!==J)return null;let i=e.noteFolder??"";if(!i)return null;let s=e.currentChildren??[],n;if(typeof e.cursorIdx=="number"&&e.cursorIdx>=0&&(n=s[e.cursorIdx]),!n&&e.selection?.size>0){let o=e.firstSelectedId??[...e.selection][0];n=s.find(r=>r.id===o)}return n?.file?{folder:i,id:n.id,file:n.file}:null}fileForPin(t,e){let i=t.replace(/\/+$/,"");for(let s of this.app.vault.getMarkdownFiles())if((s.parent?.path?.replace(/\/+$/,"")??"")===i&&this.app.metadataCache.getFileCache(s)?.frontmatter?.id===e)return s;return null}async pinNote(t){let e=this.fileForPin(t.folder,t.id);e&&this.app.metadataCache.getFileCache(e)?.frontmatter?.pinned!==!0&&(await this.app.fileManager.processFrontMatter(e,i=>{i.pinned=!0,i.pinnedAt=Date.now()}),this.refreshPanelsView())}async unpinNote(t){let e=this.fileForPin(t.folder,t.id);e&&this.app.metadataCache.getFileCache(e)?.frontmatter?.pinned===!0&&(await this.app.fileManager.processFrontMatter(e,i=>{delete i.pinned,delete i.pinnedAt}),this.refreshPanelsView())}isPinned(t){let e=this.fileForPin(t.folder,t.id);return e?this.app.metadataCache.getFileCache(e)?.frontmatter?.pinned===!0:!1}listPinnedNotes(){let t=new Set(this.discoverStashpadFolders()),e=[];for(let i of this.app.vault.getMarkdownFiles()){let s=i.parent?.path?.replace(/\/+$/,"")??"";if(!t.has(s))continue;let n=this.app.metadataCache.getFileCache(i)?.frontmatter;if(!n||n.pinned!==!0||typeof n.id!="string"||!n.id)continue;let o=typeof n.pinnedAt=="number"?n.pinnedAt:0;e.push({folder:s,id:n.id,pinnedAt:o,file:i})}return e.sort((i,s)=>i.pinnedAt-s.pinnedAt||i.file.path.localeCompare(s.file.path)),e}async migratePinnedNotesToFrontmatter(){let t=this.settings.pinnedNotes??[];if(t.length===0)return;let e=Date.now()-t.length*1e3;for(let i of t){let s=this.fileForPin(i.folder,i.id);if(!s){e+=1e3;continue}try{if(this.app.metadataCache.getFileCache(s)?.frontmatter?.pinned!==!0){let n=e;await this.app.fileManager.processFrontMatter(s,o=>{o.pinned=!0,o.pinnedAt=n})}}catch(n){console.warn("[Stashpad] pin migration failed for",i,n)}e+=1e3}this.settings.pinnedNotes=[],await this.saveSettings(),this.refreshPanelsView()}refreshPanelsView(){let t=this.app.workspace.getLeavesOfType(ie);for(let e of t){let i=e.view;i&&typeof i.render=="function"&&i.render()}}refreshAllStashpadViews(){for(let t of this.app.workspace.getLeavesOfType(J)){let e=t.view;e&&typeof e.render=="function"&&e.render()}}openFolderPicker(){let t=I=>{let f=I.getViewState().state?.folderOverride;return typeof f=="string"&&f.trim()?f.trim().replace(/^\/+|\/+$/g,""):(this.settings.folder||"Stashpad").trim().replace(/^\/+|\/+$/g,"")},e=this.app.workspace.getLeavesOfType(J),i=this.discoverStashpadFolders(),s=_t(),n=s?(s.noteFolder??"").trim().replace(/^\/+|\/+$/g,""):"",o=new Set;for(let I of this.app.vault.getAllLoadedFiles())if(I.children){let u=I.path;u&&u!=="/"&&!u.startsWith(".")&&o.add(u)}let r=I=>{let u=I.split("/").filter(Boolean).pop()??"";return u?new Set([this.settings.importDropFolder,this.settings.exportFolder,"_attachments","_processed","_authors","_exports","_imports","_archive",".archive","_deleted"].map(C=>(C??"").trim().replace(/^\/+|\/+$/g,"")).filter(Boolean)).has(u):!1},A=new Set,l=[],d=[],g=new Set;for(let I of e){let u=t(I);if(g.has(u))continue;g.add(u),A.add(u);let f=u.split("/").pop()||u;l.push({kind:"reveal",folder:u,label:`Reveal "${f}" tab`,leaf:I,icon:this.isArchiveFolder(u)?"archive":"layout-grid"}),d.push({kind:"open-anyway",folder:u,label:`Open "${f}" in another new tab`,icon:"layout-template"})}for(let I of i.filter(u=>!A.has(u))){let u=I.split("/").pop()||I;l.push({kind:"open",folder:I,label:`Open "${u}" in new tab`,icon:this.isArchiveFolder(I)?"archive":"layout-template"})}let p=this,h=new class extends T.SuggestModal{getSuggestions(I){let u=I.trim().toLowerCase(),f=u?u.split(/\s+/).filter(Boolean):[],C=Q=>{if(!f.length)return!0;let E=Q.toLowerCase();for(let v of f)if(!E.includes(v))return!1;return!0},B=u?l.filter(Q=>{let E="folder"in Q?Q.folder:"";return C(Q.label)||C(E)}):l.slice();if(u&&s&&n)for(let Q of i){if(Q.toLowerCase()===n.toLowerCase())continue;let E=Q.split("/").pop()??Q,v=`${Q} ${E}`;C(v)&&B.push({kind:"switch-current",folder:Q,label:`Switch this tab to "${E}"`,icon:"folder-input"})}let m=I.trim().replace(/^\/+|\/+$/g,"");if(m&&!r(m)){let Q=Array.from(o).find(v=>v.toLowerCase()===m.toLowerCase()),E=i.some(v=>v.toLowerCase()===m.toLowerCase());if(Q&&!E)B.push({kind:"convert",folder:Q,label:`Convert \u201C${ti(Q)}\u201D into a Stashpad\u2026`,icon:"folder-cog"});else if(!Q){let v=ti(m);B.push({kind:"create",folder:m,label:`+ Create new Stashpad \u201C${v}\u201D`,icon:"folder-plus"})}}let w=d.filter(Q=>C(Q.label)||C("folder"in Q?Q.folder:""));return B.push(...w),p.encryption?.isConfigured?.()&&C("trash deleted encrypted")&&B.push({kind:"trash",label:"Open encrypted trash",icon:"trash-2"}),B}renderSuggestion(I,u){u.addClass("stashpad-suggest-item"),u.addClass("stashpad-ribbon-suggest-item"),I.kind==="create"&&u.addClass("stashpad-suggest-create");let f=u.createSpan({cls:"stashpad-ribbon-suggest-icon"});(0,T.setIcon)(f,I.icon);let C=u.createDiv({cls:"stashpad-ribbon-suggest-body"});C.createDiv({cls:"stashpad-suggest-title",text:I.label}),"folder"in I&&I.folder&&I.label!==I.folder&&C.createDiv({cls:"stashpad-suggest-preview",text:I.folder})}async onChooseSuggestion(I){if(I.kind==="trash"){p.openEncryptedTrash();return}if(I.kind==="reveal"){p.app.workspace.revealLeaf(I.leaf);return}if(I.kind==="open"||I.kind==="open-anyway"){await p.activateViewForFolder(I.folder);return}if(I.kind==="switch-current"){let u=s;u&&typeof u.setFolderOverride=="function"&&(await u.setFolderOverride(I.folder),p.app.workspace.revealLeaf(u.leaf));return}if(I.kind==="create"){try{let u=ti(I.folder);await p.app.vault.adapter.exists(u)||await p.app.vault.createFolder(u),await p.activateViewForFolder(u)}catch(u){new T.Notice(`Stashpad: couldn't create folder (${u.message})`)}return}if(I.kind==="convert"){let{ConfirmModal:u}=await Promise.resolve().then(()=>(vt(),gi)),f=I.folder,C=[`\u201C${f}\u201D already exists as a regular vault folder.`,"Converting adds a Home note + _imports / _exports subfolders, and imports the existing loose files and subfolders inside it as notes.","(Files already structured as notes, and reserved subfolders, are left alone.)"];new u(p.app,"Convert into a Stashpad?",C.join(` -`),"Convert & import",async B=>{if(B)try{await p.activateViewForFolder(f),await p.runImportLooseFiles(f)}catch(m){new T.Notice(`Stashpad: couldn't convert folder (${m.message})`)}}).open();return}}}(this.app);h.setPlaceholder(s?"Open, switch this tab, or create a Stashpad folder \u2014 type to filter\u2026":"Open or create a Stashpad folder \u2014 type to filter\u2026"),h.open()}async openTinyWindow(){let t=_t(),e=t?.folderOverride??null,i=t?.focusId??"__root__",s=!!t?.compactMode,n=this.app.workspace.openPopoutLeaf?.();if(!n){new T.Notice("Stashpad: couldn't open popout window on this build.");return}await n.setViewState({type:J,active:!0,state:{folderOverride:e,focusId:i,tinyMode:!0,tinyAlwaysOnTop:!1,compactMode:s}});try{this.app.workspace.revealLeaf(n)}catch{}}async activateView(t={reveal:!0}){let{workspace:e}=this.app;if(t.reveal){let s=e.getLeavesOfType(J);if(s.length>0){e.revealLeaf(s[0]);return}}let i=e.getLeaf("tab");await i.setViewState({type:J,active:!0}),e.revealLeaf(i)}async focusLastStashpadTab(){let t=this.app.workspace,e=t.getLeavesOfType(J),i=this.lastActiveStashpadLeaf&&e.includes(this.lastActiveStashpadLeaf)?this.lastActiveStashpadLeaf:e[0]??null;if(!i){await this.activateView({reveal:!0});return}t.revealLeaf(i),t.setActiveLeaf(i,{focus:!0})}async focusFolderPanel(){await Ps(this.app);let t=this.app.workspace.getLeavesOfType(fe)[0];t&&this.app.workspace.setActiveLeaf(t,{focus:!0})}async reconcileLockedRegistry(){let t=this.settings.lockedSubtrees??[],e=[];for(let n of t){let o=(n.folder??"").replace(/\/+$/,"");if(!(o==="_deleted"||o.startsWith("_deleted/")))try{await this.app.vault.adapter.exists(n.blob)&&e.push(n)}catch{e.push(n)}}let i=e.length!==t.length,s=new Set(e.map(n=>n.blob));for(let n of this.app.vault.getFiles()){if(n.extension!=="stashenc"||s.has(n.path))continue;let o=n.parent?.path?.replace(/\/+$/,"")??"";if(o==="_deleted"||o.startsWith("_deleted/"))continue;let r=await Ca(this.app,n.path);r&&(e.push({folder:o,blob:n.path,parentId:r.parentId,title:r.title,count:r.count,created:r.created,rootId:r.rootId,prevSibling:r.prevSibling}),i=!0)}i&&(this.settings.lockedSubtrees=e,await this.saveSettings(),this.refreshAllStashpadViews?.())}lockedSubtreesFor(t,e){let i=t.replace(/\/+$/,""),s=[],n=new Set;for(let o of this.settings.lockedSubtrees??[])(o.folder??"").replace(/\/+$/,"")===i&&(o.parentId??F)===e&&(s.push({blob:o.blob,title:o.title??"",count:o.count??0,created:o.created??"",rootId:o.rootId,parentId:o.parentId??F,prevSibling:o.prevSibling??null}),n.add(o.blob));for(let o of this.app.vault.getFiles()){if(o.extension!=="stashenc"||n.has(o.path))continue;let r=o.parent?.path?.replace(/\/+$/,"")??"";r!==i||r==="_deleted"||r.startsWith("_deleted/")||e===F&&s.push({blob:o.path,title:o.basename,count:0,created:"",rootId:void 0,parentId:F,prevSibling:null})}return s}async ensureEncryptionUnlocked(){return this.encryption.isConfigured()?this.encryption.isUnlocked()||await this.encryption.tryAutoUnlock()?!0:new Promise(t=>{new yt(this.app,{mode:"unlock",offerKeychain:!0,onSubmit:async({current:e,remember:i})=>await this.encryption.unlock(e,i)?(t(!0),null):"Wrong password. Try again.",onCancel:()=>t(!1)}).open()}):(new T.Notice("Set up encryption first (Settings \u2192 Encryption)."),!1)}async lockNoteSubtree(t,e,i=null,s={}){if(!await this.ensureEncryptionUnlocked())return null;let n=this.encryption.getSessionKey();if(!n)return null;try{let o=this.settings.hideLockedTitles??!1,r=await ma(this.app,t,e,n,i,o,s.blobFolder),A=(s.blobFolder??t).replace(/\/+$/,"");return this.settings.lockedSubtrees=[...(this.settings.lockedSubtrees??[]).filter(l=>l.blob!==r.blobPath),{folder:A,blob:r.blobPath,parentId:r.parentId,title:r.title,count:r.noteCount,created:r.created,rootId:r.rootId,prevSibling:i}],await this.saveSettings(),r.unpurged.length>0?new T.Notice(`\u26A0\uFE0F Locked, but ${r.unpurged.length} file${r.unpurged.length===1?" is":"s are"} still in plaintext (couldn't be removed or changed during the lock): +Inspect with the buttons below \u2014 rename to .zip to crack it open in an archive tool.`,kind:"error",category:"import",affectedPaths:[t.path],actions:es(this.app,t.path,T.Platform.isMobile)}),console.error(i)}}lookupNoteAuthorIds(t){let e=new Set,i=s=>{if(typeof s!="string")return null;let n=s.match(/-([a-z0-9]{4,12})(?:\.md)?(?:\||\]\])/i);return n?n[1]:null};for(let s of this.app.vault.getMarkdownFiles()){let n=this.app.metadataCache.getFileCache(s)?.frontmatter;if(n?.id!==t)continue;let o=i(n?.author);o&&e.add(o);let r=n?.contributors;if(Array.isArray(r))for(let A of r){let l=i(A);l&&e.add(l)}break}return Array.from(e)}lookupNoteAuthorId(t){return this.lookupNoteAuthorIds(t)[0]??null}async rebootstrapAllFolders(){this.rebootstrapInProgress=!0;try{return await this.rebootstrapAllFoldersInner()}finally{window.setTimeout(()=>{this.rebootstrapInProgress=!1;for(let t of this.app.workspace.getLeavesOfType(J))t.view?.forceReconcileRender?.()},2500)}}async rebootstrapAllFoldersInner(){let t="__root__",e=new Set;for(let I of this.app.vault.getMarkdownFiles()){if(this.app.metadataCache.getFileCache(I)?.frontmatter?.id!==t)continue;let f=I.parent?.path;f&&e.add(f)}let i=(this.settings.importDropFolder||"").trim().replace(/^\/+|\/+$/g,""),s=(this.settings.exportFolder||"").trim().replace(/^\/+|\/+$/g,""),n=[],o=async I=>{if(I&&!await this.app.vault.adapter.exists(I))try{await this.app.vault.createFolder(I)}catch(u){let f=u?.message??"";if(!/already exists/i.test(f))throw u}},r=0,A=0,l=0,d=0,p=new Set(this.okfActiveFolders());for(let I of e)try{if(i&&await o(`${I}/${i}`),s&&await o(`${I}/${s}`),this.settings.autoImport)try{let f=await this.importService.importLooseInto(I);d+=f.files+f.folders+f.stashes}catch(f){console.warn("Stashpad: loose sweep failed",I,f)}let u=await Xe(this.app,I);if(r+=u.checked,A+=u.written,l+=await this.rebootstrapFolderSlugs(I),p.has(I.replace(/\/+$/,"")))try{await Io(this.app,I)}catch(f){console.warn("Stashpad: OKF rebuild during rebootstrap failed",I,f)}n.push(I)}catch(u){console.warn(`Stashpad: rebootstrap skipped ${I}`,u)}let g=0;try{g=(await this.rebuildAuthorRegistry()).total}catch(I){console.warn("Stashpad: rebootstrap author-registry rebuild failed",I)}let h=0;try{h=await this.convertAttachmentsToLinks()}catch(I){console.warn("Stashpad: attachment-link conversion failed",I)}return{touched:n,fmChecked:r,fmWritten:A,slugsRenamed:l,authors:g,imported:d,attachmentsLinked:h}}async rebootstrapFolderSlugs(t){let e="__root__",i=t.replace(/\/+$/,""),s=this.settings.slugStopWords??Jt,n=0,o=this.app.vault.getMarkdownFiles().filter(r=>(r.parent?.path?.replace(/\/+$/,"")??"")===i);for(let r of o){let A=le(r.basename);if(!(!A||A===e||this.app.metadataCache.getFileCache(r)?.frontmatter?.id!==A))try{let d=await this.app.vault.cachedRead(r),p=d.startsWith("---")?d.slice(d.indexOf(` +---`,3)+4).replace(/^\r?\n/,""):d,g=Qt(p,s),h=yt(g,A);if(r.name===h)continue;let I=r.parent?`${r.parent.path}/${h}`:h;if(this.app.vault.getAbstractFileByPath(I))continue;await this.app.fileManager.renameFile(r,I),n+=1}catch(d){console.warn(`Stashpad: slug rebootstrap skipped ${r.path}`,d)}}return n}onStashpadSelectionChange(t){return this.stashpadSelectionListeners.add(t),()=>this.stashpadSelectionListeners.delete(t)}notifyStashpadSelectionChanged(){for(let t of this.stashpadSelectionListeners)try{t()}catch(e){console.warn("[Stashpad] selection listener failed",e)}}onStashpadContentChange(t){return this.stashpadContentListeners.add(t),()=>this.stashpadContentListeners.delete(t)}notifyStashpadContentChanged(){for(let t of this.stashpadContentListeners)try{t()}catch(e){console.warn("[Stashpad] content listener failed",e)}}getActiveStashpadSelection(){let e=this.lastActiveStashpadLeaf?.view;if(!e||e.getViewType?.()!==J)return null;let i=e.noteFolder??"";if(!i)return null;let s=e.currentChildren??[],n;if(typeof e.cursorIdx=="number"&&e.cursorIdx>=0&&(n=s[e.cursorIdx]),!n&&e.selection?.size>0){let o=e.firstSelectedId??[...e.selection][0];n=s.find(r=>r.id===o)}return n?.file?{folder:i,id:n.id,file:n.file}:null}fileForPin(t,e){let i=t.replace(/\/+$/,"");for(let s of this.app.vault.getMarkdownFiles())if((s.parent?.path?.replace(/\/+$/,"")??"")===i&&this.app.metadataCache.getFileCache(s)?.frontmatter?.id===e)return s;return null}async pinNote(t){let e=this.fileForPin(t.folder,t.id);e&&this.app.metadataCache.getFileCache(e)?.frontmatter?.pinned!==!0&&(await this.app.fileManager.processFrontMatter(e,i=>{i.pinned=!0,i.pinnedAt=Date.now()}),this.refreshPanelsView())}async unpinNote(t){let e=this.fileForPin(t.folder,t.id);e&&this.app.metadataCache.getFileCache(e)?.frontmatter?.pinned===!0&&(await this.app.fileManager.processFrontMatter(e,i=>{delete i.pinned,delete i.pinnedAt}),this.refreshPanelsView())}isPinned(t){let e=this.fileForPin(t.folder,t.id);return e?this.app.metadataCache.getFileCache(e)?.frontmatter?.pinned===!0:!1}listPinnedNotes(){let t=new Set(this.discoverStashpadFolders()),e=[];for(let i of this.app.vault.getMarkdownFiles()){let s=i.parent?.path?.replace(/\/+$/,"")??"";if(!t.has(s))continue;let n=this.app.metadataCache.getFileCache(i)?.frontmatter;if(!n||n.pinned!==!0||typeof n.id!="string"||!n.id)continue;let o=typeof n.pinnedAt=="number"?n.pinnedAt:0;e.push({folder:s,id:n.id,pinnedAt:o,file:i})}return e.sort((i,s)=>i.pinnedAt-s.pinnedAt||i.file.path.localeCompare(s.file.path)),e}async migratePinnedNotesToFrontmatter(){let t=this.settings.pinnedNotes??[];if(t.length===0)return;let e=Date.now()-t.length*1e3;for(let i of t){let s=this.fileForPin(i.folder,i.id);if(!s){e+=1e3;continue}try{if(this.app.metadataCache.getFileCache(s)?.frontmatter?.pinned!==!0){let n=e;await this.app.fileManager.processFrontMatter(s,o=>{o.pinned=!0,o.pinnedAt=n})}}catch(n){console.warn("[Stashpad] pin migration failed for",i,n)}e+=1e3}this.settings.pinnedNotes=[],await this.saveSettings(),this.refreshPanelsView()}refreshPanelsView(){let t=this.app.workspace.getLeavesOfType(oe);for(let e of t){let i=e.view;i&&typeof i.render=="function"&&i.render()}}refreshAllStashpadViews(){for(let t of this.app.workspace.getLeavesOfType(J)){let e=t.view;e&&typeof e.render=="function"&&e.render()}}openFolderPicker(){let t=I=>{let f=I.getViewState().state?.folderOverride;return typeof f=="string"&&f.trim()?f.trim().replace(/^\/+|\/+$/g,""):(this.settings.folder||"Stashpad").trim().replace(/^\/+|\/+$/g,"")},e=this.app.workspace.getLeavesOfType(J),i=this.discoverStashpadFolders(),s=ie(),n=s?(s.noteFolder??"").trim().replace(/^\/+|\/+$/g,""):"",o=new Set;for(let I of this.app.vault.getAllLoadedFiles())if(I.children){let u=I.path;u&&u!=="/"&&!u.startsWith(".")&&o.add(u)}let r=I=>{let u=I.split("/").filter(Boolean).pop()??"";return u?new Set([this.settings.importDropFolder,this.settings.exportFolder,"_attachments","_processed","_authors","_exports","_imports","_archive",".archive","_deleted"].map(C=>(C??"").trim().replace(/^\/+|\/+$/g,"")).filter(Boolean)).has(u):!1},A=new Set,l=[],d=[],p=new Set;for(let I of e){let u=t(I);if(p.has(u))continue;p.add(u),A.add(u);let f=u.split("/").pop()||u;l.push({kind:"reveal",folder:u,label:`Reveal "${f}" tab`,leaf:I,icon:this.isArchiveFolder(u)?"archive":"layout-grid"}),d.push({kind:"open-anyway",folder:u,label:`Open "${f}" in another new tab`,icon:"layout-template"})}for(let I of i.filter(u=>!A.has(u))){let u=I.split("/").pop()||I;l.push({kind:"open",folder:I,label:`Open "${u}" in new tab`,icon:this.isArchiveFolder(I)?"archive":"layout-template"})}let g=this,h=new class extends T.SuggestModal{getSuggestions(I){let u=I.trim().toLowerCase(),f=u?u.split(/\s+/).filter(Boolean):[],C=Q=>{if(!f.length)return!0;let E=Q.toLowerCase();for(let v of f)if(!E.includes(v))return!1;return!0},B=u?l.filter(Q=>{let E="folder"in Q?Q.folder:"";return C(Q.label)||C(E)}):l.slice();if(u&&s&&n)for(let Q of i){if(Q.toLowerCase()===n.toLowerCase())continue;let E=Q.split("/").pop()??Q,v=`${Q} ${E}`;C(v)&&B.push({kind:"switch-current",folder:Q,label:`Switch this tab to "${E}"`,icon:"folder-input"})}let m=I.trim().replace(/^\/+|\/+$/g,"");if(m&&!r(m)){let Q=Array.from(o).find(v=>v.toLowerCase()===m.toLowerCase()),E=i.some(v=>v.toLowerCase()===m.toLowerCase());if(Q&&!E)B.push({kind:"convert",folder:Q,label:`Convert \u201C${ai(Q)}\u201D into a Stashpad\u2026`,icon:"folder-cog"});else if(!Q){let v=ai(m);B.push({kind:"create",folder:m,label:`+ Create new Stashpad \u201C${v}\u201D`,icon:"folder-plus"})}}let y=d.filter(Q=>C(Q.label)||C("folder"in Q?Q.folder:""));return B.push(...y),g.encryption?.isConfigured?.()&&C("trash deleted encrypted")&&B.push({kind:"trash",label:"Open encrypted trash",icon:"trash-2"}),B}renderSuggestion(I,u){u.addClass("stashpad-suggest-item"),u.addClass("stashpad-ribbon-suggest-item"),I.kind==="create"&&u.addClass("stashpad-suggest-create");let f=u.createSpan({cls:"stashpad-ribbon-suggest-icon"});(0,T.setIcon)(f,I.icon);let C=u.createDiv({cls:"stashpad-ribbon-suggest-body"});C.createDiv({cls:"stashpad-suggest-title",text:I.label}),"folder"in I&&I.folder&&I.label!==I.folder&&C.createDiv({cls:"stashpad-suggest-preview",text:I.folder})}async onChooseSuggestion(I){if(I.kind==="trash"){g.openEncryptedTrash();return}if(I.kind==="reveal"){g.app.workspace.revealLeaf(I.leaf);return}if(I.kind==="open"||I.kind==="open-anyway"){await g.activateViewForFolder(I.folder);return}if(I.kind==="switch-current"){let u=s;u&&typeof u.setFolderOverride=="function"&&(await u.setFolderOverride(I.folder),g.app.workspace.revealLeaf(u.leaf));return}if(I.kind==="create"){try{let u=ai(I.folder);await g.app.vault.adapter.exists(u)||await g.app.vault.createFolder(u),await g.activateViewForFolder(u)}catch(u){new T.Notice(`Stashpad: couldn't create folder (${u.message})`)}return}if(I.kind==="convert"){let{ConfirmModal:u}=await Promise.resolve().then(()=>(Ft(),fi)),f=I.folder,C=[`\u201C${f}\u201D already exists as a regular vault folder.`,"Converting adds a Home note + _imports / _exports subfolders, and imports the existing loose files and subfolders inside it as notes.","(Files already structured as notes, and reserved subfolders, are left alone.)"];new u(g.app,"Convert into a Stashpad?",C.join(` +`),"Convert & import",async B=>{if(B)try{await g.activateViewForFolder(f),await g.runImportLooseFiles(f)}catch(m){new T.Notice(`Stashpad: couldn't convert folder (${m.message})`)}}).open();return}}}(this.app);h.setPlaceholder(s?"Open, switch this tab, or create a Stashpad folder \u2014 type to filter\u2026":"Open or create a Stashpad folder \u2014 type to filter\u2026"),h.open()}async openTinyWindow(){let t=ie(),e=t?.folderOverride??null,i=t?.focusId??"__root__",s=!!t?.compactMode,n=this.app.workspace.openPopoutLeaf?.();if(!n){new T.Notice("Stashpad: couldn't open popout window on this build.");return}await n.setViewState({type:J,active:!0,state:{folderOverride:e,focusId:i,tinyMode:!0,tinyAlwaysOnTop:!1,compactMode:s}});try{this.app.workspace.revealLeaf(n)}catch{}}async activateView(t={reveal:!0}){let{workspace:e}=this.app;if(t.reveal){let s=e.getLeavesOfType(J);if(s.length>0){e.revealLeaf(s[0]);return}}let i=e.getLeaf("tab");await i.setViewState({type:J,active:!0}),e.revealLeaf(i)}async focusLastStashpadTab(){let t=this.app.workspace,e=t.getLeavesOfType(J),i=this.lastActiveStashpadLeaf&&e.includes(this.lastActiveStashpadLeaf)?this.lastActiveStashpadLeaf:e[0]??null;if(!i){await this.activateView({reveal:!0});return}t.revealLeaf(i),t.setActiveLeaf(i,{focus:!0})}async focusFolderPanel(){await Os(this.app);let t=this.app.workspace.getLeavesOfType(Qe)[0];t&&this.app.workspace.setActiveLeaf(t,{focus:!0})}async reconcileLockedRegistry(){let t=this.settings.lockedSubtrees??[],e=[];for(let n of t){let o=(n.folder??"").replace(/\/+$/,"");if(!(o==="_deleted"||o.startsWith("_deleted/")))try{await this.app.vault.adapter.exists(n.blob)&&e.push(n)}catch{e.push(n)}}let i=e.length!==t.length,s=new Set(e.map(n=>n.blob));for(let n of this.app.vault.getFiles()){if(n.extension!=="stashenc"||s.has(n.path))continue;let o=n.parent?.path?.replace(/\/+$/,"")??"";if(o==="_deleted"||o.startsWith("_deleted/"))continue;let r=await Da(this.app,n.path);r&&(e.push({folder:o,blob:n.path,parentId:r.parentId,title:r.title,count:r.count,created:r.created,rootId:r.rootId,prevSibling:r.prevSibling}),i=!0)}i&&(this.settings.lockedSubtrees=e,await this.saveSettings(),this.refreshAllStashpadViews?.())}lockedSubtreesFor(t,e){let i=t.replace(/\/+$/,""),s=[],n=new Set;for(let o of this.settings.lockedSubtrees??[])(o.folder??"").replace(/\/+$/,"")===i&&(o.parentId??F)===e&&(s.push({blob:o.blob,title:o.title??"",count:o.count??0,created:o.created??"",rootId:o.rootId,parentId:o.parentId??F,prevSibling:o.prevSibling??null}),n.add(o.blob));for(let o of this.app.vault.getFiles()){if(o.extension!=="stashenc"||n.has(o.path))continue;let r=o.parent?.path?.replace(/\/+$/,"")??"";r!==i||r==="_deleted"||r.startsWith("_deleted/")||e===F&&s.push({blob:o.path,title:o.basename,count:0,created:"",rootId:void 0,parentId:F,prevSibling:null})}return s}async ensureEncryptionUnlocked(){return this.encryption.isConfigured()?this.encryption.isUnlocked()||await this.encryption.tryAutoUnlock()?!0:new Promise(t=>{new vt(this.app,{mode:"unlock",offerKeychain:!0,onSubmit:async({current:e,remember:i})=>await this.encryption.unlock(e,i)?(t(!0),null):"Wrong password. Try again.",onCancel:()=>t(!1)}).open()}):(new T.Notice("Set up encryption first (Settings \u2192 Encryption)."),!1)}async lockNoteSubtree(t,e,i=null,s={}){if(!await this.ensureEncryptionUnlocked())return null;let n=this.encryption.getSessionKey();if(!n)return null;try{let o=this.settings.hideLockedTitles??!1,r=await Na(this.app,t,e,n,i,o,s.blobFolder),A=(s.blobFolder??t).replace(/\/+$/,"");return this.settings.lockedSubtrees=[...(this.settings.lockedSubtrees??[]).filter(l=>l.blob!==r.blobPath),{folder:A,blob:r.blobPath,parentId:r.parentId,title:r.title,count:r.noteCount,created:r.created,rootId:r.rootId,prevSibling:i}],await this.saveSettings(),r.unpurged.length>0?new T.Notice(`\u26A0\uFE0F Locked, but ${r.unpurged.length} file${r.unpurged.length===1?" is":"s are"} still in plaintext (couldn't be removed or changed during the lock): ${r.unpurged.join(` -`)}`,0):s.silent||this.notifications.show({message:`Locked ${r.title?`\u201C${r.title}\u201D`:"a note"} (${r.noteCount} note${r.noteCount===1?"":"s"}).`,kind:"success",category:"system",folder:t}),r}catch(o){return console.warn("[Stashpad] lock failed",o),new T.Notice(`Couldn't lock: ${o.message}`),null}}async unlockBundleCore(t,e,i){let s=(i??t.replace(/\/[^/]*$/,"")).replace(/\/+$/,""),n=new Set;for(let o of this.app.vault.getMarkdownFiles())if((o.parent?.path?.replace(/\/+$/,"")??"")===s)try{let r=lt(await this.app.vault.read(o)).fm.id;typeof r=="string"&&n.add(r)}catch{}return Qa(this.app,t,e,n,i)}async unlockBundleAt(t,e={}){if(!await this.ensureEncryptionUnlocked())return!1;let i=this.encryption.getSessionKey();if(!i)return!1;let s=(e.destFolder??t.replace(/\/[^/]*$/,"")).replace(/\/+$/,"");try{let n=await this.unlockBundleCore(t,i,e.destFolder);return this.settings.lockedSubtrees=(this.settings.lockedSubtrees??[]).filter(o=>o.blob!==t),await this.saveSettings(),e.silent||this.notifications.show({message:`Unlocked ${n.notesWritten} note${n.notesWritten===1?"":"s"}.`,kind:"success",category:"system",folder:s}),!0}catch(n){return console.warn("[Stashpad] unlock failed",n),new T.Notice(`Couldn't unlock: ${n.message}`),!1}}async lockFolder(t){if(!await this.ensureEncryptionUnlocked())return 0;let e=t.replace(/\/+$/,""),i=[];for(let d of this.app.vault.getMarkdownFiles()){if((d.parent?.path?.replace(/\/+$/,"")??"")!==e)continue;let g;try{g=lt(await this.app.vault.read(d)).fm}catch{continue}let p=g.id;typeof p!="string"||p===F||(typeof g.parent=="string"?g.parent:F)!==F||i.push(p)}let s=new Set((this.settings.lockedSubtrees??[]).map(d=>d.rootId).filter(d=>!!d)),n=i.filter(d=>!s.has(d));if(n.length===0)return new T.Notice("Nothing to lock in this folder."),0;let r=(await new Ke(this.app).load(e))[F]??[],A=n.length>3?new T.Notice("",0):null,l=0;for(let d=0;d<n.length;d++){let g=n[d];A?.setMessage(`\u{1F512} Encrypting ${d+1}/${n.length}\u2026`);let p=r.indexOf(g),h=p>0?r[p-1]:null;await this.lockNoteSubtree(e,g,h,{silent:!0})&&l++}return A?.hide(),l>0&&this.notifications.show({message:`Locked ${l} note${l===1?"":"s"} in \u201C${e.split("/").pop()}\u201D.`,kind:"success",category:"system",folder:e}),l}async unlockFolder(t){if(!await this.ensureEncryptionUnlocked())return 0;let e=t.replace(/\/+$/,""),i=this.app.vault.getFiles().filter(o=>o.extension==="stashenc"&&(o.parent?.path?.replace(/\/+$/,"")??"")===e).map(o=>o.path);if(i.length===0)return new T.Notice("No locked notes in this folder."),0;let s=i.length>3?new T.Notice("",0):null,n=0;for(let o=0;o<i.length;o++){s?.setMessage(`\u{1F513} Decrypting ${o+1}/${i.length}\u2026`);try{await this.unlockBundleAt(i[o],{silent:!0})&&n++}catch(r){console.warn("[Stashpad] folder unlock skipped",i[o],r)}}return s?.hide(),n>0&&this.notifications.show({message:`Unlocked ${n} note${n===1?"":"s"} in \u201C${e.split("/").pop()}\u201D.`,kind:"success",category:"system",folder:e}),n}async unlockAllInVault(){if(!await this.ensureEncryptionUnlocked())return 0;let t=this.app.vault.getFiles().filter(r=>r.extension==="stashenc"&&(r.parent?.path?.replace(/\/+$/,"")??"")!=="_deleted").map(r=>r.path);if(t.length===0)return new T.Notice("No locked notes anywhere in the vault."),0;let e=this.encryption.getSessionKey();if(!e)return 0;let i=t.length>3?new T.Notice("",0):null,s=0,n=[];for(let r=0;r<t.length;r++){i?.setMessage(`\u{1F513} Decrypting ${r+1}/${t.length}\u2026`);try{let A=await this.unlockBundleCore(t[r],e);s+=A.notesWritten,n.push(t[r])}catch(A){console.warn("[Stashpad] vault unlock skipped",t[r],A)}}if(n.length>0){let r=new Set(n);this.settings.lockedSubtrees=(this.settings.lockedSubtrees??[]).filter(A=>!r.has(A.blob)),await this.saveSettings()}i?.hide();let o=t[0].replace(/\/[^/]*$/,"");return s>0&&this.notifications.show({message:`Unlocked ${s} note${s===1?"":"s"} across the vault.`,kind:"success",category:"system",folder:o}),s}async encryptDeleteSubtree(t,e){if(!await this.ensureEncryptionUnlocked())return null;let i=this.encryption.getSessionKey();if(!i)return null;try{let s=new Date().toISOString(),n=(this.settings.hideLockedTitles??!1)||(this.settings.encryptTrashFilenames??!1),o=await ya(this.app,t,e,i,s,n);return o.unpurged.length>0&&new T.Notice(`\u26A0\uFE0F Sent to encrypted trash, but ${o.unpurged.length} file${o.unpurged.length===1?" is":"s are"} still in plaintext (couldn't be removed or changed during the delete): +`)}`,0):s.silent||this.notifications.show({message:`Locked ${r.title?`\u201C${r.title}\u201D`:"a note"} (${r.noteCount} note${r.noteCount===1?"":"s"}).`,kind:"success",category:"system",folder:t}),r}catch(o){return console.warn("[Stashpad] lock failed",o),new T.Notice(`Couldn't lock: ${o.message}`),null}}async unlockBundleCore(t,e,i){let s=(i??t.replace(/\/[^/]*$/,"")).replace(/\/+$/,""),n=new Set;for(let o of this.app.vault.getMarkdownFiles())if((o.parent?.path?.replace(/\/+$/,"")??"")===s)try{let r=lt(await this.app.vault.read(o)).fm.id;typeof r=="string"&&n.add(r)}catch{}return xa(this.app,t,e,n,i)}async unlockBundleAt(t,e={}){if(!await this.ensureEncryptionUnlocked())return!1;let i=this.encryption.getSessionKey();if(!i)return!1;let s=(e.destFolder??t.replace(/\/[^/]*$/,"")).replace(/\/+$/,"");try{let n=await this.unlockBundleCore(t,i,e.destFolder);return this.settings.lockedSubtrees=(this.settings.lockedSubtrees??[]).filter(o=>o.blob!==t),await this.saveSettings(),e.silent||this.notifications.show({message:`Unlocked ${n.notesWritten} note${n.notesWritten===1?"":"s"}.`,kind:"success",category:"system",folder:s}),!0}catch(n){return console.warn("[Stashpad] unlock failed",n),new T.Notice(`Couldn't unlock: ${n.message}`),!1}}async lockFolder(t){if(!await this.ensureEncryptionUnlocked())return 0;let e=t.replace(/\/+$/,""),i=[];for(let d of this.app.vault.getMarkdownFiles()){if((d.parent?.path?.replace(/\/+$/,"")??"")!==e)continue;let p;try{p=lt(await this.app.vault.read(d)).fm}catch{continue}let g=p.id;typeof g!="string"||g===F||(typeof p.parent=="string"?p.parent:F)!==F||i.push(g)}let s=new Set((this.settings.lockedSubtrees??[]).map(d=>d.rootId).filter(d=>!!d)),n=i.filter(d=>!s.has(d));if(n.length===0)return new T.Notice("Nothing to lock in this folder."),0;let r=(await new $e(this.app).load(e))[F]??[],A=n.length>3?new T.Notice("",0):null,l=0;for(let d=0;d<n.length;d++){let p=n[d];A?.setMessage(`\u{1F512} Encrypting ${d+1}/${n.length}\u2026`);let g=r.indexOf(p),h=g>0?r[g-1]:null;await this.lockNoteSubtree(e,p,h,{silent:!0})&&l++}return A?.hide(),l>0&&this.notifications.show({message:`Locked ${l} note${l===1?"":"s"} in \u201C${e.split("/").pop()}\u201D.`,kind:"success",category:"system",folder:e}),l}async unlockFolder(t){if(!await this.ensureEncryptionUnlocked())return 0;let e=t.replace(/\/+$/,""),i=this.app.vault.getFiles().filter(o=>o.extension==="stashenc"&&(o.parent?.path?.replace(/\/+$/,"")??"")===e).map(o=>o.path);if(i.length===0)return new T.Notice("No locked notes in this folder."),0;let s=i.length>3?new T.Notice("",0):null,n=0;for(let o=0;o<i.length;o++){s?.setMessage(`\u{1F513} Decrypting ${o+1}/${i.length}\u2026`);try{await this.unlockBundleAt(i[o],{silent:!0})&&n++}catch(r){console.warn("[Stashpad] folder unlock skipped",i[o],r)}}return s?.hide(),n>0&&this.notifications.show({message:`Unlocked ${n} note${n===1?"":"s"} in \u201C${e.split("/").pop()}\u201D.`,kind:"success",category:"system",folder:e}),n}async unlockAllInVault(){if(!await this.ensureEncryptionUnlocked())return 0;let t=this.app.vault.getFiles().filter(r=>r.extension==="stashenc"&&(r.parent?.path?.replace(/\/+$/,"")??"")!=="_deleted").map(r=>r.path);if(t.length===0)return new T.Notice("No locked notes anywhere in the vault."),0;let e=this.encryption.getSessionKey();if(!e)return 0;let i=t.length>3?new T.Notice("",0):null,s=0,n=[];for(let r=0;r<t.length;r++){i?.setMessage(`\u{1F513} Decrypting ${r+1}/${t.length}\u2026`);try{let A=await this.unlockBundleCore(t[r],e);s+=A.notesWritten,n.push(t[r])}catch(A){console.warn("[Stashpad] vault unlock skipped",t[r],A)}}if(n.length>0){let r=new Set(n);this.settings.lockedSubtrees=(this.settings.lockedSubtrees??[]).filter(A=>!r.has(A.blob)),await this.saveSettings()}i?.hide();let o=t[0].replace(/\/[^/]*$/,"");return s>0&&this.notifications.show({message:`Unlocked ${s} note${s===1?"":"s"} across the vault.`,kind:"success",category:"system",folder:o}),s}async encryptDeleteSubtree(t,e){if(!await this.ensureEncryptionUnlocked())return null;let i=this.encryption.getSessionKey();if(!i)return null;try{let s=new Date().toISOString(),n=(this.settings.hideLockedTitles??!1)||(this.settings.encryptTrashFilenames??!1),o=await Ma(this.app,t,e,i,s,n);return o.unpurged.length>0&&new T.Notice(`\u26A0\uFE0F Sent to encrypted trash, but ${o.unpurged.length} file${o.unpurged.length===1?" is":"s are"} still in plaintext (couldn't be removed or changed during the delete): ${o.unpurged.join(` -`)}`,0),o.blobPath}catch(s){return console.warn("[Stashpad] encrypt-delete failed",s),new T.Notice(`Couldn't encrypt-delete: ${s.message}`,0),null}}async restoreDeletedAt(t,e={}){if(!await this.ensureEncryptionUnlocked())return!1;let i=this.encryption.getSessionKey();if(!i)return!1;let s=await hs(this.app,t);if(s?.kind==="rawtrash")try{let n=await va(this.app,t,i);return e.silent||this.notifications.show({message:`Restored ${n.filesWritten} file${n.filesWritten===1?"":"s"} to Obsidian's trash (${Ut}/).`,kind:"success",category:"system",folder:""}),!0}catch(n){return console.warn("[Stashpad] trash-backfill restore failed",n),new T.Notice(`Couldn't restore: ${n.message}`,0),!1}try{let n=await Jn(this.app,t,s,i),o=new Set;for(let A of this.app.vault.getMarkdownFiles())if((A.parent?.path?.replace(/\/+$/,"")??"")===n.replace(/\/+$/,""))try{let l=lt(await this.app.vault.read(A)).fm.id;typeof l=="string"&&o.add(l)}catch{}let r=await Ea(this.app,t,i,o);return e.silent||this.notifications.show({message:`Restored ${r.notesWritten} note${r.notesWritten===1?"":"s"} to \u201C${r.restoredTo.split("/").pop()}\u201D.`,kind:"success",category:"system",folder:r.restoredTo}),!0}catch(n){return console.warn("[Stashpad] restore-from-trash failed",n),new T.Notice(`Couldn't restore: ${n.message}`,0),!1}}async listDeletedTrash(){let t=await Fa(this.app),e=[];for(let i of t)e.push({blob:i,meta:await hs(this.app,i)});return e}async restoreAllTrash(){if(!await this.ensureEncryptionUnlocked())return 0;let t=await this.listDeletedTrash();if(t.length===0)return new T.Notice("Nothing to restore."),0;let e=t.length>3?new T.Notice("",0):null,i=0;for(let s=0;s<t.length;s++){e?.setMessage(`\u{1F513} Restoring ${s+1}/${t.length}\u2026`);try{await this.restoreDeletedAt(t[s].blob,{silent:!0})&&i++}catch(n){console.warn("[Stashpad] restore-all skipped",t[s].blob,n)}}return e?.hide(),i>0&&this.notifications.show({message:`Restored ${i} note${i===1?"":"s"} from encrypted trash.`,kind:"success",category:"system",folder:""}),i}async encryptExistingTrash(){if(!await this.ensureEncryptionUnlocked())return!1;let t=this.encryption.getSessionKey();if(!t)return!1;try{let e=(this.settings.hideLockedTitles??!1)||(this.settings.encryptTrashFilenames??!1),i=await wa(this.app,t,new Date().toISOString(),e);return i?(i.unpurged.length>0?new T.Notice(`\u26A0\uFE0F Encrypted the trash, but ${i.unpurged.length} file${i.unpurged.length===1?" is":"s are"} still in plaintext (couldn't be removed): +`)}`,0),o.blobPath}catch(s){return console.warn("[Stashpad] encrypt-delete failed",s),new T.Notice(`Couldn't encrypt-delete: ${s.message}`,0),null}}async restoreDeletedAt(t,e={}){if(!await this.ensureEncryptionUnlocked())return!1;let i=this.encryption.getSessionKey();if(!i)return!1;let s=await Bs(this.app,t);if(s?.kind==="rawtrash")try{let n=await Pa(this.app,t,i);return e.silent||this.notifications.show({message:`Restored ${n.filesWritten} file${n.filesWritten===1?"":"s"} to Obsidian's trash (${Rt}/).`,kind:"success",category:"system",folder:""}),!0}catch(n){return console.warn("[Stashpad] trash-backfill restore failed",n),new T.Notice(`Couldn't restore: ${n.message}`,0),!1}try{let n=await Wn(this.app,t,s,i),o=new Set;for(let A of this.app.vault.getMarkdownFiles())if((A.parent?.path?.replace(/\/+$/,"")??"")===n.replace(/\/+$/,""))try{let l=lt(await this.app.vault.read(A)).fm.id;typeof l=="string"&&o.add(l)}catch{}let r=await Ta(this.app,t,i,o);return e.silent||this.notifications.show({message:`Restored ${r.notesWritten} note${r.notesWritten===1?"":"s"} to \u201C${r.restoredTo.split("/").pop()}\u201D.`,kind:"success",category:"system",folder:r.restoredTo}),!0}catch(n){return console.warn("[Stashpad] restore-from-trash failed",n),new T.Notice(`Couldn't restore: ${n.message}`,0),!1}}async listDeletedTrash(){let t=await Ua(this.app),e=[];for(let i of t)e.push({blob:i,meta:await Bs(this.app,i)});return e}async restoreAllTrash(){if(!await this.ensureEncryptionUnlocked())return 0;let t=await this.listDeletedTrash();if(t.length===0)return new T.Notice("Nothing to restore."),0;let e=t.length>3?new T.Notice("",0):null,i=0;for(let s=0;s<t.length;s++){e?.setMessage(`\u{1F513} Restoring ${s+1}/${t.length}\u2026`);try{await this.restoreDeletedAt(t[s].blob,{silent:!0})&&i++}catch(n){console.warn("[Stashpad] restore-all skipped",t[s].blob,n)}}return e?.hide(),i>0&&this.notifications.show({message:`Restored ${i} note${i===1?"":"s"} from encrypted trash.`,kind:"success",category:"system",folder:""}),i}async encryptExistingTrash(){if(!await this.ensureEncryptionUnlocked())return!1;let t=this.encryption.getSessionKey();if(!t)return!1;try{let e=(this.settings.hideLockedTitles??!1)||(this.settings.encryptTrashFilenames??!1),i=await Ha(this.app,t,new Date().toISOString(),e);return i?(i.unpurged.length>0?new T.Notice(`\u26A0\uFE0F Encrypted the trash, but ${i.unpurged.length} file${i.unpurged.length===1?" is":"s are"} still in plaintext (couldn't be removed): ${i.unpurged.join(` -`)}`,0):this.notifications.show({message:`Encrypted ${i.fileCount} trash file${i.fileCount===1?"":"s"} into the encrypted trash. Restore from the trash tab puts them back in ${Ut}/.`,kind:"success",category:"system",folder:""}),!0):(new T.Notice(`Obsidian's vault trash (${Ut}/) is empty \u2014 nothing to encrypt. (Files in the system/OS trash can't be reached.)`,8e3),!1)}catch(e){return console.warn("[Stashpad] trash backfill failed",e),new T.Notice(`Couldn't encrypt the existing trash: ${e.message}`,0),!1}}openEncryptedTrash(t){if(!this.encryption.isConfigured()){new T.Notice("Set up encryption first (Settings \u2192 Encryption).");return}$a(this)}async openRestoreTrashPicker(){if(!this.encryption.isConfigured()){new T.Notice("Set up encryption first (Settings \u2192 Encryption).");return}let t=await this.listDeletedTrash();if(t.length===0){new T.Notice("Encrypted trash is empty.");return}let e=t.map(({blob:i,meta:s})=>({blob:i,label:s?.title||i.split("/").pop()?.replace(/\.stashenc$/,"")||"Locked note",folder:s?.originalFolder||"(unknown)"}));new Ms(this.app,e,i=>{this.restoreDeletedAt(i)}).open()}isArchiveFolder(t){let e=t.replace(/\/+$/,"");return(this.settings.archiveFolders??[]).includes(e)}async ensureOkfTemplate(){let t=await Wa(this.app,this.settings.okfTemplatePath||void 0);return this.settings.okfTemplatePath!==t&&(this.settings.okfTemplatePath=t,await this.saveSettings()),t}okfTemplatePathOrDefault(){return this.settings.okfTemplatePath||so}okfActiveFolders(){return this.settings.okfEnabled?Xa(this.settings.noteTemplates,this.okfTemplatePathOrDefault()).filter(t=>!this.isArchiveFolder(t)):[]}async rebuildOkfSuppressed(t){this.okfRebuildingFolders.add(t);try{return await oo(this.app,t)}finally{window.setTimeout(()=>{this.okfRebuildingFolders.delete(t);for(let e of this.app.workspace.getLeavesOfType(J)){let i=e.view;i?.noteFolder===t&&i.forceReconcileRender?.()}},600)}}onOkfFileEvent(t){if(!this.settings.okfEnabled||!t.toLowerCase().endsWith(".md"))return;let e=t.lastIndexOf("/"),i=(e>=0?t.slice(0,e):"").replace(/\/+$/,"");(e>=0?t.slice(e+1):t)!=="index.md"&&(/(^|\/)(_imports|_exports|_attachments|_deleted|\.stashpad)(\/|$)/.test(t)||this.okfActiveFolders().includes(i)&&this.scheduleOkfRebuild(i))}scheduleOkfRebuild(t){let e=this.okfRebuildTimers.get(t);e!=null&&window.clearTimeout(e),this.okfRebuildTimers.set(t,window.setTimeout(()=>{this.okfRebuildTimers.delete(t),this.okfActiveFolders().includes(t)&&this.rebuildOkfSuppressed(t).catch(i=>console.warn("[Stashpad] OKF auto-rebuild failed",t,i))},2500))}async rebuildAllOkf(){let t=this.okfActiveFolders(),e=0,i=0;for(let s of t){let n=await this.rebuildOkfSuppressed(s);e+=n.checked,i+=n.written}return{folders:t.length,checked:e,written:i}}async exportOkf(t,e,i,s){let n=t.replace(/\/+$/,""),o=[],r=[],A=[],l=new Set;for(let f of e){let C=await he(this.app,n,f);if(C){o.push({id:C.rootNote.id,file:C.rootNote.file}),A.push(C.rootNote.file),l.add(C.rootNote.id);for(let B of C.descendants)r.push({id:B.id,file:B.file}),A.push(B.file),l.add(B.id)}}if(!A.length)return[];let d=(i||"okf-export").replace(/[\\/:*?"<>|]+/g," ").replace(/\s+/g," ").trim().slice(0,80)||"okf-export",g=new Date().toISOString().replace(/\D/g,"").slice(0,14),p=(this.settings.exportFolder||"_exports").trim().replace(/^\/+|\/+$/g,""),h=`${n}/${p}`;for(let f of[n,h])try{await this.app.vault.adapter.exists(f)||await this.app.vault.adapter.mkdir(f)}catch{}let I=[],u=async(f,C)=>{let B=`${h}/${f}`;await this.app.vault.createBinary(B,C.buffer.slice(C.byteOffset,C.byteOffset+C.byteLength)),I.push(B)};if(s.zip||s.targz){let f=await Za(this.app,A,n,l);s.zip&&await u(`${d}-${g}.okf.zip`,await ja(f)),s.targz&&await u(`${d}-${g}.okf.tar.gz`,await _a(f))}if(s.stash){let f=await Ae(this.app,{rootNotes:o,allDescendants:r,sourceFolder:n});await u(`${d}-${g}.${jt}`,f)}return I}async idsInFolder(t){let e=t.replace(/\/+$/,""),i=new Set;for(let s of this.app.vault.getMarkdownFiles())if((s.parent?.path?.replace(/\/+$/,"")??"")===e)try{let n=lt(await this.app.vault.read(s)).fm.id;typeof n=="string"&&i.add(n)}catch{}return i}async crossFolderPaste(t,e,i,s,n){let o=i.replace(/\/+$/,"");if(this.isArchiveFolder(o))return new T.Notice(`"${o.split("/").pop()}" auto-encrypts notes moved in, so cross-folder paste is disabled there. Use the "Move to archive" command \u2014 it checks the encryption key first.`),null;let r=[],A=[],l=[],d=[];for(let y of e){let b=await he(this.app,t,y);if(b){l.push(b.rootNote.id),r.push({id:b.rootNote.id,file:b.rootNote.file}),d.push(b.rootNote.file);for(let N of b.descendants)A.push({id:N.id,file:N.file}),d.push(N.file)}}if(!r.length)return null;let g=r.length+A.length,p=[],h=[];n==="cut"&&(p=await this.exclusiveAttachmentsOf(d),h=await this.snapshotPaths([...d.map(y=>y.path),...p.map(y=>y.path)]));let I=await Ae(this.app,{rootNotes:r,allDescendants:A,sourceFolder:t}),u=await this.idsInFolder(o),f=new Set(this.filesUnder(o)),C=await Kt(this.app,I,o,u,{dedupeExisting:!1,forceNewIds:n==="copy",reparentRootsTo:s}),B=this.filesUnder(o).filter(y=>!f.has(y)),m=await this.snapshotPaths(B),w=l.map(y=>C.idRemap[y]).filter(y=>!!y);if(n==="cut"){for(let y of d)try{await this.app.fileManager.trashFile(y)}catch(b){console.warn("[Stashpad] cross-folder move: couldn't trash source note",y.path,b)}for(let y of p)try{await this.app.fileManager.trashFile(y)}catch(b){console.warn("[Stashpad] cross-folder move: couldn't trash source attachment",y.path,b)}}let Q=async()=>{for(let y of[...B].reverse()){let b=this.app.vault.getAbstractFileByPath(y);if(b)try{await this.app.fileManager.trashFile(b)}catch{}}};return{rootIds:w,noteCount:g,undo:n==="cut"?async()=>{await Q(),await this.restoreSnapshot(h)}:async()=>{await Q()},redo:n==="cut"?async()=>{await this.restoreSnapshot(m);for(let y of h){let b=this.app.vault.getAbstractFileByPath(y.path);if(b)try{await this.app.fileManager.trashFile(b)}catch{}}}:async()=>{await this.restoreSnapshot(m)}}}async trashSubtrees(t,e){let i=[];for(let o of e){let r=await he(this.app,t,o);r&&i.push(r.rootNote.file,...r.descendants.map(A=>A.file))}if(!i.length)return[];let s=await this.exclusiveAttachmentsOf(i),n=[];for(let o of[...i,...s])try{await this.app.fileManager.trashFile(o),n.push(o)}catch(r){console.warn("[Stashpad] trashSubtrees: couldn't trash",o.path,r)}return n}async exclusiveAttachmentsOf(t){let e=new Set(t.map(n=>n.path)),i=new Map;for(let n of t)for(let o of await cs(this.app,n))i.set(o.path,o);let s=this.app.metadataCache.resolvedLinks??{};for(let n of Object.keys(s))if(!e.has(n))for(let o of Object.keys(s[n]??{}))i.delete(o);return[...i.values()]}async subtreeFilePaths(t,e){let i=[];for(let n of e){let o=await he(this.app,t,n);o&&i.push(o.rootNote.file,...o.descendants.map(r=>r.file))}if(!i.length)return[];let s=await this.exclusiveAttachmentsOf(i);return[...i.map(n=>n.path),...s.map(n=>n.path)]}async orderedSubtreeNodes(t,e){let i=[],s=new Set,n=o=>{let r=this.app.metadataCache.getFileCache(o)?.frontmatter?.position;return typeof r=="number"?r:Number.MAX_SAFE_INTEGER};for(let o of e){let r=await he(this.app,t,o);if(!r)continue;let A=new Map;for(let d of r.descendants){if(!d.parent)continue;let g=A.get(d.parent)??[];g.push({id:d.id,file:d.file,created:d.created}),A.set(d.parent,g)}for(let d of A.values())d.sort((g,p)=>n(g.file)-n(p.file)||g.created.localeCompare(p.created));let l=(d,g)=>{if(!s.has(d.id)){s.add(d.id),i.push({file:d.file,created:d.created,depth:g});for(let p of A.get(d.id)??[])l(p,g+1)}};l({id:r.rootNote.id,file:r.rootNote.file,created:r.rootNote.created},0)}return i}filesUnder(t){let e=t.replace(/\/+$/,"")+"/";return this.app.vault.getFiles().filter(i=>i.path.startsWith(e)).map(i=>i.path)}async snapshotPaths(t){let e=[];for(let i of t){let s=this.app.vault.getAbstractFileByPath(i);if(!s)continue;let n=!i.toLowerCase().endsWith(".md");try{n?e.push({path:i,binary:n,data:await this.app.vault.readBinary(s)}):e.push({path:i,binary:n,text:await this.app.vault.read(s)})}catch(o){console.warn("[Stashpad] snapshotPaths: couldn't read",i,o)}}return e}async restoreSnapshot(t){for(let e of t){let i=e.path.split("/").slice(0,-1).join("/");await this.ensureVaultFolder(i);let s=this.app.vault.getAbstractFileByPath(e.path);try{e.binary?s?await this.app.vault.adapter.writeBinary(e.path,e.data):await this.app.vault.createBinary(e.path,e.data):s?await this.app.vault.modify(s,e.text??""):await this.app.vault.create(e.path,e.text??"")}catch(n){console.warn("[Stashpad] restoreSnapshot: couldn't write",e.path,n)}}}async ensureVaultFolder(t){if(!t)return;let e="";for(let i of t.split("/"))if(e=e?`${e}/${i}`:i,!await this.app.vault.adapter.exists(e))try{await this.app.vault.createFolder(e)}catch{}}refreshOpenViewsForFolder(t){let e=t.replace(/\/+$/,"");for(let i of this.app.workspace.getLeavesOfType(J)){let s=i.view;if((s?.noteFolder?.replace(/\/+$/,"")??"")===e)try{s.tree?.rebuild?.(t),s.render?.()}catch(n){console.warn("[Stashpad] refresh view failed",n)}}}maybeArchiveOnMoveIn(t,e){if(t.extension!=="md")return;let i=t.parent?.path?.replace(/\/+$/,"")??"",s=e.lastIndexOf("/"),n=(s>=0?e.slice(0,s):"").replace(/\/+$/,"");if(i===n||!this.isArchiveFolder(i)||!this.encryption.isConfigured())return;let o=this.archivePending.get(i);o||(o={paths:new Set,timer:0},this.archivePending.set(i,o)),o.paths.add(t.path),window.clearTimeout(o.timer),o.timer=window.setTimeout(()=>{this.archivePending.delete(i),this.archiveSweep(i,[...o.paths])},1800)}async archiveSweep(t,e){if(!this.isArchiveFolder(t))return;let i=t.replace(/\/+$/,""),s=[];for(let l of e){let d=this.app.vault.getAbstractFileByPath(l);if(!(d instanceof T.TFile)||(d.parent?.path?.replace(/\/+$/,"")??"")!==i)continue;let g;try{g=lt(await this.app.vault.read(d)).fm}catch{continue}let p=typeof g.id=="string"?g.id:null;!p||p===F||s.push({id:p,parent:typeof g.parent=="string"?g.parent:null})}if(s.length===0)return;let n=new Set(s.map(l=>l.id)),o=new Set((this.settings.lockedSubtrees??[]).map(l=>l.rootId).filter(l=>!!l)),r=s.filter(l=>!o.has(l.id)&&!(l.parent&&n.has(l.parent)));if(r.length===0)return;if(!await this.ensureEncryptionUnlocked()){new T.Notice(`\u26A0\uFE0F Archive folder "${i.split("/").pop()}": ${r.length} arriving note${r.length===1?"":"s"} NOT encrypted (vault is locked). Unlock encryption and lock them manually.`,0);return}let A=0;for(let l of r)await this.lockNoteSubtree(i,l.id,null,{silent:!0})&&A++;A>0&&this.notifications.show({message:`Archived (encrypted) ${A} note${A===1?"":"s"} moved into \u201C${i.split("/").pop()}\u201D.`,kind:"success",category:"system",folder:i})}async activateViewForFolder(t){let e=(t||"").replace(/^\/+|\/+$/g,"");if(!e)return null;let i=this.app.workspace.getLeaf("tab");return await i.setViewState({type:J,active:!0,state:{folderOverride:e}}),this.app.workspace.revealLeaf(i),i}navigateLeafTo(t,e,i){let s=t?.view;if(s?.navigateTo&&(!s.tree||s.tree.get(i))){s.navigateTo(i);return}this.navigateWhenReady(e,i)}async openFolderInStashpad(t){let e=(t||"").replace(/^\/+|\/+$/g,"");if(!e)return;let i=await this.findStashpadLeafForFolder(e);if(i){this.app.workspace.revealLeaf(i),this.app.workspace.setActiveLeaf(i,{focus:!0});return}await this.activateViewForFolder(e)}async findStashpadLeafForFolder(t){let e=t.replace(/\/+$/,""),i=this.app.workspace.getLeavesOfType(J),s=i.find(o=>!o.isDeferred&&(o.view?.noteFolder??"").replace(/\/+$/,"")===e);if(s)return s;let n=i.find(o=>o.isDeferred&&(o.getViewState()?.state?.folderOverride??"").replace(/\/+$/,"")===e);if(n){try{await n.loadIfDeferred?.()}catch{}return n}return null}isStashpadNoteFile(t){let e=t.parent?.path?.replace(/\/+$/,"")??"";if(!this.discoverStashpadFolders().includes(e))return!1;let i=this.app.metadataCache.getFileCache(t)?.frontmatter?.id;return typeof i=="string"&&i.length>0}async revealNoteInStashpad(t){let e=t.parent?.path?.replace(/\/+$/,"")??"",i=this.app.metadataCache.getFileCache(t)?.frontmatter?.id;if(!e||typeof i!="string"||!i){new T.Notice("That note isn't a Stashpad note.");return}await this.revealNoteByRef(e,i)}async revealNoteByRef(t,e){let i=t.replace(/\/+$/,""),s=await this.findStashpadLeafForFolder(i);if(s){this.app.workspace.revealLeaf(s),this.app.workspace.setActiveLeaf(s,{focus:!0}),this.navigateLeafTo(s,i,e);return}let n=await this.activateViewForFolder(i);this.navigateLeafTo(n,i,e)}async closeDuplicateStashpadTabs(){let t=this.app.workspace.getLeavesOfType(J),e=this.app.workspace.activeLeaf;for(let I of t)try{await I.loadIfDeferred?.()}catch{}let i=I=>I.getViewState()?.state??{},s=I=>{let u=i(I);return(I.isDeferred?u.folderOverride??"":I.view?.noteFolder??u.folderOverride??"").replace(/\/+$/,"")},n=I=>{let u=i(I);return(I.isDeferred?u.focusId:I.view?.focusId??u.focusId)||F},o=I=>{let u=I.view;return!!u&&u.getViewType?.()===J&&typeof u.navigateTo=="function"&&typeof u.noteFolder=="string"},r=new Map;for(let I of this.app.vault.getMarkdownFiles()){let u=(I.parent?.path??"").replace(/\/+$/,""),f=this.app.metadataCache.getFileCache(I)?.frontmatter?.id;typeof f=="string"&&f&&(r.get(u)??r.set(u,new Set).get(u)).add(f)}let A=0,l=[];for(let I of t){let u=s(I),f=n(I);if(u&&f&&f!==F){let C=!I.isDeferred&&!!I.view?.tree?.get?.(f),B=r.get(u)?.has(f)??!1;if(!C&&!B){I.detach(),A++;continue}}l.push(I)}let d=new Map;for(let I of l){let u=s(I);if(!u)continue;let f=u+" "+n(I);(d.get(f)??d.set(f,[]).get(f)).push(I)}let g=0;for(let I of d.values()){if(I.length<=1)continue;I.sort((f,C)=>{let B=m=>m===e?2:m.isDeferred?0:1;return B(C)-B(f)});let u=null;for(let f of I){try{await f.loadIfDeferred?.()}catch{}if(o(f)){u=f;break}}u||(u=I[0]);for(let f of I)f!==u&&(f.detach(),g++)}let p=this.app.workspace.getLeavesOfType(J).length,h=document.createDocumentFragment();return h.createEl("div",{text:g+A>0?"Stashpad tabs cleaned up:":"Stashpad tabs - nothing to clean up:"}),h.createEl("div",{text:`\u2022 ${g} duplicate tab${g===1?"":"s"} closed`}),h.createEl("div",{text:`\u2022 ${A} orphaned tab${A===1?"":"s"} pruned (note no longer exists)`}),h.createEl("div",{text:`\u2022 ${p} Stashpad tab${p===1?"":"s"} remaining`}),new T.Notice(h,7e3),g+A}navigateWhenReady(t,e,i=15){let s=t.replace(/\/+$/,""),n=this.app.workspace.getLeavesOfType(J).find(o=>(o.view?.noteFolder??"").replace(/\/+$/,"")===s)?.view??this.lastActiveStashpadLeaf?.view;if(n&&typeof n.navigateTo=="function"&&(!n.tree||typeof n.tree.get!="function"||!!n.tree.get(e))){n.navigateTo(e);return}i>0?window.setTimeout(()=>this.navigateWhenReady(t,e,i-1),90):n&&typeof n.navigateTo=="function"&&n.navigateTo(e)}collectAuthoredFolders(){let t=(this.settings.authorId??"").trim();if(!t)return[];let e=`-${t}`,i=this.discoverStashpadFolders(),s=new Map;for(let n of this.app.vault.getMarkdownFiles()){let o=this.app.metadataCache.getFileCache(n)?.frontmatter;if(!o)continue;let r=typeof o.author=="string"?o.author:"",A=Array.isArray(o.contributors)?o.contributors.filter(I=>typeof I=="string"):[],l=r.includes(e),d=A.some(I=>I.includes(e));if(!l&&!d)continue;let g=n.parent?.path??"",p=i.find(I=>g===I||g.startsWith(I+"/"));if(!p)continue;s.has(p)||s.set(p,{authored:0,contributed:0});let h=s.get(p);l&&h.authored++,d&&h.contributed++}return[...s.entries()].map(([n,o])=>({folder:n,...o})).sort((n,o)=>o.authored+o.contributed-(n.authored+n.contributed))}parseAuthorRef(t){return ne(t)}authorRefFor(t,e,i){let s=i.replace(/[^\w\- ]+/g,"").trim().replace(/\s+/g,"-")||"author",n=`${t.replace(/\/+$/,"")}/_authors/${s}-${e}.md`,o=i.replace(/[\[\]|]/g,"").trim()||s;return`[[${n}|${o}]]`}async ensureAuthorStubFor(t,e,i){if(!e||!i)return!1;this.authorRegistry.record({id:e,name:i});let s=`${t.replace(/\/+$/,"")}/_authors`;if(this.app.vault.getMarkdownFiles().some(l=>l.path.startsWith(s+"/")&&this.parseAuthorFilePath(l.path)?.id===e))return!1;let o=this.authorRegistry.get(e),r=this.authorNameToSafe(i),A=`${s}/${r}-${e}.md`;try{return await this.ensureFolderPath(s),await this.app.vault.adapter.exists(A)?!1:(await this.app.vault.create(A,this.buildAuthorStub({id:e,name:i,role:o?.role,department:o?.department},new Date().toISOString())),!0)}catch(l){return console.warn("[Stashpad] ensureAuthorStubFor failed",A,l),!1}}async seedKnownAuthorsInFolder(t){let e=0;for(let i of this.collectKnownAuthors())await this.ensureAuthorStubFor(t,i.id,i.name)&&e++;return e}async checkDueReminders(){let t=Date.now(),e=new Set(this.settings.notifiedDueKeys??[]),i=(this.settings.authorId??"").trim(),s=[];for(let o of this.app.vault.getMarkdownFiles()){if(o.path.includes("/_authors/"))continue;let r=this.app.metadataCache.getFileCache(o)?.frontmatter;if(!r||r.due==null)continue;let A=typeof r.id=="string"?r.id:"";if(!A)continue;let l=String(r.due),d=typeof r.due=="number"?r.due:Date.parse(l);if(!Number.isFinite(d)||d>t)continue;let g=me(r);if(g.length>0&&!(i&&g.some(h=>h.id===i)))continue;let p=`${A}@${l}`;e.has(p)||s.push({id:A,folder:(o.parent?.path??"").replace(/\/+$/,""),file:o,dueMs:d,key:p})}if(s.length===0)return;this.settings.notifiedDueKeys=[...this.settings.notifiedDueKeys??[],...s.map(o=>o.key)].slice(-2e3),await this.saveSettings();let n=async o=>{try{let A=lt(await this.app.vault.cachedRead(o)).body.split(/\r?\n/).map(l=>l.trim()).find(l=>l.length>0);if(A)return A.replace(/^[#>\-*\s]+/,"").slice(0,60)}catch{}return o.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ")};if(s.length<=3)for(let o of s){let r=await n(o.file);this.notifications.show({message:`\u23F0 Task due: \u201C${r}\u201D (${Yt(o.dueMs,this.settings)})`,kind:"warning",category:"reminder",duration:0,folder:o.folder,affectedIds:[o.id],actions:[{label:"Open",onClick:()=>void this.revealNoteByRef(o.folder,o.id)}]})}else this.notifications.show({message:`\u23F0 ${s.length} tasks are due \u2014 open the Tasks panel to review.`,kind:"warning",category:"reminder",duration:0,folder:""})}async syncAuthorsAcrossFolders(){await this.rebuildAuthorRegistry();let t=this.collectKnownAuthors(),e=this.discoverStashpadFolders();if(!t.length||!e.length){new T.Notice("No authors or Stashpad folders to sync.");return}let i=e.length*t.length>8?new T.Notice("",0):null,s=0;for(let n of e){i?.setMessage(`Syncing authors \u2192 ${n.split("/").pop()}\u2026`);for(let o of t)await this.ensureAuthorStubFor(n,o.id,o.name)&&s++}i?.hide(),this.notifications.show({message:`Synced authors across ${e.length} folder${e.length===1?"":"s"} \u2014 ${s} new stub${s===1?"":"s"} (${t.length} author${t.length===1?"":"s"} known).`,kind:"success",category:"system",folder:""})}collectKnownAuthors(){let t=new Map,e=(this.settings.authorId??"").trim(),i=(this.settings.authorName??"").trim();e&&i&&t.set(e,i);for(let s of this.authorRegistry.all())t.has(s.id)||t.set(s.id,s.name);for(let s of this.app.vault.getMarkdownFiles()){if(!s.path.includes("/_authors/"))continue;let n=this.parseAuthorFilePath(s.path);if(!n)continue;let o=this.app.metadataCache.getFileCache(s)?.frontmatter,A=((Array.isArray(o?.aliases)?o.aliases.find(l=>typeof l=="string")??"":typeof o?.aliases=="string"?o.aliases:"")||(typeof o?.name=="string"?o.name:"")||n.name).trim();t.has(n.id)||t.set(n.id,A),this.authorRegistry.record({id:n.id,name:A})}return[...t.entries()].map(([s,n])=>({id:s,name:n}))}async rebuildAuthorRegistry(){let t=this.discoverStashpadFolders(),e=new Map,i=0;for(let n of this.app.vault.getMarkdownFiles()){let o=this.app.metadataCache.getFileCache(n)?.frontmatter;if(!o)continue;let r=[];if(typeof o.author=="string"&&r.push(o.author),Array.isArray(o.contributors))for(let A of o.contributors)typeof A=="string"&&r.push(A);for(let A of r){let l=this.parseAuthorRef(A);if(l)if(!e.has(l.id))e.set(l.id,{id:l.id,name:l.name,fromStub:!1}),i++;else{let d=e.get(l.id);!d.name&&l.name&&(d.name=l.name)}}}let s=0;for(let n of t){let o=`${n}/_authors`;for(let r of this.app.vault.getMarkdownFiles()){if(!r.path.startsWith(o+"/"))continue;let A=this.parseAuthorFilePath(r.path);if(!A)continue;let l=this.app.metadataCache.getFileCache(r)?.frontmatter,g=((Array.isArray(l?.aliases)?l.aliases.find(u=>typeof u=="string")??"":typeof l?.aliases=="string"?l.aliases:"")||(typeof l?.name=="string"?l.name:"")||A.name).trim(),p=typeof l?.role=="string"?l.role:void 0,h=typeof l?.department=="string"?l.department:void 0,I=e.get(A.id);I||s++,e.set(A.id,{id:A.id,name:g||I?.name,role:p??I?.role,department:h??I?.department,fromStub:!0})}}return await this.authorRegistry.load(),this.authorRegistry.replaceAll([...e.values()]),await this.authorRegistry.save(),{total:e.size,fromStubs:s,fromNotes:i}}buildAuthorStub(t,e){let i=r=>r.replace(/[\r\n]+/g," ").trim(),s=r=>i(r).replace(/\\/g,"\\\\").replace(/"/g,'\\"'),n=i(t.name),o=["---",`authorId: ${t.id}`,"aliases:",` - "${s(t.name)}"`];return t.role&&o.push(`role: "${s(t.role)}"`),t.department&&o.push(`department: "${s(t.department)}"`),o.push(`created: ${e}`,"---",`# ${n}`),o.join(` -`)}async restoreMissingAuthorStubs(){await this.authorRegistry.load();let t=this.authorRegistry.all().filter(n=>n.id&&n.name),e=this.discoverStashpadFolders(),i=this.app.vault.getMarkdownFiles(),s=0;for(let n of e){let o=`${n}/_authors`,r=new Set;for(let A of i){if(!A.path.startsWith(o+"/"))continue;let l=this.parseAuthorFilePath(A.path)?.id;l&&r.add(l)}for(let A of t){if(r.has(A.id))continue;let l=this.authorNameToSafe(A.name),d=`${o}/${l}-${A.id}.md`;try{if(await this.ensureFolderPath(o),await this.app.vault.adapter.exists(d))continue;await this.app.vault.create(d,this.buildAuthorStub(A,A.firstSeen??new Date().toISOString())),s++}catch(g){console.warn("[Stashpad] restore author stub failed",d,g)}}}return{created:s,folders:e.length}}async convertAttachmentsToLinks(){let t=0,e=i=>/^\[\[.*\]\]$/.test(i.trim());for(let i of this.discoverStashpadFolders()){let s=i.replace(/\/+$/,"");for(let n of this.app.vault.getMarkdownFiles()){let o=n.parent?.path?.replace(/\/+$/,"")??"";if(o!==s&&!o.startsWith(s+"/")||Ne(n.path))continue;let r=this.app.metadataCache.getFileCache(n)?.frontmatter;if(!r||typeof r.id!="string"||!r.id)continue;let A=r.attachments,l=Array.isArray(A),d=typeof A=="string"&&A.trim().length>0;if(!(!l&&!d||!(d?!e(A):A.some(p=>typeof p=="string"&&p.trim()&&!e(p)))))try{await this.app.fileManager.processFrontMatter(n,p=>{Array.isArray(p.attachments)?p.attachments=p.attachments.map(h=>typeof h=="string"&&h.trim()?Rt(h):h):typeof p.attachments=="string"&&p.attachments.trim()&&(p.attachments=[Rt(p.attachments)])}),t++}catch(p){console.warn("[Stashpad] attachment-link conversion failed",n.path,p)}}}return t}syncObsidianExcludedArchives(){try{let t=this.app.vault;if(typeof t.getConfig!="function"||typeof t.setConfig!="function")return;let e=Array.isArray(t.getConfig("userIgnoreFilters"))?t.getConfig("userIgnoreFilters"):[],i=new Set(e),s=!1;for(let n of this.discoverStashpadFolders()){let o=`${n.replace(/\/+$/,"")}/_archive/`;i.has(o)||(i.add(o),s=!0)}s&&t.setConfig("userIgnoreFilters",[...i])}catch(t){console.warn("[Stashpad] couldn't update Obsidian excluded files",t)}}openImportPicker(){let t=this.discoverStashpadFolders();if(t.length===0){new T.Notice("No Stashpad folders to import into.");return}if(t.length===1){this.importService.pickFilesInto(t[0]);return}let e=this.importService.defaultDestination()??t[0];new Ao(this.app,e,t,i=>this.importService.pickFilesInto(i)).open()}async runImportLooseFiles(t){let e=t.split("/").pop()||t,i=0,s=0,n=0;try{({files:i,folders:s,stashes:n}=await this.importService.importLooseInto(t))}catch(l){this.notifications.show({message:`Stashpad: import failed in \`${e}\` +`)}`,0):this.notifications.show({message:`Encrypted ${i.fileCount} trash file${i.fileCount===1?"":"s"} into the encrypted trash. Restore from the trash tab puts them back in ${Rt}/.`,kind:"success",category:"system",folder:""}),!0):(new T.Notice(`Obsidian's vault trash (${Rt}/) is empty \u2014 nothing to encrypt. (Files in the system/OS trash can't be reached.)`,8e3),!1)}catch(e){return console.warn("[Stashpad] trash backfill failed",e),new T.Notice(`Couldn't encrypt the existing trash: ${e.message}`,0),!1}}openEncryptedTrash(t){if(!this.encryption.isConfigured()){new T.Notice("Set up encryption first (Settings \u2192 Encryption).");return}rr(this)}async openRestoreTrashPicker(){if(!this.encryption.isConfigured()){new T.Notice("Set up encryption first (Settings \u2192 Encryption).");return}let t=await this.listDeletedTrash();if(t.length===0){new T.Notice("Encrypted trash is empty.");return}let e=t.map(({blob:i,meta:s})=>({blob:i,label:s?.title||i.split("/").pop()?.replace(/\.stashenc$/,"")||"Locked note",folder:s?.originalFolder||"(unknown)"}));new qs(this.app,e,i=>{this.restoreDeletedAt(i)}).open()}isArchiveFolder(t){let e=t.replace(/\/+$/,"");return(this.settings.archiveFolders??[]).includes(e)}async ensureOkfTemplate(){let t=await lr(this.app,this.settings.okfTemplatePath||void 0);return this.settings.okfTemplatePath!==t&&(this.settings.okfTemplatePath=t,await this.saveSettings()),t}okfTemplatePathOrDefault(){return this.settings.okfTemplatePath||po}okfActiveFolders(){return this.settings.okfEnabled?cr(this.settings.noteTemplates,this.okfTemplatePathOrDefault()).filter(t=>!this.isArchiveFolder(t)):[]}async rebuildOkfSuppressed(t){this.okfRebuildingFolders.add(t);try{return await Io(this.app,t)}finally{window.setTimeout(()=>{this.okfRebuildingFolders.delete(t);for(let e of this.app.workspace.getLeavesOfType(J)){let i=e.view;i?.noteFolder===t&&i.forceReconcileRender?.()}},600)}}onOkfFileEvent(t){if(!this.settings.okfEnabled||!t.toLowerCase().endsWith(".md"))return;let e=t.lastIndexOf("/"),i=(e>=0?t.slice(0,e):"").replace(/\/+$/,"");(e>=0?t.slice(e+1):t)!=="index.md"&&(/(^|\/)(_imports|_exports|_attachments|_deleted|\.stashpad)(\/|$)/.test(t)||this.okfActiveFolders().includes(i)&&this.scheduleOkfRebuild(i))}scheduleOkfRebuild(t){let e=this.okfRebuildTimers.get(t);e!=null&&window.clearTimeout(e),this.okfRebuildTimers.set(t,window.setTimeout(()=>{this.okfRebuildTimers.delete(t),this.okfActiveFolders().includes(t)&&this.rebuildOkfSuppressed(t).catch(i=>console.warn("[Stashpad] OKF auto-rebuild failed",t,i))},2500))}async rebuildAllOkf(){let t=this.okfActiveFolders(),e=0,i=0;for(let s of t){let n=await this.rebuildOkfSuppressed(s);e+=n.checked,i+=n.written}return{folders:t.length,checked:e,written:i}}async exportOkf(t,e,i,s){let n=t.replace(/\/+$/,""),o=[],r=[],A=[],l=new Set;for(let f of e){let C=await ue(this.app,n,f);if(C){o.push({id:C.rootNote.id,file:C.rootNote.file}),A.push(C.rootNote.file),l.add(C.rootNote.id);for(let B of C.descendants)r.push({id:B.id,file:B.file}),A.push(B.file),l.add(B.id)}}if(!A.length)return[];let d=(i||"okf-export").replace(/[\\/:*?"<>|]+/g," ").replace(/\s+/g," ").trim().slice(0,80)||"okf-export",p=new Date().toISOString().replace(/\D/g,"").slice(0,14),g=(this.settings.exportFolder||"_exports").trim().replace(/^\/+|\/+$/g,""),h=`${n}/${g}`;for(let f of[n,h])try{await this.app.vault.adapter.exists(f)||await this.app.vault.adapter.mkdir(f)}catch{}let I=[],u=async(f,C)=>{let B=`${h}/${f}`;await this.app.vault.createBinary(B,C.buffer.slice(C.byteOffset,C.byteOffset+C.byteLength)),I.push(B)};if(s.zip||s.targz){let f=await dr(this.app,A,n,l);s.zip&&await u(`${d}-${p}.okf.zip`,await hr(f)),s.targz&&await u(`${d}-${p}.okf.tar.gz`,await pr(f))}if(s.stash){let f=await he(this.app,{rootNotes:o,allDescendants:r,sourceFolder:n});await u(`${d}-${p}.${ee}`,f)}return I}async idsInFolder(t){let e=t.replace(/\/+$/,""),i=new Set;for(let s of this.app.vault.getMarkdownFiles())if((s.parent?.path?.replace(/\/+$/,"")??"")===e)try{let n=lt(await this.app.vault.read(s)).fm.id;typeof n=="string"&&i.add(n)}catch{}return i}async crossFolderPaste(t,e,i,s,n){let o=i.replace(/\/+$/,"");if(this.isArchiveFolder(o))return new T.Notice(`"${o.split("/").pop()}" auto-encrypts notes moved in, so cross-folder paste is disabled there. Use the "Move to archive" command \u2014 it checks the encryption key first.`),null;let r=[],A=[],l=[],d=[];for(let w of e){let D=await ue(this.app,t,w);if(D){l.push(D.rootNote.id),r.push({id:D.rootNote.id,file:D.rootNote.file}),d.push(D.rootNote.file);for(let N of D.descendants)A.push({id:N.id,file:N.file}),d.push(N.file)}}if(!r.length)return null;let p=r.length+A.length,g=[],h=[];n==="cut"&&(g=await this.exclusiveAttachmentsOf(d),h=await this.snapshotPaths([...d.map(w=>w.path),...g.map(w=>w.path)]));let I=await he(this.app,{rootNotes:r,allDescendants:A,sourceFolder:t}),u=await this.idsInFolder(o),f=new Set(this.filesUnder(o)),C=await Yt(this.app,I,o,u,{dedupeExisting:!1,forceNewIds:n==="copy",reparentRootsTo:s}),B=this.filesUnder(o).filter(w=>!f.has(w)),m=await this.snapshotPaths(B),y=l.map(w=>C.idRemap[w]).filter(w=>!!w);if(n==="cut"){for(let w of d)try{await this.app.fileManager.trashFile(w)}catch(D){console.warn("[Stashpad] cross-folder move: couldn't trash source note",w.path,D)}for(let w of g)try{await this.app.fileManager.trashFile(w)}catch(D){console.warn("[Stashpad] cross-folder move: couldn't trash source attachment",w.path,D)}}let Q=async()=>{for(let w of[...B].reverse()){let D=this.app.vault.getAbstractFileByPath(w);if(D)try{await this.app.fileManager.trashFile(D)}catch{}}};return{rootIds:y,noteCount:p,undo:n==="cut"?async()=>{await Q(),await this.restoreSnapshot(h)}:async()=>{await Q()},redo:n==="cut"?async()=>{await this.restoreSnapshot(m);for(let w of h){let D=this.app.vault.getAbstractFileByPath(w.path);if(D)try{await this.app.fileManager.trashFile(D)}catch{}}}:async()=>{await this.restoreSnapshot(m)}}}async trashSubtrees(t,e){let i=[];for(let o of e){let r=await ue(this.app,t,o);r&&i.push(r.rootNote.file,...r.descendants.map(A=>A.file))}if(!i.length)return[];let s=await this.exclusiveAttachmentsOf(i),n=[];for(let o of[...i,...s])try{await this.app.fileManager.trashFile(o),n.push(o)}catch(r){console.warn("[Stashpad] trashSubtrees: couldn't trash",o.path,r)}return n}async exclusiveAttachmentsOf(t){let e=new Set(t.map(n=>n.path)),i=new Map;for(let n of t)for(let o of await fs(this.app,n))i.set(o.path,o);let s=this.app.metadataCache.resolvedLinks??{};for(let n of Object.keys(s))if(!e.has(n))for(let o of Object.keys(s[n]??{}))i.delete(o);return[...i.values()]}async subtreeFilePaths(t,e){let i=[];for(let n of e){let o=await ue(this.app,t,n);o&&i.push(o.rootNote.file,...o.descendants.map(r=>r.file))}if(!i.length)return[];let s=await this.exclusiveAttachmentsOf(i);return[...i.map(n=>n.path),...s.map(n=>n.path)]}async orderedSubtreeNodes(t,e){let i=[],s=new Set,n=o=>{let r=this.app.metadataCache.getFileCache(o)?.frontmatter?.position;return typeof r=="number"?r:Number.MAX_SAFE_INTEGER};for(let o of e){let r=await ue(this.app,t,o);if(!r)continue;let A=new Map;for(let d of r.descendants){if(!d.parent)continue;let p=A.get(d.parent)??[];p.push({id:d.id,file:d.file,created:d.created}),A.set(d.parent,p)}for(let d of A.values())d.sort((p,g)=>n(p.file)-n(g.file)||p.created.localeCompare(g.created));let l=(d,p)=>{if(!s.has(d.id)){s.add(d.id),i.push({file:d.file,created:d.created,depth:p});for(let g of A.get(d.id)??[])l(g,p+1)}};l({id:r.rootNote.id,file:r.rootNote.file,created:r.rootNote.created},0)}return i}filesUnder(t){let e=t.replace(/\/+$/,"")+"/";return this.app.vault.getFiles().filter(i=>i.path.startsWith(e)).map(i=>i.path)}async snapshotPaths(t){let e=[];for(let i of t){let s=this.app.vault.getAbstractFileByPath(i);if(!s)continue;let n=!i.toLowerCase().endsWith(".md");try{n?e.push({path:i,binary:n,data:await this.app.vault.readBinary(s)}):e.push({path:i,binary:n,text:await this.app.vault.read(s)})}catch(o){console.warn("[Stashpad] snapshotPaths: couldn't read",i,o)}}return e}async restoreSnapshot(t){for(let e of t){let i=e.path.split("/").slice(0,-1).join("/");await this.ensureVaultFolder(i);let s=this.app.vault.getAbstractFileByPath(e.path);try{e.binary?s?await this.app.vault.adapter.writeBinary(e.path,e.data):await this.app.vault.createBinary(e.path,e.data):s?await this.app.vault.modify(s,e.text??""):await this.app.vault.create(e.path,e.text??"")}catch(n){console.warn("[Stashpad] restoreSnapshot: couldn't write",e.path,n)}}}async ensureVaultFolder(t){if(!t)return;let e="";for(let i of t.split("/"))if(e=e?`${e}/${i}`:i,!await this.app.vault.adapter.exists(e))try{await this.app.vault.createFolder(e)}catch{}}refreshOpenViewsForFolder(t){let e=t.replace(/\/+$/,"");for(let i of this.app.workspace.getLeavesOfType(J)){let s=i.view;if((s?.noteFolder?.replace(/\/+$/,"")??"")===e)try{s.tree?.rebuild?.(t),s.render?.()}catch(n){console.warn("[Stashpad] refresh view failed",n)}}}maybeArchiveOnMoveIn(t,e){if(t.extension!=="md")return;let i=t.parent?.path?.replace(/\/+$/,"")??"",s=e.lastIndexOf("/"),n=(s>=0?e.slice(0,s):"").replace(/\/+$/,"");if(i===n||!this.isArchiveFolder(i)||!this.encryption.isConfigured())return;let o=this.archivePending.get(i);o||(o={paths:new Set,timer:0},this.archivePending.set(i,o)),o.paths.add(t.path),window.clearTimeout(o.timer),o.timer=window.setTimeout(()=>{this.archivePending.delete(i),this.archiveSweep(i,[...o.paths])},1800)}async archiveSweep(t,e){if(!this.isArchiveFolder(t))return;let i=t.replace(/\/+$/,""),s=[];for(let l of e){let d=this.app.vault.getAbstractFileByPath(l);if(!(d instanceof T.TFile)||(d.parent?.path?.replace(/\/+$/,"")??"")!==i)continue;let p;try{p=lt(await this.app.vault.read(d)).fm}catch{continue}let g=typeof p.id=="string"?p.id:null;!g||g===F||s.push({id:g,parent:typeof p.parent=="string"?p.parent:null})}if(s.length===0)return;let n=new Set(s.map(l=>l.id)),o=new Set((this.settings.lockedSubtrees??[]).map(l=>l.rootId).filter(l=>!!l)),r=s.filter(l=>!o.has(l.id)&&!(l.parent&&n.has(l.parent)));if(r.length===0)return;if(!await this.ensureEncryptionUnlocked()){new T.Notice(`\u26A0\uFE0F Archive folder "${i.split("/").pop()}": ${r.length} arriving note${r.length===1?"":"s"} NOT encrypted (vault is locked). Unlock encryption and lock them manually.`,0);return}let A=0;for(let l of r)await this.lockNoteSubtree(i,l.id,null,{silent:!0})&&A++;A>0&&this.notifications.show({message:`Archived (encrypted) ${A} note${A===1?"":"s"} moved into \u201C${i.split("/").pop()}\u201D.`,kind:"success",category:"system",folder:i})}async activateViewForFolder(t){let e=(t||"").replace(/^\/+|\/+$/g,"");if(!e)return null;let i=this.app.workspace.getLeaf("tab");return await i.setViewState({type:J,active:!0,state:{folderOverride:e}}),this.app.workspace.revealLeaf(i),i}navigateLeafTo(t,e,i){let s=t?.view;if(s?.navigateTo&&(!s.tree||s.tree.get(i))){s.navigateTo(i);return}this.navigateWhenReady(e,i)}async openFolderInStashpad(t){let e=(t||"").replace(/^\/+|\/+$/g,"");if(!e)return;let i=await this.findStashpadLeafForFolder(e);if(i){this.app.workspace.revealLeaf(i),this.app.workspace.setActiveLeaf(i,{focus:!0});return}await this.activateViewForFolder(e)}async findStashpadLeafForFolder(t){let e=t.replace(/\/+$/,""),i=this.app.workspace.getLeavesOfType(J),s=i.find(o=>!o.isDeferred&&(o.view?.noteFolder??"").replace(/\/+$/,"")===e);if(s)return s;let n=i.find(o=>o.isDeferred&&(o.getViewState()?.state?.folderOverride??"").replace(/\/+$/,"")===e);if(n){try{await n.loadIfDeferred?.()}catch{}return n}return null}isStashpadNoteFile(t){let e=t.parent?.path?.replace(/\/+$/,"")??"";if(!this.discoverStashpadFolders().includes(e))return!1;let i=this.app.metadataCache.getFileCache(t)?.frontmatter?.id;return typeof i=="string"&&i.length>0}async revealNoteInStashpad(t){let e=t.parent?.path?.replace(/\/+$/,"")??"",i=this.app.metadataCache.getFileCache(t)?.frontmatter?.id;if(!e||typeof i!="string"||!i){new T.Notice("That note isn't a Stashpad note.");return}await this.revealNoteByRef(e,i)}async revealNoteByRef(t,e){let i=t.replace(/\/+$/,""),s=await this.findStashpadLeafForFolder(i);if(s){this.app.workspace.revealLeaf(s),this.app.workspace.setActiveLeaf(s,{focus:!0}),this.navigateLeafTo(s,i,e);return}let n=await this.activateViewForFolder(i);this.navigateLeafTo(n,i,e)}async closeDuplicateStashpadTabs(){let t=this.app.workspace.getLeavesOfType(J),e=this.app.workspace.activeLeaf;for(let I of t)try{await I.loadIfDeferred?.()}catch{}let i=I=>I.getViewState()?.state??{},s=I=>{let u=i(I);return(I.isDeferred?u.folderOverride??"":I.view?.noteFolder??u.folderOverride??"").replace(/\/+$/,"")},n=I=>{let u=i(I);return(I.isDeferred?u.focusId:I.view?.focusId??u.focusId)||F},o=I=>{let u=I.view;return!!u&&u.getViewType?.()===J&&typeof u.navigateTo=="function"&&typeof u.noteFolder=="string"},r=new Map;for(let I of this.app.vault.getMarkdownFiles()){let u=(I.parent?.path??"").replace(/\/+$/,""),f=this.app.metadataCache.getFileCache(I)?.frontmatter?.id;typeof f=="string"&&f&&(r.get(u)??r.set(u,new Set).get(u)).add(f)}let A=0,l=[];for(let I of t){let u=s(I),f=n(I);if(u&&f&&f!==F){let C=!I.isDeferred&&!!I.view?.tree?.get?.(f),B=r.get(u)?.has(f)??!1;if(!C&&!B){I.detach(),A++;continue}}l.push(I)}let d=new Map;for(let I of l){let u=s(I);if(!u)continue;let f=u+" "+n(I);(d.get(f)??d.set(f,[]).get(f)).push(I)}let p=0;for(let I of d.values()){if(I.length<=1)continue;I.sort((f,C)=>{let B=m=>m===e?2:m.isDeferred?0:1;return B(C)-B(f)});let u=null;for(let f of I){try{await f.loadIfDeferred?.()}catch{}if(o(f)){u=f;break}}u||(u=I[0]);for(let f of I)f!==u&&(f.detach(),p++)}let g=this.app.workspace.getLeavesOfType(J).length,h=document.createDocumentFragment();return h.createEl("div",{text:p+A>0?"Stashpad tabs cleaned up:":"Stashpad tabs - nothing to clean up:"}),h.createEl("div",{text:`\u2022 ${p} duplicate tab${p===1?"":"s"} closed`}),h.createEl("div",{text:`\u2022 ${A} orphaned tab${A===1?"":"s"} pruned (note no longer exists)`}),h.createEl("div",{text:`\u2022 ${g} Stashpad tab${g===1?"":"s"} remaining`}),new T.Notice(h,7e3),p+A}navigateWhenReady(t,e,i=15){let s=t.replace(/\/+$/,""),n=this.app.workspace.getLeavesOfType(J).find(o=>(o.view?.noteFolder??"").replace(/\/+$/,"")===s)?.view??this.lastActiveStashpadLeaf?.view;if(n&&typeof n.navigateTo=="function"&&(!n.tree||typeof n.tree.get!="function"||!!n.tree.get(e))){n.navigateTo(e);return}i>0?window.setTimeout(()=>this.navigateWhenReady(t,e,i-1),90):n&&typeof n.navigateTo=="function"&&n.navigateTo(e)}collectAuthoredFolders(){let t=(this.settings.authorId??"").trim();if(!t)return[];let e=`-${t}`,i=this.discoverStashpadFolders(),s=new Map;for(let n of this.app.vault.getMarkdownFiles()){let o=this.app.metadataCache.getFileCache(n)?.frontmatter;if(!o)continue;let r=typeof o.author=="string"?o.author:"",A=Array.isArray(o.contributors)?o.contributors.filter(I=>typeof I=="string"):[],l=r.includes(e),d=A.some(I=>I.includes(e));if(!l&&!d)continue;let p=n.parent?.path??"",g=i.find(I=>p===I||p.startsWith(I+"/"));if(!g)continue;s.has(g)||s.set(g,{authored:0,contributed:0});let h=s.get(g);l&&h.authored++,d&&h.contributed++}return[...s.entries()].map(([n,o])=>({folder:n,...o})).sort((n,o)=>o.authored+o.contributed-(n.authored+n.contributed))}parseAuthorRef(t){return re(t)}authorRefFor(t,e,i){let s=i.replace(/[^\w\- ]+/g,"").trim().replace(/\s+/g,"-")||"author",n=`${t.replace(/\/+$/,"")}/_authors/${s}-${e}.md`,o=i.replace(/[\[\]|]/g,"").trim()||s;return`[[${n}|${o}]]`}async ensureAuthorStubFor(t,e,i){if(!e||!i)return!1;this.authorRegistry.record({id:e,name:i});let s=`${t.replace(/\/+$/,"")}/_authors`;if(this.app.vault.getMarkdownFiles().some(l=>l.path.startsWith(s+"/")&&this.parseAuthorFilePath(l.path)?.id===e))return!1;let o=this.authorRegistry.get(e),r=this.authorNameToSafe(i),A=`${s}/${r}-${e}.md`;try{return await this.ensureFolderPath(s),await this.app.vault.adapter.exists(A)?!1:(await this.app.vault.create(A,this.buildAuthorStub({id:e,name:i,role:o?.role,department:o?.department},new Date().toISOString())),!0)}catch(l){return console.warn("[Stashpad] ensureAuthorStubFor failed",A,l),!1}}async seedKnownAuthorsInFolder(t){let e=0;for(let i of this.collectKnownAuthors())await this.ensureAuthorStubFor(t,i.id,i.name)&&e++;return e}async checkDueReminders(){let t=Date.now(),e=new Set(this.settings.notifiedDueKeys??[]),i=(this.settings.authorId??"").trim(),s=[];for(let o of this.app.vault.getMarkdownFiles()){if(o.path.includes("/_authors/"))continue;let r=this.app.metadataCache.getFileCache(o)?.frontmatter;if(!r||r.due==null)continue;let A=typeof r.id=="string"?r.id:"";if(!A)continue;let l=String(r.due),d=typeof r.due=="number"?r.due:Date.parse(l);if(!Number.isFinite(d)||d>t)continue;let p=we(r);if(p.length>0&&!(i&&p.some(h=>h.id===i)))continue;let g=`${A}@${l}`;e.has(g)||s.push({id:A,folder:(o.parent?.path??"").replace(/\/+$/,""),file:o,dueMs:d,key:g})}if(s.length===0)return;this.settings.notifiedDueKeys=[...this.settings.notifiedDueKeys??[],...s.map(o=>o.key)].slice(-2e3),await this.saveSettings();let n=async o=>{try{let A=lt(await this.app.vault.cachedRead(o)).body.split(/\r?\n/).map(l=>l.trim()).find(l=>l.length>0);if(A)return A.replace(/^[#>\-*\s]+/,"").slice(0,60)}catch{}return o.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ")};if(s.length<=3)for(let o of s){let r=await n(o.file);this.notifications.show({message:`\u23F0 Task due: \u201C${r}\u201D (${$t(o.dueMs,this.settings)})`,kind:"warning",category:"reminder",duration:0,folder:o.folder,affectedIds:[o.id],actions:[{label:"Open",onClick:()=>void this.revealNoteByRef(o.folder,o.id)}]})}else this.notifications.show({message:`\u23F0 ${s.length} tasks are due \u2014 open the Tasks panel to review.`,kind:"warning",category:"reminder",duration:0,folder:""})}async syncAuthorsAcrossFolders(){await this.rebuildAuthorRegistry();let t=this.collectKnownAuthors(),e=this.discoverStashpadFolders();if(!t.length||!e.length){new T.Notice("No authors or Stashpad folders to sync.");return}let i=e.length*t.length>8?new T.Notice("",0):null,s=0;for(let n of e){i?.setMessage(`Syncing authors \u2192 ${n.split("/").pop()}\u2026`);for(let o of t)await this.ensureAuthorStubFor(n,o.id,o.name)&&s++}i?.hide(),this.notifications.show({message:`Synced authors across ${e.length} folder${e.length===1?"":"s"} \u2014 ${s} new stub${s===1?"":"s"} (${t.length} author${t.length===1?"":"s"} known).`,kind:"success",category:"system",folder:""})}collectKnownAuthors(){let t=new Map,e=(this.settings.authorId??"").trim(),i=(this.settings.authorName??"").trim();e&&i&&t.set(e,i);for(let s of this.authorRegistry.all())t.has(s.id)||t.set(s.id,s.name);for(let s of this.app.vault.getMarkdownFiles()){if(!s.path.includes("/_authors/"))continue;let n=this.parseAuthorFilePath(s.path);if(!n)continue;let o=this.app.metadataCache.getFileCache(s)?.frontmatter,A=((Array.isArray(o?.aliases)?o.aliases.find(l=>typeof l=="string")??"":typeof o?.aliases=="string"?o.aliases:"")||(typeof o?.name=="string"?o.name:"")||n.name).trim();t.has(n.id)||t.set(n.id,A),this.authorRegistry.record({id:n.id,name:A})}return[...t.entries()].map(([s,n])=>({id:s,name:n}))}async rebuildAuthorRegistry(){let t=this.discoverStashpadFolders(),e=new Map,i=0;for(let n of this.app.vault.getMarkdownFiles()){let o=this.app.metadataCache.getFileCache(n)?.frontmatter;if(!o)continue;let r=[];if(typeof o.author=="string"&&r.push(o.author),Array.isArray(o.contributors))for(let A of o.contributors)typeof A=="string"&&r.push(A);for(let A of r){let l=this.parseAuthorRef(A);if(l)if(!e.has(l.id))e.set(l.id,{id:l.id,name:l.name,fromStub:!1}),i++;else{let d=e.get(l.id);!d.name&&l.name&&(d.name=l.name)}}}let s=0;for(let n of t){let o=`${n}/_authors`;for(let r of this.app.vault.getMarkdownFiles()){if(!r.path.startsWith(o+"/"))continue;let A=this.parseAuthorFilePath(r.path);if(!A)continue;let l=this.app.metadataCache.getFileCache(r)?.frontmatter,p=((Array.isArray(l?.aliases)?l.aliases.find(u=>typeof u=="string")??"":typeof l?.aliases=="string"?l.aliases:"")||(typeof l?.name=="string"?l.name:"")||A.name).trim(),g=typeof l?.role=="string"?l.role:void 0,h=typeof l?.department=="string"?l.department:void 0,I=e.get(A.id);I||s++,e.set(A.id,{id:A.id,name:p||I?.name,role:g??I?.role,department:h??I?.department,fromStub:!0})}}return await this.authorRegistry.load(),this.authorRegistry.replaceAll([...e.values()]),await this.authorRegistry.save(),{total:e.size,fromStubs:s,fromNotes:i}}buildAuthorStub(t,e){let i=r=>r.replace(/[\r\n]+/g," ").trim(),s=r=>i(r).replace(/\\/g,"\\\\").replace(/"/g,'\\"'),n=i(t.name),o=["---",`authorId: ${t.id}`,"aliases:",` - "${s(t.name)}"`];return t.role&&o.push(`role: "${s(t.role)}"`),t.department&&o.push(`department: "${s(t.department)}"`),o.push(`created: ${e}`,"---",`# ${n}`),o.join(` +`)}async restoreMissingAuthorStubs(){await this.authorRegistry.load();let t=this.authorRegistry.all().filter(n=>n.id&&n.name),e=this.discoverStashpadFolders(),i=this.app.vault.getMarkdownFiles(),s=0;for(let n of e){let o=`${n}/_authors`,r=new Set;for(let A of i){if(!A.path.startsWith(o+"/"))continue;let l=this.parseAuthorFilePath(A.path)?.id;l&&r.add(l)}for(let A of t){if(r.has(A.id))continue;let l=this.authorNameToSafe(A.name),d=`${o}/${l}-${A.id}.md`;try{if(await this.ensureFolderPath(o),await this.app.vault.adapter.exists(d))continue;await this.app.vault.create(d,this.buildAuthorStub(A,A.firstSeen??new Date().toISOString())),s++}catch(p){console.warn("[Stashpad] restore author stub failed",d,p)}}}return{created:s,folders:e.length}}async convertAttachmentsToLinks(){let t=0,e=i=>/^\[\[.*\]\]$/.test(i.trim());for(let i of this.discoverStashpadFolders()){let s=i.replace(/\/+$/,"");for(let n of this.app.vault.getMarkdownFiles()){let o=n.parent?.path?.replace(/\/+$/,"")??"";if(o!==s&&!o.startsWith(s+"/")||He(n.path))continue;let r=this.app.metadataCache.getFileCache(n)?.frontmatter;if(!r||typeof r.id!="string"||!r.id)continue;let A=r.attachments,l=Array.isArray(A),d=typeof A=="string"&&A.trim().length>0;if(!(!l&&!d||!(d?!e(A):A.some(g=>typeof g=="string"&&g.trim()&&!e(g)))))try{await this.app.fileManager.processFrontMatter(n,g=>{Array.isArray(g.attachments)?g.attachments=g.attachments.map(h=>typeof h=="string"&&h.trim()?qt(h):h):typeof g.attachments=="string"&&g.attachments.trim()&&(g.attachments=[qt(g.attachments)])}),t++}catch(g){console.warn("[Stashpad] attachment-link conversion failed",n.path,g)}}}return t}syncObsidianExcludedArchives(){try{let t=this.app.vault;if(typeof t.getConfig!="function"||typeof t.setConfig!="function")return;let e=Array.isArray(t.getConfig("userIgnoreFilters"))?t.getConfig("userIgnoreFilters"):[],i=new Set(e),s=!1;for(let n of this.discoverStashpadFolders()){let o=`${n.replace(/\/+$/,"")}/_archive/`;i.has(o)||(i.add(o),s=!0)}s&&t.setConfig("userIgnoreFilters",[...i])}catch(t){console.warn("[Stashpad] couldn't update Obsidian excluded files",t)}}openImportPicker(){let t=this.discoverStashpadFolders();if(t.length===0){new T.Notice("No Stashpad folders to import into.");return}if(t.length===1){this.importService.pickFilesInto(t[0]);return}let e=this.importService.defaultDestination()??t[0];new Co(this.app,e,t,i=>this.importService.pickFilesInto(i)).open()}async runImportLooseFiles(t){let e=t.split("/").pop()||t,i=0,s=0,n=0;try{({files:i,folders:s,stashes:n}=await this.importService.importLooseInto(t))}catch(l){this.notifications.show({message:`Stashpad: import failed in \`${e}\` Error: ${l.message}`,kind:"error",category:"import",folder:t}),console.error("[Stashpad] runImportLooseFiles failed",t,l);return}let o=i+s+n,r=this.lastActiveStashpadLeaf?.view;o>0&&r?.noteFolder===t&&r?.tree&&(r.tree.rebuild(t),r.render?.());let A;if(o===0)A=`Nothing to import in \`${e}\` \u2014 everything here is already a Stashpad note.`;else{let l=[];i&&l.push(`${i} loose file${i===1?"":"s"}`),s&&l.push(`${s} folder${s===1?"":"s"} (as nested notes)`),n&&l.push(`${n} .stash bundle${n===1?"":"s"}`),A=`Imported ${l.join(" + ")} in \`${e}\`.`}this.notifications.show({message:A,kind:o>0?"success":"info",category:"import",folder:t})}refreshViewIfShowing(t){let e=this.lastActiveStashpadLeaf?.view;e?.noteFolder===t&&e?.tree&&(e.tree.rebuild(t),e.render?.())}async runFolderSlugPass(t){let e=t.split("/").pop()||t,i=0;try{i=await this.rebootstrapFolderSlugs(t)}catch(s){this.notifications.show({message:`Stashpad: slug pass failed in \`${e}\` -${s.message}`,kind:"error",category:"system",folder:t}),console.error("[Stashpad] runFolderSlugPass failed",t,s);return}this.refreshViewIfShowing(t),this.notifications.show({message:i>0?`Renamed ${i} stale filename${i===1?"":"s"} in \`${e}\`.`:`No stale filenames in \`${e}\` \u2014 all slugs match their notes.`,kind:i>0?"success":"info",category:"system",folder:t})}async runFolderFrontmatterBackfill(t){let e=t.split("/").pop()||t,i=0,s=0;try{let n=await Ye(this.app,t);i=n.written,s=n.checked}catch(n){this.notifications.show({message:`Stashpad: frontmatter backfill failed in \`${e}\` -${n.message}`,kind:"error",category:"system",folder:t}),console.error("[Stashpad] runFolderFrontmatterBackfill failed",t,n);return}this.notifications.show({message:i>0?`Backfilled recovery links on ${i} note${i===1?"":"s"} in \`${e}\` (${s} checked).`:`Recovery links already up to date in \`${e}\` (${s} checked).`,kind:i>0?"success":"info",category:"system",folder:t})}async runAutoImportSweep(){if(!this.settings.autoImport||!this.importService.isArmed()||this.autoSweepInProgress)return;this.autoSweepInProgress=!0;let t=0,e=0,i=0;try{for(let n of this.discoverStashpadFolders())try{let o=await this.importService.importLooseInto(n,{auto:!0});t+=o.files,e+=o.folders,i+=o.stashes}catch(o){console.warn("[Stashpad] auto-import sweep failed",n,o)}}finally{this.autoSweepInProgress=!1}if(t+e+i>0){let n=this.lastActiveStashpadLeaf?.view;n?.tree&&n?.noteFolder&&(n.tree.rebuild(n.noteFolder),n.render?.());let o=[];t&&o.push(`${t} file${t===1?"":"s"}`),e&&o.push(`${e} folder${e===1?"":"s"}`),i&&o.push(`${i} .stash bundle${i===1?"":"s"}`),this.notifications.show({message:`Auto-imported ${o.join(" + ")} (background sweep).`,kind:"success",category:"import"})}this.notifyPendingEncrypted()}notifyPendingEncrypted(){let t=this.importService.pendingEncryptedPaths();if(t.length===0||!this.importService.shouldNotifyEncrypted())return;this.importService.snoozeEncryptedNotify(60*60*1e3);let e=t.length;this.notifications.show({message:`${e} encrypted .stash bundle${e===1?"":"s"} waiting to import. Import ${e===1?"it":"them"} with the password?`,kind:"info",category:"import",duration:0,actions:[{label:"Import now",onClick:()=>void this.importPendingEncryptedNow()},{label:"Remind me later",onClick:()=>this.importService.snoozeEncryptedNotify(60*60*1e3)},{label:"Not now (until next launch)",onClick:()=>this.importService.snoozeEncryptedNotify(1/0)}]})}async importPendingEncryptedNow(){let{imported:t,rescheduled:e}=await this.importService.importPendingEncrypted();if(t>0){let i=this.lastActiveStashpadLeaf?.view;i?.tree&&i?.noteFolder&&(i.tree.rebuild(i.noteFolder),i.render?.()),this.notifications.show({message:`Imported ${t} encrypted .stash bundle${t===1?"":"s"}.`,kind:"success",category:"import"})}}async seedLocalAuthorStub(t){let e=(this.settings.authorId??"").trim(),i=(this.settings.authorName??"").trim();if(!e||!i)return!1;let s=`${t.replace(/\/+$/,"")}/_authors`;if(this.app.vault.getMarkdownFiles().some(A=>A.path.startsWith(s+"/")&&this.parseAuthorFilePath(A.path)?.id===e))return!1;let o=this.authorNameToSafe(i),r=`${s}/${o}-${e}.md`;try{return await this.ensureFolderPath(s),await this.app.vault.adapter.exists(r)?!1:(await this.app.vault.create(r,this.buildAuthorStub({id:e,name:i,role:this.settings.authorRole,department:this.settings.authorDepartment},new Date().toISOString())),this.authorRegistry.record({id:e,name:i,role:this.settings.authorRole,department:this.settings.authorDepartment}),!0)}catch(A){return console.warn("[Stashpad] seedLocalAuthorStub failed",r,A),!1}}async seedLocalAuthorStubsEverywhere(){if(!(this.settings.authorName??"").trim())return 0;let e=0;for(let i of this.discoverStashpadFolders())await this.seedLocalAuthorStub(i)&&e++;return e}async ensureFolderPath(t){let e=this.app.vault.adapter,i=t.split("/").filter(Boolean),s="";for(let n of i){s=s?`${s}/${n}`:n;try{await e.exists(s)||await e.mkdir(s)}catch(o){if(!/already exists/i.test(o.message))throw o}}}async loadSettings(){let t=await this.loadData()??{};typeof t?.confirmMultiDelete=="boolean"&&(typeof t.confirmBulkDelete!="boolean"&&(t.confirmBulkDelete=t.confirmMultiDelete),typeof t.confirmAttachmentDelete!="boolean"&&(t.confirmAttachmentDelete=t.confirmMultiDelete),delete t.confirmMultiDelete),typeof t?.jdIndexDestFolder=="string"&&typeof t?.jdIndexStashpadFolder!="string"&&(t.jdIndexStashpadFolder=t.jdIndexDestFolder),this.settings={...ge,...t,shortcuts:{...ge.shortcuts,...t?.shortcuts??{}},mod:{...ge.mod,...t?.mod??{}},bindings:WA(t?.bindings,t?.shortcuts,t?.mod),customPalette:Array.isArray(t?.customPalette)?t.customPalette.filter(e=>typeof e=="string"&&/^#[0-9a-f]{6}$/i.test(e)):[],colorAliases:t?.colorAliases&&typeof t.colorAliases=="object"?t.colorAliases:{},noteTemplates:t?.noteTemplates&&typeof t.noteTemplates=="object"?t.noteTemplates:{},authorName:typeof t?.authorName=="string"?t.authorName:"",authorId:typeof t?.authorId=="string"?t.authorId:"",authorRole:typeof t?.authorRole=="string"?t.authorRole:"",authorDepartment:typeof t?.authorDepartment=="string"?t.authorDepartment:"",showAuthor:typeof t?.showAuthor=="boolean"?t.showAuthor:!0,showContributors:typeof t?.showContributors=="boolean"?t.showContributors:!0,showLastEdit:typeof t?.showLastEdit=="boolean"?t.showLastEdit:!0,viewModes:t?.viewModes&&typeof t.viewModes=="object"&&!Array.isArray(t.viewModes)?t.viewModes:{},includeAttachmentsInEverything:t?.includeAttachmentsInEverything&&typeof t.includeAttachmentsInEverything=="object"&&!Array.isArray(t.includeAttachmentsInEverything)?t.includeAttachmentsInEverything:{},hideChildlessNotes:t?.hideChildlessNotes&&typeof t.hideChildlessNotes=="object"&&!Array.isArray(t.hideChildlessNotes)?t.hideChildlessNotes:{},hideCompletedNotes:t?.hideCompletedNotes&&typeof t.hideCompletedNotes=="object"&&!Array.isArray(t.hideCompletedNotes)?t.hideCompletedNotes:{},mutedNotificationCategories:Array.isArray(t?.mutedNotificationCategories)?t.mutedNotificationCategories.filter(e=>typeof e=="string"):[],notificationHistoryLimit:typeof t?.notificationHistoryLimit=="number"&&Number.isFinite(t.notificationHistoryLimit)?t.notificationHistoryLimit:5e3,notifiedDueKeys:Array.isArray(t?.notifiedDueKeys)?t.notifiedDueKeys.filter(e=>typeof e=="string").slice(-2e3):[],drafts:XA(t?.drafts),lastSubmitted:t?.lastSubmitted&&typeof t.lastSubmitted=="object"?t.lastSubmitted:{},slugStopWords:Array.isArray(t?.slugStopWords)?t.slugStopWords:[...Lt]},$n(this.settings),this.notifications.loadMutedFromList(this.settings.mutedNotificationCategories),this.notifications.setHistoryLimit(this.settings.notificationHistoryLimit),this.notifications.setDefaultAuthorId(this.settings.authorId),this.attachNotificationPersistence()}notificationsPath(){return this.pluginPrivatePath("notifications.json")}async attachNotificationPersistence(){if(this.notifPersistenceWired)return;this.notifPersistenceWired=!0;let t=this.app.vault.adapter,e=this.notificationsPath();try{if(await t.exists(e)){let i=await t.read(e),s=JSON.parse(i);Array.isArray(s)&&this.notifications.loadHistory(s)}}catch(i){console.warn("[Stashpad] failed to load notification history",i)}this.notifications.onChange(()=>{this.notifSaveTimer!=null&&window.clearTimeout(this.notifSaveTimer),this.notifSaveTimer=window.setTimeout(()=>{this.notifSaveTimer=null,this.persistNotificationHistory()},1e3)})}async persistNotificationHistory(){try{let t=this.notifications.recent().slice().reverse(),e=this.notificationsPath(),i=e.replace(/\/[^/]+$/,""),s=this.app.vault.adapter;i&&!await s.exists(i)&&await s.mkdir(i),await s.write(e,JSON.stringify(t))}catch(t){console.warn("[Stashpad] failed to save notification history",t)}}readLastCursorFile(){try{let t=window.localStorage.getItem(this.LAST_CURSOR_LS_KEY);if(!t)return{};let e=JSON.parse(t);return e&&typeof e=="object"?e:{}}catch{return{}}}loadLastCursor(t){let i=this.readLastCursorFile()[t]??{};return new Map(Object.entries(i))}saveLastCursor(t,e,i){try{let s=this.readLastCursorFile();s[t]||(s[t]={}),s[t][e]=i,window.localStorage.setItem(this.LAST_CURSOR_LS_KEY,JSON.stringify(s))}catch(s){console.warn("[Stashpad] failed to save last-cursor",s)}}readLastSelectionFile(){try{let t=window.localStorage.getItem(this.LAST_SELECTION_LS_KEY);if(!t)return{};let e=JSON.parse(t);return e&&typeof e=="object"?e:{}}catch{return{}}}loadLastSelection(t){let i=this.readLastSelectionFile()[t]??{},s=new Map;for(let[n,o]of Object.entries(i))Array.isArray(o)&&s.set(n,o.filter(r=>typeof r=="string"));return s}saveLastSelection(t,e,i){try{let s=this.readLastSelectionFile();s[t]||(s[t]={}),i.length?s[t][e]=i:delete s[t][e],window.localStorage.setItem(this.LAST_SELECTION_LS_KEY,JSON.stringify(s))}catch(s){console.warn("[Stashpad] failed to save last-selection",s)}}queueWrite(){let t=this.writeChain.then(()=>this.saveData(this.settings));return this.writeChain=t.catch(()=>{}),t}async saveSettings(){await this.queueWrite(),$n(this.settings),Qt.enabled=!!this.settings.enablePerfProfiling;let t=(this.settings.authorId??"").trim();t&&this.authorRegistry.record({id:t,name:this.settings.authorName,role:this.settings.authorRole,department:this.settings.authorDepartment}),console.debug("[Stashpad] saveSettings",{shortcuts:this.settings.shortcuts,mod:this.settings.mod})}async persistSettingsQuiet(){await this.queueWrite()}async fixOrphanParents(){let t=new Set(this.discoverStashpadFolders());if(t.size===0){new T.Notice("No Stashpad folders found.");return}let e=new Set,i=this.app.vault.getMarkdownFiles();for(let g of i){let p=this.app.metadataCache.getFileCache(g)?.frontmatter,h=typeof p?.id=="string"?p.id.trim():"";h&&e.add(h)}let{newId:s}=await Promise.resolve().then(()=>(xt(),Ri)),n=()=>{for(let g=0;g<100;g++){let p=s();if(!e.has(p))return e.add(p),p}for(let g=8;g<=16;g+=2){let p=s(g);if(!e.has(p))return e.add(p),p}throw new Error("Could not generate a unique id")},o=[];for(let g of i){let p=g.parent?.path?.replace(/\/+$/,"")??"";if(!t.has(p))continue;let h=this.app.metadataCache.getFileCache(g)?.frontmatter,I=typeof h?.id=="string"?h.id.trim():"",u=h?.parent,f=typeof u=="string"?u.trim()!=="":u!=null,C=typeof h?.created=="string"&&h.created.trim()!=="",B=!I,m=!f,w=!C;!B&&!m&&!w||o.push({file:g,addId:B,addParent:m,addCreated:w})}if(o.length===0){new T.Notice("Nothing to fix \u2014 every note in a Stashpad folder already has id + parent + created.");return}let r=0,A=0,l=this.newLog();for(let g of o)try{let p;await this.app.fileManager.processFrontMatter(g.file,u=>{if(g.addId&&(typeof u.id=="string"&&u.id.trim()||(p=n(),u.id=p)),g.addParent){let f=u.parent;(typeof f=="string"?f.trim()!=="":f!=null)||(u.parent=F)}g.addCreated&&(typeof u.created=="string"&&u.created.trim()||(u.created=new Date(g.file.stat.ctime).toISOString()))});let h=this.app.metadataCache.getFileCache(g.file)?.frontmatter,I=p??h?.id??"";I&&await l.append({type:"parent_change",id:I,payload:{from:null,to:F,reason:"orphan_fix",path:g.file.path,addedId:g.addId,addedParent:g.addParent,addedCreated:g.addCreated}}),r++}catch(p){console.warn("Stashpad: orphan fix failed for",g.file.path,p),A++}let d=A?` (${A} failed \u2014 see console)`:"";new T.Notice(`Fixed ${r} note${r===1?"":"s"} in Stashpad folders${d}.`)}async adoptNote(t){let{newId:e}=await Promise.resolve().then(()=>(xt(),Ri)),i=new Set;for(let l of this.app.vault.getMarkdownFiles()){if(l.path===t.path)continue;let d=this.app.metadataCache.getFileCache(l)?.frontmatter,g=typeof d?.id=="string"?d.id.trim():"";g&&i.add(g)}let s=()=>{for(let l=0;l<50;l++){let d=e();if(!i.has(d))return d}for(let l=8;l<=16;l+=2){let d=e(l);if(!i.has(d))return d}throw new Error("Could not generate a unique id")},n=[],o=[];try{await this.app.fileManager.processFrontMatter(t,l=>{let d=typeof l.id=="string"?l.id.trim():"";!d||/\s/.test(d)||i.has(d)?(l.id=s(),n.push("id")):o.push("id"),l.parent!==void 0&&l.parent!==null&&String(l.parent).trim()!==""?o.push("parent"):(l.parent=F,n.push("parent")),typeof l.created=="string"&&l.created.trim()!==""?o.push("created"):(l.created=new Date(t.stat.ctime).toISOString(),n.push("created"))})}catch(l){new T.Notice(`Adopt failed: ${l.message}`);return}let r=!1;try{let l=this.app.metadataCache.getFileCache(t)?.frontmatter,d=typeof l?.id=="string"?l.id.trim():"";if(d&&t.basename&&!t.basename.endsWith(`-${d}`)){let g=`${t.parent?t.parent.path+"/":""}${t.basename}-${d}.md`;await this.app.vault.adapter.exists(g)||(await this.app.fileManager.renameFile(t,g),r=!0)}}catch(l){console.warn("Stashpad: adopt rename failed",l)}if(n.length===0&&!r){new T.Notice(`Already a Stashpad note (${o.join(", ")} present).`);return}let A=[];n.length&&A.push(`added: ${n.join(", ")}`),r&&A.push("renamed with id"),new T.Notice(`Adopted into Stashpad \u2014 ${A.join("; ")}.`);try{let l=this.newLog(),d=this.app.metadataCache.getFileCache(t)?.frontmatter,g=d?.id??"";g&&await l.append({type:"create",id:g,payload:{path:t.path,parent:d?.parent??F,source:"adopt",added:n}})}catch{}}};function WA(c,a,t){let e=zn();for(let i of qe){let s=a&&typeof a[i.id]=="string"?a[i.id]:t&&typeof t[i.id]=="string"?t[i.id]:null;s!=null&&s!==""&&(e[i.id].primary=s)}if(c&&typeof c=="object")for(let i of qe){let s=c[i.id];!s||typeof s!="object"||(e[i.id]={primary:typeof s.primary=="string"?s.primary:e[i.id].primary,secondary:typeof s.secondary=="string"?s.secondary:"",preferRight:!!s.preferRight,useBoth:!!s.useBoth})}for(let i of qe){if(!i.defaultSecondary&&!i.defaultUseBoth)continue;let s=e[i.id];s.primary===i.defaultPrimary&&!s.secondary&&!s.useBoth&&(s.secondary=i.defaultSecondary??"",s.useBoth=!!i.defaultUseBoth)}return e}function XA(c){let a={};if(!c||typeof c!="object")return a;for(let[t,e]of Object.entries(c))if(typeof e=="string")a[t]=e;else if(e&&typeof e=="object"){for(let i of Object.values(e))if(typeof i=="string"&&i.length>0){a[t]=i;break}}return a}var Ao=class extends T.SuggestModal{constructor(t,e,i,s){super(t);this.def=e;this.folders=i;this.onPick=s;this.setPlaceholder("Choose a Stashpad folder to import into\u2026")}getSuggestions(t){let e=t.toLowerCase();return[this.def,...this.folders.filter(s=>s!==this.def)].filter(s=>s.toLowerCase().includes(e)).map(s=>({label:s,folder:s,current:s===this.def}))}renderSuggestion(t,e){e.createDiv({text:t.label}),t.current&&(e.createDiv({cls:"stashpad-suggest-note",text:"current"}),e.addClass("is-pinned-import-target"))}onChooseSuggestion(t){this.onPick(t.folder)}}; +${s.message}`,kind:"error",category:"system",folder:t}),console.error("[Stashpad] runFolderSlugPass failed",t,s);return}this.refreshViewIfShowing(t),this.notifications.show({message:i>0?`Renamed ${i} stale filename${i===1?"":"s"} in \`${e}\`.`:`No stale filenames in \`${e}\` \u2014 all slugs match their notes.`,kind:i>0?"success":"info",category:"system",folder:t})}async runFolderFrontmatterBackfill(t){let e=t.split("/").pop()||t,i=0,s=0;try{let n=await Xe(this.app,t);i=n.written,s=n.checked}catch(n){this.notifications.show({message:`Stashpad: frontmatter backfill failed in \`${e}\` +${n.message}`,kind:"error",category:"system",folder:t}),console.error("[Stashpad] runFolderFrontmatterBackfill failed",t,n);return}this.notifications.show({message:i>0?`Backfilled recovery links on ${i} note${i===1?"":"s"} in \`${e}\` (${s} checked).`:`Recovery links already up to date in \`${e}\` (${s} checked).`,kind:i>0?"success":"info",category:"system",folder:t})}async runAutoImportSweep(){if(!this.settings.autoImport||!this.importService.isArmed()||this.autoSweepInProgress)return;this.autoSweepInProgress=!0;let t=0,e=0,i=0;try{for(let n of this.discoverStashpadFolders())try{let o=await this.importService.importLooseInto(n,{auto:!0});t+=o.files,e+=o.folders,i+=o.stashes}catch(o){console.warn("[Stashpad] auto-import sweep failed",n,o)}}finally{this.autoSweepInProgress=!1}if(t+e+i>0){let n=this.lastActiveStashpadLeaf?.view;n?.tree&&n?.noteFolder&&(n.tree.rebuild(n.noteFolder),n.render?.());let o=[];t&&o.push(`${t} file${t===1?"":"s"}`),e&&o.push(`${e} folder${e===1?"":"s"}`),i&&o.push(`${i} .stash bundle${i===1?"":"s"}`),this.notifications.show({message:`Auto-imported ${o.join(" + ")} (background sweep).`,kind:"success",category:"import"})}this.notifyPendingEncrypted()}notifyPendingEncrypted(){let t=this.importService.pendingEncryptedPaths();if(t.length===0||!this.importService.shouldNotifyEncrypted())return;this.importService.snoozeEncryptedNotify(60*60*1e3);let e=t.length;this.notifications.show({message:`${e} encrypted .stash bundle${e===1?"":"s"} waiting to import. Import ${e===1?"it":"them"} with the password?`,kind:"info",category:"import",duration:0,actions:[{label:"Import now",onClick:()=>void this.importPendingEncryptedNow()},{label:"Remind me later",onClick:()=>this.importService.snoozeEncryptedNotify(60*60*1e3)},{label:"Not now (until next launch)",onClick:()=>this.importService.snoozeEncryptedNotify(1/0)}]})}async importPendingEncryptedNow(){let{imported:t,rescheduled:e}=await this.importService.importPendingEncrypted();if(t>0){let i=this.lastActiveStashpadLeaf?.view;i?.tree&&i?.noteFolder&&(i.tree.rebuild(i.noteFolder),i.render?.()),this.notifications.show({message:`Imported ${t} encrypted .stash bundle${t===1?"":"s"}.`,kind:"success",category:"import"})}}async seedLocalAuthorStub(t){let e=(this.settings.authorId??"").trim(),i=(this.settings.authorName??"").trim();if(!e||!i)return!1;let s=`${t.replace(/\/+$/,"")}/_authors`;if(this.app.vault.getMarkdownFiles().some(A=>A.path.startsWith(s+"/")&&this.parseAuthorFilePath(A.path)?.id===e))return!1;let o=this.authorNameToSafe(i),r=`${s}/${o}-${e}.md`;try{return await this.ensureFolderPath(s),await this.app.vault.adapter.exists(r)?!1:(await this.app.vault.create(r,this.buildAuthorStub({id:e,name:i,role:this.settings.authorRole,department:this.settings.authorDepartment},new Date().toISOString())),this.authorRegistry.record({id:e,name:i,role:this.settings.authorRole,department:this.settings.authorDepartment}),!0)}catch(A){return console.warn("[Stashpad] seedLocalAuthorStub failed",r,A),!1}}async seedLocalAuthorStubsEverywhere(){if(!(this.settings.authorName??"").trim())return 0;let e=0;for(let i of this.discoverStashpadFolders())await this.seedLocalAuthorStub(i)&&e++;return e}async ensureFolderPath(t){let e=this.app.vault.adapter,i=t.split("/").filter(Boolean),s="";for(let n of i){s=s?`${s}/${n}`:n;try{await e.exists(s)||await e.mkdir(s)}catch(o){if(!/already exists/i.test(o.message))throw o}}}async loadSettings(){let t=await this.loadData()??{};typeof t?.confirmMultiDelete=="boolean"&&(typeof t.confirmBulkDelete!="boolean"&&(t.confirmBulkDelete=t.confirmMultiDelete),typeof t.confirmAttachmentDelete!="boolean"&&(t.confirmAttachmentDelete=t.confirmMultiDelete),delete t.confirmMultiDelete),typeof t?.jdIndexDestFolder=="string"&&typeof t?.jdIndexStashpadFolder!="string"&&(t.jdIndexStashpadFolder=t.jdIndexDestFolder),this.settings={...fe,...t,shortcuts:{...fe.shortcuts,...t?.shortcuts??{}},mod:{...fe.mod,...t?.mod??{}},bindings:hl(t?.bindings,t?.shortcuts,t?.mod),customPalette:Array.isArray(t?.customPalette)?t.customPalette.filter(e=>typeof e=="string"&&/^#[0-9a-f]{6}$/i.test(e)):[],colorAliases:t?.colorAliases&&typeof t.colorAliases=="object"?t.colorAliases:{},noteTemplates:t?.noteTemplates&&typeof t.noteTemplates=="object"?t.noteTemplates:{},authorName:typeof t?.authorName=="string"?t.authorName:"",authorId:typeof t?.authorId=="string"?t.authorId:"",authorRole:typeof t?.authorRole=="string"?t.authorRole:"",authorDepartment:typeof t?.authorDepartment=="string"?t.authorDepartment:"",showAuthor:typeof t?.showAuthor=="boolean"?t.showAuthor:!0,showContributors:typeof t?.showContributors=="boolean"?t.showContributors:!0,showLastEdit:typeof t?.showLastEdit=="boolean"?t.showLastEdit:!0,viewModes:t?.viewModes&&typeof t.viewModes=="object"&&!Array.isArray(t.viewModes)?t.viewModes:{},includeAttachmentsInEverything:t?.includeAttachmentsInEverything&&typeof t.includeAttachmentsInEverything=="object"&&!Array.isArray(t.includeAttachmentsInEverything)?t.includeAttachmentsInEverything:{},hideChildlessNotes:t?.hideChildlessNotes&&typeof t.hideChildlessNotes=="object"&&!Array.isArray(t.hideChildlessNotes)?t.hideChildlessNotes:{},hideCompletedNotes:t?.hideCompletedNotes&&typeof t.hideCompletedNotes=="object"&&!Array.isArray(t.hideCompletedNotes)?t.hideCompletedNotes:{},mutedNotificationCategories:Array.isArray(t?.mutedNotificationCategories)?t.mutedNotificationCategories.filter(e=>typeof e=="string"):[],notificationHistoryLimit:typeof t?.notificationHistoryLimit=="number"&&Number.isFinite(t.notificationHistoryLimit)?t.notificationHistoryLimit:5e3,notifiedDueKeys:Array.isArray(t?.notifiedDueKeys)?t.notifiedDueKeys.filter(e=>typeof e=="string").slice(-2e3):[],drafts:pl(t?.drafts),lastSubmitted:t?.lastSubmitted&&typeof t.lastSubmitted=="object"?t.lastSubmitted:{},slugStopWords:Array.isArray(t?.slugStopWords)?t.slugStopWords:[...Jt]},to(this.settings),this.notifications.loadMutedFromList(this.settings.mutedNotificationCategories),this.notifications.setHistoryLimit(this.settings.notificationHistoryLimit),this.notifications.setDefaultAuthorId(this.settings.authorId),this.attachNotificationPersistence()}notificationsPath(){return this.pluginPrivatePath("notifications.json")}async attachNotificationPersistence(){if(this.notifPersistenceWired)return;this.notifPersistenceWired=!0;let t=this.app.vault.adapter,e=this.notificationsPath();try{if(await t.exists(e)){let i=await t.read(e),s=JSON.parse(i);Array.isArray(s)&&this.notifications.loadHistory(s)}}catch(i){console.warn("[Stashpad] failed to load notification history",i)}this.notifications.onChange(()=>{this.notifSaveTimer!=null&&window.clearTimeout(this.notifSaveTimer),this.notifSaveTimer=window.setTimeout(()=>{this.notifSaveTimer=null,this.persistNotificationHistory()},1e3)})}async persistNotificationHistory(){try{let t=this.notifications.recent().slice().reverse(),e=this.notificationsPath(),i=e.replace(/\/[^/]+$/,""),s=this.app.vault.adapter;i&&!await s.exists(i)&&await s.mkdir(i),await s.write(e,JSON.stringify(t))}catch(t){console.warn("[Stashpad] failed to save notification history",t)}}readLastCursorFile(){try{let t=window.localStorage.getItem(this.LAST_CURSOR_LS_KEY);if(!t)return{};let e=JSON.parse(t);return e&&typeof e=="object"?e:{}}catch{return{}}}loadLastCursor(t){let i=this.readLastCursorFile()[t]??{};return new Map(Object.entries(i))}saveLastCursor(t,e,i){try{let s=this.readLastCursorFile();s[t]||(s[t]={}),s[t][e]=i,window.localStorage.setItem(this.LAST_CURSOR_LS_KEY,JSON.stringify(s))}catch(s){console.warn("[Stashpad] failed to save last-cursor",s)}}readLastSelectionFile(){try{let t=window.localStorage.getItem(this.LAST_SELECTION_LS_KEY);if(!t)return{};let e=JSON.parse(t);return e&&typeof e=="object"?e:{}}catch{return{}}}loadLastSelection(t){let i=this.readLastSelectionFile()[t]??{},s=new Map;for(let[n,o]of Object.entries(i))Array.isArray(o)&&s.set(n,o.filter(r=>typeof r=="string"));return s}saveLastSelection(t,e,i){try{let s=this.readLastSelectionFile();s[t]||(s[t]={}),i.length?s[t][e]=i:delete s[t][e],window.localStorage.setItem(this.LAST_SELECTION_LS_KEY,JSON.stringify(s))}catch(s){console.warn("[Stashpad] failed to save last-selection",s)}}readActiveVersionsFile(){try{let t=window.localStorage.getItem(this.ACTIVE_VERSIONS_LS_KEY);if(!t)return{};let e=JSON.parse(t);return e&&typeof e=="object"?e:{}}catch{return{}}}loadActiveVersions(t){let e=this.readActiveVersionsFile();return new Map(Object.entries(e[t]??{}))}saveActiveVersion(t,e,i){try{let s=this.readActiveVersionsFile();s[t]||(s[t]={}),s[t][e]=i,window.localStorage.setItem(this.ACTIVE_VERSIONS_LS_KEY,JSON.stringify(s))}catch(s){console.warn("[Stashpad] failed to save active-version",s)}}queueWrite(){let t=this.writeChain.then(()=>this.saveData(this.settings));return this.writeChain=t.catch(()=>{}),t}async saveSettings(){await this.queueWrite(),to(this.settings),wt.enabled=!!this.settings.enablePerfProfiling;let t=(this.settings.authorId??"").trim();t&&this.authorRegistry.record({id:t,name:this.settings.authorName,role:this.settings.authorRole,department:this.settings.authorDepartment}),console.debug("[Stashpad] saveSettings",{shortcuts:this.settings.shortcuts,mod:this.settings.mod})}async persistSettingsQuiet(){await this.queueWrite()}async fixOrphanParents(){let t=new Set(this.discoverStashpadFolders());if(t.size===0){new T.Notice("No Stashpad folders found.");return}let e=new Set,i=this.app.vault.getMarkdownFiles();for(let p of i){let g=this.app.metadataCache.getFileCache(p)?.frontmatter,h=typeof g?.id=="string"?g.id.trim():"";h&&e.add(h)}let{newId:s}=await Promise.resolve().then(()=>(Tt(),zi)),n=()=>{for(let p=0;p<100;p++){let g=s();if(!e.has(g))return e.add(g),g}for(let p=8;p<=16;p+=2){let g=s(p);if(!e.has(g))return e.add(g),g}throw new Error("Could not generate a unique id")},o=[];for(let p of i){let g=p.parent?.path?.replace(/\/+$/,"")??"";if(!t.has(g))continue;let h=this.app.metadataCache.getFileCache(p)?.frontmatter,I=typeof h?.id=="string"?h.id.trim():"",u=h?.parent,f=typeof u=="string"?u.trim()!=="":u!=null,C=typeof h?.created=="string"&&h.created.trim()!=="",B=!I,m=!f,y=!C;!B&&!m&&!y||o.push({file:p,addId:B,addParent:m,addCreated:y})}if(o.length===0){new T.Notice("Nothing to fix \u2014 every note in a Stashpad folder already has id + parent + created.");return}let r=0,A=0,l=this.newLog();for(let p of o)try{let g;await this.app.fileManager.processFrontMatter(p.file,u=>{if(p.addId&&(typeof u.id=="string"&&u.id.trim()||(g=n(),u.id=g)),p.addParent){let f=u.parent;(typeof f=="string"?f.trim()!=="":f!=null)||(u.parent=F)}p.addCreated&&(typeof u.created=="string"&&u.created.trim()||(u.created=new Date(p.file.stat.ctime).toISOString()))});let h=this.app.metadataCache.getFileCache(p.file)?.frontmatter,I=g??h?.id??"";I&&await l.append({type:"parent_change",id:I,payload:{from:null,to:F,reason:"orphan_fix",path:p.file.path,addedId:p.addId,addedParent:p.addParent,addedCreated:p.addCreated}}),r++}catch(g){console.warn("Stashpad: orphan fix failed for",p.file.path,g),A++}let d=A?` (${A} failed \u2014 see console)`:"";new T.Notice(`Fixed ${r} note${r===1?"":"s"} in Stashpad folders${d}.`)}async adoptNote(t){let{newId:e}=await Promise.resolve().then(()=>(Tt(),zi)),i=new Set;for(let l of this.app.vault.getMarkdownFiles()){if(l.path===t.path)continue;let d=this.app.metadataCache.getFileCache(l)?.frontmatter,p=typeof d?.id=="string"?d.id.trim():"";p&&i.add(p)}let s=()=>{for(let l=0;l<50;l++){let d=e();if(!i.has(d))return d}for(let l=8;l<=16;l+=2){let d=e(l);if(!i.has(d))return d}throw new Error("Could not generate a unique id")},n=[],o=[];try{await this.app.fileManager.processFrontMatter(t,l=>{let d=typeof l.id=="string"?l.id.trim():"";!d||/\s/.test(d)||i.has(d)?(l.id=s(),n.push("id")):o.push("id"),l.parent!==void 0&&l.parent!==null&&String(l.parent).trim()!==""?o.push("parent"):(l.parent=F,n.push("parent")),typeof l.created=="string"&&l.created.trim()!==""?o.push("created"):(l.created=new Date(t.stat.ctime).toISOString(),n.push("created"))})}catch(l){new T.Notice(`Adopt failed: ${l.message}`);return}let r=!1;try{let l=this.app.metadataCache.getFileCache(t)?.frontmatter,d=typeof l?.id=="string"?l.id.trim():"";if(d&&t.basename&&!t.basename.endsWith(`-${d}`)){let p=`${t.parent?t.parent.path+"/":""}${t.basename}-${d}.md`;await this.app.vault.adapter.exists(p)||(await this.app.fileManager.renameFile(t,p),r=!0)}}catch(l){console.warn("Stashpad: adopt rename failed",l)}if(n.length===0&&!r){new T.Notice(`Already a Stashpad note (${o.join(", ")} present).`);return}let A=[];n.length&&A.push(`added: ${n.join(", ")}`),r&&A.push("renamed with id"),new T.Notice(`Adopted into Stashpad \u2014 ${A.join("; ")}.`);try{let l=this.newLog(),d=this.app.metadataCache.getFileCache(t)?.frontmatter,p=d?.id??"";p&&await l.append({type:"create",id:p,payload:{path:t.path,parent:d?.parent??F,source:"adopt",added:n}})}catch{}}};function hl(c,a,t){let e=_n();for(let i of ze){let s=a&&typeof a[i.id]=="string"?a[i.id]:t&&typeof t[i.id]=="string"?t[i.id]:null;s!=null&&s!==""&&(e[i.id].primary=s)}if(c&&typeof c=="object")for(let i of ze){let s=c[i.id];!s||typeof s!="object"||(e[i.id]={primary:typeof s.primary=="string"?s.primary:e[i.id].primary,secondary:typeof s.secondary=="string"?s.secondary:"",preferRight:!!s.preferRight,useBoth:!!s.useBoth})}for(let i of ze){if(!i.defaultSecondary&&!i.defaultUseBoth)continue;let s=e[i.id];s.primary===i.defaultPrimary&&!s.secondary&&!s.useBoth&&(s.secondary=i.defaultSecondary??"",s.useBoth=!!i.defaultUseBoth)}return e}function pl(c){let a={};if(!c||typeof c!="object")return a;for(let[t,e]of Object.entries(c))if(typeof e=="string")a[t]=e;else if(e&&typeof e=="object"){for(let i of Object.values(e))if(typeof i=="string"&&i.length>0){a[t]=i;break}}return a}var Co=class extends T.SuggestModal{constructor(t,e,i,s){super(t);this.def=e;this.folders=i;this.onPick=s;this.setPlaceholder("Choose a Stashpad folder to import into\u2026")}getSuggestions(t){let e=t.toLowerCase();return[this.def,...this.folders.filter(s=>s!==this.def)].filter(s=>s.toLowerCase().includes(e)).map(s=>({label:s,folder:s,current:s===this.def}))}renderSuggestion(t,e){e.createDiv({text:t.label}),t.current&&(e.createDiv({cls:"stashpad-suggest-note",text:"current"}),e.addClass("is-pinned-import-target"))}onChooseSuggestion(t){this.onPick(t.folder)}}; /*! Bundled license information: hash-wasm/dist/index.esm.js: diff --git a/manifest.json b/manifest.json index d237154..ffa4c6a 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "stashpad", "name": "Stashpad", - "version": "0.103.10", + "version": "0.107.1", "minAppVersion": "1.13.0", "description": "A chat-style, nested-notes workspace: rapid capture, outliner navigation, fast search, tasks, and per-folder templates, with one-click Open Knowledge Format (OKF) export for LLMs and agents.", "author": "Human", diff --git a/package.json b/package.json index aae5f07..7f544e0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "stashpad-obsidian", - "version": "0.103.10", + "version": "0.107.1", "private": true, "scripts": { "dev": "node esbuild.config.mjs", diff --git a/release-notes/0.107.1.md b/release-notes/0.107.1.md new file mode 100644 index 0000000..687f99b --- /dev/null +++ b/release-notes/0.107.1.md @@ -0,0 +1,29 @@ +# 0.107.1 — Sheet versions, list pins, note forking + +## Sheet versions +Keep multiple tabbed versions of a single note (drafts/variants) and switch between +them inline. The active version persists across reloads, is hardened against being +hidden by accident, and is gated behind a settings toggle that ships **off** by +default — turn it on under settings when you want it. + +## Pin notes in the list +Pin notes to the top of a Stashpad list so they stay put above the rest. Pinned rows +are marked with a `pin` icon in the meta column, and the folder panel can reveal a +folder's Home list-pinned notes. + +## Fork a note +Fork any note into a variant under a parent you choose — a quick way to branch an +idea without losing the original. + +## Tasks +- Unified due-date / assignee modal with dedicated clear (×) buttons on the date and + time fields. +- Right-click task actions are grouped under a single **Task** submenu, with + context-menu gating so options only appear when relevant. +- `Remove task` renamed to `Remove from tasks`; the redundant `Set due date` entry is + dropped from the Task submenu. + +## List & filtering +- Collapse or expand every note body at once, plus an **expand bodies by default** + setting. +- Reworked tags filter: a searchable, ranked, keyboard-navigable popover. diff --git a/src/folder-panel-view.ts b/src/folder-panel-view.ts index 0e8788c..9b33197 100644 --- a/src/folder-panel-view.ts +++ b/src/folder-panel-view.ts @@ -119,6 +119,10 @@ export class StashpadFolderPanelView extends ItemView { /** Pin subtree expansion state (key = `folder|id`), kept across re-renders. */ private pinExpanded = new Set<string>(); + /** 0.105.1: which folder rows are expanded to reveal their Home list-pinned + * notes (key = folder path), kept across re-renders. */ + private folderPinExpanded = new Set<string>(); + private openPinnedOptionsMenu(e: MouseEvent): void { const cur = this.plugin.settings.folderPanelPinnedGrouping ?? "pin-order"; const menu = new Menu(); @@ -456,6 +460,25 @@ export class StashpadFolderPanelView extends ItemView { pin.setAttr("aria-label", "Pinned"); } + // 0.105.1: reveal this folder's Home list-pinned notes inline. The chevron + // shows only when the folder has any; clicking toggles a sub-list below the + // row. stopPropagation so it doesn't trigger the row's folder navigation. + const homePinned = this.folderHomePinnedNotes(folder); + const pinKey = StashpadFolderPanelView.clean(folder); + const pinsExpanded = this.folderPinExpanded.has(pinKey); + if (homePinned.length > 0) { + const chev = row.createSpan({ cls: "stashpad-folderpanel-pinreveal" }); + renderCountBadge(chev, homePinned.length, pinsExpanded); + chev.setAttr("aria-label", pinsExpanded ? "Hide pinned notes" : `${homePinned.length} pinned note${homePinned.length === 1 ? "" : "s"}`); + chev.addEventListener("mousedown", (e) => { e.stopPropagation(); e.preventDefault(); }); + chev.onclick = (e) => { + e.stopPropagation(); + if (this.folderPinExpanded.has(pinKey)) this.folderPinExpanded.delete(pinKey); + else this.folderPinExpanded.add(pinKey); + this.render(); + }; + } + // 0.95.1: per-folder icon. Tinted by the folder's Home-note color when set. // 0.98.37: archive folders show the ARCHIVE icon in place of the folder icon // (one icon instead of folder + a separate badge). @@ -495,6 +518,28 @@ export class StashpadFolderPanelView extends ItemView { this.onNavigateAway(); this.jumpToFolder(folder); }); row.oncontextmenu = (e) => { e.preventDefault(); this.openFolderMenu(e, folder); }; + + // 0.105.1: when expanded, list the folder's Home list-pinned notes as a + // sub-list below the folder row. Clicking one reveals it in its Stashpad. + if (homePinned.length > 0 && pinsExpanded) { + const box = list.createDiv({ cls: "stashpad-folderpanel-pinlist" }); + for (const f of homePinned) { + const prow = box.createDiv({ cls: "stashpad-folderpanel-pinrow" }); + const fmc = (this.app.metadataCache.getFileCache(f)?.frontmatter ?? {}) as any; + const pic = prow.createSpan({ cls: "stashpad-folderpanel-pinrow-icon" }); + setIcon(pic, "arrow-up-to-line"); + if (typeof fmc.color === "string") pic.style.color = fmc.color; + prow.createSpan({ cls: "stashpad-folderpanel-pinrow-label", text: this.titleFromFile(f) }); + prow.onclick = () => { this.onNavigateAway(); void this.plugin.revealNoteInStashpad(f); }; + } + } + } + + /** A folder's ROOT-level (Home) list-pinned notes — backs the folder-panel + * reveal. Reuses childrenOf(folder, ROOT_ID) + the listPinned frontmatter. */ + private folderHomePinnedNotes(folder: string): TFile[] { + return this.childrenOf(folder, ROOT_ID).filter((f) => + (this.app.metadataCache.getFileCache(f)?.frontmatter as any)?.listPinned === true); } /** Collapsible "Hidden (N)" group at the bottom of the Folders list, so hidden diff --git a/src/main.ts b/src/main.ts index dd431d5..2eff55c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1034,6 +1034,16 @@ export default class StashpadPlugin extends Plugin { name: "Toggle split-on-newlines", callback: () => call("toggleSplit"), }); + this.addCommand({ + id: "stashpad-fork-version", + name: "Fork as version (alternate draft / sheet)", + callback: () => call("cmdForkVersion"), + }); + this.addCommand({ + id: "stashpad-mark-version-final", + name: "Mark version as final (sheet)", + callback: () => call("cmdMarkVersionFinal"), + }); this.addCommand({ id: "stashpad-command-palette", name: "Command palette (Stashpad only)", @@ -1190,8 +1200,11 @@ export default class StashpadPlugin extends Plugin { // "Clone / duplicate / copy" — three synonyms in the name so command-palette // fuzzy search hits regardless of which word the user reaches for. this.addCommand({ id: "stashpad-clone", name: "Clone selection (duplicate / copy notes)", callback: () => call("cmdClone") }); + this.addCommand({ id: "stashpad-fork-note", name: "Fork note (copy as a variant under a chosen parent)", callback: () => call("cmdForkNote") }); this.addCommand({ id: "stashpad-insert-template", name: "Insert template (clone an existing note)", callback: () => call("cmdInsertTemplate") }); this.addCommand({ id: "stashpad-toggle-expand", name: "Show more / show less (expand toggle)", callback: () => call("cmdToggleExpand") }); + this.addCommand({ id: "stashpad-expand-all", name: "Expand all (show every note's full body)", callback: () => call("cmdExpandAll") }); + this.addCommand({ id: "stashpad-collapse-all", name: "Collapse all (clamp every note's body)", callback: () => call("cmdCollapseAll") }); // Three view-level keybinds that previously had no command-palette // entry. Names mirror their COMMAND_META labels for fuzzy lookup. this.addCommand({ id: "stashpad-pick-move", name: "Move (in-list, arrow + Enter)", callback: () => call("cmdInListPicker") }); @@ -1333,6 +1346,7 @@ export default class StashpadPlugin extends Plugin { } this.addCommand({ id: "stashpad-swap-with-parent", name: "Swap with parent (ouroboros)", callback: () => call("cmdSwapWithParent") }); this.addCommand({ id: "stashpad-toggle-pin", name: "Pin / unpin selected note (sidebar)", callback: () => call("cmdTogglePin") }); + this.addCommand({ id: "stashpad-list-pin", name: "Pin / unpin to top of list", callback: () => call("cmdToggleListPin") }); // 0.61.1: tiny mode — opens a popout window with the minimal shell // (folder/focus title + list + composer + sticky/expand controls). this.addCommand({ @@ -4875,6 +4889,38 @@ export default class StashpadPlugin extends Plugin { } } + // Sheet versions: which version (note id) of each `sheet:` group is the one + // shown as a row. Persisted to localStorage (like last-cursor) so the choice + // survives reloads. Keyed by group id (globally unique) within a folder. + // Storage key: "stashpad:active-versions" → { "<folder>": { "<groupId>": "<noteId>" } } + private readonly ACTIVE_VERSIONS_LS_KEY = "stashpad:active-versions"; + private readActiveVersionsFile(): Record<string, Record<string, string>> { + try { + const raw = window.localStorage.getItem(this.ACTIVE_VERSIONS_LS_KEY); + if (!raw) return {}; + const parsed = JSON.parse(raw); + return parsed && typeof parsed === "object" ? parsed as Record<string, Record<string, string>> : {}; + } catch { + return {}; + } + } + /** Map of <groupId> → <active version note id> for the given folder. */ + loadActiveVersions(folder: string): Map<string, string> { + const all = this.readActiveVersionsFile(); + return new Map(Object.entries(all[folder] ?? {})); + } + /** Synchronously persist the active version for one (folder, group). */ + saveActiveVersion(folder: string, groupId: string, noteId: string): void { + try { + const all = this.readActiveVersionsFile(); + if (!all[folder]) all[folder] = {}; + all[folder][groupId] = noteId; + window.localStorage.setItem(this.ACTIVE_VERSIONS_LS_KEY, JSON.stringify(all)); + } catch (e) { + console.warn("[Stashpad] failed to save active-version", e); + } + } + /** Serializes ALL settings writes so a fast draft-write can't race with * a settings-tab edit and clobber a freshly-changed shortcut. Both * saveSettings() and persistSettingsQuiet() funnel through here. */ diff --git a/src/modals.ts b/src/modals.ts index 368660b..31ac715 100644 --- a/src/modals.ts +++ b/src/modals.ts @@ -13,6 +13,9 @@ export interface DuePickerOptions { knownAuthors?: AssigneeRef[]; /** Assignees already on the note, to pre-fill the chips. */ currentAssignees?: AssigneeRef[]; + /** Modal title. Defaults to "Set due date". The "Assign to" command + * opens this same modal with a different title. */ + title?: string; } import type { NotificationCategory, NotificationRecord, NotificationService } from "./notifications"; // Obsidian types `moment` as the namespace (not callable); a callable view. @@ -1519,36 +1522,6 @@ export function buildAssigneePicker( /** 0.78.3: standalone "Assign to" modal — assignment without touching the * due date. onPick gets the chosen assignee set; not called on dismiss. */ -export class AssignModal extends Modal { - private didChoose = false; - private assignees: AssigneeRef[] = []; - constructor( - app: App, - private opts: { knownAuthors: AssigneeRef[]; currentAssignees: AssigneeRef[] }, - private onPick: (assignees: AssigneeRef[]) => void, - ) { - super(app); - this.assignees = [...opts.currentAssignees]; - } - onOpen(): void { - this.modalEl?.addClass("stashpad-compact-modal"); - this.contentEl.empty(); - this.titleEl.setText("Assign task"); - const wrap = this.contentEl.createDiv({ cls: "stashpad-due-picker" }); - buildAssigneePicker(wrap, { - knownAuthors: this.opts.knownAuthors, - initial: this.assignees, - onChange: (list) => { this.assignees = list; }, - }); - const row = this.contentEl.createDiv({ cls: "stashpad-modal-btns" }); - const cancel = row.createEl("button", { text: "Cancel" }); - cancel.onclick = () => { this.didChoose = true; this.close(); }; - const ok = row.createEl("button", { cls: "mod-cta", text: "Save" }); - ok.onclick = () => { this.didChoose = true; this.close(); this.onPick(this.assignees); }; - } - onClose(): void { this.contentEl.empty(); void this.didChoose; } -} - export class DueDatePickerModal extends Modal { private didChoose = false; /** Working set of assignees, mutated by the chips UI. */ @@ -1571,7 +1544,7 @@ export class DueDatePickerModal extends Modal { onOpen(): void { this.modalEl?.addClass("stashpad-compact-modal"); // 0.76.18 this.contentEl.empty(); - this.titleEl.setText("Set due date"); + this.titleEl.setText(this.opts.title ?? "Set due date"); // Pre-fill from the current value when parseable. let initial: Date | null = null; @@ -1589,10 +1562,17 @@ export class DueDatePickerModal extends Modal { const dateIcon = dateField.createSpan({ cls: "stashpad-due-field-icon" }); setIcon(dateIcon, "calendar"); const dateInput = dateField.createEl("input", { type: "date", cls: "stashpad-due-date" }); + // 0.104.x: dedicated × to clear this field independently. + const dateClear = dateField.createSpan({ cls: "stashpad-due-clear", attr: { "aria-label": "Clear date" } }); + setIcon(dateClear, "x"); + dateClear.onclick = () => { dateInput.value = ""; dateInput.focus(); }; const timeField = fields.createDiv({ cls: "stashpad-due-field" }); const timeIcon = timeField.createSpan({ cls: "stashpad-due-field-icon" }); setIcon(timeIcon, "clock"); const timeInput = timeField.createEl("input", { type: "time", cls: "stashpad-due-time" }); + const timeClear = timeField.createSpan({ cls: "stashpad-due-clear", attr: { "aria-label": "Clear time" } }); + setIcon(timeClear, "x"); + timeClear.onclick = () => { timeInput.value = ""; timeInput.focus(); }; // 0.76.8: the leading icon IS the picker button. The native // ::-webkit-calendar-picker-indicator (on the input's right) is // hidden via CSS; clicking our left icon opens the OS picker via diff --git a/src/settings.ts b/src/settings.ts index 0f96bd8..3280745 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -55,12 +55,12 @@ export type CommandId = | "toggleSplit" | "pickDestination" | "search" | "searchInParent" | "delete" | "undo" | "redo" | "toggleComplete" | "moveUp" | "moveDown" | "moveToTop" | "moveToBottom" | "outdent" | "setColor" - | "clone" | "insertTemplate" - | "toggleExpand" + | "clone" | "forkNote" | "insertTemplate" + | "toggleExpand" | "expandAll" | "collapseAll" | "exportStash" | "importStash" | "pickFolder" | "cloneStashpadTab" | "selectAll" | "copyCodeBlock" | "swapWithParent" - | "togglePin" + | "togglePin" | "listPin" | "toggleTask" | "setDue" | "jumpToTop" | "jumpToBottom" | "lockSelection" | "unlockAll" | "moveToArchive" | "encryptDelete" @@ -119,8 +119,11 @@ export const COMMAND_META: CommandMeta[] = [ { id: "outdent", label: "Outdent (move to grandparent)", desc: "Default: Mod+[ — re-parents the selection one level up.", defaultPrimary: "Mod+[" }, { id: "setColor", label: "Set note color", desc: "Default: Shift+: or ; — open the color picker for the selection (both chords active).", defaultPrimary: "Shift+:", defaultSecondary: ";", defaultUseBoth: true }, { id: "clone", label: "Clone (duplicate / copy) selection", desc: "Default: Mod+Shift+D — clone selected notes (with their subtrees) as siblings.", defaultPrimary: "Mod+Shift+D" }, + { id: "forkNote", label: "Fork note (copy under a chosen parent)", desc: "Duplicate the cursor row (with its subtree) as a variant and pick which parent it nests under. No default chord.", defaultPrimary: "" }, { id: "insertTemplate", label: "Insert template (clone an existing note)", desc: "Pick any note in this Stashpad; clone it (with subtree + attachments) into the current view, retimestamped.", defaultPrimary: "" }, { id: "toggleExpand", label: "Show more / show less (expand toggle)", desc: "Default: Shift+? — toggle the clamp on the cursor row (or every selected row).", defaultPrimary: "Shift+?" }, + { id: "expandAll", label: "Expand all (show every note's full body)", desc: "Un-clamp every note in the current list at once.", defaultPrimary: "" }, + { id: "collapseAll", label: "Collapse all (clamp every note's body)", desc: "Re-clamp every note in the current list at once.", defaultPrimary: "" }, { id: "exportStash", label: "Export selection to .stash", desc: "Export the selected subtree(s) as a .stash bundle (notes + attachments).", defaultPrimary: "" }, { id: "importStash", label: "Import .stash file", desc: "Open the .stash bundle picker and import its notes into this Stashpad.", defaultPrimary: "" }, { id: "pickFolder", label: "Open / switch / create Stashpad folder", desc: "Default: Mod+S — opens the unified folder picker (reveal, switch, create, convert).", defaultPrimary: "Mod+S" }, @@ -129,6 +132,7 @@ export const COMMAND_META: CommandMeta[] = [ { id: "copyCodeBlock", label: "Copy code from codeblock", desc: "Default: { — copy the contents of the cursor row's first codeblock (or pick one when multiple exist).", defaultPrimary: "{" }, { id: "swapWithParent", label: "Swap with parent (ouroboros)", desc: "Promote the cursor row above its current parent; the parent slides under it (carrying its other children). No default — bind in this tab.", defaultPrimary: "" }, { id: "togglePin", label: "Pin / unpin selected note", desc: "Default: P — toggle the sidebar pin state of the cursor row (or focused note).", defaultPrimary: "P" }, + { id: "listPin", label: "Pin / unpin to top of list", desc: "Float the cursor row (or selection) to the TOP of its list — distinct from the sidebar pin. No default chord.", defaultPrimary: "" }, { id: "toggleTask", label: "Toggle task (todo)", desc: "Default: H — mark the selection (or cursor row) as a task / todo, or clear it. Tasks appear in the Tasks panel.", defaultPrimary: "H" }, { id: "setDue", label: "Set due date…", desc: "Default: D — open a date+time picker to set (or clear) the due date on the selection. Setting a due date also marks the note as a task.", defaultPrimary: "D" }, { id: "jumpToTop", label: "Jump to top of list", desc: "Default: Home — move the cursor to the first note in the current list.", defaultPrimary: "Home" }, @@ -386,6 +390,12 @@ export interface StashpadSettings { * effect that vanishes the moment the cursor moves. Off by * default. */ autoExpandCursorRow: boolean; + /** When on, note bodies render fully expanded by default; the + * per-note "Show more / show less" toggle and the expand/collapse-all + * commands then act as a *collapse* opt-out (the expandedNotes Set is + * interpreted as "differs from this default"). Off = current behavior + * (bodies clamp by default, expand is opt-in). */ + expandBodiesByDefault: boolean; /** 0.74.1: auto-open the right-sidebar detail panel whenever a * Stashpad view becomes active. Off by default — opt in via this * toggle or the matching palette command. */ @@ -394,6 +404,11 @@ export interface StashpadSettings { * focus/open it — navigate into it, same as ArrowRight or the * enter arrow. On by default. Single click still just selects. */ doubleClickToFocus: boolean; + /** 0.107.0: enable "Sheet versions" — treat notes sharing a `sheet-group` + * frontmatter id as alternate versions of one item (only the active one + * shows as a row; siblings collapse into a tab bar). Off by default so the + * collapse filter never touches anyone who hasn't opted in. */ + enableSheetVersions: boolean; /** 0.76.6: how dates (due dates, created/modified) display across * the Tasks panel + detail panel. One of locale / iso / us / eu / * long. Default "locale". */ @@ -522,8 +537,10 @@ export const DEFAULT_SETTINGS: StashpadSettings = { autoNavOnMoveIn: false, autoNavOnMoveOut: false, autoExpandCursorRow: false, + expandBodiesByDefault: false, autoOpenDetailPanel: false, doubleClickToFocus: true, + enableSheetVersions: false, dateDisplayFormat: "locale", dateDisplayTimezone: "", jdIndexScope: "vault", @@ -943,10 +960,14 @@ export class StashpadSettingTab extends PluginSettingTab { () => this.plugin.settings.autoNavOnMoveOut, (v) => { this.plugin.settings.autoNavOnMoveOut = v; }, ["navigate", "move", "out"])); items.push(toggle("Double-click a note to open it", "Double-click (or double-tap on mobile) a note in the list to focus/open it — the same as pressing → or clicking the enter arrow. Single click still just selects. On by default.", () => this.plugin.settings.doubleClickToFocus, (v) => { this.plugin.settings.doubleClickToFocus = v; }, ["double", "click", "open", "focus"])); + items.push(toggle("Sheet versions (alternate drafts)", "Treat notes that share a 'sheet-group' frontmatter id as alternate versions of one item: only the active version shows as a row, and its siblings collapse into a tab bar at the bottom of that row. Use \"Fork as version\" on a note to start. Off by default — when off, no note is ever hidden by this feature and the commands do nothing.", + () => this.plugin.settings.enableSheetVersions, (v) => { this.plugin.settings.enableSheetVersions = v; }, ["sheet", "version", "draft", "alternate", "fork"])); items.push(toggle("Auto-open the detail panel", "Open the right-sidebar Stashpad detail panel automatically whenever a Stashpad view becomes active. The panel shows the cursored note's body, metadata, and children. Off = open manually via ribbon or command palette.", () => this.plugin.settings.autoOpenDetailPanel, (v) => { this.plugin.settings.autoOpenDetailPanel = v; }, ["detail", "panel", "sidebar"])); items.push(toggle("Expand the cursor row's body automatically", "As you arrow-key through the list, the row under the cursor temporarily un-clamps to show its full body. Moving away re-collapses it. Doesn't affect the persistent 'Show more' state — this is a transient view-only effect.", () => this.plugin.settings.autoExpandCursorRow, (v) => { this.plugin.settings.autoExpandCursorRow = v; }, ["expand", "cursor", "body"])); + items.push(toggle("Expand note bodies by default", "Show every note's full body by default instead of clamping long notes. The per-note 'Show more / show less' toggle and the Expand-all / Collapse-all commands then work in reverse — they let you collapse individual notes back down. Off = bodies clamp by default (expand is opt-in).", + () => this.plugin.settings.expandBodiesByDefault, (v) => { this.plugin.settings.expandBodiesByDefault = v; }, ["expand", "collapse", "default", "body", "clamp"])); items.push(toggle("Confirm cross-parent drag-and-drop", "When dragging notes onto a note that has a different parent, ask before re-parenting (turn off to allow direct moves).", () => this.plugin.settings.confirmCrossParentDrag, (v) => { this.plugin.settings.confirmCrossParentDrag = v; }, ["confirm", "drag", "drop", "reparent"])); items.push(toggle("Confirm bulk deletes", "Warn before deletes that affect more than one note — multi-selection delete OR deleting a note that has descendants. A single childless note with no attachments never prompts. Off = those deletes apply immediately (undo still recovers everything).", diff --git a/src/sheets-versions.ts b/src/sheets-versions.ts new file mode 100644 index 0000000..633a145 --- /dev/null +++ b/src/sheets-versions.ts @@ -0,0 +1,90 @@ +// Sheet "versions" — several notes sharing a `sheet-group` id are treated as +// alternate versions of one item. Only the active version shows as a row; its +// siblings collapse into a small tab bar on that row. The frontmatter keys are +// shared with the standalone Sheets plugin so the same notes work in both. +// +// The group key is `sheet-group` (NOT the generic `sheet`) to avoid colliding +// with a user's own unrelated frontmatter, AND a note only counts as a version +// when it carries BOTH `sheet-group` and a numeric `sheet-order` (see +// isVersionMember) — so a stray single key can never silently hide a note. +import { App, TFile } from "obsidian"; +import { TreeNode } from "./types"; + +export const SHEET_KEY = "sheet-group"; // group id shared by all versions (string) +export const SHEET_ORDER_KEY = "sheet-order"; // numeric order within the group +export const SHEET_FINAL_KEY = "sheet-final"; // true on the chosen version +export const SHEET_LABEL_KEY = "sheet-label"; // optional custom tab label + +type Fm = Record<string, unknown> | null | undefined; + +export function sheetIdOf(fm: Fm): string | null { + if (!fm) return null; + const v = fm[SHEET_KEY]; + return typeof v === "string" && v.trim() ? v : null; +} + +export function sheetOrderOf(fm: Fm): number | null { + const v = fm?.[SHEET_ORDER_KEY]; + return typeof v === "number" ? v : null; +} + +/** A note is a version-group member only when it carries BOTH a group id and a + * numeric order. Requiring two keys makes accidental collisions (a user with + * an unrelated `sheet-group` key) essentially impossible — the collapse filter + * ignores anything that isn't a deliberate, fully-stamped version. */ +export function isVersionMember(fm: Fm): boolean { + return sheetIdOf(fm) !== null && sheetOrderOf(fm) !== null; +} + +export function sheetIsFinal(fm: Fm): boolean { + return fm?.[SHEET_FINAL_KEY] === true; +} + +export function sheetLabelOf(fm: Fm): string | null { + const v = fm?.[SHEET_LABEL_KEY]; + return typeof v === "string" && v.trim() ? v : null; +} + +/** Generate a fresh, reasonably-unique group id (matches the Sheets plugin). */ +export function newSheetGroupId(): string { + const t = Date.now().toString(36); + const r = Math.floor(Math.random() * 1e6).toString(36); + return `s-${t}-${r}`; +} + +/** Read a node's frontmatter via the metadata cache. */ +export function nodeFm(app: App, node: TreeNode): Fm { + if (!node.file) return null; + return app.metadataCache.getFileCache(node.file)?.frontmatter as Fm; +} + +/** Sort group members by order, then created, then id — stable + deterministic. */ +export function sortVersions(app: App, members: TreeNode[]): TreeNode[] { + return members.slice().sort((a, b) => { + const oa = sheetOrderOf(nodeFm(app, a)); + const ob = sheetOrderOf(nodeFm(app, b)); + if (oa != null && ob != null && oa !== ob) return oa - ob; + if (oa != null && ob == null) return -1; + if (oa == null && ob != null) return 1; + const ca = a.created ?? ""; + const cb = b.created ?? ""; + if (ca !== cb) return ca < cb ? -1 : 1; + return a.id < b.id ? -1 : a.id > b.id ? 1 : 0; + }); +} + +/** The default active version of a group: the final pick, else the first by + * order. `members` should already be the ones present in the current list. */ +export function defaultActive(app: App, members: TreeNode[]): TreeNode | null { + if (members.length === 0) return null; + const sorted = sortVersions(app, members); + return sorted.find((m) => sheetIsFinal(nodeFm(app, m))) ?? sorted[0]; +} + +/** A short label for a tab: the custom label, else the note's first body line + * (the title Stashpad shows), falling back to the basename. */ +export function tabTitle(app: App, node: TreeNode, fallbackTitle: string): string { + const label = sheetLabelOf(nodeFm(app, node)); + if (label) return label; + return fallbackTitle; +} diff --git a/src/types.ts b/src/types.ts index b7ebcc6..d4b82db 100644 --- a/src/types.ts +++ b/src/types.ts @@ -107,6 +107,9 @@ export const RESERVED_FRONTMATTER: readonly string[] = [ // 0.86.3: sidebar pin state lives on the note (so it SYNCS with the note // across devices). Stashpad-managed; clones/templates must not inherit it. "pinned", "pinnedAt", + // 0.105.0: list pin — floats a note to the TOP of its sibling list (distinct + // from the sidebar pin above). Stashpad-managed; not inherited by clones. + "listPinned", "listPinnedAt", // 0.88.0: marks a note that came in via import (used by the "imported only" // view filter). Stashpad-managed; a clone of an imported note isn't imported. "imported", diff --git a/src/view-helpers.ts b/src/view-helpers.ts index 01b9a8f..1d2dd42 100644 --- a/src/view-helpers.ts +++ b/src/view-helpers.ts @@ -157,3 +157,51 @@ export function arraysEqual<T>(a: T[], b: T[]): boolean { for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false; return true; } + +// --- Tag filter: special sentinel modes + ranked matching -------------------- + +/** Sentinel `tagFilter` values for the "has any tag" / "has no tags" filter + * modes. The `__stashpad:` prefix can't collide with a real tag name. */ +export const TAG_FILTER_TAGGED = "__stashpad:tagged__"; +export const TAG_FILTER_UNTAGGED = "__stashpad:untagged__"; + +/** Score a tag name against a query for the tag-filter search box. + * Higher = closer match; -1 = no match. Tiers (closest first): + * exact (1000) > prefix (800) > word-boundary substring (≈600) > + * mid-word substring (≈500) > subsequence/fuzzy (200). + * Substring tiers subtract the match index so earlier hits rank higher. */ +export function rankTagMatch(query: string, tag: string): number { + const q = query.toLowerCase().trim(); + const t = tag.toLowerCase(); + if (!q) return 0; + if (t === q) return 1000; + if (t.startsWith(q)) return 800; + const idx = t.indexOf(q); + if (idx > 0) { + const prev = t[idx - 1]; + const boundary = !/[a-z0-9]/.test(prev); // after a separator (-, _, /, space) + return (boundary ? 600 : 500) - Math.min(idx, 99); + } + // Subsequence fuzzy: every query char appears in order somewhere. + let qi = 0; + for (let i = 0; i < t.length && qi < q.length; i++) { + if (t[i] === q[qi]) qi++; + } + return qi === q.length ? 200 : -1; +} + +/** Rank + filter a tag list by `query`. Empty query returns the list + * unchanged (caller's original frequency/alpha order). Otherwise drops + * non-matches and sorts by score desc, then count desc, then label. */ +export function rankTags<T extends { raw: string; label: string; count: number }>( + query: string, + tags: T[], +): T[] { + const q = query.trim(); + if (!q) return tags; + return tags + .map((t) => ({ t, s: rankTagMatch(q, t.raw) })) + .filter((x) => x.s >= 0) + .sort((a, b) => b.s - a.s || b.t.count - a.t.count || a.t.label.localeCompare(b.t.label)) + .map((x) => x.t); +} diff --git a/src/view.ts b/src/view.ts index 851a6ea..b9a0cab 100644 --- a/src/view.ts +++ b/src/view.ts @@ -22,16 +22,29 @@ import { getSettings, getTemplatesFormats, onSettingsChange } from "./settings"; import { StashpadSuggest } from "./note-picker"; import { StashpadCommandPalette } from "./command-palette"; import { setActiveView, clearActiveView } from "./active-view"; -import { AssignModal, ColorPickerModal, ConfirmDeleteModal, ConfirmModal, DueDatePickerModal, SplitNoteModal } from "./modals"; +import { ColorPickerModal, ConfirmDeleteModal, ConfirmModal, DueDatePickerModal, SplitNoteModal } from "./modals"; import { ComposerAutocomplete } from "./composer-autocomplete"; import { matchBinding, humanCombo } from "./view-keys"; import { AuthorshipTracker } from "./authorship-tracker"; import { ViewDnD } from "./view-dnd"; import { NoteBodyRenderer } from "./note-body-renderer"; import { computeSortedIds } from "./view-sort"; +import { + SHEET_KEY, + SHEET_ORDER_KEY, + SHEET_FINAL_KEY, + sheetIdOf, + isVersionMember, + sheetIsFinal, + newSheetGroupId, + nodeFm, + sortVersions, + defaultActive, + tabTitle, +} from "./sheets-versions"; import * as clipboardCmds from "./commands/clipboard-cmds"; import * as ioCmds from "./commands/io-cmds"; -import { setIconSafe, isAnyModalOpen, properCaseFolderPath, computeReorder, arraysEqual, splitIntoChunks, SPLIT_MODE_LABELS, type SplitMode } from "./view-helpers"; +import { setIconSafe, isAnyModalOpen, properCaseFolderPath, computeReorder, arraysEqual, splitIntoChunks, SPLIT_MODE_LABELS, type SplitMode, rankTags, TAG_FILTER_TAGGED, TAG_FILTER_UNTAGGED } from "./view-helpers"; import type StashpadPlugin from "./main"; const IMG_EXT = new Set(["png", "jpg", "jpeg", "gif", "webp", "svg", "bmp", "avif"]); @@ -251,6 +264,10 @@ export class StashpadView extends ItemView { * (lazy-loaded) on reload. 0.91.0. */ private lastSelectionByFocus = new Map<StashpadId, StashpadId[]>(); private expandedNotes = new Set<StashpadId>(); + /** Sheet versions: which version (note id) of a `sheet:` group is currently + * shown as the row. View-state only (not persisted) — falls back to the + * final pick / first-by-order when unset. */ + private activeVersionByGroup = new Map<string, StashpadId>(); private focusComposerOnNextRender = false; /** 0.76.21: timestamp until which the activation auto-focus * (focusComposer) is suppressed. Set after actions that close a @@ -310,8 +327,8 @@ export class StashpadView extends ItemView { this.tree.setOrderProvider((parentId) => { const folder = this.noteFolder; const mode = this.sortStore.getMode(folder, parentId); - if (mode === "manual") return this.order.getOrder(folder, parentId); - return computeSortedIds(this, parentId, mode); + const base = mode === "manual" ? this.order.getOrder(folder, parentId) : computeSortedIds(this, parentId, mode); + return this.hoistListPinned(parentId, base); }); this.debouncedRender = debounce(() => { if (this.renderSuppressed()) return; this.render(); }, 80); this.authorship = new AuthorshipTracker(this); @@ -568,6 +585,8 @@ export class StashpadView extends ItemView { for (const [focusId, noteId] of loaded) this.lastCursorByFocus.set(focusId, noteId); // 0.91.0: hydrate the persisted multi-selection alongside the cursor. this.lastSelectionByFocus = this.plugin.loadLastSelection(this.noteFolder); + // Sheet versions: restore which version of each group is shown. + this.activeVersionByGroup = this.plugin.loadActiveVersions(this.noteFolder); } catch { /* ignore */ } // On a fresh mount (app reload, tab restore, first-ever open), scroll // to the end of the list so the newest notes are visible. Once the @@ -898,6 +917,8 @@ export class StashpadView extends ItemView { for (const [focusId, noteId] of loaded) this.lastCursorByFocus.set(focusId, noteId); // 0.91.0: re-hydrate the persisted multi-selection for the new folder. this.lastSelectionByFocus = this.plugin.loadLastSelection(this.noteFolder); + // Sheet versions: re-hydrate active versions for the new folder. + this.activeVersionByGroup = this.plugin.loadActiveVersions(this.noteFolder); } catch { /* ignore */ } const savedCursorId = this.lastCursorByFocus.get(this.focusId); let policy: ScrollPolicy; @@ -1893,6 +1914,10 @@ export class StashpadView extends ItemView { } private filterChildren(children: TreeNode[]): TreeNode[] { + // Sheet versions collapse FIRST and unconditionally (before the + // no-filters early-return below): non-active versions of a group are + // hidden so only the active one shows as a row. + children = this.collapseVersions(children); const cutoff = this.timeFilterCutoff(); const tag = this.tagFilter?.toLowerCase(); const color = this.colorFilter?.toLowerCase() ?? null; @@ -1918,7 +1943,9 @@ export class StashpadView extends ItemView { } if (tag) { if (!n.file) return false; - if (!this.nodeHasTag(n, tag)) return false; + if (this.tagFilter === TAG_FILTER_TAGGED) { if (!this.nodeHasAnyTag(n)) return false; } + else if (this.tagFilter === TAG_FILTER_UNTAGGED) { if (this.nodeHasAnyTag(n)) return false; } + else if (!this.nodeHasTag(n, tag)) return false; } if (color) { const c = this.colorForNode(n)?.toLowerCase() ?? null; @@ -1936,6 +1963,70 @@ export class StashpadView extends ItemView { }); } + /** Collapse `sheet:` version groups so only the active version remains in + * the list. Notes without a sheet id pass through untouched. */ + private collapseVersions(children: TreeNode[]): TreeNode[] { + // Feature is opt-in: when off, never hide anything. + if (!this.plugin.settings.enableSheetVersions) return children; + // Bucket nodes by group id; non-sheet nodes go straight through. + const groups = new Map<string, TreeNode[]>(); + let anyGroup = false; + for (const n of children) { + const fm = nodeFm(this.app, n); + if (!isVersionMember(fm)) continue; // needs BOTH sheet-group + sheet-order + anyGroup = true; + const gid = sheetIdOf(fm)!; + const arr = groups.get(gid); + if (arr) arr.push(n); + else groups.set(gid, [n]); + } + if (!anyGroup) return children; + // For each group, decide the single active member to keep. + const keep = new Set<StashpadId>(); + for (const [gid, members] of groups) { + const active = this.activeVersionNode(gid, members); + if (active) keep.add(active.id); + } + return children.filter((n) => { + // Only fully-stamped version members are eligible to be hidden. + if (!isVersionMember(nodeFm(this.app, n))) return true; + return keep.has(n.id); + }); + } + + /** The version node to show for a group, honoring an explicit user choice + * when that choice is still present in the current set. */ + private activeVersionNode(groupId: string, members: TreeNode[]): TreeNode | null { + const chosen = this.activeVersionByGroup.get(groupId); + if (chosen) { + const hit = members.find((m) => m.id === chosen); + if (hit) return hit; + } + return defaultActive(this.app, members); + } + + /** Switch which version of a group is shown, persist it, then repaint. */ + private setActiveVersion(groupId: string, id: StashpadId): void { + this.activeVersionByGroup.set(groupId, id); + this.plugin.saveActiveVersion(this.noteFolder, groupId, id); + this.render(); + } + + /** True if `node`'s file carries ANY tag (inline or frontmatter) — + * backs the "Tagged"/"Untagged" filter modes. */ + private nodeHasAnyTag(node: TreeNode): boolean { + if (!node.file) return false; + const cache = this.app.metadataCache.getFileCache(node.file); + if (!cache) return false; + if (cache.tags && cache.tags.length > 0) return true; + const fmTags = cache.frontmatter?.tags; + if (fmTags) { + const arr = Array.isArray(fmTags) ? fmTags : [fmTags]; + if (arr.some((t) => typeof t === "string" && t.trim().length > 0)) return true; + } + return false; + } + /** True if `node`'s file carries `tag` (case-insensitive) — checks * inline tags AND frontmatter `tags`. */ private nodeHasTag(node: TreeNode, tagLower: string): boolean { @@ -2743,6 +2834,10 @@ export class StashpadView extends ItemView { // group so it's visible without scrolling past the selection commands. menu.addItem((it: any) => it.setTitle("Reload without saving").setIcon("rotate-ccw").onClick(() => this.plugin.reloadAppForUpdate())); menu.addSeparator(); + // List-wide expand/collapse — operate on every note, independent of selection. + menu.addItem((it: any) => it.setTitle("Expand all").setIcon("unfold-vertical").onClick(() => this.cmdExpandAll())); + menu.addItem((it: any) => it.setTitle("Collapse all").setIcon("fold-vertical").onClick(() => this.cmdCollapseAll())); + menu.addSeparator(); menu.addItem((it: any) => it.setTitle("Open in new Stashpad tab").setIcon("list-tree").setDisabled(!hasTargets).onClick(() => this.cmdOpenInNewStashpadTab())); menu.addItem((it: any) => it.setTitle("Open in editor").setIcon("pencil").setDisabled(!hasTargets).onClick(() => this.cmdOpenInEditor())); menu.addSeparator(); @@ -2758,6 +2853,10 @@ export class StashpadView extends ItemView { menu.addItem((it: any) => it.setTitle("Copy").setIcon("copy").setDisabled(!hasTargets).onClick(() => void this.cmdCopy())); menu.addItem((it: any) => it.setTitle("Copy tree").setIcon("copy-plus").setDisabled(!hasTargets).onClick(() => void this.cmdCopyTree())); menu.addItem((it: any) => it.setTitle("Clone (duplicate / copy)").setIcon("files").setDisabled(!hasTargets).onClick(() => void this.cmdClone())); + if (this.plugin.settings.enableSheetVersions) { + menu.addItem((it: any) => it.setTitle("Fork as version").setIcon("git-fork").setDisabled(!hasTargets || !exactlyOne).onClick(() => void this.cmdForkVersion())); + menu.addItem((it: any) => it.setTitle("Mark version as final").setIcon("star").setDisabled(!hasTargets || !exactlyOne).onClick(() => void this.cmdMarkVersionFinal())); + } menu.addItem((it: any) => it.setTitle("Insert template…").setIcon("file-plus-2").onClick(() => this.cmdInsertTemplate())); menu.addItem((it: any) => it.setTitle("Merge").setIcon("merge").setDisabled(this.selection.size < 2).onClick(() => void this.cmdMerge())); // Split only operates on a single note — the cmdSplit modal would @@ -2786,27 +2885,131 @@ export class StashpadView extends ItemView { new StashpadCommandPalette(this.app).open(); } - /** Render the tag-filter <select>. Folder tags are tallied + sorted - * here on each render so newly-added tags appear without a refresh. */ + /** Human label for the current tag filter (button text). */ + private tagFilterLabel(): string { + if (this.tagFilter === TAG_FILTER_TAGGED) return "Tagged"; + if (this.tagFilter === TAG_FILTER_UNTAGGED) return "Untagged"; + if (this.tagFilter) return `#${this.formatTagLabel(this.tagFilter)}`; + return this.collectFolderTags().length === 0 ? "No tags" : "All tags"; + } + + /** 0.104.x: the tag filter is a custom button + searchable popover + * (fused from the iOS/macOS Drafts design) instead of a native + * <select>. Clicking opens a popover with a search box (ranked, X to + * clear), the "Tagged"/"Untagged" special modes, and every folder tag — + * navigable by ↑/↓ + Enter. Tags are tallied each render so new ones + * appear without a refresh. */ private renderTagFilterDropdown(bar: HTMLElement): void { - const sel = bar.createEl("select", { cls: "stashpad-tag-filter-select" }); - const all = sel.createEl("option", { text: "All tags" }); - all.value = ""; - if (!this.tagFilter) all.selected = true; - const tags = this.collectFolderTags(); - if (tags.length === 0) { - sel.disabled = true; - all.text = "No tags"; - } else { - for (const t of tags) { - const opt = sel.createEl("option", { text: `${t.label} (${t.count})` }); - opt.value = t.raw; - if (this.tagFilter && this.tagFilter.toLowerCase() === t.raw.toLowerCase()) opt.selected = true; - } - } + const btn = bar.createDiv({ cls: "stashpad-tag-filter-btn" }); + btn.setAttribute("role", "button"); + btn.setAttribute("tabindex", "0"); + const icon = btn.createSpan({ cls: "stashpad-tag-filter-btn-icon" }); + setIconSafe(icon, "tag", "#"); + btn.createSpan({ cls: "stashpad-tag-filter-label", text: this.tagFilterLabel() }); + if (tags.length === 0 && !this.tagFilter) btn.addClass("is-disabled"); + const open = (e: Event): void => { + e.preventDefault(); + // Allow opening with a stale filter active even if no tags remain, so + // it's always recoverable via the "All tags" reset. + if (tags.length === 0 && !this.tagFilter) return; + this.openTagFilterMenu(btn); + }; + btn.onclick = open; + btn.onkeydown = (e) => { if (e.key === "Enter" || e.key === " ") open(e); }; + } - sel.onchange = () => this.setTagFilter(sel.value || null); + /** Searchable tag-filter popover anchored beneath `anchor`. Mirrors the + * color-filter popover's outside-click + Escape teardown. */ + private openTagFilterMenu(anchor: HTMLElement): void { + const doc = anchor.ownerDocument ?? document; + doc.querySelectorAll(".stashpad-tag-filter-popover").forEach((el) => el.remove()); + + const pop = doc.body.createDiv({ cls: "stashpad-tag-filter-popover" }); + const r = anchor.getBoundingClientRect(); + pop.setCssStyles({ + left: `${Math.max(8, r.left)}px`, + top: `${r.bottom + 4}px`, + minWidth: `${Math.max(r.width, 200)}px`, + maxWidth: "min(320px, calc(100vw - 16px))", + width: "max-content", + }); + + const scope = new Scope((this.app as any).scope); + const close = (): void => { + pop.remove(); + doc.removeEventListener("mousedown", outside, true); + try { (this.app as any).keymap?.popScope(scope); } catch { /* ignore */ } + }; + const outside = (ev: MouseEvent): void => { + if (!pop.contains(ev.target as Node) && ev.target !== anchor && !anchor.contains(ev.target as Node)) close(); + }; + + // Search row: icon + input + (conditionally) an X-to-clear button. + const searchRow = pop.createDiv({ cls: "stashpad-tag-filter-search" }); + const sIcon = searchRow.createSpan({ cls: "stashpad-tag-filter-search-icon" }); + setIconSafe(sIcon, "search", "⌕"); + const input = searchRow.createEl("input", { type: "text", cls: "stashpad-tag-filter-input", attr: { placeholder: "Filter tags…" } }); + const clearX = searchRow.createSpan({ cls: "stashpad-tag-filter-clear", attr: { "aria-label": "Clear" } }); + setIconSafe(clearX, "x", "×"); + clearX.setCssStyles({ display: "none" }); + + const list = pop.createDiv({ cls: "stashpad-tag-filter-list" }); + const allTags = this.collectFolderTags(); + let rows: Array<{ value: string | null; el: HTMLElement }> = []; + let highlight = 0; + + const select = (value: string | null): void => { this.setTagFilter(value); close(); }; + const setHighlight = (i: number): void => { + if (rows.length === 0) { highlight = 0; return; } + highlight = (i + rows.length) % rows.length; + rows.forEach((row, k) => row.el.toggleClass("is-highlighted", k === highlight)); + rows[highlight].el.scrollIntoView({ block: "nearest" }); + }; + const addRow = (label: string, value: string | null, count: number | undefined, active: boolean): void => { + const row = list.createDiv({ cls: "stashpad-tag-filter-row" }); + if (active) row.addClass("is-active"); + row.createSpan({ cls: "stashpad-tag-filter-row-label", text: label }); + if (typeof count === "number") row.createSpan({ cls: "stashpad-tag-filter-row-count", text: String(count) }); + const idx = rows.length; + rows.push({ value, el: row }); + row.onmousedown = (e) => { e.preventDefault(); select(value); }; + row.onmouseenter = () => setHighlight(idx); + }; + const renderList = (): void => { + const q = input.value; + clearX.setCssStyles({ display: q ? "" : "none" }); + list.empty(); + rows = []; + const activeRaw = this.tagFilter?.toLowerCase(); + if (!q.trim()) { + // Empty query: special modes pinned on top, then every tag. + addRow("All tags", null, undefined, !this.tagFilter); + addRow("Tagged", TAG_FILTER_TAGGED, undefined, this.tagFilter === TAG_FILTER_TAGGED); + addRow("Untagged", TAG_FILTER_UNTAGGED, undefined, this.tagFilter === TAG_FILTER_UNTAGGED); + for (const t of allTags) addRow(`#${t.label}`, t.raw, t.count, activeRaw === t.raw.toLowerCase()); + } else { + // Typing: hide the specials so ↑/↓ jump straight to ranked tags. + const ranked = rankTags(q, allTags); + if (ranked.length === 0) list.createDiv({ cls: "stashpad-tag-filter-empty", text: "No matching tags" }); + else for (const t of ranked) addRow(`#${t.label}`, t.raw, t.count, activeRaw === t.raw.toLowerCase()); + } + setHighlight(0); + }; + + clearX.onclick = () => { input.value = ""; renderList(); input.focus(); }; + input.addEventListener("input", renderList); + input.addEventListener("keydown", (e) => { + if (e.key === "ArrowDown") { e.preventDefault(); setHighlight(highlight + 1); } + else if (e.key === "ArrowUp") { e.preventDefault(); setHighlight(highlight - 1); } + else if (e.key === "Enter") { e.preventDefault(); if (rows[highlight]) select(rows[highlight].value); } + }); + + scope.register([], "Escape", (ev: KeyboardEvent) => { ev.preventDefault(); close(); return false; }); + (this.app as any).keymap?.pushScope(scope); + + renderList(); + setTimeout(() => { doc.addEventListener("mousedown", outside, true); input.focus(); }, 0); } /** Color filter — custom button + popover. Native <select> is unable @@ -3524,6 +3727,8 @@ export class StashpadView extends ItemView { }; }; addRow(tags.length === 0 ? "No tags" : "All tags", null); + addRow("Tagged", TAG_FILTER_TAGGED); + addRow("Untagged", TAG_FILTER_UNTAGGED); for (const t of tags) addRow(`${t.label} (${t.count})`, t.raw); } @@ -4250,6 +4455,7 @@ export class StashpadView extends ItemView { if (isCursor && this.plugin.settings.autoExpandCursorRow) row.addClass("is-cursor-expanded"); if (isPickTarget) row.addClass("is-pick-target"); if (this.isCompleted(node)) row.addClass("is-completed"); + if (this.isListPinned(node.id)) row.addClass("is-list-pinned"); // 0.99.5: ghost rows that are sitting on a pending CUT (note clipboard), // mirroring a file manager — they're about to move/be-extracted on paste. if (this.isCutPending(node.id)) row.addClass("is-cut-pending"); @@ -4314,8 +4520,16 @@ export class StashpadView extends ItemView { // horizontal line below the timestamp — the mobile checkbox sits just to the // LEFT of the arrow (see the desktop addTaskCheckbox call above). const mobileTask = showCheckbox && Platform.isMobile; - if (childCount > 0 || mobileTask) { + const isPinnedRow = this.isListPinned(node.id); + if (childCount > 0 || mobileTask || isPinnedRow) { const metaBottom = meta.createDiv({ cls: "stashpad-note-meta-bottom" }); + // 0.106.x: list-pin indicator — a lucide pin icon under the timestamp, + // placed before the children-count arrow. + if (isPinnedRow) { + const pin = metaBottom.createSpan({ cls: "stashpad-note-listpin" }); + setIcon(pin, "pin"); + pin.setAttr("aria-label", "Pinned to top of list"); + } if (mobileTask) this.addTaskCheckbox(metaBottom, node); if (childCount > 0) { const enter = metaBottom.createSpan({ cls: "stashpad-note-enter" }); @@ -4387,9 +4601,54 @@ export class StashpadView extends ItemView { // Show More toggle into that cluster (anchored before the first button). this.renderNoteBody(bodyContent, node, { clamp: true, toggleHost: actions, toggleAnchor }); + // Sheet version tabs (only when this row is part of a multi-version group). + this.renderVersionTabs(body, node); + row.oncontextmenu = (evt) => { evt.preventDefault(); this.openNoteMenu(evt, node); }; } + /** Render the version tab bar at the bottom of a row whose note belongs to a + * `sheet:` group with more than one version. */ + private renderVersionTabs(body: HTMLElement, node: TreeNode): void { + if (!this.plugin.settings.enableSheetVersions) return; + if (!isVersionMember(nodeFm(this.app, node))) return; + const gid = sheetIdOf(nodeFm(this.app, node))!; + const parent = node.parent ?? this.focusId; + const siblings = this.tree.getChildren(parent); + const members = sortVersions( + this.app, + siblings.filter((s) => { + const fm = nodeFm(this.app, s); + return isVersionMember(fm) && sheetIdOf(fm) === gid; + }), + ); + if (members.length < 2) return; + + const bar = body.createDiv({ cls: "stashpad-version-tabs" }); + for (const m of members) { + const isActive = m.id === node.id; + const isFinal = sheetIsFinal(nodeFm(this.app, m)); + const tab = bar.createDiv({ + cls: + "stashpad-version-tab" + + (isActive ? " is-active" : "") + + (isFinal ? " is-final" : ""), + }); + if (isFinal) tab.createSpan({ cls: "stashpad-version-star", text: "★" }); + tab.createSpan({ + cls: "stashpad-version-tab-label", + text: tabTitle(this.app, m, this.titleForNode(m).trim() || "Untitled"), + }); + tab.title = this.titleForNode(m).trim(); + if (!isActive) { + tab.onclick = (e) => { e.stopPropagation(); this.setActiveVersion(gid, m.id); }; + } + } + const add = bar.createEl("button", { cls: "stashpad-version-add", text: "+" }); + add.title = "New version"; + add.onclick = (e) => { e.stopPropagation(); void this.cmdForkVersion(node, true); }; + } + /** Create + wire the task checkbox (used at the row's left edge on desktop, * or inside the meta column on mobile). 0.87.1. */ private addTaskCheckbox(parent: HTMLElement, node: TreeNode): void { @@ -4455,7 +4714,7 @@ export class StashpadView extends ItemView { // appending fresh nodes. container.empty(); const textEl = container.createDiv({ cls: "stashpad-note-text" }); - const expanded = this.expandedNotes.has(node.id); + const expanded = this.isNoteExpanded(node.id); if (opts.clamp && !expanded) textEl.addClass("is-clamped"); // 0.71.23: in compact/tiny modes the row is too short to host // rendered markdown — headings overflow, code blocks get clipped @@ -4557,8 +4816,7 @@ export class StashpadView extends ItemView { } toggle.onclick = (e) => { e.stopPropagation(); - if (this.expandedNotes.has(node.id)) this.expandedNotes.delete(node.id); - else this.expandedNotes.add(node.id); + this.setNoteExpanded(node.id, !this.isNoteExpanded(node.id)); // Re-render just this body in place to preserve list scroll. container.empty(); this.renderNoteBody(container, node, opts); @@ -5524,9 +5782,13 @@ export class StashpadView extends ItemView { if (matchBinding(e, sb.openTab)) { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); this.cmdOpenInNewStashpadTab(); return; } if (matchBinding(e, sb.split)) { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); void this.cmdSplit(); return; } if (matchBinding(e, sb.clone)) { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); void this.cmdClone(); return; } + if (matchBinding(e, sb.forkNote)) { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); this.cmdForkNote(); return; } if (matchBinding(e, sb.insertTemplate)) { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); this.cmdInsertTemplate(); return; } if (matchBinding(e, sb.toggleExpand)) { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); this.cmdToggleExpand(); return; } + if (matchBinding(e, sb.expandAll)) { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); this.cmdExpandAll(); return; } + if (matchBinding(e, sb.collapseAll)) { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); this.cmdCollapseAll(); return; } if (matchBinding(e, sb.togglePin)) { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); void this.cmdTogglePin(); return; } + if (matchBinding(e, sb.listPin)) { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); void this.cmdToggleListPin(); return; } if (matchBinding(e, sb.toggleTask)) { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); void this.cmdToggleTask(); return; } if (matchBinding(e, sb.setDue)) { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); this.cmdSetDue(); return; } } @@ -6855,11 +7117,37 @@ export class StashpadView extends ItemView { cmdToggleExpand(): void { const targets = this.getActionTargets(); if (!targets.length) return; - const anyCollapsed = targets.some((t) => !this.expandedNotes.has(t.id)); - for (const t of targets) { - if (anyCollapsed) this.expandedNotes.add(t.id); - else this.expandedNotes.delete(t.id); - } + const anyCollapsed = targets.some((t) => !this.isNoteExpanded(t.id)); + for (const t of targets) this.setNoteExpanded(t.id, anyCollapsed); + this.render(); + } + + /** Is this note's body currently shown expanded (un-clamped)? + * The expandedNotes Set stores ids that DIFFER from the default: + * when expandBodiesByDefault is off (default), membership = expanded; + * when on, membership = collapsed. This lets one Set serve both modes. */ + isNoteExpanded(id: StashpadId): boolean { + const differsFromDefault = this.expandedNotes.has(id); + return this.plugin.settings.expandBodiesByDefault ? !differsFromDefault : differsFromDefault; + } + + /** Set a note's expanded/collapsed state, normalizing against the + * default so the Set only ever holds the non-default ids. */ + setNoteExpanded(id: StashpadId, expanded: boolean): void { + const defaultExpanded = this.plugin.settings.expandBodiesByDefault; + if (expanded === defaultExpanded) this.expandedNotes.delete(id); + else this.expandedNotes.add(id); + } + + /** Expand every note in the current list (un-clamp all bodies). */ + cmdExpandAll(): void { + for (const n of this.currentChildren) this.setNoteExpanded(n.id, true); + this.render(); + } + + /** Collapse every note in the current list (re-clamp all bodies). */ + cmdCollapseAll(): void { + for (const n of this.currentChildren) this.setNoteExpanded(n.id, false); this.render(); } @@ -7023,6 +7311,187 @@ export class StashpadView extends ItemView { }); } + /** Fork a single note: duplicate its subtree as a standalone "variant" and + * place it under a parent chosen via the picker. The current parent is + * named as the default in the placeholder; Esc cancels. Same-folder only + * for now (cross-folder forking deferred). NOTE: distinct from the sheet + * "Fork as version" (cmdForkVersion) — that makes a draft within a sheet + * group; this makes a separate note you can re-home. */ + cmdForkNote(): void { + const node = this.getActionTargets()[0]; + if (!node?.file) { new Notice("Nothing to fork."); return; } + const curParent = node.parent ?? ROOT_ID; + const curNode = curParent === ROOT_ID ? null : this.tree.get(curParent); + const curLabel = curNode ? this.titleForNode(curNode) : "Home"; + new StashpadSuggest(this.app, this.tree, (n) => this.titleForNode(n), { + mode: "pick", + allowCreate: true, + placeholder: `Fork "${this.titleForNode(node)}" under… (default: ${curLabel})`, + onPick: (item) => { + if (item.crossFolder) { new Notice("Fork stays in this folder for now."); return; } + void this.forkNoteUnder(node, item.id); + }, + onCreate: (q) => { void (async () => { const id = await this.createNoteUnder(q, this.focusId); if (id) await this.forkNoteUnder(node, id); })(); }, + }).open(); + } + + /** Clone `node`'s subtree under `parentId`, focus the new root, with undo. + * Mirrors cmdClone's clone+snapshot+undo machinery for a single node. */ + private async forkNoteUnder(node: TreeNode, parentId: StashpadId): Promise<void> { + if (!node.file) return; + const folder = this.noteFolder; + const createdPaths: string[] = []; + const newRootId = await this.cloneSubtree(node, parentId, createdPaths); + if (!newRootId) return; + this.tree.rebuild(folder); + this.pendingFocusIds = [newRootId]; + this.render(); + const snapNodes: TreeNode[] = createdPaths + .map((p) => this.app.vault.getAbstractFileByPath(p)) + .filter((f): f is TFile => !!f && (f as any).extension === "md") + .map((file) => ({ id: parseIdFromFilename(file.basename) ?? file.basename, parent: null, children: [], file, created: new Date().toISOString() })); + const snap = await this.snapshotNotes(snapNodes, false); + this.plugin.getUndoStack(folder).push({ + label: "Fork note", + undo: async () => { + for (const p of [...createdPaths].reverse()) { + const f = this.app.vault.getAbstractFileByPath(p) as TFile | null; + if (f) { try { await this.app.fileManager.trashFile(f); } catch { /* ignore */ } } + } + this.tree.rebuild(folder); + this.render(); + }, + redo: async () => { await this.restoreSnapshots(snap, [newRootId]); }, + }); + const forked = this.tree.get(newRootId); + this.plugin.notifications.show({ + message: forked + ? `Forked "${this.titleForNode(node)}" → "${this.titleForNode(forked)}" (${createdPaths.length} file${createdPaths.length === 1 ? "" : "s"})` + : "Forked note", + kind: "success", + category: "clone", + affectedIds: [newRootId], + folder, + }); + } + + // --- Sheet versions --- + + /** Ensure a note carries a `sheet:` group id, stamping a fresh one (and an + * initial order of 0) if it doesn't. Returns the group id. */ + private async ensureSheetGroup(file: TFile): Promise<string> { + const existing = sheetIdOf(this.app.metadataCache.getFileCache(file)?.frontmatter); + if (existing) return existing; + const gid = newSheetGroupId(); + await this.app.fileManager.processFrontMatter(file, (m: any) => { + m[SHEET_KEY] = gid; + if (typeof m[SHEET_ORDER_KEY] !== "number") m[SHEET_ORDER_KEY] = 0; + }); + return gid; + } + + /** Create a new version of `source` as a sibling sharing its sheet group. + * `blank` → empty body; otherwise the source body is duplicated (a fork). + * The new version becomes the shown one. Used by the row "+" button, the + * context menu, and the command. */ + async cmdForkVersion(source?: TreeNode, blank = false): Promise<void> { + if (!this.plugin.settings.enableSheetVersions) { + new Notice("Sheet versions are off — enable them in Settings → General."); + return; + } + const src = source ?? this.getActionTargets()[0]; + if (!src?.file) { new Notice("Select a note to version."); return; } + const folder = this.noteFolder; + const gid = await this.ensureSheetGroup(src.file); + const parent = src.parent ?? this.focusId; + + // Next order = one past the current highest in the group. + const siblings = this.tree.getChildren(parent) + .filter((s) => sheetIdOf(nodeFm(this.app, s)) === gid); + let maxOrder = -1; + for (const s of siblings) { + const o = this.app.metadataCache.getFileCache(s.file!)?.frontmatter?.[SHEET_ORDER_KEY]; + if (typeof o === "number" && o > maxOrder) maxOrder = o; + } + const order = maxOrder + 1; + + const body = blank ? "" : this.stripFrontmatter(await this.app.vault.read(src.file)); + const cloneId = newId(); + const slug = bodyToSlug(body, this.activeStopwords()); + const filename = buildFilename(slug, cloneId); + const path = `${folder}/${filename}`; + const created = new Date().toISOString(); + const attachments = this.extractAttachments(body); + + const fmInit = ["---", `id: ${cloneId}`, `parent: ${parent}`, `created: ${created}`]; + if (attachments.length > 0) { + fmInit.push("attachments:"); + for (const a of attachments) fmInit.push(` - "${a.replace(/"/g, '\\"')}"`); + } else { + fmInit.push("attachments: []"); + } + fmInit.push("---", body); + await this.ensureFolder(folder); + await this.app.vault.create(path, fmInit.join("\n")); + + const newFile = this.app.vault.getAbstractFileByPath(path) as TFile | null; + if (!newFile) { new Notice("Sheets: could not create version."); return; } + await this.app.fileManager.processFrontMatter(newFile, (m: any) => { + m[SHEET_KEY] = gid; + m[SHEET_ORDER_KEY] = order; + delete m[SHEET_FINAL_KEY]; + }); + try { + this.tree.insertSynthetic({ id: cloneId, parent, children: [], file: newFile, created }); + } catch { /* ignore */ } + this.fmSync.scheduleParentChange(cloneId, null, parent); + + this.tree.rebuild(folder); + this.activeVersionByGroup.set(gid, cloneId); // show the new version + this.plugin.saveActiveVersion(folder, gid, cloneId); + this.render(); + + this.plugin.getUndoStack(folder).push({ + label: blank ? "New version" : "Fork version", + undo: async () => { + const f = this.app.vault.getAbstractFileByPath(path) as TFile | null; + if (f) { try { await this.app.fileManager.trashFile(f); } catch { /* ignore */ } } + this.activeVersionByGroup.delete(gid); + this.tree.rebuild(folder); + this.render(); + }, + redo: async () => { /* best-effort: re-running the command recreates it */ }, + }); + new Notice(blank ? "New version added" : "Forked a new version"); + } + + /** Toggle the "final" flag on a version, clearing it from its group-mates. */ + async cmdMarkVersionFinal(target?: TreeNode): Promise<void> { + if (!this.plugin.settings.enableSheetVersions) { + new Notice("Sheet versions are off — enable them in Settings → General."); + return; + } + const node = target ?? this.getActionTargets()[0]; + if (!node?.file) return; + const gid = sheetIdOf(nodeFm(this.app, node)); + if (!gid) { new Notice("Not a versioned note."); return; } + const makeFinal = !sheetIsFinal(nodeFm(this.app, node)); + const parent = node.parent ?? this.focusId; + const members = this.tree.getChildren(parent) + .filter((s) => sheetIdOf(nodeFm(this.app, s)) === gid); + for (const m of members) { + if (!m.file) continue; + const wasFinal = sheetIsFinal(nodeFm(this.app, m)); + const shouldBeFinal = makeFinal && m.id === node.id; + if (wasFinal === shouldBeFinal) continue; + await this.app.fileManager.processFrontMatter(m.file, (fm: any) => { + if (shouldBeFinal) fm[SHEET_FINAL_KEY] = true; + else delete fm[SHEET_FINAL_KEY]; + }); + } + this.render(); + } + // ---- 0.99.0: note clipboard — copy / cut / paste of note BLOCKS ---- // Runs in parallel with the system clipboard: copy/cut also put the bodies // on the system clipboard as text (so pasting in the composer or any app @@ -7372,7 +7841,9 @@ export class StashpadView extends ItemView { // Clear an active tag/color filter if the new subtree doesn't // contain it — otherwise we'd show "All …" in the dropdown while // a hidden filter empties the list. - if (this.tagFilter) { + if (this.tagFilter && this.tagFilter !== TAG_FILTER_TAGGED && this.tagFilter !== TAG_FILTER_UNTAGGED) { + // Sentinel modes (Tagged/Untagged) are always valid; only real tags + // get cleared when the new subtree doesn't contain them. const wanted = this.tagFilter.toLowerCase(); const present = this.collectFolderTags().some((t) => t.raw.toLowerCase() === wanted); if (!present) this.tagFilter = null; @@ -7909,6 +8380,92 @@ export class StashpadView extends ItemView { else if (unpinned > 0) new Notice(`Unpinned ${unpinned} note${unpinned === 1 ? "" : "s"} from sidebar.`); } + /** Is this note list-pinned (floated to the top of its sibling list)? + * Distinct from the sidebar pin (plugin.isPinned). Reads frontmatter. */ + isListPinned(id: StashpadId): boolean { + const node = this.tree.get(id); + if (!node?.file) return false; + const ov = this.listPinnedState.get(node.file.path); + if (ov) return ov.pinned; + return this.app.metadataCache.getFileCache(node.file)?.frontmatter?.listPinned === true; + } + private listPinnedAt(id: StashpadId): number { + const node = this.tree.get(id); + if (!node?.file) return 0; + const ov = this.listPinnedState.get(node.file.path); + if (ov) return ov.at; + const v = this.app.metadataCache.getFileCache(node.file)?.frontmatter?.listPinnedAt; + const t = typeof v === "string" ? Date.parse(v) : NaN; + return Number.isNaN(t) ? 0 : t; + } + /** Float list-pinned children to the top of `base` (in pin order). Returns + * `base` unchanged when nothing in this parent is pinned — so unpinned + * lists keep EXACTLY their prior ordering/behavior (zero regression risk). */ + private hoistListPinned(parentId: StashpadId, base: StashpadId[]): StashpadId[] { + const childIds = this.tree.getChildren(parentId).map((n) => n.id); + if (!childIds.some((id) => this.isListPinned(id))) return base; + // base may be empty (manual order unset) — fall back to the tree's order. + const seen = new Set(base); + const full = [...base, ...childIds.filter((id) => !seen.has(id))]; + const pinned = full.filter((id) => this.isListPinned(id)).sort((a, b) => this.listPinnedAt(a) - this.listPinnedAt(b)); + const rest = full.filter((id) => !this.isListPinned(id)); + return [...pinned, ...rest]; + } + + /** Toggle the list pin (float-to-top) on the action targets. Distinct from + * the sidebar pin (cmdTogglePin). Writes listPinned/listPinnedAt + undo. */ + async cmdToggleListPin(): Promise<void> { + let targets = this.getActionTargets(); + if (targets.length === 0) { + const focused = this.tree.get(this.focusId); + if (focused?.file) targets = [focused]; + } + if (targets.length === 0) { new Notice("Nothing to pin."); return; } + const anyUnpinned = targets.some((t) => !this.isListPinned(t.id)); + const prior: { path: string; listPinned: unknown; listPinnedAt: unknown }[] = []; + const stamp = new Date().toISOString(); + const changed: StashpadId[] = []; + for (const t of targets) { + if (!t.file) continue; + const fm = this.app.metadataCache.getFileCache(t.file)?.frontmatter as any; + prior.push({ path: t.file.path, listPinned: fm?.listPinned, listPinnedAt: fm?.listPinnedAt }); + const at = anyUnpinned ? (typeof fm?.listPinnedAt === "string" ? Date.parse(fm.listPinnedAt) || Date.parse(stamp) : Date.parse(stamp)) : 0; + // Override now so the re-sort below reflects the new state immediately + // (the metadata cache lags the frontmatter write by a tick). + this.listPinnedState.set(t.file.path, { pinned: anyUnpinned, at }); + await this.app.fileManager.processFrontMatter(t.file, (m) => { + if (anyUnpinned) { m.listPinned = true; if (!m.listPinnedAt) m.listPinnedAt = stamp; } + else { delete m.listPinned; delete m.listPinnedAt; } + }); + changed.push(t.id); + } + const folder = this.noteFolder; + this.tree.rebuild(folder); + this.render(); + this.plugin.notifications.show({ + message: anyUnpinned ? `Pinned ${changed.length} to top of list` : `Unpinned ${changed.length} from list`, + kind: "success", category: "edit", affectedIds: changed, folder, + }); + this.plugin.getUndoStack(folder).push({ + label: anyUnpinned ? `Pin to top (${changed.length})` : `Unpin from top (${changed.length})`, + undo: async () => { + for (const p of prior) { + const f = this.app.vault.getAbstractFileByPath(p.path) as TFile | null; + if (!f) continue; + await this.app.fileManager.processFrontMatter(f, (m) => { + if (p.listPinned === undefined) delete m.listPinned; else m.listPinned = p.listPinned; + if (p.listPinnedAt === undefined) delete m.listPinnedAt; else m.listPinnedAt = p.listPinnedAt; + }); + const wasPinned = p.listPinned === true; + const at = typeof p.listPinnedAt === "string" ? (Date.parse(p.listPinnedAt) || 0) : 0; + this.listPinnedState.set(p.path, { pinned: wasPinned, at }); + } + this.tree.rebuild(folder); + this.render(); + }, + }); + } + async cmdToggleComplete(): Promise<void> { let targets = this.getActionTargets(); if (targets.length === 0) { @@ -8032,6 +8589,12 @@ export class StashpadView extends ItemView { * back to the live cache when there's no override. */ private taskTaggedState = new Map<string, boolean>(); + /** 0.105.0: list-pin override per path (pinned flag + pin timestamp), so a + * pin/unpin re-sorts the list on THIS render rather than n+1 (the metadata + * cache lags a frontmatter write). Reads fall back to the live cache when + * there's no override. */ + private listPinnedState = new Map<string, { pinned: boolean; at: number }>(); + private isCompleted(node: TreeNode): boolean { if (!node.file) return false; const override = this.completedState.get(node.file.path); @@ -8146,9 +8709,12 @@ export class StashpadView extends ItemView { }); } - /** 0.78.3: standalone assign command — assign people to the target - * task(s) without touching the due date. Opens AssignModal pre-filled - * with the first target's current assignees. */ + /** 0.104.x: "Assign to" opens the SAME unified modal as "Set due date" + * (date+time picker + assignee picker). Both commands now share one + * modal — only the title differs. Pre-fills the first target's current + * due date AND assignees, and commits through applyDue (which flips + * `task: true` on any due/assignment — so assigning or scheduling a + * plain note auto-converts it to a task). */ cmdAssign(): void { let targets = this.getActionTargets(); if (targets.length === 0) { @@ -8158,76 +8724,12 @@ export class StashpadView extends ItemView { if (targets.length === 0) { new Notice("Nothing to assign."); return; } const first = targets[0]; const curFm = first.file ? this.app.metadataCache.getFileCache(first.file)?.frontmatter as any : null; + const current = curFm && (typeof curFm.due === "string" || typeof curFm.due === "number") ? String(curFm.due) : null; const knownAuthors = this.plugin.collectKnownAuthors(); const currentAssignees = parseAssignees(curFm ?? {}); - new AssignModal(this.app, { knownAuthors, currentAssignees }, (assignees) => { - void this.applyAssignees(targets, assignees); - }).open(); - } - - /** Write `assignedTo`/`assignedBy` across `targets` (without touching - * `due`), with undo. An empty list clears the assignment. Assigning - * also flips `task: true`. */ - private async applyAssignees(targets: TreeNode[], assignees: Array<{ id: string; name: string }>): Promise<void> { - const me = this.authorship.currentAuthorLink(); - for (const a of assignees) { - await this.plugin.ensureAuthorStubFor(this.noteFolder, a.id, a.name); - } - const assignLinks = assignees.map((a) => this.plugin.authorRefFor(this.noteFolder, a.id, a.name)); - const prior: { path: string; assignedTo: unknown; assignedBy: unknown; task: unknown; wasTagged: boolean }[] = []; - const changedIds: StashpadId[] = []; - for (const t of targets) { - if (!t.file) continue; - const fm = this.app.metadataCache.getFileCache(t.file)?.frontmatter as any; - const wasTagged = this.isTaskTagged(t); - prior.push({ path: t.file.path, assignedTo: fm?.assignedTo, assignedBy: fm?.assignedBy, task: fm?.task, wasTagged }); - await this.app.fileManager.processFrontMatter(t.file, (m) => { - if (assignLinks.length > 0) { - m.assignedTo = assignLinks; - if (me) m.assignedBy = me.link; - m.task = true; - } else { - delete m.assignedTo; - delete m.assignedBy; - } - }); - // 0.85.1: assigning makes it a task; clearing leaves task-ness unchanged. - this.taskTaggedState.set(t.file.path, assignLinks.length > 0 || wasTagged); - changedIds.push(t.id); - } - this.render(); - if (changedIds.length > 0) { - const nodes = changedIds.map((id) => this.tree.get(id)).filter((n): n is TreeNode => !!n); - const names = assignees.map((a) => a.name).join(", "); - this.plugin.notifications.show({ - message: this.bulkActionMessage({ - verb: assignLinks.length > 0 ? `Assigned to ${names}` : "Cleared assignment", - nodes, - }), - kind: "success", - category: "edit", - affectedIds: changedIds, - folder: this.noteFolder, - }); - } - const folder = this.noteFolder; - this.plugin.getUndoStack(folder).push({ - label: assignLinks.length > 0 ? `Assign (${targets.length})` : `Clear assignment (${targets.length})`, - undo: async () => { - for (const p of prior) { - const f = this.app.vault.getAbstractFileByPath(p.path) as TFile | null; - if (!f) continue; - await this.app.fileManager.processFrontMatter(f, (m) => { - if (p.assignedTo === undefined) delete m.assignedTo; else m.assignedTo = p.assignedTo; - if (p.assignedBy === undefined) delete m.assignedBy; else m.assignedBy = p.assignedBy; - if (p.task === undefined) delete m.task; else m.task = p.task; - }); - this.taskTaggedState.set(p.path, p.wasTagged); // 0.85.1 - } - this.tree.rebuild(folder); - this.render(); - }, - }); + new DueDatePickerModal(this.app, current, (result) => { + void this.applyDue(targets, result.iso, result.assignees); + }, { knownAuthors, currentAssignees, title: "Assign / schedule task" }).open(); } /** 0.76.3: a note is a task when it carries the `task` tag in @@ -9943,6 +10445,10 @@ export class StashpadView extends ItemView { if (!this.selection.has(node.id)) { this.selection.clear(); this.selection.add(node.id); this.lastSelected = node.id; } void this.cmdClone(); })); + menu.addItem((it: any) => it.setTitle("Fork (copy under another parent)…").setIcon("git-branch").onClick(() => { + if (!this.selection.has(node.id)) { this.selection.clear(); this.selection.add(node.id); this.lastSelected = node.id; } + this.cmdForkNote(); + })); menu.addItem((it: any) => it.setTitle("Insert template…").setIcon("file-plus-2").onClick(() => this.cmdInsertTemplate())); menu.addItem((it: any) => it.setTitle("Export to .stash").setIcon("package").onClick(() => { // Multi-select normalisation (matches Clone / Delete / Set color): @@ -9991,19 +10497,52 @@ export class StashpadView extends ItemView { if (pinned) await this.plugin.unpinNote(pinRef); else await this.plugin.pinNote(pinRef); })); + // 0.105.0: list pin — float to the top of THIS list (distinct from sidebar). + const listPinned = this.isListPinned(node.id); + menu.addItem((it: any) => it + .setTitle(listPinned ? "Unpin from top of list" : "Pin to top of list") + .setIcon(listPinned ? "pin-off" : "arrow-up-to-line") + .onClick(() => { + if (!this.selection.has(node.id)) { this.selection.clear(); this.selection.add(node.id); this.lastSelected = node.id; } + void this.cmdToggleListPin(); + })); menu.addItem((it: any) => it.setTitle("Set color…").setIcon("palette").onClick(() => { // Operate on the right-clicked row even if it isn't selected. if (!this.selection.has(node.id)) { this.selection.clear(); this.selection.add(node.id); this.lastSelected = node.id; } this.cmdSetColor(); })); - // 0.58.0: toggle complete — label flips based on current state of the - // right-clicked node. Operates on the right-clicked row, normalising - // selection first so cmdToggleComplete picks the right target. - const isDone = this.isCompleted(node); - menu.addItem((it: any) => it.setTitle(isDone ? "Mark incomplete" : "Mark complete").setIcon(isDone ? "circle" : "check-circle").onClick(() => { + // 0.104.x: task actions grouped under a "Task ▸" submenu to keep the + // right-click menu compact (Obsidian already repositions to stay + // on-screen; height is the real lever). Task gating: completion is only + // offered once a note IS a task — non-tasks show "Turn into task"; tasks + // show "Mark complete" + "Remove from tasks". Right-click is single-node, + // so the gate is unambiguous (the mobile ⚡ menu keeps its multi-select + // toggles). Every entry normalises selection to the right-clicked row. + // setSubmenu is internal/untyped — accessed via the existing `it: any` + // pattern; falls back to opening the command palette if unavailable + // (effectively never on the 1.13 minAppVersion floor). + const focusClicked = (): void => { if (!this.selection.has(node.id)) { this.selection.clear(); this.selection.add(node.id); this.lastSelected = node.id; } - void this.cmdToggleComplete(); - })); + }; + const addTaskItems = (target: { addItem: (cb: (it: any) => unknown) => unknown }): void => { + const isTaskNote = this.isTask(node); + if (isTaskNote) { + const isDone = this.isCompleted(node); + target.addItem((it: any) => it.setTitle(isDone ? "Mark incomplete" : "Mark complete").setIcon(isDone ? "circle" : "check-circle").onClick(() => { focusClicked(); void this.cmdToggleComplete(); })); + } else { + target.addItem((it: any) => it.setTitle("Turn into task").setIcon("check-square").onClick(() => { focusClicked(); void this.cmdToggleTask(); })); + } + target.addItem((it: any) => it.setTitle("Assign / schedule…").setIcon("user-plus").onClick(() => { focusClicked(); this.cmdAssign(); })); + if (isTaskNote) { + target.addItem((it: any) => it.setTitle("Remove from tasks").setIcon("square").onClick(() => { focusClicked(); void this.cmdToggleTask(); })); + } + }; + menu.addItem((it: any) => { + it.setTitle("Task").setIcon("check-square"); + const sub = typeof it.setSubmenu === "function" ? it.setSubmenu() : null; + if (sub && typeof sub.addItem === "function") addTaskItems(sub); + else it.onClick(() => this.openCommandPalette()); // degraded fallback + }); menu.addSeparator(); menu.addItem((it: any) => it.setTitle("Delete").setIcon("trash").onClick(async () => { // Route through cmdDelete (not deleteNote directly) so the encryptTrash diff --git a/styles.css b/styles.css index 6be66c6..8e1fe92 100644 --- a/styles.css +++ b/styles.css @@ -704,6 +704,109 @@ .stashpad-color-filter-popover-label { white-space: nowrap; } + +/* --- Tag filter: custom button + searchable popover (0.104.x) --- */ +.stashpad-tag-filter-btn { + flex: 0 0 auto; + width: max-content; + min-width: 0; + display: inline-flex; + align-items: center; + gap: 6px; + padding: 6px 10px; + border-radius: 6px; + background: var(--background-secondary); + color: var(--text-normal); + border: 1px solid var(--background-modifier-border); + font-size: var(--font-ui-smaller); + cursor: pointer; + user-select: none; + white-space: nowrap; +} +.stashpad-tag-filter-btn:hover { background: var(--background-modifier-hover); } +.stashpad-tag-filter-btn.is-disabled { opacity: 0.5; cursor: not-allowed; } +.stashpad-tag-filter-btn-icon { + display: inline-flex; + align-items: center; + color: var(--text-muted); +} +.stashpad-tag-filter-btn-icon .svg-icon { width: 14px; height: 14px; } +.stashpad-tag-filter-label { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 16ch; +} +.stashpad-view.is-mobile .stashpad-tag-filter-btn { height: 28px; } + +.stashpad-tag-filter-popover { + position: fixed; + z-index: var(--layer-popover, 30); + display: flex; + flex-direction: column; + background: var(--background-primary); + border: 1px solid var(--background-modifier-border); + border-radius: 6px; + box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18); + font-size: var(--font-ui-small); + max-height: 340px; + overflow: hidden; +} +.stashpad-tag-filter-search { + display: flex; + align-items: center; + gap: 6px; + padding: 6px 8px; + border-bottom: 1px solid var(--background-modifier-border); +} +.stashpad-tag-filter-search-icon { + display: inline-flex; + align-items: center; + color: var(--text-muted); +} +.stashpad-tag-filter-search-icon .svg-icon { width: 14px; height: 14px; } +.stashpad-tag-filter-input { + flex: 1 1 auto; + min-width: 0; + border: none; + background: transparent; + color: var(--text-normal); + font-size: var(--font-ui-small); + outline: none; + padding: 2px 0; +} +.stashpad-tag-filter-clear { + display: inline-flex; + align-items: center; + color: var(--text-muted); + cursor: pointer; + border-radius: 4px; + padding: 2px; +} +.stashpad-tag-filter-clear:hover { color: var(--text-normal); background: var(--background-modifier-hover); } +.stashpad-tag-filter-clear .svg-icon { width: 13px; height: 13px; } +.stashpad-tag-filter-list { + overflow-y: auto; + padding: 4px 0; +} +.stashpad-tag-filter-row { + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; + padding: 5px 10px; + cursor: pointer; +} +.stashpad-tag-filter-row.is-highlighted { background: var(--background-modifier-hover); } +.stashpad-tag-filter-row.is-active { font-weight: var(--font-semibold); } +.stashpad-tag-filter-row.is-active .stashpad-tag-filter-row-label::after { + content: "✓"; + margin-left: 6px; + color: var(--text-accent); +} +.stashpad-tag-filter-row-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } +.stashpad-tag-filter-row-count { color: var(--text-muted); font-size: var(--font-ui-smaller); flex: 0 0 auto; } +.stashpad-tag-filter-empty { padding: 8px 10px; color: var(--text-muted); } @container (max-width: 360px) { .stashpad-time-filter-btns { display: none; } .stashpad-time-filter-select { display: block; } @@ -1036,6 +1139,22 @@ opacity: 0.55; } +/* 0.105.0 / 0.106.x: list-pinned note — floated to the top of its list. Left + accent bar; the pin indicator is a lucide icon in the meta column (under the + timestamp, before the children-count arrow) — see .stashpad-note-listpin. */ +.stashpad-note.is-list-pinned { + box-shadow: inset 3px 0 0 var(--text-accent); +} +.stashpad-note-listpin { + display: inline-flex; + align-items: center; + color: var(--text-accent); +} +.stashpad-note-listpin svg { + width: 13px; + height: 13px; +} + /* 0.99.5: a note sitting on a pending CUT (note clipboard) — ghosted + dashed outline, like a cut file in a file manager. Cleared when the cut is pasted or replaced. */ @@ -2636,6 +2755,20 @@ .stashpad-due-field-icon:hover { color: var(--text-normal); background: var(--interactive-hover); } .stashpad-due-field-icon:active { background: var(--background-modifier-active-hover); } .stashpad-due-field-icon svg { width: 16px; height: 16px; } +/* 0.104.x: dedicated × to clear a single field (date or time). */ +.stashpad-due-clear { + display: inline-flex; + align-items: center; + justify-content: center; + width: 22px; + height: 22px; + flex: 0 0 auto; + color: var(--text-faint); + cursor: pointer; + border-radius: 5px; +} +.stashpad-due-clear:hover { color: var(--text-normal); background: var(--background-modifier-hover); } +.stashpad-due-clear svg { width: 13px; height: 13px; } /* 0.76.8: hide the native right-side picker indicator — our left icon is the picker button now (calls showPicker). */ .stashpad-due-date::-webkit-calendar-picker-indicator, @@ -4439,6 +4572,40 @@ body.stashpad-folderpanel-resizing { cursor: row-resize; user-select: none; } color: var(--text-accent); } .stashpad-folderpanel-pinmark svg { width: 12px; height: 12px; } +/* 0.105.1: folder-row chevron + inline list of the folder's Home list-pinned + notes (revealed on click). */ +.stashpad-folderpanel-pinreveal { + flex: 0 0 auto; + display: inline-flex; + align-items: center; + cursor: pointer; + color: var(--text-muted); +} +.stashpad-folderpanel-pinreveal:hover { color: var(--text-normal); } +.stashpad-folderpanel-pinlist { + display: flex; + flex-direction: column; + margin: 0 0 4px 28px; +} +.stashpad-folderpanel-pinrow { + display: flex; + align-items: center; + gap: 7px; + padding: 4px 8px; + border-radius: 6px; + cursor: pointer; + color: var(--text-normal); +} +.stashpad-folderpanel-pinrow:hover { background: var(--background-modifier-hover); } +.stashpad-folderpanel-pinrow-icon { display: inline-flex; flex: 0 0 auto; color: var(--text-accent); } +.stashpad-folderpanel-pinrow-icon svg { width: 13px; height: 13px; } +.stashpad-folderpanel-pinrow-label { + flex: 1 1 auto; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + font-size: var(--font-ui-smaller); +} /* 0.98.25: archive-folder badge (auto-encrypt incoming). */ .stashpad-folderpanel-archive-badge { flex: 0 0 auto; display: inline-flex; align-items: center; @@ -4489,3 +4656,48 @@ body.stashpad-folderpanel-resizing { cursor: row-resize; user-select: none; } .stashpad-split-quick-label { font-size: var(--font-ui-smaller); color: var(--text-muted); margin-right: 2px; } .stashpad-split-quick-btn { font-size: var(--font-ui-smaller); padding: 2px 8px; } .stashpad-split-quick-btn:disabled { opacity: 0.5; cursor: default; } + +/* --- Sheet version tabs (a row's alternate versions) --- */ +.stashpad-version-tabs { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 4px; + margin-top: 6px; + padding-top: 6px; + border-top: 1px solid var(--background-modifier-border); +} +.stashpad-version-tab { + display: inline-flex; + align-items: center; + gap: 4px; + max-width: 18ch; + padding: 1px 8px; + border: 1px solid var(--background-modifier-border); + border-radius: var(--radius-s); + background: var(--background-secondary); + color: var(--text-muted); + font-size: var(--font-ui-smaller); + cursor: pointer; + user-select: none; +} +.stashpad-version-tab:hover { color: var(--text-normal); background: var(--background-modifier-hover); } +.stashpad-version-tab.is-active { + color: var(--text-normal); + background: var(--background-primary); + border-color: var(--interactive-accent); + font-weight: var(--font-semibold); + cursor: default; +} +.stashpad-version-tab.is-final { border-color: var(--text-accent); } +.stashpad-version-tab-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.stashpad-version-star { color: var(--text-accent); font-size: 0.85em; line-height: 1; } +.stashpad-version-add { + font-size: var(--font-ui-smaller); + line-height: 1; + padding: 1px 7px; + height: auto; + box-shadow: none; + color: var(--text-muted); +} +.stashpad-version-add:hover { color: var(--text-normal); }