From bd4b50576ae18edbde6e327dc3958401620feede Mon Sep 17 00:00:00 2001 From: Human Date: Thu, 9 Jul 2026 13:12:12 -0700 Subject: [PATCH] 0.157.0: unified action menus (Share & export everywhere), unified due-date dialog, note-picker search ranking, aggregate-view menus + hide-filename --- .gitattributes | 22 +++- main.js | 179 ++++++++++++++-------------- manifest.json | 2 +- package.json | 2 +- release-notes/0.157.0.md | 57 +++++++++ scripts/obs-dev.mjs | 26 ++++- src/aggregate-view.ts | 81 ++++++++++++- src/locked-menu.ts | 195 +++++++++++++++++++++++++++++++ src/main.ts | 71 +++++++---- src/modals.ts | 15 ++- src/note-picker.ts | 75 ++++++++---- src/view.ts | 246 +++++++++++++++------------------------ 12 files changed, 675 insertions(+), 296 deletions(-) create mode 100644 release-notes/0.157.0.md create mode 100644 src/locked-menu.ts diff --git a/.gitattributes b/.gitattributes index dfe0770..15b8582 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,20 @@ -# Auto detect text files and perform LF normalization -* text=auto +# Line endings: store LF in the repo AND check out LF on every platform +# (macOS + Windows), so there's no CRLF churn, noisy diffs, or broken shell +# scripts when the repo is used cross-platform. Git auto-detects text vs binary; +# the explicit `binary` rules below are belt-and-suspenders so EOL conversion is +# never applied to assets (a mangled .stash fixture or PNG would be bad). +* text=auto eol=lf + +# Binary assets — no EOL conversion, no diffing. +*.stash binary +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.ico binary +*.webp binary +*.woff binary +*.woff2 binary +*.ttf binary +*.zip binary +*.wasm binary diff --git a/main.js b/main.js index 55f13e8..755de8b 100644 --- a/main.js +++ b/main.js @@ -1,156 +1,157 @@ -"use strict";var Yn=Object.defineProperty;var Sl=Object.getOwnPropertyDescriptor;var bl=Object.getOwnPropertyNames;var Dl=Object.prototype.hasOwnProperty;var qe=(d,a)=>()=>(d&&(a=d(d=0)),a);var ki=(d,a)=>{for(var e in a)Yn(d,e,{get:a[e],enumerable:!0})},xl=(d,a,e,t)=>{if(a&&typeof a=="object"||typeof a=="function")for(let i of bl(a))!Dl.call(d,i)&&i!==e&&Yn(d,i,{get:()=>a[i],enumerable:!(t=Sl(a,i))||t.enumerable});return d};var Nl=d=>xl(Yn({},"__esModule",{value:!0}),d);var jn={};ki(jn,{freshId:()=>Zn,newId:()=>Ae});function Ae(d=6){let a="",e=new Uint8Array(d);crypto.getRandomValues(e);for(let t=0;t{"use strict";yr="abcdefghijkmnpqrstuvwxyz23456789"});function _n(d){return Array.isArray(d)?d.filter(a=>typeof a=="string"):typeof d=="string"?d.split(/[,\s]+/).filter(Boolean):[]}function Zt(d,a){let e=a.replace(/^#/,"");return _n(d?.tags).some(t=>t.replace(/^#/,"")===e)}function eo(d,a){let e=a.replace(/^#/,""),t=_n(d.tags);t.some(i=>i.replace(/^#/,"")===e)||t.push(e),d.tags=t}function to(d,a){let e=a.replace(/^#/,""),t=_n(d.tags).filter(i=>i.replace(/^#/,"")!==e);t.length?d.tags=t:delete d.tags}function Er(d){return ys.has(d)||wr.has(d)}function yt(d){return`${(d||"").replace(/\/+$/,"")}/archive`}function ws(d){return(d||"").replace(/\/+$/,"").split("/").slice(1).includes("archive")}function Nt(d){return d.split("/").some((a,e)=>ys.has(a)||e>0&&wr.has(a))}function Qr(d){return d.split("/").some(a=>a==="_archive"||a===".archive")}function Ve(d){let a=(d??"").trim();return!a||/^\[\[.*\]\]$/.test(a)?a:`[[${a}]]`}function Mt(d){let a=(d??"").trim(),e=a.match(/^\[\[(.*)\]\]$/);return e&&(a=e[1]),a.split("|")[0].split("#")[0].split("^")[0].trim()}function vr(d){let a=d.match(/\.([^./]+)$/);return!!a&&Pl.has(a[1].toLowerCase())}function Fr(d,a){if(!Array.isArray(a))return!1;for(let e of a){let t=(e??"").trim();if(t){if(t.length>2&&t.startsWith("/")&&t.endsWith("/"))try{if(new RegExp(t.slice(1,-1)).test(d))return!0}catch{}else if(d===t||d.startsWith(t.endsWith("/")?t:t+"/"))return!0}}return!1}function Es(d,a){let e=d.toLowerCase().split(/\s+/).filter(Boolean);if(e.length===0)return!0;let t=a.toLowerCase();return e.every(i=>t.includes(i))}function rt(d){if(typeof d!="string")return null;let a=d.replace(/^\[\[/,"").replace(/\]\]$/,""),[e,t]=a.split("|"),i=e.match(/_authors\/(.+?)-([a-z0-9]{4,12})(?:\.md)?$/i);if(!i)return null;let s=i[2],n=(t??"").trim()||i[1].replace(/-/g," ").trim();return{id:s,name:n}}function Tt(d){let a=d?.assignedTo,e=Array.isArray(a)?a:a!=null?[a]:[],t=[];for(let i of e){let s=rt(i);s&&t.push(s)}return t}var z,Ct,Bt,xt,Wt,Xt,S,ze,ys,wr,Pl,ae=qe(()=>{"use strict";z="stashpad-view",Ct="stashpad-panels",Bt="stashpad-folder-panel",xt="stashpad-detail",Wt="stashpad-trash",Xt="stashpad-aggregate",S="__root__";ze=["id","parent","created","modified","attachments","position","author","contributors","parentLink","children","due","assignedTo","assignedBy","pinned","pinnedAt","listPinned","listPinnedAt","imported","okfParent","okfChildren"],ys=new Set(["_attachments","_authors","_exports","_imports","_processed","_archive",".archive"]),wr=new Set(["archive","trash"]);Pl=new Set(["edtz"])});function Mi(d,a){let e=d.replace(/\r\n/g,` +"use strict";var Wn=Object.defineProperty;var Nl=Object.getOwnPropertyDescriptor;var Ml=Object.getOwnPropertyNames;var Tl=Object.prototype.hasOwnProperty;var $e=(d,a)=>()=>(d&&(a=d(d=0)),a);var Si=(d,a)=>{for(var e in a)Wn(d,e,{get:a[e],enumerable:!0})},Pl=(d,a,e,t)=>{if(a&&typeof a=="object"||typeof a=="function")for(let i of Ml(a))!Tl.call(d,i)&&i!==e&&Wn(d,i,{get:()=>a[i],enumerable:!(t=Nl(a,i))||t.enumerable});return d};var Hl=d=>Pl(Wn({},"__esModule",{value:!0}),d);var to={};Si(to,{freshId:()=>eo,newId:()=>he});function he(d=6){let a="",e=new Uint8Array(d);crypto.getRandomValues(e);for(let t=0;t{"use strict";Er="abcdefghijkmnpqrstuvwxyz23456789"});function io(d){return Array.isArray(d)?d.filter(a=>typeof a=="string"):typeof d=="string"?d.split(/[,\s]+/).filter(Boolean):[]}function jt(d,a){let e=a.replace(/^#/,"");return io(d?.tags).some(t=>t.replace(/^#/,"")===e)}function so(d,a){let e=a.replace(/^#/,""),t=io(d.tags);t.some(i=>i.replace(/^#/,"")===e)||t.push(e),d.tags=t}function no(d,a){let e=a.replace(/^#/,""),t=io(d.tags).filter(i=>i.replace(/^#/,"")!==e);t.length?d.tags=t:delete d.tags}function vr(d){return ws.has(d)||Qr.has(d)}function wt(d){return`${(d||"").replace(/\/+$/,"")}/archive`}function Es(d){return(d||"").replace(/\/+$/,"").split("/").slice(1).includes("archive")}function Mt(d){return d.split("/").some((a,e)=>ws.has(a)||e>0&&Qr.has(a))}function Fr(d){return d.split("/").some(a=>a==="_archive"||a===".archive")}function We(d){let a=(d??"").trim();return!a||/^\[\[.*\]\]$/.test(a)?a:`[[${a}]]`}function Tt(d){let a=(d??"").trim(),e=a.match(/^\[\[(.*)\]\]$/);return e&&(a=e[1]),a.split("|")[0].split("#")[0].split("^")[0].trim()}function kr(d){let a=d.match(/\.([^./]+)$/);return!!a&&Gl.has(a[1].toLowerCase())}function Sr(d,a){if(!Array.isArray(a))return!1;for(let e of a){let t=(e??"").trim();if(t){if(t.length>2&&t.startsWith("/")&&t.endsWith("/"))try{if(new RegExp(t.slice(1,-1)).test(d))return!0}catch{}else if(d===t||d.startsWith(t.endsWith("/")?t:t+"/"))return!0}}return!1}function Qs(d,a){let e=d.toLowerCase().split(/\s+/).filter(Boolean);if(e.length===0)return!0;let t=a.toLowerCase();return e.every(i=>t.includes(i))}function at(d){if(typeof d!="string")return null;let a=d.replace(/^\[\[/,"").replace(/\]\]$/,""),[e,t]=a.split("|"),i=e.match(/_authors\/(.+?)-([a-z0-9]{4,12})(?:\.md)?$/i);if(!i)return null;let s=i[2],n=(t??"").trim()||i[1].replace(/-/g," ").trim();return{id:s,name:n}}function Pt(d){let a=d?.assignedTo,e=Array.isArray(a)?a:a!=null?[a]:[],t=[];for(let i of e){let s=at(i);s&&t.push(s)}return t}var z,Bt,yt,Nt,Xt,Zt,k,Ve,ws,Qr,Gl,le=$e(()=>{"use strict";z="stashpad-view",Bt="stashpad-panels",yt="stashpad-folder-panel",Nt="stashpad-detail",Xt="stashpad-trash",Zt="stashpad-aggregate",k="__root__";Ve=["id","parent","created","modified","attachments","position","author","contributors","parentLink","children","due","assignedTo","assignedBy","pinned","pinnedAt","listPinned","listPinnedAt","imported","okfParent","okfChildren"],ws=new Set(["_attachments","_authors","_exports","_imports","_processed","_archive",".archive"]),Qr=new Set(["archive","trash"]);Gl=new Set(["edtz"])});function Ti(d,a){let e=d.replace(/\r\n/g,` `);if(a==="lines")return e.split(` `).map(n=>n.trim()).filter(Boolean);if(a==="paragraphs")return e.split(/\n[ \t]*\n+/).map(n=>n.trim()).filter(Boolean);let t=[],i=[],s=n=>/^#{1,6}\s/.test(n);for(let n of e.split(` `))s(n)&&i.some(o=>o.trim())&&(t.push(i.join(` `).trim()),i=[]),i.push(n);return i.some(n=>n.trim())&&t.push(i.join(` -`).trim()),t.filter(Boolean)}function Fe(d,a,e){d.empty();try{(0,Sr.setIcon)(d,a)}catch{}let t=d.querySelector("svg");t&&t.querySelector("path, line, circle, rect, polyline, polygon, ellipse")||(d.empty(),d.createSpan({cls:"stashpad-icon-fallback",text:e}))}function br(d){if(d instanceof Element&&d.closest(".modal, .modal-container, .suggestion-container, .menu, .prompt"))return!0;let a=new Set([document]);d instanceof Element&&d.ownerDocument&&a.add(d.ownerDocument);for(let e of a)if(e.body?.querySelector(".modal-bg")||e.body?.querySelector(".modal-container .modal")||e.body?.querySelector(".suggestion-container")||e.body?.querySelector(".menu.mod-active"))return!0;return!1}function Dr(d){let a=[],e=/^([ \t]*)(`{3,})[ \t]*([^\n`]*)\n([\s\S]*?)\n\1\2[ \t]*$/gm,t;for(;(t=e.exec(d))!=null;)a.push({lang:t[3].trim(),code:t[4]});return a}function Ti(d){return d.split("/").map(a=>a.split(" ").map(e=>e&&/^[a-z]/.test(e)?e[0].toUpperCase()+e.slice(1):e).join(" ")).join("/")}function xr(d,a,e){let t=new Set(a),i=d.filter(n=>!t.has(n)),s=d.findIndex(n=>t.has(n));if(s<0)return d.slice();switch(e){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 c=-1;return d.forEach((A,h)=>{t.has(A)&&(c=h)}),c})(),o=0;for(let c=0;c0){let n=t[i-1];return(!/[a-z0-9]/.test(n)?600:500)-Math.min(i,99)}let s=0;for(let n=0;n({t,s:Hl(e,t.raw)})).filter(t=>t.s>=0).sort((t,i)=>i.s-t.s||i.t.count-t.t.count||t.t.label.localeCompare(i.t.label)).map(t=>t.t):a}var Sr,_t,Pt,Ht,Pi=qe(()=>{"use strict";Sr=require("obsidian"),_t={lines:"Each line",paragraphs:"Paragraphs (blank line)",headings:"Headings"};Pt="__stashpad:tagged__",Ht="__stashpad:untagged__"});function Rl(d,a){return d===0?0:d>12?d>=24?0:d:a==="am"?d===12?0:d:d===12?12:d+12}function vs(d,a){d.addClass("stashpad-when-pop-time");let e=a.seedPeriod,t=d.createDiv({cls:"stashpad-when-time-display"}),i=t.createEl("input",{cls:"stashpad-when-time-field",attr:{type:"text",inputmode:"numeric",maxlength:"2"}});i.value=String(a.seedH),t.createSpan({cls:"stashpad-when-time-colon",text:":"});let s=t.createEl("input",{cls:"stashpad-when-time-field",attr:{type:"text",inputmode:"numeric",maxlength:"2"}});s.value=String(a.seedM).padStart(2,"0");let n=t.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 l=()=>{o.toggleClass("is-active",e==="am"),r.toggleClass("is-active",e==="pm")};l(),o.addEventListener("mousedown",C=>C.preventDefault()),r.addEventListener("mousedown",C=>C.preventDefault()),o.addEventListener("click",C=>{C.preventDefault(),e="am",l()}),r.addEventListener("click",C=>{C.preventDefault(),e="pm",l()});let c=i;i.addEventListener("focus",()=>{c=i,i.select()}),s.addEventListener("focus",()=>{c=s,s.select()});let A=()=>{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},h=C=>{let w=C.value.replace(/\D/g,"").slice(0,2);if(C.value=w,w===""){C===i&&A();return}let y=parseInt(w,10),v=C===i?24:59;y>v&&(C.value=String(v)),C===i&&A()};for(let C of[i,s])C.addEventListener("input",()=>h(C));A();let g=()=>{let C=parseInt(i.value,10),w=Number.isNaN(C)?12:C,y=parseInt(s.value||"0",10)||0,v=w>12||w===0;a.onFinalize({hours24:Rl(w,e),minutes:y,raw:{hh:w,mm:y,period:e,is24:v}}),a.close()};a.setOnEnter?.(g);let u=[i,s,o,r],f=(C,w)=>{let y=u.indexOf(C);if(y===-1)return;let v=(y+w+u.length)%u.length;u[v].focus()},p=C=>{C.addEventListener("keydown",w=>{w.key==="Enter"?(w.preventDefault(),w.stopPropagation(),g()):w.key==="Escape"?(w.preventDefault(),w.stopPropagation(),a.close()):w.key==="Tab"&&(w.preventDefault(),w.stopPropagation(),f(C,w.shiftKey?-1:1))})},I=d.createDiv({cls:"stashpad-when-time-pad"}),m=["1","2","3","4","5","6","7","8","9","backspace","0","insert"],B=null;for(let C of m){let w=I.createEl("button",{cls:"stashpad-when-time-padbtn"});w.type="button",C==="backspace"?(0,Mr.setIcon)(w,"delete"):C==="insert"?(w.setText("OK"),B=w):w.setText(C),C==="insert"&&w.addClass("is-go"),w.addEventListener("mousedown",y=>y.preventDefault()),w.addEventListener("click",y=>{if(y.preventDefault(),C==="insert"){g();return}if(C==="backspace"){c.value=c.value.slice(0,-1),h(c),c.focus();return}let v=c.selectionStart===0&&c.selectionEnd===c.value.length&&c.value.length>0,E=2,Q=v||c.value.length>=E?C:c.value+C;c.value=Q,h(c),c.focus(),c.setSelectionRange(c.value.length,c.value.length),c===i&&c.value.length>=E&&(s.focus(),s.select())})}B&&u.push(B);for(let C of u)p(C);i.focus(),i.select()}function Tr(d){let{hh:a,mm:e,period:t,is24:i}=d.raw;return i?`${a}:${String(e).padStart(2,"0")}`:`${a}:${String(e).padStart(2,"0")}${t}`}var Mr,so=qe(()=>{"use strict";Mr=require("obsidian")});function Hr(d){let a=Math.floor(4294967296/d)*d,e=new Uint32Array(1),t;do crypto.getRandomValues(e),t=e[0];while(t>=a);return t%d}function no(d=5){let a=[];for(let e=0;e=1&&s.every(r=>/^[a-zA-Z]+$/.test(r))&&(i=Math.min(i,s.length*11)),Ul.has(d.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 Gl(d){let a=2166136261;for(let e=0;e>>0).toString(16).padStart(8,"0")}function ei(d){let a="stashpad-",e=Gl(d),t=64-a.length-1-e.length,i=d.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,Math.max(0,t)).replace(/-+$/g,"");return`${a}${i}-${e}`}var Pr,Ul,Fs=qe(()=>{"use strict";Pr="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((d,a,e)=>e.indexOf(d)===a);Ul=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 $i={};ki($i,{BreadcrumbLevelsModal:()=>Li,ColorPickerModal:()=>Gt,ConfirmDeleteModal:()=>ii,ConfirmModal:()=>_,CustomColorModal:()=>ks,DueDatePickerModal:()=>Ue,EncryptionPasswordModal:()=>Ne,ExportStashModal:()=>si,ImportDupChoiceModal:()=>Ki,ImportLogModal:()=>ro,LogModal:()=>ti,NotificationHistoryModal:()=>Oi,OkfExportModal:()=>Ji,OpenDeepLinkModal:()=>Gi,ReEncryptReviewModal:()=>qi,SplitNoteModal:()=>Ri,StashPasswordModal:()=>Ui,TypeToConfirmModal:()=>ni,buildAssigneePicker:()=>Ur,parseAdjustMinutes:()=>Rr});function Rr(d){let a=/^\s*(\d+)\s*(m|h|d|w)\s*$/i.exec(d);if(!a)return null;let e=parseInt(a[1],10);if(!Number.isFinite(e)||e<=0)return null;let t={m:1,h:60,d:1440,w:10080}[a[2].toLowerCase()]??1;return e*t}function Ur(d,a){let e=[...a.initial],t=a.knownAuthors,i=d.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 l=()=>a.onChange([...e]),c=()=>{s.empty(),e.length===0&&s.createSpan({cls:"stashpad-assign-empty",text:"No one yet"});for(let g of e){let u=s.createSpan({cls:"stashpad-assign-chip"});u.createSpan({cls:"stashpad-assign-chip-name",text:g.name});let f=u.createSpan({cls:"stashpad-assign-chip-x",text:"\xD7"});f.title=`Remove ${g.name}`,f.onclick=()=>{e=e.filter(p=>p.id!==g.id),l(),c()}}},A=g=>{g.name.trim()&&(e.some(u=>u.id===g.id)||e.push(g),o.value="",r.setCssStyles({display:"none"}),l(),c(),o.focus())},h=()=>{let g=o.value.trim();r.empty();let u=new Set(e.map(I=>I.id)),p=t.filter(I=>!u.has(I.id)&&Es(g,I.name)).slice(0,6).map(I=>({label:I.name,onPick:()=>A(I)}));if(g&&!t.some(I=>I.name.toLowerCase()===g.toLowerCase())&&p.push({label:`Create \u201C${g}\u201D`,onPick:()=>A({id:Ae(6),name:g})}),p.length===0){r.setCssStyles({display:"none"});return}r.setCssStyles({display:""});for(let I of p){let m=r.createDiv({cls:"stashpad-assign-suggest-item",text:I.label});m.onmousedown=B=>{B.preventDefault(),I.onPick()}}};o.addEventListener("input",h),o.addEventListener("focus",h),o.addEventListener("keydown",g=>{if(g.key==="Enter"){g.preventDefault();let u=r.querySelector(".stashpad-assign-suggest-item");u&&u.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)}),c()}var J,Ll,Rt,ti,ii,Ri,si,Ui,Ne,ni,Gi,ks,Hi,Gt,_,Li,Ue,Ut,Oi,ro,Ki,Ji,qi,we=qe(()=>{"use strict";J=require("obsidian");Pi();so();ae();Fs();ot();Ll=J.moment,Rt=class Rt extends J.Modal{constructor(e,t,i){super(e);this.text=t;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 o of this.text.trim().split(/\r?\n/))if(o)try{this.events.push(JSON.parse(o))}catch{}this.events.reverse();let e=this.contentEl.createDiv({cls:"stashpad-log-toolbar"});if(this.countEl=e.createSpan({cls:"stashpad-log-count"}),this.updateCount(),this.filterSelEl=e.createEl("select",{cls:"stashpad-log-type-filter"}),this.filterSelEl.onchange=()=>this.setTypeFilter(this.filterSelEl.value||null),this.refreshTypeFilter(),!J.Platform.isMobile){let o=e.createEl("button",{text:"Reveal JSONL"});o.onclick=()=>this.shellAct("reveal");let r=e.createEl("button",{text:"Open in default app"});r.onclick=()=>this.shellAct("open")}let t=e.createEl("button",{text:"Copy raw JSONL"}),i=null;t.onclick=async()=>{await navigator.clipboard.writeText(this.text),t.setText("Copied"),i!=null&&window.clearTimeout(i),i=window.setTimeout(()=>{t.setText("Copy raw JSONL"),i=null},1500)};let s=e.createEl("button",{text:"Export copy"});s.onclick=()=>this.exportCopy();let n=e.createEl("button",{cls:"mod-warning",text:"Clear log"});n.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(e=>e.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(Rt.PAGE)}}setTypeFilter(e){(this.typeFilter??null)!==(e??null)&&(this.typeFilter=e,this.refreshList(),this.renderFooter())}refreshTypeFilter(){if(!this.filterSelEl)return;let e=this.filterSelEl;e.empty();let t=new Map;for(let n of this.events)t.set(n.type,(t.get(n.type)??0)+1);let i=[...t.entries()].sort((n,o)=>o[1]-n[1]||n[0].localeCompare(o[0])),s=e.createEl("option",{text:`All types (${this.events.length})`});s.value="";for(let[n,o]of i){let r=e.createEl("option",{text:`${n} (${o})`});r.value=n}this.typeFilter&&!t.has(this.typeFilter)&&(this.typeFilter=null),e.value=this.typeFilter??""}updateCount(){if(!this.countEl)return;let e=this.visible.length,t=this.typeFilter?`${e} ${this.typeFilter} event${e===1?"":"s"}`:`${e} event${e===1?"":"s"}`;this.shownCount===0||this.shownCount>=e?this.countEl.setText(t):this.countEl.setText(`Showing ${this.shownCount} of ${t}`)}appendMore(e){if(!this.listEl)return;let t=Math.min(this.visible.length,this.shownCount+e);for(let i=this.shownCount;i{this.appendMore(Rt.PAGE),this.renderFooter()},e>Rt.PAGE){let i=this.footerEl.createEl("button",{text:`Load all (${e})`});i.onclick=()=>{this.appendMore(e),this.renderFooter()}}}shellAct(e){try{let t=this.app.vault.adapter.getFullPath?.(this.jsonlPath);if(!t)throw new Error("no full path");let{shell:i}=window.require("electron");e==="reveal"?i.showItemInFolder(t):i.openPath(t)}catch(t){new J.Notice(`Couldn't ${e}: ${t.message}`)}}async exportCopy(){try{let e=(0,J.moment)().format("YYYY-MM-DD_HHmmss"),t=this.jsonlPath.replace(/\/[^/]+$/,"")||"",i=t?`${t}/${e}-log.jsonl`:`${e}-log.jsonl`;return await this.app.vault.adapter.write(i,this.text),new J.Notice(`Exported log \u2192 ${i}`),i}catch(e){return new J.Notice(`Export failed: ${e.message}`),null}}clearLog(){new _(this.app,"Clear log?","A timestamped copy will be saved alongside the active log before it's truncated.","Export & clear",async e=>{if(!(!e||!await this.exportCopy())){try{await this.app.vault.adapter.write(this.jsonlPath,"")}catch(i){new J.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 J.Notice("Log cleared.")}},"Cancel",!0).open()}renderEvent(e){let t=document.createElement("div");t.className=`stashpad-log-row stashpad-log-${e.type}`;let i=(0,J.moment)(e.ts).isValid()?(0,J.moment)(e.ts).format("YYYY-MM-DD HH:mm:ss"):e.ts,s=document.createElement("span");s.className="stashpad-log-ts",s.textContent=i,t.appendChild(s);let n=document.createElement("span");n.className="stashpad-log-type",n.textContent=e.type,t.appendChild(n);let o=document.createElement("span");o.className="stashpad-log-author",o.textContent=e.author?e.author:"\u2014",e.author||o.classList.add("is-empty"),t.appendChild(o);let r=document.createElement("span");return r.className="stashpad-log-msg",r.textContent=this.describe(e),t.appendChild(r),t}describe(e){let t=e.payload??{};switch(e.type){case"create":return`Created "${t.path??e.id}" under ${t.parent??"?"}`;case"delete":{let i=Array.isArray(t.attachmentsRemoved)?t.attachmentsRemoved.length:0,s=t.mergedInto?` (merged into ${t.mergedInto})`:"",n=t.to==="trash"?" \u2192 Trash":"";return`Deleted ${e.id}${n}${s}${i?` \u2014 also removed ${i} attachment${i===1?"":"s"}`:""}`}case"missing":return`Missing: ${t.lastPath??e.id}`;case"parent_change":{let i=t.reason?` (${t.reason})`:"";return`Moved ${e.id} from ${t.from??"null"} \u2192 ${t.to??"null"}${i}`}case"rename":return`Renamed ${t.from??"?"} \u2192 ${t.to??"?"}`;case"reorder":{let i=t.count??1,s=t.dir??"?",n=t.parent??e.id??"?";return`Reordered ${i} note${i===1?"":"s"} (${s}) under ${n}`}case"complete":{let i=t.count??1,s=t.undo?" (undo)":t.redo?" (redo)":"";return`Marked ${i} note${i===1?"":"s"} complete${s}`}case"uncomplete":{let i=t.count??1,s=t.undo?" (undo)":t.redo?" (redo)":"";return`Unmarked ${i} note${i===1?"":"s"}${s}`}case"stash_export":{let i=t.noteCount??"?";return`Exported ${i} note${i===1?"":"s"} \u2192 ${t.path??"?"}`}case"stash_import":{let i=t.noteCount??"?",s=[];t.attachmentsWritten&&s.push(`${t.attachmentsWritten} attachment${t.attachmentsWritten===1?"":"s"}`),t.collisionsRenamed&&s.push(`${t.collisionsRenamed} renamed`);let n=s.length?` (${s.join(", ")})`:"";return`Imported ${i} note${i===1?"":"s"} from ${t.from??"?"} \u2192 ${t.into??"?"}${n}`}case"attachment_add":return`Added attachment ${t.path??e.id}`;case"attachment_remove":return`Removed attachment ${t.path??e.id}`;case"palette_color_add":return`Added palette color ${t.color??e.id}`;case"palette_color_remove":return`Removed palette color ${t.color??e.id}`;case"lock":return`Locked (encrypted) ${e.id}`;case"unlock":return`Unlocked ${e.id}`;case"archive":return`Archived ${e.id}${t.to?` \u2192 ${t.to}`:""}${t.encrypted===!1?" (plaintext)":""}`;case"restore":return`Restored ${e.id}${t.to?` \u2192 ${t.to}`:""} from trash`;default:return JSON.stringify(t)}}onClose(){this.contentEl.empty()}};Rt.PAGE=100;ti=Rt,ii=class extends J.Modal{constructor(e,t,i,s,n,o){super(e);this.noteTitle=t;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 e=[];this.descendantCount>0&&e.push(`${this.descendantCount} descendant note${this.descendantCount===1?"":"s"} will also be deleted.`),this.attachmentCount>0&&e.push(`${this.attachmentCount} attachment${this.attachmentCount===1?"":"s"} found across these notes.`),this.contentEl.createEl("p",{text:e.join(" ")});let t=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=t,r.onchange=()=>{t=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(t)}}onClose(){this.contentEl.empty()}},Ri=class extends J.Modal{constructor(e,t,i,s,n){super(e);this.body=t;this.onSplitAtLine=i;this.onSplitAtChar=s;this.onSplitMany=n;this.mode="line";this.cursorTextarea=null;this.lines=t.replace(/\r\n/g,` +`).trim()),t.filter(Boolean)}function Fe(d,a,e){d.empty();try{(0,Dr.setIcon)(d,a)}catch{}let t=d.querySelector("svg");t&&t.querySelector("path, line, circle, rect, polyline, polygon, ellipse")||(d.empty(),d.createSpan({cls:"stashpad-icon-fallback",text:e}))}function xr(d){if(d instanceof Element&&d.closest(".modal, .modal-container, .suggestion-container, .menu, .prompt"))return!0;let a=new Set([document]);d instanceof Element&&d.ownerDocument&&a.add(d.ownerDocument);for(let e of a)if(e.body?.querySelector(".modal-bg")||e.body?.querySelector(".modal-container .modal")||e.body?.querySelector(".suggestion-container")||e.body?.querySelector(".menu.mod-active"))return!0;return!1}function Nr(d){let a=[],e=/^([ \t]*)(`{3,})[ \t]*([^\n`]*)\n([\s\S]*?)\n\1\2[ \t]*$/gm,t;for(;(t=e.exec(d))!=null;)a.push({lang:t[3].trim(),code:t[4]});return a}function Pi(d){return d.split("/").map(a=>a.split(" ").map(e=>e&&/^[a-z]/.test(e)?e[0].toUpperCase()+e.slice(1):e).join(" ")).join("/")}function Mr(d,a,e){let t=new Set(a),i=d.filter(n=>!t.has(n)),s=d.findIndex(n=>t.has(n));if(s<0)return d.slice();switch(e){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 c=-1;return d.forEach((A,h)=>{t.has(A)&&(c=h)}),c})(),o=0;for(let c=0;c0){let n=t[i-1];return(!/[a-z0-9]/.test(n)?600:500)-Math.min(i,99)}let s=0;for(let n=0;n({t,s:Ll(e,t.raw)})).filter(t=>t.s>=0).sort((t,i)=>i.s-t.s||i.t.count-t.t.count||t.t.label.localeCompare(i.t.label)).map(t=>t.t):a}var Dr,ei,Ht,Rt,Hi=$e(()=>{"use strict";Dr=require("obsidian"),ei={lines:"Each line",paragraphs:"Paragraphs (blank line)",headings:"Headings"};Ht="__stashpad:tagged__",Rt="__stashpad:untagged__"});function Ol(d,a){return d===0?0:d>12?d>=24?0:d:a==="am"?d===12?0:d:d===12?12:d+12}function Fs(d,a){d.addClass("stashpad-when-pop-time");let e=a.seedPeriod,t=d.createDiv({cls:"stashpad-when-time-display"}),i=t.createEl("input",{cls:"stashpad-when-time-field",attr:{type:"text",inputmode:"numeric",maxlength:"2"}});i.value=String(a.seedH),t.createSpan({cls:"stashpad-when-time-colon",text:":"});let s=t.createEl("input",{cls:"stashpad-when-time-field",attr:{type:"text",inputmode:"numeric",maxlength:"2"}});s.value=String(a.seedM).padStart(2,"0");let n=t.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 l=()=>{o.toggleClass("is-active",e==="am"),r.toggleClass("is-active",e==="pm")};l(),o.addEventListener("mousedown",C=>C.preventDefault()),r.addEventListener("mousedown",C=>C.preventDefault()),o.addEventListener("click",C=>{C.preventDefault(),e="am",l()}),r.addEventListener("click",C=>{C.preventDefault(),e="pm",l()});let c=i;i.addEventListener("focus",()=>{c=i,i.select()}),s.addEventListener("focus",()=>{c=s,s.select()});let A=()=>{let Q=(parseInt(i.value||"0",10)||0)>12;o.toggleClass("is-disabled",Q),r.toggleClass("is-disabled",Q),o.disabled=Q,r.disabled=Q},h=C=>{let Q=C.value.replace(/\D/g,"").slice(0,2);if(C.value=Q,Q===""){C===i&&A();return}let y=parseInt(Q,10),E=C===i?24:59;y>E&&(C.value=String(E)),C===i&&A()};for(let C of[i,s])C.addEventListener("input",()=>h(C));A();let p=()=>{let C=parseInt(i.value,10),Q=Number.isNaN(C)?12:C,y=parseInt(s.value||"0",10)||0,E=Q>12||Q===0;a.onFinalize({hours24:Ol(Q,e),minutes:y,raw:{hh:Q,mm:y,period:e,is24:E}}),a.close()};a.setOnEnter?.(p);let u=[i,s,o,r],f=(C,Q)=>{let y=u.indexOf(C);if(y===-1)return;let E=(y+Q+u.length)%u.length;u[E].focus()},g=C=>{C.addEventListener("keydown",Q=>{Q.key==="Enter"?(Q.preventDefault(),Q.stopPropagation(),p()):Q.key==="Escape"?(Q.preventDefault(),Q.stopPropagation(),a.close()):Q.key==="Tab"&&(Q.preventDefault(),Q.stopPropagation(),f(C,Q.shiftKey?-1:1))})},I=d.createDiv({cls:"stashpad-when-time-pad"}),m=["1","2","3","4","5","6","7","8","9","backspace","0","insert"],B=null;for(let C of m){let Q=I.createEl("button",{cls:"stashpad-when-time-padbtn"});Q.type="button",C==="backspace"?(0,Pr.setIcon)(Q,"delete"):C==="insert"?(Q.setText("OK"),B=Q):Q.setText(C),C==="insert"&&Q.addClass("is-go"),Q.addEventListener("mousedown",y=>y.preventDefault()),Q.addEventListener("click",y=>{if(y.preventDefault(),C==="insert"){p();return}if(C==="backspace"){c.value=c.value.slice(0,-1),h(c),c.focus();return}let E=c.selectionStart===0&&c.selectionEnd===c.value.length&&c.value.length>0,w=2,v=E||c.value.length>=w?C:c.value+C;c.value=v,h(c),c.focus(),c.setSelectionRange(c.value.length,c.value.length),c===i&&c.value.length>=w&&(s.focus(),s.select())})}B&&u.push(B);for(let C of u)g(C);i.focus(),i.select()}function Hr(d){let{hh:a,mm:e,period:t,is24:i}=d.raw;return i?`${a}:${String(e).padStart(2,"0")}`:`${a}:${String(e).padStart(2,"0")}${t}`}var Pr,ro=$e(()=>{"use strict";Pr=require("obsidian")});function Ur(d){let a=Math.floor(4294967296/d)*d,e=new Uint32Array(1),t;do crypto.getRandomValues(e),t=e[0];while(t>=a);return t%d}function ao(d=5){let a=[];for(let e=0;e=1&&s.every(r=>/^[a-zA-Z]+$/.test(r))&&(i=Math.min(i,s.length*11)),Kl.has(d.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 Jl(d){let a=2166136261;for(let e=0;e>>0).toString(16).padStart(8,"0")}function ti(d){let a="stashpad-",e=Jl(d),t=64-a.length-1-e.length,i=d.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,Math.max(0,t)).replace(/-+$/g,"");return`${a}${i}-${e}`}var Rr,Kl,ks=$e(()=>{"use strict";Rr="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((d,a,e)=>e.indexOf(d)===a);Kl=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 Yi={};Si(Yi,{BreadcrumbLevelsModal:()=>Oi,ColorPickerModal:()=>Lt,ConfirmDeleteModal:()=>si,ConfirmModal:()=>_,CustomColorModal:()=>Ss,DEFAULT_QUICK_ADJUSTS:()=>Gr,DueDatePickerModal:()=>Ge,EncryptionPasswordModal:()=>Ne,ExportStashModal:()=>ni,ImportDupChoiceModal:()=>Ji,ImportLogModal:()=>co,LogModal:()=>ii,NotificationHistoryModal:()=>Ki,OkfExportModal:()=>qi,OpenDeepLinkModal:()=>Li,ReEncryptReviewModal:()=>$i,SplitNoteModal:()=>Ui,StashPasswordModal:()=>Gi,TypeToConfirmModal:()=>oi,buildAssigneePicker:()=>Or,parseAdjustMinutes:()=>Lr});function Lr(d){let a=/^\s*(\d+)\s*(m|h|d|w)\s*$/i.exec(d);if(!a)return null;let e=parseInt(a[1],10);if(!Number.isFinite(e)||e<=0)return null;let t={m:1,h:60,d:1440,w:10080}[a[2].toLowerCase()]??1;return e*t}function Or(d,a){let e=[...a.initial],t=a.knownAuthors,i=d.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 l=()=>a.onChange([...e]),c=()=>{s.empty(),e.length===0&&s.createSpan({cls:"stashpad-assign-empty",text:"No one yet"});for(let p of e){let u=s.createSpan({cls:"stashpad-assign-chip"});u.createSpan({cls:"stashpad-assign-chip-name",text:p.name});let f=u.createSpan({cls:"stashpad-assign-chip-x",text:"\xD7"});f.title=`Remove ${p.name}`,f.onclick=()=>{e=e.filter(g=>g.id!==p.id),l(),c()}}},A=p=>{p.name.trim()&&(e.some(u=>u.id===p.id)||e.push(p),o.value="",r.setCssStyles({display:"none"}),l(),c(),o.focus())},h=()=>{let p=o.value.trim();r.empty();let u=new Set(e.map(I=>I.id)),g=t.filter(I=>!u.has(I.id)&&Qs(p,I.name)).slice(0,6).map(I=>({label:I.name,onPick:()=>A(I)}));if(p&&!t.some(I=>I.name.toLowerCase()===p.toLowerCase())&&g.push({label:`Create \u201C${p}\u201D`,onPick:()=>A({id:he(6),name:p})}),g.length===0){r.setCssStyles({display:"none"});return}r.setCssStyles({display:""});for(let I of g){let m=r.createDiv({cls:"stashpad-assign-suggest-item",text:I.label});m.onmousedown=B=>{B.preventDefault(),I.onPick()}}};o.addEventListener("input",h),o.addEventListener("focus",h),o.addEventListener("keydown",p=>{if(p.key==="Enter"){p.preventDefault();let u=r.querySelector(".stashpad-assign-suggest-item");u&&u.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)}),c()}var J,Gr,ql,Ut,ii,si,Ui,ni,Gi,Ne,oi,Li,Ss,Ri,Lt,_,Oi,Ge,Gt,Ki,co,Ji,qi,$i,me=$e(()=>{"use strict";J=require("obsidian");Hi();ro();le();ks();rt();Gr=["5m","15m","30m","1h","1d","1w"];ql=J.moment,Ut=class Ut extends J.Modal{constructor(e,t,i){super(e);this.text=t;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 o of this.text.trim().split(/\r?\n/))if(o)try{this.events.push(JSON.parse(o))}catch{}this.events.reverse();let e=this.contentEl.createDiv({cls:"stashpad-log-toolbar"});if(this.countEl=e.createSpan({cls:"stashpad-log-count"}),this.updateCount(),this.filterSelEl=e.createEl("select",{cls:"stashpad-log-type-filter"}),this.filterSelEl.onchange=()=>this.setTypeFilter(this.filterSelEl.value||null),this.refreshTypeFilter(),!J.Platform.isMobile){let o=e.createEl("button",{text:"Reveal JSONL"});o.onclick=()=>this.shellAct("reveal");let r=e.createEl("button",{text:"Open in default app"});r.onclick=()=>this.shellAct("open")}let t=e.createEl("button",{text:"Copy raw JSONL"}),i=null;t.onclick=async()=>{await navigator.clipboard.writeText(this.text),t.setText("Copied"),i!=null&&window.clearTimeout(i),i=window.setTimeout(()=>{t.setText("Copy raw JSONL"),i=null},1500)};let s=e.createEl("button",{text:"Export copy"});s.onclick=()=>this.exportCopy();let n=e.createEl("button",{cls:"mod-warning",text:"Clear log"});n.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(e=>e.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(Ut.PAGE)}}setTypeFilter(e){(this.typeFilter??null)!==(e??null)&&(this.typeFilter=e,this.refreshList(),this.renderFooter())}refreshTypeFilter(){if(!this.filterSelEl)return;let e=this.filterSelEl;e.empty();let t=new Map;for(let n of this.events)t.set(n.type,(t.get(n.type)??0)+1);let i=[...t.entries()].sort((n,o)=>o[1]-n[1]||n[0].localeCompare(o[0])),s=e.createEl("option",{text:`All types (${this.events.length})`});s.value="";for(let[n,o]of i){let r=e.createEl("option",{text:`${n} (${o})`});r.value=n}this.typeFilter&&!t.has(this.typeFilter)&&(this.typeFilter=null),e.value=this.typeFilter??""}updateCount(){if(!this.countEl)return;let e=this.visible.length,t=this.typeFilter?`${e} ${this.typeFilter} event${e===1?"":"s"}`:`${e} event${e===1?"":"s"}`;this.shownCount===0||this.shownCount>=e?this.countEl.setText(t):this.countEl.setText(`Showing ${this.shownCount} of ${t}`)}appendMore(e){if(!this.listEl)return;let t=Math.min(this.visible.length,this.shownCount+e);for(let i=this.shownCount;i{this.appendMore(Ut.PAGE),this.renderFooter()},e>Ut.PAGE){let i=this.footerEl.createEl("button",{text:`Load all (${e})`});i.onclick=()=>{this.appendMore(e),this.renderFooter()}}}shellAct(e){try{let t=this.app.vault.adapter.getFullPath?.(this.jsonlPath);if(!t)throw new Error("no full path");let{shell:i}=window.require("electron");e==="reveal"?i.showItemInFolder(t):i.openPath(t)}catch(t){new J.Notice(`Couldn't ${e}: ${t.message}`)}}async exportCopy(){try{let e=(0,J.moment)().format("YYYY-MM-DD_HHmmss"),t=this.jsonlPath.replace(/\/[^/]+$/,"")||"",i=t?`${t}/${e}-log.jsonl`:`${e}-log.jsonl`;return await this.app.vault.adapter.write(i,this.text),new J.Notice(`Exported log \u2192 ${i}`),i}catch(e){return new J.Notice(`Export failed: ${e.message}`),null}}clearLog(){new _(this.app,"Clear log?","A timestamped copy will be saved alongside the active log before it's truncated.","Export & clear",async e=>{if(!(!e||!await this.exportCopy())){try{await this.app.vault.adapter.write(this.jsonlPath,"")}catch(i){new J.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 J.Notice("Log cleared.")}},"Cancel",!0).open()}renderEvent(e){let t=document.createElement("div");t.className=`stashpad-log-row stashpad-log-${e.type}`;let i=(0,J.moment)(e.ts).isValid()?(0,J.moment)(e.ts).format("YYYY-MM-DD HH:mm:ss"):e.ts,s=document.createElement("span");s.className="stashpad-log-ts",s.textContent=i,t.appendChild(s);let n=document.createElement("span");n.className="stashpad-log-type",n.textContent=e.type,t.appendChild(n);let o=document.createElement("span");o.className="stashpad-log-author",o.textContent=e.author?e.author:"\u2014",e.author||o.classList.add("is-empty"),t.appendChild(o);let r=document.createElement("span");return r.className="stashpad-log-msg",r.textContent=this.describe(e),t.appendChild(r),t}describe(e){let t=e.payload??{};switch(e.type){case"create":return`Created "${t.path??e.id}" under ${t.parent??"?"}`;case"delete":{let i=Array.isArray(t.attachmentsRemoved)?t.attachmentsRemoved.length:0,s=t.mergedInto?` (merged into ${t.mergedInto})`:"",n=t.to==="trash"?" \u2192 Trash":"";return`Deleted ${e.id}${n}${s}${i?` \u2014 also removed ${i} attachment${i===1?"":"s"}`:""}`}case"missing":return`Missing: ${t.lastPath??e.id}`;case"parent_change":{let i=t.reason?` (${t.reason})`:"";return`Moved ${e.id} from ${t.from??"null"} \u2192 ${t.to??"null"}${i}`}case"rename":return`Renamed ${t.from??"?"} \u2192 ${t.to??"?"}`;case"reorder":{let i=t.count??1,s=t.dir??"?",n=t.parent??e.id??"?";return`Reordered ${i} note${i===1?"":"s"} (${s}) under ${n}`}case"complete":{let i=t.count??1,s=t.undo?" (undo)":t.redo?" (redo)":"";return`Marked ${i} note${i===1?"":"s"} complete${s}`}case"uncomplete":{let i=t.count??1,s=t.undo?" (undo)":t.redo?" (redo)":"";return`Unmarked ${i} note${i===1?"":"s"}${s}`}case"stash_export":{let i=t.noteCount??"?";return`Exported ${i} note${i===1?"":"s"} \u2192 ${t.path??"?"}`}case"stash_import":{let i=t.noteCount??"?",s=[];t.attachmentsWritten&&s.push(`${t.attachmentsWritten} attachment${t.attachmentsWritten===1?"":"s"}`),t.collisionsRenamed&&s.push(`${t.collisionsRenamed} renamed`);let n=s.length?` (${s.join(", ")})`:"";return`Imported ${i} note${i===1?"":"s"} from ${t.from??"?"} \u2192 ${t.into??"?"}${n}`}case"attachment_add":return`Added attachment ${t.path??e.id}`;case"attachment_remove":return`Removed attachment ${t.path??e.id}`;case"palette_color_add":return`Added palette color ${t.color??e.id}`;case"palette_color_remove":return`Removed palette color ${t.color??e.id}`;case"lock":return`Locked (encrypted) ${e.id}`;case"unlock":return`Unlocked ${e.id}`;case"archive":return`Archived ${e.id}${t.to?` \u2192 ${t.to}`:""}${t.encrypted===!1?" (plaintext)":""}`;case"restore":return`Restored ${e.id}${t.to?` \u2192 ${t.to}`:""} from trash`;default:return JSON.stringify(t)}}onClose(){this.contentEl.empty()}};Ut.PAGE=100;ii=Ut,si=class extends J.Modal{constructor(e,t,i,s,n,o){super(e);this.noteTitle=t;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 e=[];this.descendantCount>0&&e.push(`${this.descendantCount} descendant note${this.descendantCount===1?"":"s"} will also be deleted.`),this.attachmentCount>0&&e.push(`${this.attachmentCount} attachment${this.attachmentCount===1?"":"s"} found across these notes.`),this.contentEl.createEl("p",{text:e.join(" ")});let t=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=t,r.onchange=()=>{t=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(t)}}onClose(){this.contentEl.empty()}},Ui=class extends J.Modal{constructor(e,t,i,s,n){super(e);this.body=t;this.onSplitAtLine=i;this.onSplitAtChar=s;this.onSplitMany=n;this.mode="line";this.cursorTextarea=null;this.lines=t.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",e=>{this.lines.length<2||(e.preventDefault(),this.mode=this.mode==="line"?"cursor":"line",this.render())}),this.scope.register([],"Enter",e=>{this.mode==="line"&&(e.preventDefault(),this.commitLine())}),this.scope.register(["Mod"],"Enter",e=>{this.mode==="cursor"&&(e.preventDefault(),this.commitCursor())}),this.scope.register([],"ArrowUp",e=>{this.mode==="line"&&(e.preventDefault(),this.lineCursorIdx=Math.max(1,this.lineCursorIdx-1),this.render())}),this.scope.register([],"ArrowDown",e=>{this.mode==="line"&&(e.preventDefault(),this.lineCursorIdx=Math.min(this.lines.length-1,this.lineCursorIdx+1),this.render())})}commitLine(){let e=this.lineCursorIdx;this.close(),this.onSplitAtLine(e)}commitCursor(){let e=this.cursorTextarea;if(!e)return;let t=e.selectionStart;if(t<=0||t>=e.value.length){new J.Notice("Move the cursor inside the text \u2014 neither end can be empty.");return}this.close(),this.onSplitAtChar(t)}render(){this.contentEl.empty();let e=this.contentEl.createDiv({cls:"stashpad-split-quick"});e.createSpan({cls:"stashpad-split-quick-label",text:"Split by:"}),["lines","paragraphs","headings"].forEach(o=>{let r=Mi(this.body,o),l=e.createEl("button",{cls:"stashpad-split-quick-btn",text:`${_t[o]} (${r.length})`});l.disabled=r.length<2,l.onmousedown=c=>c.preventDefault(),l.onclick=()=>{let c=Mi(this.body,o);if(c.length<2){new J.Notice("That delimiter wouldn't split this note.");return}this.close(),this.onSplitMany(c)}});let t=this.contentEl.createDiv({cls:"stashpad-split-toggle-bar"});if(this.lines.length>=2){let o=t.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=t.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=t.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"});J.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 e=this.contentEl.createDiv({cls:"stashpad-split-list"}),t=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())}}t&&window.requestAnimationFrame(()=>t.scrollIntoView({block:"center"}))}renderCursorMode(){let t=this.contentEl.createDiv({cls:"stashpad-split-cursor-wrap"}).createEl("textarea",{cls:"stashpad-split-cursor-ta"});t.value=this.body,t.readOnly=!1,this.cursorTextarea=t;let i=parseFloat(getComputedStyle(t).lineHeight)||22,s=J.Platform.isMobile?3:12,n=2,o=()=>{t.setCssStyles({height:"auto"});let r=Math.min(t.scrollHeight,i*s+16);t.setCssStyles({height:`${Math.max(r,i*n+16)}px`})};requestAnimationFrame(()=>{o();let r=Math.floor(t.value.length/2);t.focus(),t.setSelectionRange(r,r)}),t.addEventListener("input",o)}onClose(){this.cursorTextarea=null,this.contentEl.empty()}},si=class extends J.Modal{constructor(e,t,i,s,n){super(e);this.defaultBaseName=t;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 e=this.contentEl.createDiv({cls:"stashpad-export-field"});e.createEl("label",{cls:"stashpad-export-label",text:"File name"});let t=e.createEl("input",{type:"text"});t.addClass("stashpad-export-name"),t.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 l=s.createDiv({cls:"stashpad-export-pw-area"});l.setCssStyles({display:"none"});let c=[],A=K=>{let V=l.createDiv({cls:"stashpad-export-pw-row"}),Y=V.createEl("input",{type:"password"});Y.addClass("stashpad-export-name"),Y.placeholder=K;let $=V.createEl("button",{cls:"stashpad-export-copy"}),j=()=>{let le=Y.value.length===0;$.setText(le?"Paste":"Copy"),$.toggleClass("is-paste",le),$.setAttr("aria-label",`${le?"Paste into":"Copy"} ${K.toLowerCase()}`)};return $.onclick=async le=>{if(le.preventDefault(),Y.value.length===0)try{let oe=(await navigator.clipboard?.readText())?.trim();if(!oe){new J.Notice("Clipboard is empty.");return}Y.value=oe,Y.dispatchEvent(new Event("input")),new J.Notice("Pasted from clipboard.")}catch{new J.Notice("Couldn't read the clipboard.")}else navigator.clipboard?.writeText(Y.value).then(()=>new J.Notice("Passphrase copied to clipboard."),()=>new J.Notice("Couldn't access the clipboard."))},j(),c.push(j),Y},h=A("Password"),g=A("Confirm password"),u=l.createDiv({cls:"stashpad-export-strength"}),f=u.createDiv({cls:"stashpad-strength-bar"}),p=[0,1,2,3].map(()=>f.createDiv({cls:"stashpad-strength-seg"})),I=u.createEl("span",{cls:"stashpad-strength-label"}),m=l.createDiv({cls:"stashpad-export-genrow"}),B=m.createEl("button",{cls:"stashpad-export-gen",text:"Generate strong passphrase"}),C=m.createEl("button",{cls:"stashpad-export-show",text:"Show"}),w=l.createEl("div",{cls:"stashpad-export-pw-hint"}),y=l.createEl("div",{cls:"stashpad-export-pw-suite"});y.setText("Encryption: AES-256-GCM. Checking key-derivation suite for this device\u2026"),this.kdfProbe?this.kdfProbe().then(K=>{y.toggleClass("is-weak",!K),y.setText(K?"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(()=>{y.setText("Encryption: AES-256-GCM with a password-derived key.")}):y.setText("Encryption: Argon2id + AES-256-GCM (falls back to PBKDF2 if Argon2 can't run here).");let v=this.app.secretStorage,E=l.createDiv({cls:"stashpad-export-remember"}),Q=E.createEl("input",{type:"checkbox"});Q.id="stashpad-export-remember-cb";let b=E.createEl("label",{text:"Remember in this vault (this device) \u2014 skips the prompt when you re-import here."});b.htmlFor=Q.id;let D=l.createDiv({cls:"stashpad-export-remember-note"});D.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."),D.setCssStyles({display:"none"}),Q.onchange=()=>{D.setCssStyles({display:Q.checked?"":"none"})},v||E.setCssStyles({display:"none"});let H=()=>{let K=t.value.trim()||this.defaultBaseName;return o.checked?`${K}-encrypted`:K},G=()=>i.setText(`Saves as: ${H()}-.stash`);t.oninput=G;let x=this.contentEl.createDiv({cls:"stashpad-export-footer"}),U=x.createEl("button",{text:"Cancel"});U.onclick=()=>this.close();let R=x.createEl("button",{cls:"mod-cta",text:"Export"}),M=()=>{let K=oo(h.value);u.style.visibility=h.value?"visible":"hidden",p.forEach((V,Y)=>V.toggleClass("is-on",h.value!==""&&Y<=K.level)),f.dataset.level=String(K.level),I.setText(K.label)},k=()=>{let K=o.checked;l.setCssStyles({display:K?"":"none"});let V=!0;K&&(h.value?h.value!==g.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)),M(),c.forEach(Y=>Y()),R.disabled=!V,R.toggleClass("is-disabled",!V),G()},P=!1,O=K=>{P=K,h.type=g.type=K?"text":"password",C.setText(K?"Hide":"Show")};C.onclick=K=>{K.preventDefault(),O(!P)},B.onclick=K=>{K.preventDefault(),h.value=g.value=no(),O(!1),new J.Notice("Passphrase generated (hidden) \u2014 Show to view, or Copy to save it."),k()},o.onchange=k,h.oninput=k,g.oninput=k,k();let L=()=>this.commit(H(),o.checked?h.value:null,o.checked&&Q.checked);R.onclick=L,this.scope.register([],"Enter",K=>{K.preventDefault(),R.disabled||L()}),requestAnimationFrame(()=>{t.focus(),t.select()})}commit(e,t,i){let s=e.trim()||this.defaultBaseName,n=t&&t.length?t:null;this.delivered=!0,this.close(),this.onConfirm(s,n,!!n&&i)}onClose(){this.contentEl.empty()}},Ui=class extends J.Modal{constructor(e,t,i,s){super(e);this.errorMsg=t;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 e=this.contentEl.createEl("input",{type:"password"});e.addClass("stashpad-export-name"),e.placeholder="Password";let t=this.contentEl.createDiv({cls:"stashpad-export-footer"});if(t.createEl("button",{text:"Cancel"}).onclick=()=>this.close(),this.allowLater){let s=t.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=t.createEl("button",{cls:"mod-cta",text:"Decrypt & import"});i.onclick=()=>this.submit(e.value),this.scope.register([],"Enter",s=>{s.preventDefault(),this.submit(e.value)}),requestAnimationFrame(()=>e.focus())}submit(e){e&&this.finish({kind:"password",value:e})}finish(e){this.delivered=!0,this.close(),this.onResult(e)}onClose(){this.delivered||(this.delivered=!0,this.onResult({kind:"cancel"})),this.contentEl.empty()}},Ne=class extends J.Modal{constructor(e,t){super(e);this.opts=t;this.succeeded=!1}onOpen(){let{mode:e}=this.opts;this.contentEl.empty(),this.modalEl.addClass("stashpad-export-modal","stashpad-encryption-modal"),this.titleEl.setText(this.opts.title??(e==="setup"?"Set up encryption password":e==="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}):e==="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 t=[],i=p=>{let I=this.contentEl.createDiv({cls:"stashpad-export-pw-row stashpad-encryption-row"}),m=I.createEl("input",{type:"password"});m.addClass("stashpad-export-name","stashpad-encryption-field"),m.placeholder=p;let B=I.createEl("button",{cls:"stashpad-export-copy"}),C=()=>{let w=m.value.length===0;B.setText(w?"Paste":"Copy"),B.toggleClass("is-paste",w),B.setAttr("aria-label",`${w?"Paste into":"Copy"} ${p.toLowerCase()}`)};return B.onclick=async w=>{if(w.preventDefault(),m.value.length===0)try{let y=(await navigator.clipboard?.readText())?.trim();if(!y){new J.Notice("Clipboard is empty.");return}m.value=y,m.dispatchEvent(new Event("input")),new J.Notice("Pasted from clipboard.")}catch{new J.Notice("Couldn't read the clipboard.")}else navigator.clipboard?.writeText(m.value).then(()=>new J.Notice("Copied to clipboard."),()=>new J.Notice("Couldn't access the clipboard."))},m.addEventListener("input",C),C(),t.push(C),m},s=null,n=null,o=null;if((e==="unlock"||e==="change")&&(s=i("Current password")),(e==="setup"||e==="change")&&(n=i(e==="change"?"New password":"Password"),o=i("Confirm password")),n){let p=this.contentEl.createDiv({cls:"stashpad-export-strength"}),I=p.createDiv({cls:"stashpad-strength-bar"}),m=[0,1,2,3].map(()=>I.createDiv({cls:"stashpad-strength-seg"})),B=p.createEl("span",{cls:"stashpad-strength-label"}),C=this.contentEl.createDiv({cls:"stashpad-encryption-counter"}),w=()=>{let Q=n.value,b=oo(Q);m.forEach((D,H)=>D.toggleClass("is-on",H0&&Q.length<6?" \u2014 use at least 6":""}`),C.toggleClass("is-weak",Q.length>0&&Q.length<6)};n.addEventListener("input",w),w();let y=this.contentEl.createDiv({cls:"stashpad-export-genrow"});y.createEl("button",{cls:"stashpad-export-gen",text:"Generate strong passphrase"}).onclick=Q=>{Q.preventDefault();let b=no(5);n.value=b,o&&(o.value=b),w(),t.forEach(D=>D()),new J.Notice("Generated \u2014 copy it somewhere safe; there's no recovery."),navigator.clipboard?.writeText(b).catch(()=>{})};let v=y.createEl("button",{cls:"stashpad-export-show",text:"Show"});v.onclick=Q=>{Q.preventDefault();let b=n.type==="password";n.type=b?"text":"password",o&&(o.type=b?"text":"password"),v.setText(b?"Hide":"Show")};let E=this.contentEl.createEl("div",{cls:"stashpad-export-pw-suite"});E.setText("Encryption: AES-256-GCM. Checking key-derivation suite\u2026"),this.opts.kdfProbe?this.opts.kdfProbe().then(Q=>{E.toggleClass("is-weak",!Q),E.setText(Q?"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(()=>E.setText("Encryption: AES-256-GCM with a password-derived key.")):E.setText("Encryption: Argon2id + AES-256-GCM (PBKDF2 fallback if Argon2 can't run here).")}let r=null,l=this.app.secretStorage;if(this.opts.offerKeychain&&l){let p=this.contentEl.createDiv({cls:"stashpad-export-remember"});r=p.createEl("input",{type:"checkbox"}),r.id="stashpad-enc-remember",r.checked=!0;let I=p.createEl("label",{text:"Remember on this device (keychain) \u2014 auto-unlock here without re-typing."});I.htmlFor=r.id;let m=this.contentEl.createDiv({cls:"stashpad-export-remember-note"});m.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."),m.setCssStyles({display:r.checked?"":"none"}),r.onchange=()=>{m.setCssStyles({display:r.checked?"":"none"})}}let c=this.contentEl.createEl("div",{cls:"stashpad-export-error"});c.setCssStyles({display:"none"});let A=p=>{c.setText(p),c.setCssStyles({display:""})},h=this.contentEl.createDiv({cls:"stashpad-export-footer"});h.createEl("button",{text:"Cancel"}).onclick=()=>this.close();let g=h.createEl("button",{cls:"mod-cta",text:e==="setup"?"Set up":e==="change"?"Change":"Unlock"}),u=!1,f=async()=>{if(u)return;let p=s?.value??void 0,I=n?.value??void 0;if((e==="unlock"||e==="change")&&!p){A("Enter your current password.");return}if(e==="setup"||e==="change"){if(!I){A("Enter a password.");return}if(I.length<6){A("Use at least 6 characters.");return}if(I!==o?.value){A("Passwords don't match.");return}}u=!0,g.disabled=!0,c.setCssStyles({display:"none"});let m=g.textContent;g.setText("Working\u2026");try{let B=await this.opts.onSubmit({current:p,next:I,remember:!!r?.checked});if(B){A(B),u=!1,g.disabled=!1,g.setText(m??"OK");return}this.succeeded=!0,this.close()}catch(B){A(`Failed: ${B.message}`),u=!1,g.disabled=!1,g.setText(m??"OK")}};g.onclick=()=>void f(),this.scope.register([],"Enter",p=>{p.preventDefault(),f()}),requestAnimationFrame(()=>(s??n)?.focus())}onClose(){this.contentEl.empty(),this.succeeded||this.opts.onCancel?.()}},ni=class extends J.Modal{constructor(e,t){super(e);this.opts=t}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 e=null;this.opts.requirePassword&&(this.contentEl.createEl("p",{cls:"stashpad-export-desc"}).setText("Enter your encryption password:"),e=this.contentEl.createEl("input",{type:"password"}),e.addClass("stashpad-export-name","stashpad-encryption-field"),e.placeholder="Password"),this.contentEl.createEl("p",{cls:"stashpad-export-desc"}).setText(`Type "${this.opts.phrase}" to confirm.`);let t=this.contentEl.createEl("input",{type:"text"});t.addClass("stashpad-export-name","stashpad-encryption-field"),t.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=()=>t.value.trim().toLowerCase()===this.opts.phrase.trim().toLowerCase(),r=()=>{n.disabled=!o()||!!this.opts.requirePassword&&!e?.value};t.addEventListener("input",r),e?.addEventListener("input",r),r();let l=!1,c=async()=>{if(!(l||!o())){if(this.opts.requirePassword&&(l=!0,n.disabled=!0,i.setCssStyles({display:"none"}),!await this.opts.requirePassword(e.value))){i.setText("Wrong password."),i.setCssStyles({display:""}),l=!1,r();return}this.close(),await this.opts.onConfirm()}};n.onclick=()=>void c(),this.scope.register([],"Enter",A=>{A.preventDefault(),c()}),requestAnimationFrame(()=>(e??t).focus())}onClose(){this.contentEl.empty()}},Gi=class extends J.Modal{constructor(e,t){super(e);this.onSubmit=t}onOpen(){this.contentEl.empty(),this.modalEl.addClass("stashpad-export-modal"),this.titleEl.setText("Open Stashpad link"),this.contentEl.createEl("p",{cls:"stashpad-export-desc",text:"Paste an obsidian://stashpad link to jump to the note it points to."});let e=this.contentEl.createDiv({cls:"stashpad-open-link-row"}),t=e.createEl("button",{cls:"stashpad-open-link-paste"});(0,J.setIcon)(t.createSpan({cls:"stashpad-open-link-paste-icon"}),"clipboard-paste"),t.createSpan({text:"Paste"}),t.title="Paste from clipboard";let i=e.createEl("input",{type:"text"});i.addClass("stashpad-export-name"),i.placeholder="obsidian://stashpad?folder=\u2026¬e=\u2026",t.onclick=async()=>{try{let r=(await navigator.clipboard?.readText?.())?.trim();r&&(i.value=r),i.focus()}catch{new J.Notice("Couldn't read the clipboard \u2014 paste manually.")}};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",text:"Open"}),o=()=>{let r=i.value.trim();r&&(this.close(),this.onSubmit(r))};n.onclick=()=>o(),this.scope.register([],"Enter",r=>{r.preventDefault(),o()}),requestAnimationFrame(()=>{i.focus(),navigator.clipboard?.readText?.().then(r=>{!i.value&&r&&/obsidian:\/\/stashpad\?/i.test(r.trim())&&(i.value=r.trim(),i.select())}).catch(()=>{})})}onClose(){this.contentEl.empty()}},ks=class extends J.Modal{constructor(e,t,i){super(e);this.onResult=i;this.delivered=!1;this.touched=!1;this.value=t&&/^#[0-9a-f]{6}$/i.test(t)?t:"#888888"}onOpen(){this.contentEl.empty(),this.titleEl.setText("Custom color"),this.modalEl.addClass("stashpad-custom-color-modal");let e=this.contentEl.createDiv({cls:"stashpad-custom-color-row"}),t=e.createDiv({cls:"stashpad-custom-color-preview"});t.style.background=this.value;let i=e.createEl("input",{type:"color"});i.value=this.value,i.addClass("stashpad-custom-color-wheel"),t.onclick=()=>i.click();let s=e.createEl("input",{type:"text"});s.addClass("stashpad-custom-color-hex"),s.placeholder="#RRGGBB",s.value=this.value,s.maxLength=7;let n=A=>{let h=A.startsWith("#")?A:"#"+A;/^#[0-9a-f]{6}$/i.test(h)&&(this.touched=!0,this.value=h,t.style.background=h,i.value=h,s.value!==h&&(s.value=h))};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 l=o.createEl("button",{cls:"mod-cta",text:"Save"});l.title="Apply this color to the selection (without adding to your palette).",l.onclick=()=>this.commit({addToPalette:!1});let c=o.createEl("button",{cls:"mod-cta",text:"Add to palette"});c.title="Apply and save this color so it appears as a tile next time.",c.onclick=()=>this.commit({addToPalette:!0}),this.scope.register([],"Enter",A=>{A.preventDefault(),this.commit({addToPalette:!1})}),this.scope.register(["Mod"],"Enter",A=>{A.preventDefault(),this.commit({addToPalette:!0})}),requestAnimationFrame(()=>s.focus())}commit(e){this.delivered=!0,this.close(),this.onResult(this.value,e)}onClose(){!this.delivered&&this.touched&&(this.delivered=!0,this.onResult(this.value,{addToPalette:!1})),this.contentEl.empty()}},Hi=class Hi extends J.Modal{constructor(e,t,i,s,n){super(e);this.currentColor=t;this.customPalette=i;this.onPick=s;this.onDeleteCustom=n;this.focusIdx=-1;this.scopeBound=!1;this.items=[]}onOpen(){this.contentEl.empty(),this.titleEl.setText("Pick a color"),this.modalEl.addClass("stashpad-color-modal");let e=this.contentEl.createDiv({cls:"stashpad-color-grid"});this.items=[];let t=e.createDiv({cls:"stashpad-color-tile stashpad-color-none"});t.title="No color",t.onclick=()=>this.activate(0),this.items.push({kind:"none",color:null,el:t});let i=[...Hi.DEFAULT_PALETTE,...this.customPalette];for(let r of i){let l=e.createDiv({cls:"stashpad-color-tile"});l.style.background=r,l.title=r;let c=!Hi.DEFAULT_PALETTE.some(h=>h.toLowerCase()===r.toLowerCase()),A=this.items.length;if(l.onclick=()=>this.activate(A),c&&this.onDeleteCustom){let h=l.createSpan({cls:"stashpad-color-tile-del",text:"\xD7"});h.title="Remove from palette",h.onclick=g=>{g.stopPropagation(),this.handleDelete(r)}}this.items.push({kind:c?"custom":"preset",color:r,el:l})}let s=e.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.scopeBound||(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)}),this.scopeBound=!0),requestAnimationFrame(()=>this.modalEl.focus())}activate(e){if(e<0||e>=this.items.length)return;this.focusIdx=e,this.refreshActive();let t=this.items[e];if(t.kind==="add"){this.close(),new ks(this.app,this.currentColor,(i,s)=>{this.onPick(i,s)}).open();return}this.close(),this.onPick(t.color,{addToPalette:!1})}columns(){if(!this.items.length)return 1;let e=this.items[0].el.parentElement;if(!e)return 1;let t=e.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(e){if(this.onDeleteCustom)try{let t=await this.onDeleteCustom(e);this.customPalette=Array.isArray(t)?t:this.customPalette.filter(i=>i.toLowerCase()!==e.toLowerCase()),this.onOpen()}catch(t){console.warn("Stashpad: palette delete failed",t)}}moveFocus(e){if(!this.items.length)return;let t=Math.max(0,Math.min(this.items.length-1,this.focusIdx+e));this.focusIdx=t,this.refreshActive()}refreshActive(){for(let e=0;e{this.didChoose=!0,this.close(),this.onChoose(!1)};let s=t.createEl("button",{cls:"mod-cta",text:this.confirmText});s.onclick=()=>{this.didChoose=!0,this.close(),this.onChoose(!0)},requestAnimationFrame(()=>(this.dangerous?i:s).focus())}onClose(){this.contentEl.empty(),this.didChoose||(this.didChoose=!0,this.onChoose(!1))}},Li=class extends J.Modal{constructor(e,t,i,s={}){super(e);this.levels=t;this.onPick=i;this.opts=s}onOpen(){this.modalEl?.addClass("stashpad-compact-modal"),this.modalEl?.addClass("stashpad-breadcrumb-modal"),this.contentEl.empty(),this.titleEl.setText("Jump to level");let e=this.contentEl.createDiv({cls:"stashpad-bc-levels"});for(let t of this.levels){let i=e.createDiv({cls:"stashpad-bc-level-row"});if(t.isCurrent&&i.addClass("is-current"),i.createSpan({cls:"stashpad-bc-level-num",text:String(t.level)}),i.createSpan({cls:"stashpad-bc-level-label",text:t.label}),!t.isCurrent){i.setAttribute("role","button"),i.setAttribute("tabindex","0");let s=()=>{this.close(),this.onPick(t.id)};i.onclick=s,i.onkeydown=n=>{(n.key==="Enter"||n.key===" ")&&(n.preventDefault(),s())}}this.opts.onContext&&(i.oncontextmenu=s=>{s.preventDefault(),this.opts.onContext(t.id,s,i,()=>this.close())},this.opts.attachLongPress?.(i,()=>this.opts.onContext(t.id,null,i,()=>this.close())))}}onClose(){this.contentEl.empty()}};Ue=class extends J.Modal{constructor(e,t,i,s={}){super(e);this.current=t;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 e=null;if(this.current){let E=Date.parse(this.current);Number.isNaN(E)||(e=new Date(E))}let t=this.contentEl.createDiv({cls:"stashpad-due-picker"}),i=t.createDiv({cls:"stashpad-due-fields"}),s=i.createDiv({cls:"stashpad-due-field"}),n=s.createSpan({cls:"stashpad-due-field-icon"});(0,J.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,J.setIcon)(r,"x"),r.onclick=()=>{o.value="",o.focus()};let l=i.createDiv({cls:"stashpad-due-field"}),c=l.createSpan({cls:"stashpad-due-field-icon"});(0,J.setIcon)(c,"clock");let A=l.createEl("input",{type:"time",cls:"stashpad-due-time"}),h=l.createSpan({cls:"stashpad-due-clear",attr:{"aria-label":"Clear time"}});(0,J.setIcon)(h,"x"),h.onclick=()=>{A.value="",A.focus()},n.onclick=()=>{try{o.showPicker?.()}catch{}},c.onclick=()=>this.openTimeNumpad(c,A),e&&(o.value=this.toDateValue(e),A.value=this.toTimeValue(e));let g=(this.opts.quickAdjusts??[]).map(E=>({raw:E,min:Rr(E)})).filter(E=>E.min!=null);if(g.length>0){let E=1,Q=t.createDiv({cls:"stashpad-due-quickadjust"}),b=Q.createEl("button",{cls:"stashpad-due-adjust-flip",attr:{type:"button"}}),D=()=>{b.setText(E>0?"+":"\u2212"),b.toggleClass("is-minus",E<0),b.title=E>0?"Adding time (click to subtract)":"Subtracting time (click to add)"};D(),b.onclick=()=>{E=-E,D()};let H=G=>{let x=new Date,U,R,M;if(o.value){let[L,K,V]=o.value.split("-").map(Y=>parseInt(Y,10));U=L,R=K-1,M=V}else U=x.getFullYear(),R=x.getMonth(),M=x.getDate();let k,P;if(A.value){let[L,K]=A.value.split(":").map(V=>parseInt(V,10));k=L,P=K}else k=x.getHours(),P=x.getMinutes();let O=new Date(U,R,M,k,P,0,0);O.setMinutes(O.getMinutes()+E*G),o.value=this.toDateValue(O),A.value=this.toTimeValue(O)};for(let G of g){let x=Q.createEl("button",{cls:"stashpad-due-adjust-btn",text:G.raw,attr:{type:"button"}});x.onclick=()=>H(G.min)}}this.opts.hideAssignees||this.renderAssignSection(t);let u=t.createDiv({cls:"stashpad-due-grid"}),f=(E,Q)=>{let b=u.createEl("button",{cls:"stashpad-due-btn stashpad-due-preset",text:E});b.onclick=()=>{let D=Q();o.value=this.toDateValue(D),A.value||(A.value=this.toTimeValue(D))}},p=E=>(E.setHours(9,0,0,0),E);f("Today",()=>p(this.startOfTodayLocal())),f("Tomorrow",()=>{let E=this.startOfTodayLocal();return E.setDate(E.getDate()+1),p(E)}),f("Next week",()=>{let E=this.startOfTodayLocal();return E.setDate(E.getDate()+7),p(E)});let I=u.createEl("button",{cls:"stashpad-due-btn",text:"Clear"});I.onclick=()=>{o.value="",A.value="",o.focus()};let m=null,B=null,C=null;if(this.opts.showRecurrence){let E=t.createEl("details",{cls:"stashpad-due-recur"});(this.opts.currentRepeat||this.opts.currentAutoDoneAfter||this.opts.currentRemindEvery)&&(E.open=!0),E.createEl("summary",{text:"\u{1F501} Repeat & reminders"});let Q=(b,D,H)=>{let G=E.createDiv({cls:"stashpad-due-recur-row"});G.createEl("label",{text:b});let x=G.createEl("input",{type:"text",attr:{placeholder:D}});return H&&(x.value=H),x};m=Q("Repeat",'e.g. "every weekday", "every 30 days when done"',this.opts.currentRepeat),B=Q("Auto-complete after",'e.g. "1d" \u2014 mark done once this overdue',this.opts.currentAutoDoneAfter),C=Q("Remind every",'e.g. "2h" \u2014 re-notify until done',this.opts.currentRemindEvery)}let w=()=>this.opts.showRecurrence?{repeat:m.value.trim(),autoDoneAfter:B.value.trim(),remindEvery:C.value.trim()}:{},y=u.createEl("button",{cls:"stashpad-due-btn",text:"Cancel"});y.onclick=()=>{this.didChoose=!0,this.close()};let v=u.createEl("button",{cls:"stashpad-due-btn mod-cta",text:"Set"});v.onclick=()=>{if(!o.value){this.didChoose=!0,this.close(),this.onPick({iso:null,assignees:this.assignees,...w()});return}let[E,Q,b]=o.value.split("-").map(x=>parseInt(x,10)),D=9,H=0;if(A.value){let[x,U]=A.value.split(":").map(R=>parseInt(R,10));D=x,H=U}let G=new Date(E,Q-1,b,D,H,0,0);this.didChoose=!0,this.close(),this.onPick({iso:G.toISOString(),assignees:this.assignees,...w()})},requestAnimationFrame(()=>o.focus())}onClose(){this.tinyClosePopover?.(),this.contentEl.empty(),this.didChoose}renderAssignSection(e){Ur(e,{knownAuthors:this.opts.knownAuthors??[],initial:this.assignees,onChange:t=>{this.assignees=t}})}openTimeNumpad(e,t){this.tinyClosePopover?.();let i=e.ownerDocument??document,s=i.defaultView??window,n=9,o=0;if(t.value){let[I,m]=t.value.split(":").map(B=>parseInt(B,10));Number.isFinite(I)&&(n=I),Number.isFinite(m)&&(o=m)}else{let I=new Date;n=I.getHours(),o=I.getMinutes()}let r=n>=12?"pm":"am",l=n===0?12:n>12?n-12:n,A=(this.modalEl??i.body).createDiv({cls:"stashpad-when-popover stashpad-due-time-pop"});A.setCssStyles({position:"fixed",zIndex:"9999"});let h=null,g=()=>{A.remove(),i.removeEventListener("mousedown",u,!0),i.removeEventListener("keydown",f,!0),this.tinyClosePopover===g&&(this.tinyClosePopover=null)},u=I=>{!A.contains(I.target)&&I.target!==e&&!e.contains(I.target)&&g()},f=I=>{I.key==="Escape"?(I.preventDefault(),I.stopPropagation(),g()):I.key==="Enter"&&h&&(I.preventDefault(),I.stopPropagation(),h())};this.tinyClosePopover=g,vs(A,{seedH:l,seedM:o,seedPeriod:r,close:g,setOnEnter:I=>{h=I},onFinalize:I=>{t.value=`${String(I.hours24).padStart(2,"0")}:${String(I.minutes).padStart(2,"0")}`}});let p=e.getBoundingClientRect();A.setCssStyles({left:`${Math.max(8,Math.min(p.left,s.innerWidth-220))}px`,top:`${p.bottom+4}px`}),setTimeout(()=>{i.addEventListener("mousedown",u,!0),i.addEventListener("keydown",f,!0),A.querySelector(".stashpad-when-time-field")?.focus()},0)}startOfTodayLocal(){let e=new Date;return e.setHours(0,0,0,0),e}toDateValue(e){let t=e.getFullYear(),i=String(e.getMonth()+1).padStart(2,"0"),s=String(e.getDate()).padStart(2,"0");return`${t}-${i}-${s}`}toTimeValue(e){let t=String(e.getHours()).padStart(2,"0"),i=String(e.getMinutes()).padStart(2,"0");return`${t}:${i}`}},Ut=class Ut extends J.Modal{constructor(e,t,i,s=null,n){super(e);this.service=t;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 e=this.contentEl.createDiv({cls:"stashpad-log-toolbar"});if(this.countEl=e.createSpan({cls:"stashpad-log-count"}),this.updateCount(),this.filterSelEl=e.createEl("select",{cls:"stashpad-log-type-filter"}),this.filterSelEl.onchange=()=>this.setCategoryFilter(this.filterSelEl.value||null),this.refreshCategoryFilter(),this.authorSelEl=e.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=e.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 t=e.createEl("button",{cls:"mod-warning",text:"Clear history"});t.onclick=()=>{new _(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()},"Cancel",!0).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(e){this.authorFilter!==e&&(this.authorFilter=e,this.refreshList(),this.renderFooter())}refreshAuthorFilter(){if(!this.authorSelEl)return;let e=this.authorSelEl;e.empty(),e.createEl("option",{text:"All authors"}).value="all",this.currentAuthorId&&(e.createEl("option",{text:"Me"}).value="me"),e.createEl("option",{text:"Cross-author"}).value="cross";let t=new Set;for(let s of this.records)s.authorId&&s.authorId!==this.currentAuthorId&&t.add(s.authorId);if(t.size>0){let s=e.createEl("option",{text:"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"});s.disabled=!0;for(let n of[...t].sort())e.createEl("option",{text:n}).value=n}new Set(["all","cross",...this.currentAuthorId?["me"]:[],...t]).has(this.authorFilter)||(this.authorFilter="all"),e.value=this.authorFilter}isCrossAuthor(e){let t=e.authorId??null;if(!t)return!1;for(let i of e.affectedAuthorIds??[])if(i&&i!==t)return!0;if(!this.getNoteAuthorIds)return!1;for(let i of e.affectedIds){let s=this.getNoteAuthorIds(i);for(let n of s)if(n&&n!==t)return!0}return!1}onClose(){this.unsubscribe?.(),this.unsubscribe=null,this.contentEl.empty()}setCategoryFilter(e){(this.categoryFilter??null)!==(e??null)&&(this.categoryFilter=e,this.refreshList(),this.renderFooter())}refreshCategoryFilter(){if(!this.filterSelEl)return;let e=this.filterSelEl;e.empty();let t=new Map;for(let n of this.records)t.set(n.category,(t.get(n.category)??0)+1);let i=[...t.entries()].sort((n,o)=>o[1]-n[1]||n[0].localeCompare(o[0])),s=e.createEl("option",{text:`All categories (${this.records.length})`});s.value="";for(let[n,o]of i){let r=e.createEl("option",{text:`${n} (${o})`});r.value=n}this.categoryFilter&&!t.has(this.categoryFilter)&&(this.categoryFilter=null),e.value=this.categoryFilter??""}refreshList(){if(this.listEl){if(this.visible=this.records.filter(e=>{if(this.categoryFilter&&e.category!==this.categoryFilter)return!1;switch(this.authorFilter){case"all":return!0;case"me":return!!this.currentAuthorId&&e.authorId===this.currentAuthorId;case"cross":return this.isCrossAuthor(e);default:return e.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(Ut.PAGE)}}appendMore(e){if(!this.listEl)return;let t=Math.min(this.visible.length,this.shownCount+e);for(let i=this.shownCount;i0){let c=i.createDiv({cls:"stashpad-notif-actions-snapshot"});for(let A of t.actionLabels){let h=c.createSpan({cls:"stashpad-notif-action-chip"});h.setText(A),h.title="Action button was shown on the original toast (handler not retained)."}}}updateCount(){if(!this.countEl)return;let e=this.visible.length,t=this.categoryFilter?`${e} ${this.categoryFilter} notification${e===1?"":"s"}`:`${e} notification${e===1?"":"s"}`;this.shownCount===0||this.shownCount>=e?this.countEl.setText(t):this.countEl.setText(`Showing ${this.shownCount} of ${t}`)}renderFooter(){if(!this.footerEl)return;this.footerEl.empty();let e=this.visible.length-this.shownCount;if(e<=0)return;let t=this.footerEl.createEl("button",{text:`Load ${Math.min(Ut.PAGE,e)} more`});if(t.onclick=()=>{this.appendMore(Ut.PAGE),this.renderFooter()},e>Ut.PAGE){let i=this.footerEl.createEl("button",{text:`Load all (${e})`});i.onclick=()=>{this.appendMore(e),this.renderFooter()}}}};Ut.PAGE=100;Oi=Ut,ro=class extends J.Modal{constructor(e,t){super(e);this.entries=t}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 e=this.contentEl.createDiv({cls:"stashpad-import-log-list"});for(let t of this.entries){let i=e.createDiv({cls:"stashpad-import-log-row"}),s=(0,J.moment)(t.ts).format("YYYY-MM-DD HH:mm");i.createSpan({cls:"stashpad-import-log-when",text:s});let n=t.kind==="folder"?"folder":t.kind==="md"?"note":"file";i.createSpan({cls:`stashpad-import-log-kind is-${t.kind}`,text:n}),i.createSpan({cls:"stashpad-import-log-name",text:t.originalName});let o=[t.folder.split("/").pop()||t.folder];t.notePaths.length>1&&o.push(`${t.notePaths.length} notes`),i.createSpan({cls:"stashpad-import-log-meta",text:o.join(" \xB7 ")})}}onClose(){this.contentEl.empty()}},Ki=class extends J.Modal{constructor(e,t,i){super(e);this.message=t;this.onChoose=i;this.chose=!1}onOpen(){this.modalEl?.addClass("stashpad-compact-modal"),this.contentEl.empty(),this.titleEl.setText("Possible duplicate import");let e=this.contentEl.createDiv({cls:"stashpad-confirm-body"});for(let o of this.message.split(` -`))e.createDiv({cls:"stashpad-confirm-line",text:o});let t=this.contentEl.createDiv({cls:"stashpad-modal-btns"}),i=t.createEl("button",{text:"Skip duplicates"});i.onclick=()=>{this.chose=!0,this.close(),this.onChoose("skip")};let s=t.createEl("button",{text:"Replace existing"});s.onclick=()=>{this.chose=!0,this.close(),this.onChoose("replace")};let n=t.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()}},Ji=class extends J.Modal{constructor(e,t,i,s){super(e);this.noteCount=i;this.onConfirm=s;this.base=t}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 e=this.contentEl.createEl("input",{type:"text"});e.addClass("stashpad-export-name"),e.value=this.base,e.placeholder="Export name";let t=(l,c)=>{let A=this.contentEl.createDiv({cls:"stashpad-okf-fmt"}),h=A.createEl("input",{type:"checkbox"});return h.checked=c,A.createEl("label",{text:l}),h},i=t(".zip \u2014 OKF bundle (portable)",!0),s=t(".tar.gz \u2014 OKF bundle (tarball)",!1),n=t(".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 J.Notice("Pick at least one format.");return}this.close(),this.onConfirm(e.value.trim()||this.base,{zip:i.checked,targz:s.checked,stash:n.checked})},requestAnimationFrame(()=>e.focus())}onClose(){this.contentEl.empty()}},qi=class extends J.Modal{constructor(e,t,i){super(e);this.items=t;this.onConfirm=i}onOpen(){this.titleEl.setText("Re-encrypt everything applicable?");let{contentEl:e}=this;e.createEl("p",{cls:"setting-item-description",text:"These notes should be encrypted (they were unlocked/restored, or their folder is set to encrypt) but are currently plaintext. Untick anything you want to leave readable."});let t=e.createDiv({cls:"stashpad-reenc-list"}),i=[];this.items.forEach(o=>{let r=t.createEl("label",{cls:"stashpad-reenc-row"}),l=r.createEl("input",{type:"checkbox"});l.checked=!0,i.push(l);let c=r.createDiv({cls:"stashpad-reenc-body"});c.createDiv({cls:"stashpad-reenc-label",text:o.label}),c.createDiv({cls:"stashpad-reenc-detail",text:o.detail})});let s=e.createDiv({cls:"modal-button-container"}),n=s.createEl("button",{cls:"mod-cta",text:"Re-encrypt checked"});n.onclick=()=>{let o=i.map((r,l)=>r.checked?l:-1).filter(r=>r>=0);this.close(),o.length&&this.onConfirm(o)},s.createEl("button",{text:"Cancel"}).onclick=()=>this.close()}onClose(){this.contentEl.empty()}}});function Se(d,a=Ze){let e=a instanceof Set?a:new Set(a.map(o=>o.toLowerCase())),t=(d.split(/\r?\n/).find(o=>o.trim().length>0)??"").trim();if(!t)return"Untitled";let s=t.replace(/['‘-‛ʼ]/g,"").replace(/[^A-Za-z0-9\s]+/g," ").split(/\s+/).filter(o=>o&&!e.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 be(d,a){return`${d}-${a}.md`}function lt(d){let a=d.match(/-([abcdefghijkmnpqrstuvwxyz23456789]{6})$/);return a?a[1]:null}function Ns(d){return typeof d=="string"&&/^[abcdefghijkmnpqrstuvwxyz23456789]{6}$/.test(d)}function Ms(d,a){let e=d.lastIndexOf(".");return e>0?`${d.slice(0,e)}-${a}${d.slice(e)}`:`${d}-${a}`}function Lr(d){let a=d.match(/^([0-9a-z]{7,9})-(.+)$/);if(!a)return null;let e=parseInt(a[1],36);return!Number.isFinite(e)||e<142e10||e>Date.now()+864e5?null:{stamp:a[1],rest:a[2]}}var Ze,ri=qe(()=>{"use strict";Ze=["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 Hs={};ki(Hs,{JdBuildConfirmModal:()=>Vi,buildJdIndexNotes:()=>Ao,buildJdIndexPreview:()=>Ts,buildJdPreviewNotice:()=>Ps,scanForJdNotes:()=>ai});function co(d,a){if(/^\d+-\d+$/.test(d))return null;if(d.includes(".")){let t=d.split(".").slice(0,-1).join(".");return a.has(t)?t:co(t,a)}if(/^\d+$/.test(d)){let e=parseInt(d,10);for(let t of a){let i=t.match(/^(\d+)-(\d+)$/);if(!i)continue;let s=parseInt(i[1],10),n=parseInt(i[2],10);if(e>=s&&e<=n)return t}return null}return null}function ai(d,a,e){let t=d.vault.getMarkdownFiles(),i=ql(t,e),s=e.jdIndexIncludeStashpadFolders===!0,n=s?new Set:new Set(a.discoverStashpadFolders()),o=u=>s?!1:Array.from(n).some(f=>u===f||u.startsWith(f+"/")),r=[],l=[],c=[];for(let u of i){let f=u.parent?.path?.replace(/\/+$/,"")??"";if(o(f)){c.push(u);continue}let p=u.basename.match(Or);p?r.push({prefix:p[1],segments:p[1].split("."),title:p[2],file:u,folder:null}):l.push(u)}let A=(e.jdIndexScope??"vault")==="folder"?(e.jdIndexScopeFolder??"").trim().replace(/^\/+|\/+$/g,""):"",h=u=>{let f=u.path.replace(/\/+$/,"");if(!(A&&f&&f!==A&&!f.startsWith(A+"/"))){if(f&&!o(f)){let p=u.name.match(Or);p&&r.push({prefix:p[1],segments:p[1].split("."),title:p[2],file:null,folder:u})}}for(let p of u.children)p instanceof Ie.TFolder&&h(p)};h(d.vault.getRoot());let g=e.jdIndexSort??"natural";return r.sort((u,f)=>$l(u,f,g)),{indexed:r,nonIndex:l,skippedStashpadNotes:c}}async function Ts(d,a,e){let t=ho(e.jdIndexStashpadFolder??"");if(!t)return{...ai(d,a,e),previewPath:null,error:"no-dest"};let i=ai(d,a,e),s=Jl(d,t);if(!s)return{...i,previewPath:null,error:"no-home"};let n=Yl(i.indexed,i.nonIndex,i.skippedStashpadNotes),r=(await d.vault.read(s)).match(/^---\r?\n[\s\S]*?\r?\n---\r?\n/),l=r?`${r[0]}${n}`:n;return await d.vault.modify(s,l),{...i,previewPath:s.path}}function Jl(d,a){let e=d.vault.getAbstractFileByPath(a);if(!(e instanceof Ie.TFolder))return null;for(let t of e.children){if(!(t instanceof Ie.TFile)||t.extension!=="md")continue;if((d.metadataCache.getFileCache(t)?.frontmatter??{}).id===S)return t}return null}async function Ao(d,a,e){let t=ho(e.jdIndexStashpadFolder??"");if(!t)return{created:0,updated:0,skipped:0,destFolder:"",error:"no-dest"};if(!new Set(a.discoverStashpadFolders()).has(t))return{created:0,updated:0,skipped:0,destFolder:t,error:"dest-not-stashpad"};let s=ai(d,a,e),n=new Map;for(let I of s.indexed)n.set(I.prefix,I);for(let I of s.indexed)if(I.prefix.includes("."))for(let m=1;m{l.push(I);for(let m of r.get(I)??[])c(m)};for(let I of o)c(I);let A=new Map,h=d.vault.getAbstractFileByPath(t);if(h instanceof Ie.TFolder)for(let I of h.children){if(!(I instanceof Ie.TFile)||I.extension!=="md")continue;let m=d.metadataCache.getFileCache(I)?.frontmatter??{};typeof m.jdPrefix=="string"&&A.set(m.jdPrefix,I)}let g=new Map,u=0,f=0,p=0;for(let I of l){let m=n.get(I)??null,B=co(I,new Set(n.keys())),C=B?g.get(B)??S:S,w=m?`${I} ${m.title}`:I,y=m?.file?`[[${m.file.basename}]]`:"",v=y?`${y} -`:`${w} -`,E=A.get(I);if(E){try{let Q=null;await d.fileManager.processFrontMatter(E,G=>{G.jdPrefix=I,C&&(G.parent=C),(!G.id||typeof G.id!="string")&&(G.id=a.mintNoteId()),G.created||(G.created=new Date().toISOString()),G.attachments||(G.attachments=[]),Q=G.id});let D=(await d.vault.read(E)).match(/^---\r?\n[\s\S]*?\r?\n---\r?\n/),H=D?`${D[0]}${v}`:v;await d.vault.modify(E,H),Q&&g.set(I,Q),f++}catch(Q){console.error("[stashpad] buildJdIndexNotes: update failed",Q),p++}continue}try{let Q=a.mintNoteId();g.set(I,Q);let b=Se(w,e.slugStopWords),D=be(b,Q),H=`${t}/${D}`,G=["---",`id: ${Q}`,`parent: ${C}`,`created: "${new Date().toISOString()}"`,"attachments: []",`jdPrefix: "${I}"`,"---",""].join(` -`);await d.vault.create(H,G+v),u++}catch(Q){console.error("[stashpad] buildJdIndexNotes: create failed for",I,Q),p++}}return{created:u,updated:f,skipped:p,destFolder:t}}function ho(d){return(d||"").trim().replace(/^\/+|\/+$/g,"")}function ql(d,a){if((a.jdIndexScope??"vault")==="vault")return d;let e=ho(a.jdIndexScopeFolder??"");return e?d.filter(t=>{let i=t.parent?.path?.replace(/\/+$/,"")??"";return i===e||i.startsWith(e+"/")}):d}function $l(d,a,e){if(e==="created"){let t=d.file?.stat?.ctime??0,i=a.file?.stat?.ctime??0;if(t!==i)return t-i}return Jr(d.segments,a.segments)}function Kr(d,a){let e=d.match(/^(\d+)-(\d+)$/),t=a.match(/^(\d+)-(\d+)$/),i=e?[e[1]]:d.split("."),s=t?[t[1]]:a.split(".");return Jr(i,s)}function Jr(d,a){let e=Math.min(d.length,a.length);for(let t=0;t{s.set(o,r);for(let l of t.get(o)??[])n(l,r+1)};for(let o of i)n(o,0);return{roots:i,childrenOf:t,depthOf:s}}function Yl(d,a,e){let t=[],i=s=>"#".repeat(Math.min(s+1,6));if(t.push("# Indexed"),t.push(""),d.length===0){let s=e.length>0?`_No notes matched. ${e.length} note${e.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._";t.push(s)}else{let s=new Map;for(let c of d)s.set(c.prefix,c);for(let c of d)if(c.prefix.includes("."))for(let A=1;A{let A=s.get(c),h=r.get(c)??0,g=" ".repeat(h),u=i(h),f=A?.folder?` ${A.title} _(folder)_`:(A?.file,"");A?.file?t.push(`${g}- ${u} [[${A.file.basename}|${A.prefix} ${A.title}]]`):A?.folder?t.push(`${g}- ${u} ${A.prefix}${f}`):t.push(`${g}- ${u} ${c}`);for(let p of o.get(c)??[])l(p)};for(let c of n)l(c)}if(a.length>0){t.push(""),t.push(`# Non-indexed (${a.length})`),t.push(""),t.push("_These notes don't match the JD-prefix convention. Rename them to ` ` and re-run to include them._"),t.push("");for(let s of a)t.push(`- # [[${s.basename}]] \xB7 \`${s.path}\``)}if(e.length>0){let s=new Map;for(let o of e){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]));t.push(""),t.push(`# Excluded folders (${n.length})`),t.push(""),t.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._`),t.push("");for(let[o,r]of n)t.push(`- # All ${r} file${r===1?"":"s"} in \`${o||"(vault root)"}\``)}return t.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",e=>{this.lines.length<2||(e.preventDefault(),this.mode=this.mode==="line"?"cursor":"line",this.render())}),this.scope.register([],"Enter",e=>{this.mode==="line"&&(e.preventDefault(),this.commitLine())}),this.scope.register(["Mod"],"Enter",e=>{this.mode==="cursor"&&(e.preventDefault(),this.commitCursor())}),this.scope.register([],"ArrowUp",e=>{this.mode==="line"&&(e.preventDefault(),this.lineCursorIdx=Math.max(1,this.lineCursorIdx-1),this.render())}),this.scope.register([],"ArrowDown",e=>{this.mode==="line"&&(e.preventDefault(),this.lineCursorIdx=Math.min(this.lines.length-1,this.lineCursorIdx+1),this.render())})}commitLine(){let e=this.lineCursorIdx;this.close(),this.onSplitAtLine(e)}commitCursor(){let e=this.cursorTextarea;if(!e)return;let t=e.selectionStart;if(t<=0||t>=e.value.length){new J.Notice("Move the cursor inside the text \u2014 neither end can be empty.");return}this.close(),this.onSplitAtChar(t)}render(){this.contentEl.empty();let e=this.contentEl.createDiv({cls:"stashpad-split-quick"});e.createSpan({cls:"stashpad-split-quick-label",text:"Split by:"}),["lines","paragraphs","headings"].forEach(o=>{let r=Ti(this.body,o),l=e.createEl("button",{cls:"stashpad-split-quick-btn",text:`${ei[o]} (${r.length})`});l.disabled=r.length<2,l.onmousedown=c=>c.preventDefault(),l.onclick=()=>{let c=Ti(this.body,o);if(c.length<2){new J.Notice("That delimiter wouldn't split this note.");return}this.close(),this.onSplitMany(c)}});let t=this.contentEl.createDiv({cls:"stashpad-split-toggle-bar"});if(this.lines.length>=2){let o=t.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=t.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=t.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"});J.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 e=this.contentEl.createDiv({cls:"stashpad-split-list"}),t=null;for(let i=0;i<this.lines.length;i++){i===this.lineCursorIdx&&(t=e.createDiv({cls:"stashpad-split-divider",text:"\u2500\u2500 split here \u2500\u2500"}));let s=e.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())}}t&&window.requestAnimationFrame(()=>t.scrollIntoView({block:"center"}))}renderCursorMode(){let t=this.contentEl.createDiv({cls:"stashpad-split-cursor-wrap"}).createEl("textarea",{cls:"stashpad-split-cursor-ta"});t.value=this.body,t.readOnly=!1,this.cursorTextarea=t;let i=parseFloat(getComputedStyle(t).lineHeight)||22,s=J.Platform.isMobile?3:12,n=2,o=()=>{t.setCssStyles({height:"auto"});let r=Math.min(t.scrollHeight,i*s+16);t.setCssStyles({height:`${Math.max(r,i*n+16)}px`})};requestAnimationFrame(()=>{o();let r=Math.floor(t.value.length/2);t.focus(),t.setSelectionRange(r,r)}),t.addEventListener("input",o)}onClose(){this.cursorTextarea=null,this.contentEl.empty()}},ni=class extends J.Modal{constructor(e,t,i,s,n){super(e);this.defaultBaseName=t;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 e=this.contentEl.createDiv({cls:"stashpad-export-field"});e.createEl("label",{cls:"stashpad-export-label",text:"File name"});let t=e.createEl("input",{type:"text"});t.addClass("stashpad-export-name"),t.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 l=s.createDiv({cls:"stashpad-export-pw-area"});l.setCssStyles({display:"none"});let c=[],A=K=>{let V=l.createDiv({cls:"stashpad-export-pw-row"}),Y=V.createEl("input",{type:"password"});Y.addClass("stashpad-export-name"),Y.placeholder=K;let $=V.createEl("button",{cls:"stashpad-export-copy"}),j=()=>{let ce=Y.value.length===0;$.setText(ce?"Paste":"Copy"),$.toggleClass("is-paste",ce),$.setAttr("aria-label",`${ce?"Paste into":"Copy"} ${K.toLowerCase()}`)};return $.onclick=async ce=>{if(ce.preventDefault(),Y.value.length===0)try{let re=(await navigator.clipboard?.readText())?.trim();if(!re){new J.Notice("Clipboard is empty.");return}Y.value=re,Y.dispatchEvent(new Event("input")),new J.Notice("Pasted from clipboard.")}catch{new J.Notice("Couldn't read the clipboard.")}else navigator.clipboard?.writeText(Y.value).then(()=>new J.Notice("Passphrase copied to clipboard."),()=>new J.Notice("Couldn't access the clipboard."))},j(),c.push(j),Y},h=A("Password"),p=A("Confirm password"),u=l.createDiv({cls:"stashpad-export-strength"}),f=u.createDiv({cls:"stashpad-strength-bar"}),g=[0,1,2,3].map(()=>f.createDiv({cls:"stashpad-strength-seg"})),I=u.createEl("span",{cls:"stashpad-strength-label"}),m=l.createDiv({cls:"stashpad-export-genrow"}),B=m.createEl("button",{cls:"stashpad-export-gen",text:"Generate strong passphrase"}),C=m.createEl("button",{cls:"stashpad-export-show",text:"Show"}),Q=l.createEl("div",{cls:"stashpad-export-pw-hint"}),y=l.createEl("div",{cls:"stashpad-export-pw-suite"});y.setText("Encryption: AES-256-GCM. Checking key-derivation suite for this device\u2026"),this.kdfProbe?this.kdfProbe().then(K=>{y.toggleClass("is-weak",!K),y.setText(K?"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(()=>{y.setText("Encryption: AES-256-GCM with a password-derived key.")}):y.setText("Encryption: Argon2id + AES-256-GCM (falls back to PBKDF2 if Argon2 can't run here).");let E=this.app.secretStorage,w=l.createDiv({cls:"stashpad-export-remember"}),v=w.createEl("input",{type:"checkbox"});v.id="stashpad-export-remember-cb";let F=w.createEl("label",{text:"Remember in this vault (this device) \u2014 skips the prompt when you re-import here."});F.htmlFor=v.id;let D=l.createDiv({cls:"stashpad-export-remember-note"});D.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."),D.setCssStyles({display:"none"}),v.onchange=()=>{D.setCssStyles({display:v.checked?"":"none"})},E||w.setCssStyles({display:"none"});let R=()=>{let K=t.value.trim()||this.defaultBaseName;return o.checked?`${K}-encrypted`:K},G=()=>i.setText(`Saves as: ${R()}-<timestamp>.stash`);t.oninput=G;let x=this.contentEl.createDiv({cls:"stashpad-export-footer"}),H=x.createEl("button",{text:"Cancel"});H.onclick=()=>this.close();let U=x.createEl("button",{cls:"mod-cta",text:"Export"}),N=()=>{let K=lo(h.value);u.style.visibility=h.value?"visible":"hidden",g.forEach((V,Y)=>V.toggleClass("is-on",h.value!==""&&Y<=K.level)),f.dataset.level=String(K.level),I.setText(K.label)},S=()=>{let K=o.checked;l.setCssStyles({display:K?"":"none"});let V=!0;K&&(h.value?h.value!==p.value?(Q.setText("Passwords don't match."),Q.addClass("is-error"),V=!1):(Q.setText("\u26A0\uFE0F If you lose this password, the export can't be recovered."),Q.removeClass("is-error")):(Q.setText("Enter a password to encrypt this export."),Q.removeClass("is-error"),V=!1)),N(),c.forEach(Y=>Y()),U.disabled=!V,U.toggleClass("is-disabled",!V),G()},P=!1,O=K=>{P=K,h.type=p.type=K?"text":"password",C.setText(K?"Hide":"Show")};C.onclick=K=>{K.preventDefault(),O(!P)},B.onclick=K=>{K.preventDefault(),h.value=p.value=ao(),O(!1),new J.Notice("Passphrase generated (hidden) \u2014 Show to view, or Copy to save it."),S()},o.onchange=S,h.oninput=S,p.oninput=S,S();let L=()=>this.commit(R(),o.checked?h.value:null,o.checked&&v.checked);U.onclick=L,this.scope.register([],"Enter",K=>{K.preventDefault(),U.disabled||L()}),requestAnimationFrame(()=>{t.focus(),t.select()})}commit(e,t,i){let s=e.trim()||this.defaultBaseName,n=t&&t.length?t:null;this.delivered=!0,this.close(),this.onConfirm(s,n,!!n&&i)}onClose(){this.contentEl.empty()}},Gi=class extends J.Modal{constructor(e,t,i,s){super(e);this.errorMsg=t;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 e=this.contentEl.createEl("input",{type:"password"});e.addClass("stashpad-export-name"),e.placeholder="Password";let t=this.contentEl.createDiv({cls:"stashpad-export-footer"});if(t.createEl("button",{text:"Cancel"}).onclick=()=>this.close(),this.allowLater){let s=t.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=t.createEl("button",{cls:"mod-cta",text:"Decrypt & import"});i.onclick=()=>this.submit(e.value),this.scope.register([],"Enter",s=>{s.preventDefault(),this.submit(e.value)}),requestAnimationFrame(()=>e.focus())}submit(e){e&&this.finish({kind:"password",value:e})}finish(e){this.delivered=!0,this.close(),this.onResult(e)}onClose(){this.delivered||(this.delivered=!0,this.onResult({kind:"cancel"})),this.contentEl.empty()}},Ne=class extends J.Modal{constructor(e,t){super(e);this.opts=t;this.succeeded=!1}onOpen(){let{mode:e}=this.opts;this.contentEl.empty(),this.modalEl.addClass("stashpad-export-modal","stashpad-encryption-modal"),this.titleEl.setText(this.opts.title??(e==="setup"?"Set up encryption password":e==="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}):e==="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 t=[],i=g=>{let I=this.contentEl.createDiv({cls:"stashpad-export-pw-row stashpad-encryption-row"}),m=I.createEl("input",{type:"password"});m.addClass("stashpad-export-name","stashpad-encryption-field"),m.placeholder=g;let B=I.createEl("button",{cls:"stashpad-export-copy"}),C=()=>{let Q=m.value.length===0;B.setText(Q?"Paste":"Copy"),B.toggleClass("is-paste",Q),B.setAttr("aria-label",`${Q?"Paste into":"Copy"} ${g.toLowerCase()}`)};return B.onclick=async Q=>{if(Q.preventDefault(),m.value.length===0)try{let y=(await navigator.clipboard?.readText())?.trim();if(!y){new J.Notice("Clipboard is empty.");return}m.value=y,m.dispatchEvent(new Event("input")),new J.Notice("Pasted from clipboard.")}catch{new J.Notice("Couldn't read the clipboard.")}else navigator.clipboard?.writeText(m.value).then(()=>new J.Notice("Copied to clipboard."),()=>new J.Notice("Couldn't access the clipboard."))},m.addEventListener("input",C),C(),t.push(C),m},s=null,n=null,o=null;if((e==="unlock"||e==="change")&&(s=i("Current password")),(e==="setup"||e==="change")&&(n=i(e==="change"?"New password":"Password"),o=i("Confirm password")),n){let g=this.contentEl.createDiv({cls:"stashpad-export-strength"}),I=g.createDiv({cls:"stashpad-strength-bar"}),m=[0,1,2,3].map(()=>I.createDiv({cls:"stashpad-strength-seg"})),B=g.createEl("span",{cls:"stashpad-strength-label"}),C=this.contentEl.createDiv({cls:"stashpad-encryption-counter"}),Q=()=>{let v=n.value,F=lo(v);m.forEach((D,R)=>D.toggleClass("is-on",R<F.level)),B.setText(v?F.label:""),C.setText(`${v.length} character${v.length===1?"":"s"}${v.length>0&&v.length<6?" \u2014 use at least 6":""}`),C.toggleClass("is-weak",v.length>0&&v.length<6)};n.addEventListener("input",Q),Q();let y=this.contentEl.createDiv({cls:"stashpad-export-genrow"});y.createEl("button",{cls:"stashpad-export-gen",text:"Generate strong passphrase"}).onclick=v=>{v.preventDefault();let F=ao(5);n.value=F,o&&(o.value=F),Q(),t.forEach(D=>D()),new J.Notice("Generated \u2014 copy it somewhere safe; there's no recovery."),navigator.clipboard?.writeText(F).catch(()=>{})};let E=y.createEl("button",{cls:"stashpad-export-show",text:"Show"});E.onclick=v=>{v.preventDefault();let F=n.type==="password";n.type=F?"text":"password",o&&(o.type=F?"text":"password"),E.setText(F?"Hide":"Show")};let w=this.contentEl.createEl("div",{cls:"stashpad-export-pw-suite"});w.setText("Encryption: AES-256-GCM. Checking key-derivation suite\u2026"),this.opts.kdfProbe?this.opts.kdfProbe().then(v=>{w.toggleClass("is-weak",!v),w.setText(v?"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(()=>w.setText("Encryption: AES-256-GCM with a password-derived key.")):w.setText("Encryption: Argon2id + AES-256-GCM (PBKDF2 fallback if Argon2 can't run here).")}let r=null,l=this.app.secretStorage;if(this.opts.offerKeychain&&l){let g=this.contentEl.createDiv({cls:"stashpad-export-remember"});r=g.createEl("input",{type:"checkbox"}),r.id="stashpad-enc-remember",r.checked=!0;let I=g.createEl("label",{text:"Remember on this device (keychain) \u2014 auto-unlock here without re-typing."});I.htmlFor=r.id;let m=this.contentEl.createDiv({cls:"stashpad-export-remember-note"});m.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."),m.setCssStyles({display:r.checked?"":"none"}),r.onchange=()=>{m.setCssStyles({display:r.checked?"":"none"})}}let c=this.contentEl.createEl("div",{cls:"stashpad-export-error"});c.setCssStyles({display:"none"});let A=g=>{c.setText(g),c.setCssStyles({display:""})},h=this.contentEl.createDiv({cls:"stashpad-export-footer"});h.createEl("button",{text:"Cancel"}).onclick=()=>this.close();let p=h.createEl("button",{cls:"mod-cta",text:e==="setup"?"Set up":e==="change"?"Change":"Unlock"}),u=!1,f=async()=>{if(u)return;let g=s?.value??void 0,I=n?.value??void 0;if((e==="unlock"||e==="change")&&!g){A("Enter your current password.");return}if(e==="setup"||e==="change"){if(!I){A("Enter a password.");return}if(I.length<6){A("Use at least 6 characters.");return}if(I!==o?.value){A("Passwords don't match.");return}}u=!0,p.disabled=!0,c.setCssStyles({display:"none"});let m=p.textContent;p.setText("Working\u2026");try{let B=await this.opts.onSubmit({current:g,next:I,remember:!!r?.checked});if(B){A(B),u=!1,p.disabled=!1,p.setText(m??"OK");return}this.succeeded=!0,this.close()}catch(B){A(`Failed: ${B.message}`),u=!1,p.disabled=!1,p.setText(m??"OK")}};p.onclick=()=>void f(),this.scope.register([],"Enter",g=>{g.preventDefault(),f()}),requestAnimationFrame(()=>(s??n)?.focus())}onClose(){this.contentEl.empty(),this.succeeded||this.opts.onCancel?.()}},oi=class extends J.Modal{constructor(e,t){super(e);this.opts=t}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 e=null;this.opts.requirePassword&&(this.contentEl.createEl("p",{cls:"stashpad-export-desc"}).setText("Enter your encryption password:"),e=this.contentEl.createEl("input",{type:"password"}),e.addClass("stashpad-export-name","stashpad-encryption-field"),e.placeholder="Password"),this.contentEl.createEl("p",{cls:"stashpad-export-desc"}).setText(`Type "${this.opts.phrase}" to confirm.`);let t=this.contentEl.createEl("input",{type:"text"});t.addClass("stashpad-export-name","stashpad-encryption-field"),t.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=()=>t.value.trim().toLowerCase()===this.opts.phrase.trim().toLowerCase(),r=()=>{n.disabled=!o()||!!this.opts.requirePassword&&!e?.value};t.addEventListener("input",r),e?.addEventListener("input",r),r();let l=!1,c=async()=>{if(!(l||!o())){if(this.opts.requirePassword&&(l=!0,n.disabled=!0,i.setCssStyles({display:"none"}),!await this.opts.requirePassword(e.value))){i.setText("Wrong password."),i.setCssStyles({display:""}),l=!1,r();return}this.close(),await this.opts.onConfirm()}};n.onclick=()=>void c(),this.scope.register([],"Enter",A=>{A.preventDefault(),c()}),requestAnimationFrame(()=>(e??t).focus())}onClose(){this.contentEl.empty()}},Li=class extends J.Modal{constructor(e,t){super(e);this.onSubmit=t}onOpen(){this.contentEl.empty(),this.modalEl.addClass("stashpad-export-modal"),this.titleEl.setText("Open Stashpad link"),this.contentEl.createEl("p",{cls:"stashpad-export-desc",text:"Paste one or more obsidian://stashpad links (one per line) to jump to the notes they point to. Multiple links each open in their own tab."});let e=this.contentEl.createDiv({cls:"stashpad-open-link-row"}),t=e.createEl("button",{cls:"stashpad-open-link-paste"});(0,J.setIcon)(t.createSpan({cls:"stashpad-open-link-paste-icon"}),"clipboard-paste"),t.createSpan({text:"Paste"}),t.title="Paste from clipboard";let i=e.createEl("textarea",{attr:{rows:"3"}});i.addClass("stashpad-export-name"),i.placeholder="obsidian://stashpad?folder=\u2026¬e=\u2026",t.onclick=async()=>{try{let r=(await navigator.clipboard?.readText?.())?.trim();r&&(i.value=r),i.focus()}catch{new J.Notice("Couldn't read the clipboard \u2014 paste manually.")}};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",text:"Open"}),o=()=>{let r=i.value.trim();r&&(this.close(),this.onSubmit(r))};n.onclick=()=>o(),this.scope.register([],"Enter",r=>{r.preventDefault(),o()}),requestAnimationFrame(()=>{i.focus(),navigator.clipboard?.readText?.().then(r=>{!i.value&&r&&/obsidian:\/\/stashpad\?/i.test(r.trim())&&(i.value=r.trim(),i.select())}).catch(()=>{})})}onClose(){this.contentEl.empty()}},Ss=class extends J.Modal{constructor(e,t,i){super(e);this.onResult=i;this.delivered=!1;this.touched=!1;this.value=t&&/^#[0-9a-f]{6}$/i.test(t)?t:"#888888"}onOpen(){this.contentEl.empty(),this.titleEl.setText("Custom color"),this.modalEl.addClass("stashpad-custom-color-modal");let e=this.contentEl.createDiv({cls:"stashpad-custom-color-row"}),t=e.createDiv({cls:"stashpad-custom-color-preview"});t.style.background=this.value;let i=e.createEl("input",{type:"color"});i.value=this.value,i.addClass("stashpad-custom-color-wheel"),t.onclick=()=>i.click();let s=e.createEl("input",{type:"text"});s.addClass("stashpad-custom-color-hex"),s.placeholder="#RRGGBB",s.value=this.value,s.maxLength=7;let n=A=>{let h=A.startsWith("#")?A:"#"+A;/^#[0-9a-f]{6}$/i.test(h)&&(this.touched=!0,this.value=h,t.style.background=h,i.value=h,s.value!==h&&(s.value=h))};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 l=o.createEl("button",{cls:"mod-cta",text:"Save"});l.title="Apply this color to the selection (without adding to your palette).",l.onclick=()=>this.commit({addToPalette:!1});let c=o.createEl("button",{cls:"mod-cta",text:"Add to palette"});c.title="Apply and save this color so it appears as a tile next time.",c.onclick=()=>this.commit({addToPalette:!0}),this.scope.register([],"Enter",A=>{A.preventDefault(),this.commit({addToPalette:!1})}),this.scope.register(["Mod"],"Enter",A=>{A.preventDefault(),this.commit({addToPalette:!0})}),requestAnimationFrame(()=>s.focus())}commit(e){this.delivered=!0,this.close(),this.onResult(this.value,e)}onClose(){!this.delivered&&this.touched&&(this.delivered=!0,this.onResult(this.value,{addToPalette:!1})),this.contentEl.empty()}},Ri=class Ri extends J.Modal{constructor(e,t,i,s,n){super(e);this.currentColor=t;this.customPalette=i;this.onPick=s;this.onDeleteCustom=n;this.focusIdx=-1;this.scopeBound=!1;this.items=[]}onOpen(){this.contentEl.empty(),this.titleEl.setText("Pick a color"),this.modalEl.addClass("stashpad-color-modal");let e=this.contentEl.createDiv({cls:"stashpad-color-grid"});this.items=[];let t=e.createDiv({cls:"stashpad-color-tile stashpad-color-none"});t.title="No color",t.onclick=()=>this.activate(0),this.items.push({kind:"none",color:null,el:t});let i=[...Ri.DEFAULT_PALETTE,...this.customPalette];for(let r of i){let l=e.createDiv({cls:"stashpad-color-tile"});l.style.background=r,l.title=r;let c=!Ri.DEFAULT_PALETTE.some(h=>h.toLowerCase()===r.toLowerCase()),A=this.items.length;if(l.onclick=()=>this.activate(A),c&&this.onDeleteCustom){let h=l.createSpan({cls:"stashpad-color-tile-del",text:"\xD7"});h.title="Remove from palette",h.onclick=p=>{p.stopPropagation(),this.handleDelete(r)}}this.items.push({kind:c?"custom":"preset",color:r,el:l})}let s=e.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.scopeBound||(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)}),this.scopeBound=!0),requestAnimationFrame(()=>this.modalEl.focus())}activate(e){if(e<0||e>=this.items.length)return;this.focusIdx=e,this.refreshActive();let t=this.items[e];if(t.kind==="add"){this.close(),new Ss(this.app,this.currentColor,(i,s)=>{this.onPick(i,s)}).open();return}this.close(),this.onPick(t.color,{addToPalette:!1})}columns(){if(!this.items.length)return 1;let e=this.items[0].el.parentElement;if(!e)return 1;let t=e.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(e){if(this.onDeleteCustom)try{let t=await this.onDeleteCustom(e);this.customPalette=Array.isArray(t)?t:this.customPalette.filter(i=>i.toLowerCase()!==e.toLowerCase()),this.onOpen()}catch(t){console.warn("Stashpad: palette delete failed",t)}}moveFocus(e){if(!this.items.length)return;let t=Math.max(0,Math.min(this.items.length-1,this.focusIdx+e));this.focusIdx=t,this.refreshActive()}refreshActive(){for(let e=0;e<this.items.length;e++)this.items[e].el.toggleClass("is-active",e===this.focusIdx)}onClose(){this.contentEl.empty()}};Ri.DEFAULT_PALETTE=["#E07A78","#E08A47","#E0A744","#B0CC6E","#6BC07A","#5BA9CE","#9B82C9","#C57AB5","#D75AA8"];Lt=Ri,_=class extends J.Modal{constructor(e,t,i,s,n,o="Cancel",r=!1){super(e);this.titleText=t;this.message=i;this.confirmText=s;this.onChoose=n;this.cancelText=o;this.dangerous=r;this.didChoose=!1}onOpen(){this.modalEl?.addClass("stashpad-compact-modal"),this.contentEl.empty(),this.titleEl.setText(this.titleText);let e=this.contentEl.createDiv({cls:"stashpad-confirm-body"});for(let n of this.message.split(` +`))e.createDiv({cls:"stashpad-confirm-line",text:n});let t=this.contentEl.createDiv({cls:"stashpad-modal-btns"}),i=t.createEl("button",{text:this.cancelText});i.onclick=()=>{this.didChoose=!0,this.close(),this.onChoose(!1)};let s=t.createEl("button",{cls:"mod-cta",text:this.confirmText});s.onclick=()=>{this.didChoose=!0,this.close(),this.onChoose(!0)},requestAnimationFrame(()=>(this.dangerous?i:s).focus())}onClose(){this.contentEl.empty(),this.didChoose||(this.didChoose=!0,this.onChoose(!1))}},Oi=class extends J.Modal{constructor(e,t,i,s={}){super(e);this.levels=t;this.onPick=i;this.opts=s}onOpen(){this.modalEl?.addClass("stashpad-compact-modal"),this.modalEl?.addClass("stashpad-breadcrumb-modal"),this.contentEl.empty(),this.titleEl.setText("Jump to level");let e=this.contentEl.createDiv({cls:"stashpad-bc-levels"});for(let t of this.levels){let i=e.createDiv({cls:"stashpad-bc-level-row"});if(t.isCurrent&&i.addClass("is-current"),i.createSpan({cls:"stashpad-bc-level-num",text:String(t.level)}),i.createSpan({cls:"stashpad-bc-level-label",text:t.label}),!t.isCurrent){i.setAttribute("role","button"),i.setAttribute("tabindex","0");let s=()=>{this.close(),this.onPick(t.id)};i.onclick=s,i.onkeydown=n=>{(n.key==="Enter"||n.key===" ")&&(n.preventDefault(),s())}}this.opts.onContext&&(i.oncontextmenu=s=>{s.preventDefault(),this.opts.onContext(t.id,s,i,()=>this.close())},this.opts.attachLongPress?.(i,()=>this.opts.onContext(t.id,null,i,()=>this.close())))}}onClose(){this.contentEl.empty()}};Ge=class extends J.Modal{constructor(e,t,i,s={}){super(e);this.current=t;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 e=null;if(this.current){let w=Date.parse(this.current);Number.isNaN(w)||(e=new Date(w))}let t=this.contentEl.createDiv({cls:"stashpad-due-picker"}),i=t.createDiv({cls:"stashpad-due-fields"}),s=i.createDiv({cls:"stashpad-due-field"}),n=s.createSpan({cls:"stashpad-due-field-icon"});(0,J.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,J.setIcon)(r,"x"),r.onclick=()=>{o.value="",o.focus()};let l=i.createDiv({cls:"stashpad-due-field"}),c=l.createSpan({cls:"stashpad-due-field-icon"});(0,J.setIcon)(c,"clock");let A=l.createEl("input",{type:"time",cls:"stashpad-due-time"}),h=l.createSpan({cls:"stashpad-due-clear",attr:{"aria-label":"Clear time"}});(0,J.setIcon)(h,"x"),h.onclick=()=>{A.value="",A.focus()},n.onclick=()=>{try{o.showPicker?.()}catch{}},c.onclick=()=>this.openTimeNumpad(c,A),e&&(o.value=this.toDateValue(e),A.value=this.toTimeValue(e));let p=(this.opts.quickAdjusts??Gr).map(w=>({raw:w,min:Lr(w)})).filter(w=>w.min!=null);if(p.length>0){let w=1,v=t.createDiv({cls:"stashpad-due-quickadjust"}),F=v.createEl("button",{cls:"stashpad-due-adjust-flip",attr:{type:"button"}}),D=()=>{F.setText(w>0?"+":"\u2212"),F.toggleClass("is-minus",w<0),F.title=w>0?"Adding time (click to subtract)":"Subtracting time (click to add)"};D(),F.onclick=()=>{w=-w,D()};let R=G=>{let x=new Date,H,U,N;if(o.value){let[L,K,V]=o.value.split("-").map(Y=>parseInt(Y,10));H=L,U=K-1,N=V}else H=x.getFullYear(),U=x.getMonth(),N=x.getDate();let S,P;if(A.value){let[L,K]=A.value.split(":").map(V=>parseInt(V,10));S=L,P=K}else S=x.getHours(),P=x.getMinutes();let O=new Date(H,U,N,S,P,0,0);O.setMinutes(O.getMinutes()+w*G),o.value=this.toDateValue(O),A.value=this.toTimeValue(O)};for(let G of p){let x=v.createEl("button",{cls:"stashpad-due-adjust-btn",text:G.raw,attr:{type:"button"}});x.onclick=()=>R(G.min)}}this.opts.hideAssignees||this.renderAssignSection(t);let u=t.createDiv({cls:"stashpad-due-grid"}),f=(w,v)=>{let F=u.createEl("button",{cls:"stashpad-due-btn stashpad-due-preset",text:w});F.onclick=()=>{let D=v();o.value=this.toDateValue(D),A.value||(A.value=this.toTimeValue(D))}},g=w=>(w.setHours(9,0,0,0),w);f("Today",()=>g(this.startOfTodayLocal())),f("Tomorrow",()=>{let w=this.startOfTodayLocal();return w.setDate(w.getDate()+1),g(w)}),f("Next week",()=>{let w=this.startOfTodayLocal();return w.setDate(w.getDate()+7),g(w)});let I=u.createEl("button",{cls:"stashpad-due-btn",text:"Clear"});I.onclick=()=>{o.value="",A.value="",o.focus()};let m=null,B=null,C=null;if(this.opts.showRecurrence){let w=t.createEl("details",{cls:"stashpad-due-recur"});(this.opts.currentRepeat||this.opts.currentAutoDoneAfter||this.opts.currentRemindEvery)&&(w.open=!0),w.createEl("summary",{text:"\u{1F501} Repeat & reminders"});let v=(F,D,R)=>{let G=w.createDiv({cls:"stashpad-due-recur-row"});G.createEl("label",{text:F});let x=G.createEl("input",{type:"text",attr:{placeholder:D}});return R&&(x.value=R),x};m=v("Repeat",'e.g. "every weekday", "every 30 days when done"',this.opts.currentRepeat),B=v("Auto-complete after",'e.g. "1d" \u2014 mark done once this overdue',this.opts.currentAutoDoneAfter),C=v("Remind every",'e.g. "2h" \u2014 re-notify until done',this.opts.currentRemindEvery)}let Q=()=>this.opts.showRecurrence?{repeat:m.value.trim(),autoDoneAfter:B.value.trim(),remindEvery:C.value.trim()}:{},y=u.createEl("button",{cls:"stashpad-due-btn",text:"Cancel"});y.onclick=()=>{this.didChoose=!0,this.close()};let E=u.createEl("button",{cls:"stashpad-due-btn mod-cta",text:"Set"});E.onclick=()=>{if(!o.value){this.didChoose=!0,this.close(),this.onPick({iso:null,assignees:this.assignees,...Q()});return}let[w,v,F]=o.value.split("-").map(x=>parseInt(x,10)),D=9,R=0;if(A.value){let[x,H]=A.value.split(":").map(U=>parseInt(U,10));D=x,R=H}let G=new Date(w,v-1,F,D,R,0,0);this.didChoose=!0,this.close(),this.onPick({iso:G.toISOString(),assignees:this.assignees,...Q()})},requestAnimationFrame(()=>o.focus())}onClose(){this.tinyClosePopover?.(),this.contentEl.empty(),this.didChoose}renderAssignSection(e){Or(e,{knownAuthors:this.opts.knownAuthors??[],initial:this.assignees,onChange:t=>{this.assignees=t}})}openTimeNumpad(e,t){this.tinyClosePopover?.();let i=e.ownerDocument??document,s=i.defaultView??window,n=9,o=0;if(t.value){let[I,m]=t.value.split(":").map(B=>parseInt(B,10));Number.isFinite(I)&&(n=I),Number.isFinite(m)&&(o=m)}else{let I=new Date;n=I.getHours(),o=I.getMinutes()}let r=n>=12?"pm":"am",l=n===0?12:n>12?n-12:n,A=(this.modalEl??i.body).createDiv({cls:"stashpad-when-popover stashpad-due-time-pop"});A.setCssStyles({position:"fixed",zIndex:"9999"});let h=null,p=()=>{A.remove(),i.removeEventListener("mousedown",u,!0),i.removeEventListener("keydown",f,!0),this.tinyClosePopover===p&&(this.tinyClosePopover=null)},u=I=>{!A.contains(I.target)&&I.target!==e&&!e.contains(I.target)&&p()},f=I=>{I.key==="Escape"?(I.preventDefault(),I.stopPropagation(),p()):I.key==="Enter"&&h&&(I.preventDefault(),I.stopPropagation(),h())};this.tinyClosePopover=p,Fs(A,{seedH:l,seedM:o,seedPeriod:r,close:p,setOnEnter:I=>{h=I},onFinalize:I=>{t.value=`${String(I.hours24).padStart(2,"0")}:${String(I.minutes).padStart(2,"0")}`}});let g=e.getBoundingClientRect();A.setCssStyles({left:`${Math.max(8,Math.min(g.left,s.innerWidth-220))}px`,top:`${g.bottom+4}px`}),setTimeout(()=>{i.addEventListener("mousedown",u,!0),i.addEventListener("keydown",f,!0),A.querySelector(".stashpad-when-time-field")?.focus()},0)}startOfTodayLocal(){let e=new Date;return e.setHours(0,0,0,0),e}toDateValue(e){let t=e.getFullYear(),i=String(e.getMonth()+1).padStart(2,"0"),s=String(e.getDate()).padStart(2,"0");return`${t}-${i}-${s}`}toTimeValue(e){let t=String(e.getHours()).padStart(2,"0"),i=String(e.getMinutes()).padStart(2,"0");return`${t}:${i}`}},Gt=class Gt extends J.Modal{constructor(e,t,i,s=null,n){super(e);this.service=t;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 e=this.contentEl.createDiv({cls:"stashpad-log-toolbar"});if(this.countEl=e.createSpan({cls:"stashpad-log-count"}),this.updateCount(),this.filterSelEl=e.createEl("select",{cls:"stashpad-log-type-filter"}),this.filterSelEl.onchange=()=>this.setCategoryFilter(this.filterSelEl.value||null),this.refreshCategoryFilter(),this.authorSelEl=e.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=e.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 t=e.createEl("button",{cls:"mod-warning",text:"Clear history"});t.onclick=()=>{new _(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()},"Cancel",!0).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(e){this.authorFilter!==e&&(this.authorFilter=e,this.refreshList(),this.renderFooter())}refreshAuthorFilter(){if(!this.authorSelEl)return;let e=this.authorSelEl;e.empty(),e.createEl("option",{text:"All authors"}).value="all",this.currentAuthorId&&(e.createEl("option",{text:"Me"}).value="me"),e.createEl("option",{text:"Cross-author"}).value="cross";let t=new Set;for(let s of this.records)s.authorId&&s.authorId!==this.currentAuthorId&&t.add(s.authorId);if(t.size>0){let s=e.createEl("option",{text:"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"});s.disabled=!0;for(let n of[...t].sort())e.createEl("option",{text:n}).value=n}new Set(["all","cross",...this.currentAuthorId?["me"]:[],...t]).has(this.authorFilter)||(this.authorFilter="all"),e.value=this.authorFilter}isCrossAuthor(e){let t=e.authorId??null;if(!t)return!1;for(let i of e.affectedAuthorIds??[])if(i&&i!==t)return!0;if(!this.getNoteAuthorIds)return!1;for(let i of e.affectedIds){let s=this.getNoteAuthorIds(i);for(let n of s)if(n&&n!==t)return!0}return!1}onClose(){this.unsubscribe?.(),this.unsubscribe=null,this.contentEl.empty()}setCategoryFilter(e){(this.categoryFilter??null)!==(e??null)&&(this.categoryFilter=e,this.refreshList(),this.renderFooter())}refreshCategoryFilter(){if(!this.filterSelEl)return;let e=this.filterSelEl;e.empty();let t=new Map;for(let n of this.records)t.set(n.category,(t.get(n.category)??0)+1);let i=[...t.entries()].sort((n,o)=>o[1]-n[1]||n[0].localeCompare(o[0])),s=e.createEl("option",{text:`All categories (${this.records.length})`});s.value="";for(let[n,o]of i){let r=e.createEl("option",{text:`${n} (${o})`});r.value=n}this.categoryFilter&&!t.has(this.categoryFilter)&&(this.categoryFilter=null),e.value=this.categoryFilter??""}refreshList(){if(this.listEl){if(this.visible=this.records.filter(e=>{if(this.categoryFilter&&e.category!==this.categoryFilter)return!1;switch(this.authorFilter){case"all":return!0;case"me":return!!this.currentAuthorId&&e.authorId===this.currentAuthorId;case"cross":return this.isCrossAuthor(e);default:return e.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(Gt.PAGE)}}appendMore(e){if(!this.listEl)return;let t=Math.min(this.visible.length,this.shownCount+e);for(let i=this.shownCount;i<t;i++)this.renderRow(this.listEl,this.visible[i]);this.shownCount=t,this.updateCount()}renderRow(e,t){let i=e.createDiv({cls:`stashpad-notif-row stashpad-notif-row-${t.kind}`}),s=i.createDiv({cls:"stashpad-notif-meta"}),n=s.createSpan({cls:"stashpad-notif-time"}),o=ql(t.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-${t.category}`}).setText(t.category),i.createDiv({cls:"stashpad-notif-msg"}).setText(t.message),t.actionLabels.length>0){let c=i.createDiv({cls:"stashpad-notif-actions-snapshot"});for(let A of t.actionLabels){let h=c.createSpan({cls:"stashpad-notif-action-chip"});h.setText(A),h.title="Action button was shown on the original toast (handler not retained)."}}}updateCount(){if(!this.countEl)return;let e=this.visible.length,t=this.categoryFilter?`${e} ${this.categoryFilter} notification${e===1?"":"s"}`:`${e} notification${e===1?"":"s"}`;this.shownCount===0||this.shownCount>=e?this.countEl.setText(t):this.countEl.setText(`Showing ${this.shownCount} of ${t}`)}renderFooter(){if(!this.footerEl)return;this.footerEl.empty();let e=this.visible.length-this.shownCount;if(e<=0)return;let t=this.footerEl.createEl("button",{text:`Load ${Math.min(Gt.PAGE,e)} more`});if(t.onclick=()=>{this.appendMore(Gt.PAGE),this.renderFooter()},e>Gt.PAGE){let i=this.footerEl.createEl("button",{text:`Load all (${e})`});i.onclick=()=>{this.appendMore(e),this.renderFooter()}}}};Gt.PAGE=100;Ki=Gt,co=class extends J.Modal{constructor(e,t){super(e);this.entries=t}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 e=this.contentEl.createDiv({cls:"stashpad-import-log-list"});for(let t of this.entries){let i=e.createDiv({cls:"stashpad-import-log-row"}),s=(0,J.moment)(t.ts).format("YYYY-MM-DD HH:mm");i.createSpan({cls:"stashpad-import-log-when",text:s});let n=t.kind==="folder"?"folder":t.kind==="md"?"note":"file";i.createSpan({cls:`stashpad-import-log-kind is-${t.kind}`,text:n}),i.createSpan({cls:"stashpad-import-log-name",text:t.originalName});let o=[t.folder.split("/").pop()||t.folder];t.notePaths.length>1&&o.push(`${t.notePaths.length} notes`),i.createSpan({cls:"stashpad-import-log-meta",text:o.join(" \xB7 ")})}}onClose(){this.contentEl.empty()}},Ji=class extends J.Modal{constructor(e,t,i){super(e);this.message=t;this.onChoose=i;this.chose=!1}onOpen(){this.modalEl?.addClass("stashpad-compact-modal"),this.contentEl.empty(),this.titleEl.setText("Possible duplicate import");let e=this.contentEl.createDiv({cls:"stashpad-confirm-body"});for(let o of this.message.split(` +`))e.createDiv({cls:"stashpad-confirm-line",text:o});let t=this.contentEl.createDiv({cls:"stashpad-modal-btns"}),i=t.createEl("button",{text:"Skip duplicates"});i.onclick=()=>{this.chose=!0,this.close(),this.onChoose("skip")};let s=t.createEl("button",{text:"Replace existing"});s.onclick=()=>{this.chose=!0,this.close(),this.onChoose("replace")};let n=t.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()}},qi=class extends J.Modal{constructor(e,t,i,s){super(e);this.noteCount=i;this.onConfirm=s;this.base=t}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 e=this.contentEl.createEl("input",{type:"text"});e.addClass("stashpad-export-name"),e.value=this.base,e.placeholder="Export name";let t=(l,c)=>{let A=this.contentEl.createDiv({cls:"stashpad-okf-fmt"}),h=A.createEl("input",{type:"checkbox"});return h.checked=c,A.createEl("label",{text:l}),h},i=t(".zip \u2014 OKF bundle (portable)",!0),s=t(".tar.gz \u2014 OKF bundle (tarball)",!1),n=t(".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 J.Notice("Pick at least one format.");return}this.close(),this.onConfirm(e.value.trim()||this.base,{zip:i.checked,targz:s.checked,stash:n.checked})},requestAnimationFrame(()=>e.focus())}onClose(){this.contentEl.empty()}},$i=class extends J.Modal{constructor(e,t,i){super(e);this.items=t;this.onConfirm=i}onOpen(){this.titleEl.setText("Re-encrypt everything applicable?");let{contentEl:e}=this;e.createEl("p",{cls:"setting-item-description",text:"These notes should be encrypted (they were unlocked/restored, or their folder is set to encrypt) but are currently plaintext. Untick anything you want to leave readable."});let t=e.createDiv({cls:"stashpad-reenc-list"}),i=[];this.items.forEach(o=>{let r=t.createEl("label",{cls:"stashpad-reenc-row"}),l=r.createEl("input",{type:"checkbox"});l.checked=!0,i.push(l);let c=r.createDiv({cls:"stashpad-reenc-body"});c.createDiv({cls:"stashpad-reenc-label",text:o.label}),c.createDiv({cls:"stashpad-reenc-detail",text:o.detail})});let s=e.createDiv({cls:"modal-button-container"}),n=s.createEl("button",{cls:"mod-cta",text:"Re-encrypt checked"});n.onclick=()=>{let o=i.map((r,l)=>r.checked?l:-1).filter(r=>r>=0);this.close(),o.length&&this.onConfirm(o)},s.createEl("button",{text:"Cancel"}).onclick=()=>this.close()}onClose(){this.contentEl.empty()}}});function Se(d,a=je){let e=a instanceof Set?a:new Set(a.map(o=>o.toLowerCase())),t=(d.split(/\r?\n/).find(o=>o.trim().length>0)??"").trim();if(!t)return"Untitled";let s=t.replace(/['‘-‛ʼ]/g,"").replace(/[^A-Za-z0-9\s]+/g," ").split(/\s+/).filter(o=>o&&!e.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 be(d,a){return`${d}-${a}.md`}function ct(d){let a=d.match(/-([abcdefghijkmnpqrstuvwxyz23456789]{6})$/);return a?a[1]:null}function Ms(d){return typeof d=="string"&&/^[abcdefghijkmnpqrstuvwxyz23456789]{6}$/.test(d)}function Ts(d,a){let e=d.lastIndexOf(".");return e>0?`${d.slice(0,e)}-${a}${d.slice(e)}`:`${d}-${a}`}function Jr(d){let a=d.match(/^([0-9a-z]{7,9})-(.+)$/);if(!a)return null;let e=parseInt(a[1],36);return!Number.isFinite(e)||e<142e10||e>Date.now()+864e5?null:{stamp:a[1],rest:a[2]}}var je,ai=$e(()=>{"use strict";je=["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 Rs={};Si(Rs,{JdBuildConfirmModal:()=>Wi,buildJdIndexNotes:()=>go,buildJdIndexPreview:()=>Ps,buildJdPreviewNotice:()=>Hs,scanForJdNotes:()=>li});function po(d,a){if(/^\d+-\d+$/.test(d))return null;if(d.includes(".")){let t=d.split(".").slice(0,-1).join(".");return a.has(t)?t:po(t,a)}if(/^\d+$/.test(d)){let e=parseInt(d,10);for(let t of a){let i=t.match(/^(\d+)-(\d+)$/);if(!i)continue;let s=parseInt(i[1],10),n=parseInt(i[2],10);if(e>=s&&e<=n)return t}return null}return null}function li(d,a,e){let t=d.vault.getMarkdownFiles(),i=Vl(t,e),s=e.jdIndexIncludeStashpadFolders===!0,n=s?new Set:new Set(a.discoverStashpadFolders()),o=u=>s?!1:Array.from(n).some(f=>u===f||u.startsWith(f+"/")),r=[],l=[],c=[];for(let u of i){let f=u.parent?.path?.replace(/\/+$/,"")??"";if(o(f)){c.push(u);continue}let g=u.basename.match(qr);g?r.push({prefix:g[1],segments:g[1].split("."),title:g[2],file:u,folder:null}):l.push(u)}let A=(e.jdIndexScope??"vault")==="folder"?(e.jdIndexScopeFolder??"").trim().replace(/^\/+|\/+$/g,""):"",h=u=>{let f=u.path.replace(/\/+$/,"");if(!(A&&f&&f!==A&&!f.startsWith(A+"/"))){if(f&&!o(f)){let g=u.name.match(qr);g&&r.push({prefix:g[1],segments:g[1].split("."),title:g[2],file:null,folder:u})}}for(let g of u.children)g instanceof Ce.TFolder&&h(g)};h(d.vault.getRoot());let p=e.jdIndexSort??"natural";return r.sort((u,f)=>Wl(u,f,p)),{indexed:r,nonIndex:l,skippedStashpadNotes:c}}async function Ps(d,a,e){let t=uo(e.jdIndexStashpadFolder??"");if(!t)return{...li(d,a,e),previewPath:null,error:"no-dest"};let i=li(d,a,e),s=zl(d,t);if(!s)return{...i,previewPath:null,error:"no-home"};let n=Xl(i.indexed,i.nonIndex,i.skippedStashpadNotes),r=(await d.vault.read(s)).match(/^---\r?\n[\s\S]*?\r?\n---\r?\n/),l=r?`${r[0]}${n}`:n;return await d.vault.modify(s,l),{...i,previewPath:s.path}}function zl(d,a){let e=d.vault.getAbstractFileByPath(a);if(!(e instanceof Ce.TFolder))return null;for(let t of e.children){if(!(t instanceof Ce.TFile)||t.extension!=="md")continue;if((d.metadataCache.getFileCache(t)?.frontmatter??{}).id===k)return t}return null}async function go(d,a,e){let t=uo(e.jdIndexStashpadFolder??"");if(!t)return{created:0,updated:0,skipped:0,destFolder:"",error:"no-dest"};if(!new Set(a.discoverStashpadFolders()).has(t))return{created:0,updated:0,skipped:0,destFolder:t,error:"dest-not-stashpad"};let s=li(d,a,e),n=new Map;for(let I of s.indexed)n.set(I.prefix,I);for(let I of s.indexed)if(I.prefix.includes("."))for(let m=1;m<I.segments.length;m++){let B=I.segments.slice(0,m).join(".");n.has(B)||n.set(B,null)}let{roots:o,childrenOf:r}=zr(n),l=[],c=I=>{l.push(I);for(let m of r.get(I)??[])c(m)};for(let I of o)c(I);let A=new Map,h=d.vault.getAbstractFileByPath(t);if(h instanceof Ce.TFolder)for(let I of h.children){if(!(I instanceof Ce.TFile)||I.extension!=="md")continue;let m=d.metadataCache.getFileCache(I)?.frontmatter??{};typeof m.jdPrefix=="string"&&A.set(m.jdPrefix,I)}let p=new Map,u=0,f=0,g=0;for(let I of l){let m=n.get(I)??null,B=po(I,new Set(n.keys())),C=B?p.get(B)??k:k,Q=m?`${I} ${m.title}`:I,y=m?.file?`[[${m.file.basename}]]`:"",E=y?`${y} +`:`${Q} +`,w=A.get(I);if(w){try{let v=null;await d.fileManager.processFrontMatter(w,G=>{G.jdPrefix=I,C&&(G.parent=C),(!G.id||typeof G.id!="string")&&(G.id=a.mintNoteId()),G.created||(G.created=new Date().toISOString()),G.attachments||(G.attachments=[]),v=G.id});let D=(await d.vault.read(w)).match(/^---\r?\n[\s\S]*?\r?\n---\r?\n/),R=D?`${D[0]}${E}`:E;await d.vault.modify(w,R),v&&p.set(I,v),f++}catch(v){console.error("[stashpad] buildJdIndexNotes: update failed",v),g++}continue}try{let v=a.mintNoteId();p.set(I,v);let F=Se(Q,e.slugStopWords),D=be(F,v),R=`${t}/${D}`,G=["---",`id: ${v}`,`parent: ${C}`,`created: "${new Date().toISOString()}"`,"attachments: []",`jdPrefix: "${I}"`,"---",""].join(` +`);await d.vault.create(R,G+E),u++}catch(v){console.error("[stashpad] buildJdIndexNotes: create failed for",I,v),g++}}return{created:u,updated:f,skipped:g,destFolder:t}}function uo(d){return(d||"").trim().replace(/^\/+|\/+$/g,"")}function Vl(d,a){if((a.jdIndexScope??"vault")==="vault")return d;let e=uo(a.jdIndexScopeFolder??"");return e?d.filter(t=>{let i=t.parent?.path?.replace(/\/+$/,"")??"";return i===e||i.startsWith(e+"/")}):d}function Wl(d,a,e){if(e==="created"){let t=d.file?.stat?.ctime??0,i=a.file?.stat?.ctime??0;if(t!==i)return t-i}return Yr(d.segments,a.segments)}function $r(d,a){let e=d.match(/^(\d+)-(\d+)$/),t=a.match(/^(\d+)-(\d+)$/),i=e?[e[1]]:d.split("."),s=t?[t[1]]:a.split(".");return Yr(i,s)}function Yr(d,a){let e=Math.min(d.length,a.length);for(let t=0;t<e;t++){let i=d[t],s=a[t],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 d.length-a.length}function zr(d){let a=new Set(d.keys()),e=new Map,t=new Map;for(let o of a){let r=po(o,a);if(e.set(o,r),r!==null){let l=t.get(r)??[];l.push(o),t.set(r,l)}}let i=[];for(let o of a)e.get(o)===null&&i.push(o);i.sort($r);for(let o of t.values())o.sort($r);let s=new Map,n=(o,r)=>{s.set(o,r);for(let l of t.get(o)??[])n(l,r+1)};for(let o of i)n(o,0);return{roots:i,childrenOf:t,depthOf:s}}function Xl(d,a,e){let t=[],i=s=>"#".repeat(Math.min(s+1,6));if(t.push("# Indexed"),t.push(""),d.length===0){let s=e.length>0?`_No notes matched. ${e.length} note${e.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._";t.push(s)}else{let s=new Map;for(let c of d)s.set(c.prefix,c);for(let c of d)if(c.prefix.includes("."))for(let A=1;A<c.segments.length;A++){let h=c.segments.slice(0,A).join(".");s.has(h)||s.set(h,null)}let{roots:n,childrenOf:o,depthOf:r}=zr(s),l=c=>{let A=s.get(c),h=r.get(c)??0,p=" ".repeat(h),u=i(h),f=A?.folder?` ${A.title} _(folder)_`:(A?.file,"");A?.file?t.push(`${p}- ${u} [[${A.file.basename}|${A.prefix} ${A.title}]]`):A?.folder?t.push(`${p}- ${u} ${A.prefix}${f}`):t.push(`${p}- ${u} ${c}`);for(let g of o.get(c)??[])l(g)};for(let c of n)l(c)}if(a.length>0){t.push(""),t.push(`# Non-indexed (${a.length})`),t.push(""),t.push("_These notes don't match the JD-prefix convention. Rename them to `<prefix> <title>` and re-run to include them._"),t.push("");for(let s of a)t.push(`- # [[${s.basename}]] \xB7 \`${s.path}\``)}if(e.length>0){let s=new Map;for(let o of e){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]));t.push(""),t.push(`# Excluded folders (${n.length})`),t.push(""),t.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._`),t.push("");for(let[o,r]of n)t.push(`- # All ${r} file${r===1?"":"s"} in \`${o||"(vault root)"}\``)}return t.join(` `)+` -`}function Ps(d,a){let e=document.createDocumentFragment();e.createEl("div",{text:"Home note updated"}).setCssStyles({fontWeight:"600",marginBottom:"6px"});let i=e.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=e.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=d.vault.getAbstractFileByPath(a.previewPath);r instanceof Ie.TFile&&await d.workspace.getLeaf("tab").openFile(r)}n?.hide()},n=new Ie.Notice(e,0),n}var Ie,Or,Vi,Wi=qe(()=>{"use strict";Ie=require("obsidian");ri();ae();Or=/^(\d+-\d+|\d+|[A-Za-z0-9]+(?:\.[A-Za-z0-9]+)+)\s+(.+)$/;Vi=class extends Ie.Modal{constructor(e,t,i,s,n){super(e);this.plugin=t;this.settings=i;this.indexedCount=s;this.onBuild=n;this.LARGE_BUILD=50;this.previewRan=!1;this.previewPath=null}onOpen(){let{contentEl:e,titleEl:t}=this,i=!this.settings.jdIndexHasBuilt,s=this.indexedCount>this.LARGE_BUILD;t.setText(i?"Build JD index \u2014 first time?":"Build JD index");let n=this.settings.jdIndexStashpadFolder,o=e.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."),e.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&&e.createEl("p",{cls:"setting-item-description"}).setText(`\u2713 Preview written to home note (${this.previewPath}). Open it before building if you haven't.`);let l=new Ie.Setting(e);(i||s)&&l.addButton(c=>{c.setButtonText(this.previewRan?"Re-run preview":"Run preview first"),c.setCta(),c.onClick(async()=>{try{let A=await Ts(this.app,this.plugin,this.settings);if(A.error==="no-dest"){new Ie.Notice("Set a Designated Stashpad folder for Index first.",5e3),this.close();return}if(A.error==="no-home"){new Ie.Notice(`"${this.settings.jdIndexStashpadFolder}" has no Stashpad home note. Open the folder in Stashpad first.`,7e3),this.close();return}this.previewRan=!0,this.previewPath=A.previewPath,Ps(this.app,A),this.contentEl.empty(),this.titleEl.empty(),this.onOpen()}catch(A){new Ie.Notice(`Preview failed: ${A?.message??A}`,8e3)}})}),l.addButton(c=>{c.setButtonText(i?"Build anyway":"Build"),!i&&!s&&c.setCta(),c.onClick(async()=>{this.close(),await this.onBuild()})}),l.addButton(c=>{c.setButtonText("Cancel"),c.onClick(()=>this.close())})}onClose(){this.contentEl.empty()}}});function Wc(d,a){return Vc(d,a||{},0,0)}function Xc(d,a){return Jc(d,{i:2},a&&a.out,a&&a.dictionary)}function In(d,a){if(a){for(var e=new ce(d.length),t=0;t<d.length;++t)e[t]=d.charCodeAt(t);return e}if(Ma)return Ma.encode(d);for(var i=d.length,s=new ce(d.length+(d.length>>1)),n=0,o=function(c){s[n++]=c},t=0;t<i;++t){if(n+5>s.length){var r=new ce(n+8+(i-t<<1));r.set(s),s=r}var l=d.charCodeAt(t);l<128||a?o(l):l<2048?(o(192|l>>6),o(128|l&63)):l>55295&&l<57344?(l=65536+(l&1047552)|d.charCodeAt(++t)&1023,o(240|l>>18),o(128|l>>12&63),o(128|l>>6&63),o(128|l&63)):(o(224|l>>12),o(128|l>>6&63),o(128|l&63))}return ls(s,0,n)}function er(d,a){if(a){for(var e="",t=0;t<d.length;t+=16384)e+=String.fromCharCode.apply(null,d.subarray(t,t+16384));return e}else{if(Xo)return Xo.decode(d);var i=jc(d),s=i.s,e=i.r;return e.length&&Ee(8),s}}function Ja(d,a){a||(a={});var e={},t=[];Ka(d,"",e,a);var i=0,s=0;for(var n in e){var o=e[n],r=o[0],l=o[1],c=l.level==0?0:8,A=In(n),h=A.length,g=l.comment,u=g&&In(g),f=u&&u.length,p=Zo(l.extra);h>65535&&Ee(11);var I=c?Wc(r,l):r,m=I.length,B=zc();B.p(r),t.push(Oa(l,{size:r.length,crc:B.d(),c:I,f:A,m:u,u:h!=n.length||u&&g.length!=f,o:i,compression:c})),i+=30+h+p+m,s+=76+2*(h+p)+(f||0)+m}for(var C=new ce(s+22),w=i,y=s-i,v=0;v<t.length;++v){var A=t[v];Ta(C,A.o,A,A.f,A.u,A.c.length);var E=30+A.f.length+Zo(A.extra);C.set(A.c,A.o+E),Ta(C,i,A,A.f,A.u,A.c.length,A.o,A.m),i+=16+E+(A.m?A.m.length:0)}return id(C,i,t.length,y,w),C}function qa(d,a){for(var e={},t=d.length-22;He(d,t)!=101010256;--t)(!t||d.length-t>65558)&&Ee(13);var i=_e(d,t+8);if(!i)return{};var s=He(d,t+16),n=He(d,t-20)==117853008;if(n){var o=He(d,t-12);n=He(d,o)==101075792,n&&(i=He(d,o+32),s=He(d,o+48))}for(var r=a&&a.filter,l=0;l<i;++l){var c=ed(d,s,n),A=c[0],h=c[1],g=c[2],u=c[3],f=c[4],p=c[5],I=_c(d,p);s=f,(!r||r({name:u,size:h,originalSize:g,compression:A}))&&(A?A==8?e[u]=Xc(d.subarray(I,I+h),{out:new ce(g)}):Ee(14,"unknown compression type "+A):e[u]=ls(d,I,I+h))}return e}var ce,De,jo,mn,Cn,Yo,Pa,Ha,Ra,zo,Ua,Rc,Da,Vo,gt,Z,et,St,Z,Z,Z,Z,as,Z,Uc,Gc,Lc,Oc,Ko,Ke,Jo,_o,ls,Kc,Ee,Jc,ut,os,qo,Wo,xa,rs,Ga,Na,qc,La,$c,Yc,zc,Vc,Oa,_e,He,$o,Be,Ka,Ma,Xo,Zc,jc,_c,ed,td,Zo,Ta,id,$a=qe(()=>{ce=Uint8Array,De=Uint16Array,jo=Int32Array,mn=new ce([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]),Cn=new ce([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]),Yo=new ce([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),Pa=function(d,a){for(var e=new De(31),t=0;t<31;++t)e[t]=a+=1<<d[t-1];for(var i=new jo(e[30]),t=1;t<30;++t)for(var s=e[t];s<e[t+1];++s)i[s]=s-e[t]<<5|t;return{b:e,r:i}},Ha=Pa(mn,2),Ra=Ha.b,zo=Ha.r;Ra[28]=258,zo[258]=28;Ua=Pa(Cn,0),Rc=Ua.b,Da=Ua.r,Vo=new De(32768);for(Z=0;Z<32768;++Z)gt=(Z&43690)>>1|(Z&21845)<<1,gt=(gt&52428)>>2|(gt&13107)<<2,gt=(gt&61680)>>4|(gt&3855)<<4,Vo[Z]=((gt&65280)>>8|(gt&255)<<8)>>1;et=function(d,a,e){for(var t=d.length,i=0,s=new De(a);i<t;++i)d[i]&&++s[d[i]-1];var n=new De(a);for(i=1;i<a;++i)n[i]=n[i-1]+s[i-1]<<1;var o;if(e){o=new De(1<<a);var r=15-a;for(i=0;i<t;++i)if(d[i])for(var l=i<<4|d[i],c=a-d[i],A=n[d[i]-1]++<<c,h=A|(1<<c)-1;A<=h;++A)o[Vo[A]>>r]=l}else for(o=new De(t),i=0;i<t;++i)d[i]&&(o[i]=Vo[n[d[i]-1]++]>>15-d[i]);return o},St=new ce(288);for(Z=0;Z<144;++Z)St[Z]=8;for(Z=144;Z<256;++Z)St[Z]=9;for(Z=256;Z<280;++Z)St[Z]=7;for(Z=280;Z<288;++Z)St[Z]=8;as=new ce(32);for(Z=0;Z<32;++Z)as[Z]=5;Uc=et(St,9,0),Gc=et(St,9,1),Lc=et(as,5,0),Oc=et(as,5,1),Ko=function(d){for(var a=d[0],e=1;e<d.length;++e)d[e]>a&&(a=d[e]);return a},Ke=function(d,a,e){var t=a/8|0;return(d[t]|d[t+1]<<8)>>(a&7)&e},Jo=function(d,a){var e=a/8|0;return(d[e]|d[e+1]<<8|d[e+2]<<16)>>(a&7)},_o=function(d){return(d+7)/8|0},ls=function(d,a,e){return(a==null||a<0)&&(a=0),(e==null||e>d.length)&&(e=d.length),new ce(d.subarray(a,e))},Kc=["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"],Ee=function(d,a,e){var t=new Error(a||Kc[d]);if(t.code=d,Error.captureStackTrace&&Error.captureStackTrace(t,Ee),!e)throw t;return t},Jc=function(d,a,e,t){var i=d.length,s=t?t.length:0;if(!i||a.f&&!a.l)return e||new ce(0);var n=!e,o=n||a.i!=2,r=a.i;n&&(e=new ce(i*3));var l=function(pe){var xe=e.length;if(pe>xe){var se=new ce(Math.max(xe*2,pe));se.set(e),e=se}},c=a.f||0,A=a.p||0,h=a.b||0,g=a.l,u=a.d,f=a.m,p=a.n,I=i*8;do{if(!g){c=Ke(d,A,1);var m=Ke(d,A+1,3);if(A+=3,m)if(m==1)g=Gc,u=Oc,f=9,p=5;else if(m==2){var y=Ke(d,A,31)+257,v=Ke(d,A+10,15)+4,E=y+Ke(d,A+5,31)+1;A+=14;for(var Q=new ce(E),b=new ce(19),D=0;D<v;++D)b[Yo[D]]=Ke(d,A+D*3,7);A+=v*3;for(var H=Ko(b),G=(1<<H)-1,x=et(b,H,1),D=0;D<E;){var U=x[Ke(d,A,G)];A+=U&15;var B=U>>4;if(B<16)Q[D++]=B;else{var R=0,M=0;for(B==16?(M=3+Ke(d,A,3),A+=2,R=Q[D-1]):B==17?(M=3+Ke(d,A,7),A+=3):B==18&&(M=11+Ke(d,A,127),A+=7);M--;)Q[D++]=R}}var k=Q.subarray(0,y),P=Q.subarray(y);f=Ko(k),p=Ko(P),g=et(k,f,1),u=et(P,p,1)}else Ee(1);else{var B=_o(A)+4,C=d[B-4]|d[B-3]<<8,w=B+C;if(w>i){r&&Ee(0);break}o&&l(h+C),e.set(d.subarray(B,w),h),a.b=h+=C,a.p=A=w*8,a.f=c;continue}if(A>I){r&&Ee(0);break}}o&&l(h+131072);for(var O=(1<<f)-1,L=(1<<p)-1,K=A;;K=A){var R=g[Jo(d,A)&O],V=R>>4;if(A+=R&15,A>I){r&&Ee(0);break}if(R||Ee(2),V<256)e[h++]=V;else if(V==256){K=A,g=null;break}else{var Y=V-254;if(V>264){var D=V-257,$=mn[D];Y=Ke(d,A,(1<<$)-1)+Ra[D],A+=$}var j=u[Jo(d,A)&L],le=j>>4;j||Ee(3),A+=j&15;var P=Rc[le];if(le>3){var $=Cn[le];P+=Jo(d,A)&(1<<$)-1,A+=$}if(A>I){r&&Ee(0);break}o&&l(h+131072);var oe=h+Y;if(h<P){var ie=s-P,te=Math.min(P,oe);for(ie+h<0&&Ee(3);h<te;++h)e[h]=t[ie+h]}for(;h<oe;++h)e[h]=e[h-P]}}a.l=g,a.p=K,a.b=h,a.f=c,g&&(c=1,a.m=f,a.d=u,a.n=p)}while(!c);return h!=e.length&&n?ls(e,0,h):e.subarray(0,h)},ut=function(d,a,e){e<<=a&7;var t=a/8|0;d[t]|=e,d[t+1]|=e>>8},os=function(d,a,e){e<<=a&7;var t=a/8|0;d[t]|=e,d[t+1]|=e>>8,d[t+2]|=e>>16},qo=function(d,a){for(var e=[],t=0;t<d.length;++t)d[t]&&e.push({s:t,f:d[t]});var i=e.length,s=e.slice();if(!i)return{t:La,l:0};if(i==1){var n=new ce(e[0].s+1);return n[e[0].s]=1,{t:n,l:1}}e.sort(function(w,y){return w.f-y.f}),e.push({s:-1,f:25001});var o=e[0],r=e[1],l=0,c=1,A=2;for(e[0]={s:-1,f:o.f+r.f,l:o,r};c!=i-1;)o=e[e[l].f<e[A].f?l++:A++],r=e[l!=c&&e[l].f<e[A].f?l++:A++],e[c++]={s:-1,f:o.f+r.f,l:o,r};for(var h=s[0].s,t=1;t<i;++t)s[t].s>h&&(h=s[t].s);var g=new De(h+1),u=Wo(e[c-1],g,0);if(u>a){var t=0,f=0,p=u-a,I=1<<p;for(s.sort(function(y,v){return g[v.s]-g[y.s]||y.f-v.f});t<i;++t){var m=s[t].s;if(g[m]>a)f+=I-(1<<u-g[m]),g[m]=a;else break}for(f>>=p;f>0;){var B=s[t].s;g[B]<a?f-=1<<a-g[B]++-1:++t}for(;t>=0&&f;--t){var C=s[t].s;g[C]==a&&(--g[C],++f)}u=a}return{t:new ce(g),l:u}},Wo=function(d,a,e){return d.s==-1?Math.max(Wo(d.l,a,e+1),Wo(d.r,a,e+1)):a[d.s]=e},xa=function(d){for(var a=d.length;a&&!d[--a];);for(var e=new De(++a),t=0,i=d[0],s=1,n=function(r){e[t++]=r},o=1;o<=a;++o)if(d[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=d[o]}return{c:e.subarray(0,t),n:a}},rs=function(d,a){for(var e=0,t=0;t<a.length;++t)e+=d[t]*a[t];return e},Ga=function(d,a,e){var t=e.length,i=_o(a+2);d[i]=t&255,d[i+1]=t>>8,d[i+2]=d[i]^255,d[i+3]=d[i+1]^255;for(var s=0;s<t;++s)d[i+s+4]=e[s];return(i+4+t)*8},Na=function(d,a,e,t,i,s,n,o,r,l,c){ut(a,c++,e),++i[256];for(var A=qo(i,15),h=A.t,g=A.l,u=qo(s,15),f=u.t,p=u.l,I=xa(h),m=I.c,B=I.n,C=xa(f),w=C.c,y=C.n,v=new De(19),E=0;E<m.length;++E)++v[m[E]&31];for(var E=0;E<w.length;++E)++v[w[E]&31];for(var Q=qo(v,7),b=Q.t,D=Q.l,H=19;H>4&&!b[Yo[H-1]];--H);var G=l+5<<3,x=rs(i,St)+rs(s,as)+n,U=rs(i,h)+rs(s,f)+n+14+3*H+rs(v,b)+2*v[16]+3*v[17]+7*v[18];if(r>=0&&G<=x&&G<=U)return Ga(a,c,d.subarray(r,r+l));var R,M,k,P;if(ut(a,c,1+(U<x)),c+=2,U<x){R=et(h,g,0),M=h,k=et(f,p,0),P=f;var O=et(b,D,0);ut(a,c,B-257),ut(a,c+5,y-1),ut(a,c+10,H-4),c+=14;for(var E=0;E<H;++E)ut(a,c+3*E,b[Yo[E]]);c+=3*H;for(var L=[m,w],K=0;K<2;++K)for(var V=L[K],E=0;E<V.length;++E){var Y=V[E]&31;ut(a,c,O[Y]),c+=b[Y],Y>15&&(ut(a,c,V[E]>>5&127),c+=V[E]>>12)}}else R=Uc,M=St,k=Lc,P=as;for(var E=0;E<o;++E){var $=t[E];if($>255){var Y=$>>18&31;os(a,c,R[Y+257]),c+=M[Y+257],Y>7&&(ut(a,c,$>>23&31),c+=mn[Y]);var j=$&31;os(a,c,k[j]),c+=P[j],j>3&&(os(a,c,$>>5&8191),c+=Cn[j])}else os(a,c,R[$]),c+=M[$]}return os(a,c,R[256]),c+M[256]},qc=new jo([65540,131080,131088,131104,262176,1048704,1048832,2114560,2117632]),La=new ce(0),$c=function(d,a,e,t,i,s){var n=s.z||d.length,o=new ce(t+n+5*(1+Math.ceil(n/7e3))+i),r=o.subarray(t,o.length-i),l=s.l,c=(s.r||0)&7;if(a){c&&(r[0]=s.r>>3);for(var A=qc[a-1],h=A>>13,g=A&8191,u=(1<<e)-1,f=s.p||new De(32768),p=s.h||new De(u+1),I=Math.ceil(e/3),m=2*I,B=function(ve){return(d[ve]^d[ve+1]<<I^d[ve+2]<<m)&u},C=new jo(25e3),w=new De(288),y=new De(32),v=0,E=0,Q=s.i||0,b=0,D=s.w||0,H=0;Q+2<n;++Q){var G=B(Q),x=Q&32767,U=p[G];if(f[x]=U,p[G]=x,D<=Q){var R=n-Q;if((v>7e3||b>24576)&&(R>423||!l)){c=Na(d,r,0,C,w,y,E,b,H,Q-H,c),b=v=E=0,H=Q;for(var M=0;M<286;++M)w[M]=0;for(var M=0;M<30;++M)y[M]=0}var k=2,P=0,O=g,L=x-U&32767;if(R>2&&G==B(Q-L))for(var K=Math.min(h,R)-1,V=Math.min(32767,Q),Y=Math.min(258,R);L<=V&&--O&&x!=U;){if(d[Q+k]==d[Q+k-L]){for(var $=0;$<Y&&d[Q+$]==d[Q+$-L];++$);if($>k){if(k=$,P=L,$>K)break;for(var j=Math.min(L,$-2),le=0,M=0;M<j;++M){var oe=Q-L+M&32767,ie=f[oe],te=oe-ie&32767;te>le&&(le=te,U=oe)}}}x=U,U=f[x],L+=x-U&32767}if(P){C[b++]=268435456|zo[k]<<18|Da[P];var pe=zo[k]&31,xe=Da[P]&31;E+=mn[pe]+Cn[xe],++w[257+pe],++y[xe],D=Q+k,++v}else C[b++]=d[Q],++w[d[Q]]}}for(Q=Math.max(Q,D);Q<n;++Q)C[b++]=d[Q],++w[d[Q]];c=Na(d,r,l,C,w,y,E,b,H,Q-H,c),l||(s.r=c&7|r[c/8|0]<<3,c-=7,s.h=p,s.p=f,s.i=Q,s.w=D)}else{for(var Q=s.w||0;Q<n+l;Q+=65535){var se=Q+65535;se>=n&&(r[c/8|0]=l,se=n),c=Ga(r,c+1,d.subarray(Q,se))}s.i=n}return ls(o,0,t+_o(c)+i)},Yc=function(){for(var d=new Int32Array(256),a=0;a<256;++a){for(var e=a,t=9;--t;)e=(e&1&&-306674912)^e>>>1;d[a]=e}return d}(),zc=function(){var d=-1;return{p:function(a){for(var e=d,t=0;t<a.length;++t)e=Yc[e&255^a[t]]^e>>>8;d=e},d:function(){return~d}}},Vc=function(d,a,e,t,i){if(!i&&(i={l:1},a.dictionary)){var s=a.dictionary.subarray(-32768),n=new ce(s.length+d.length);n.set(s),n.set(d,s.length),d=n,i.w=s.length}return $c(d,a.level==null?6:a.level,a.mem==null?i.l?Math.ceil(Math.max(8,Math.min(13,Math.log(d.length)))*1.5):20:12+a.mem,e,t,i)},Oa=function(d,a){var e={};for(var t in d)e[t]=d[t];for(var t in a)e[t]=a[t];return e},_e=function(d,a){return d[a]|d[a+1]<<8},He=function(d,a){return(d[a]|d[a+1]<<8|d[a+2]<<16|d[a+3]<<24)>>>0},$o=function(d,a){return He(d,a)+He(d,a+4)*4294967296},Be=function(d,a,e){for(;e;++a)d[a]=e,e>>>=8};Ka=function(d,a,e,t){for(var i in d){var s=d[i],n=a+i,o=t;Array.isArray(s)&&(o=Oa(t,s[1]),s=s[0]),ArrayBuffer.isView(s)?e[n]=[s,o]:(e[n+="/"]=[new ce(0),o],Ka(s,n,e,t))}},Ma=typeof TextEncoder<"u"&&new TextEncoder,Xo=typeof TextDecoder<"u"&&new TextDecoder,Zc=0;try{Xo.decode(La,{stream:!0}),Zc=1}catch{}jc=function(d){for(var a="",e=0;;){var t=d[e++],i=(t>127)+(t>223)+(t>239);if(e+i>d.length)return{s:a,r:ls(d,e-1)};i?i==3?(t=((t&15)<<18|(d[e++]&63)<<12|(d[e++]&63)<<6|d[e++]&63)-65536,a+=String.fromCharCode(55296|t>>10,56320|t&1023)):i&1?a+=String.fromCharCode((t&31)<<6|d[e++]&63):a+=String.fromCharCode((t&15)<<12|(d[e++]&63)<<6|d[e++]&63):a+=String.fromCharCode(t)}};_c=function(d,a){return a+30+_e(d,a+26)+_e(d,a+28)},ed=function(d,a,e){var t=_e(d,a+28),i=_e(d,a+30),s=er(d.subarray(a+46,a+46+t),!(_e(d,a+8)&2048)),n=a+46+t,o=td(d,n,i,e,He(d,a+20),He(d,a+24),He(d,a+42)),r=o[0],l=o[1],c=o[2];return[_e(d,a+10),r,l,s,n+i+_e(d,a+32),c]},td=function(d,a,e,t,i,s,n){var o=i==4294967295,r=s==4294967295,l=n==4294967295,c=a+e,A=o+r+l;if(t&&A){for(;a+4<c;a+=4+_e(d,a+2))if(_e(d,a)==1)return[o?$o(d,a+4+8*r):i,r?$o(d,a+4):s,l?$o(d,a+4+8*(r+o)):n,1];t<2&&Ee(13)}return[i,s,n,0]},Zo=function(d){var a=0;if(d)for(var e in d){var t=d[e].length;t>65535&&Ee(9),a+=t+4}return a},Ta=function(d,a,e,t,i,s,n,o){var r=t.length,l=e.extra,c=o&&o.length,A=Zo(l);Be(d,a,n!=null?33639248:67324752),a+=4,n!=null&&(d[a++]=20,d[a++]=e.os),d[a]=20,a+=2,d[a++]=e.flag<<1|(s<0&&8),d[a++]=i&&8,d[a++]=e.compression&255,d[a++]=e.compression>>8;var h=new Date(e.mtime==null?Date.now():e.mtime),g=h.getFullYear()-1980;if((g<0||g>119)&&Ee(10),Be(d,a,g<<25|h.getMonth()+1<<21|h.getDate()<<16|h.getHours()<<11|h.getMinutes()<<5|h.getSeconds()>>1),a+=4,s!=-1&&(Be(d,a,e.crc),Be(d,a+4,s<0?-s-2:s),Be(d,a+8,e.size)),Be(d,a+12,r),Be(d,a+14,A),a+=16,n!=null&&(Be(d,a,c),Be(d,a+6,e.attrs),Be(d,a+10,n),a+=14),d.set(t,a),a+=r,A)for(var u in l){var f=l[u],p=f.length;Be(d,a,+u),Be(d,a+2,p),d.set(f,a+4),a+=4+p}return c&&(d.set(o,a),a+=c),a},id=function(d,a,e,t,i){Be(d,a,101010256),Be(d,a+8,e),Be(d,a+10,e),Be(d,a+12,t),Be(d,a+16,i)}});var Va={};ki(Va,{bytesToStr:()=>Bn,unzipFiles:()=>wi,zipFiles:()=>cs});function nd(d){return typeof d=="string"?In(d):d instanceof Uint8Array?d:new Uint8Array(d)}function cs(d,a=6){let e={};for(let t of d)e[t.name]=[nd(t.data),{level:a}];return Promise.resolve(Ja(e,{level:a}))}function Bn(d){return er(d)}function wi(d){let a=d instanceof Uint8Array?d:new Uint8Array(d),e=0,t=0,i=s=>{if(t+=1,t>za)throw new Error(`Refusing to unzip: too many entries (>${za}) \u2014 possible zip bomb.`);if(s.originalSize>sd)throw new Error(`Refusing to unzip: entry "${s.name}" is ${Math.round(s.originalSize/1048576)} MiB \u2014 possible zip bomb.`);if(e+=s.originalSize,e>Ya)throw new Error(`Refusing to unzip: total size >${Math.round(Ya/1048576)} MiB \u2014 possible zip bomb.`);return!0};return Promise.resolve(qa(a,{filter:i}))}var Ya,sd,za,yn=qe(()=>{"use strict";$a();Ya=512*1024*1024,sd=256*1024*1024,za=2e4});var bd={};ki(bd,{default:()=>qn});module.exports=Nl(bd);var N=require("obsidian");var Si="sheet-group",nt="sheet-order",Vt="sheet-final",ur="sheet-label",bi="sheet-origin",Di="forked-from",$e="fork-siblings",Vn="forked-at",Wn=[Si,nt,Vt,ur,bi,Di,$e,Vn];function Ye(d){if(!d)return null;let a=d[Si];return typeof a=="string"&&a.trim()?a:null}function zn(d){let a=d?.[nt];return typeof a=="number"?a:null}function xi(d){return Ye(d)!==null&&zn(d)!==null}function Ni(d){return d?.[Vt]===!0}function fr(d){return d?.[bi]===!0}function Ml(d){let a=d?.[Di];return typeof a=="string"&&a.trim()?a:null}function Bs(d){return typeof d!="string"?null:d.replace(/^\[\[/,"").replace(/\]\]$/,"").split("|")[0].split("#")[0].trim()||null}function Ir(d){return Bs(Ml(d))}function Tl(d){let a=d?.[ur];return typeof a=="string"&&a.trim()?a:null}function mr(){let d=Date.now().toString(36),a=Math.floor(Math.random()*1e6).toString(36);return`s-${d}-${a}`}function ye(d,a){return a.file?d.metadataCache.getFileCache(a.file)?.frontmatter:null}function Xn(d,a){return a.slice().sort((e,t)=>{let i=zn(ye(d,e)),s=zn(ye(d,t));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=e.created??"",o=t.created??"";return n!==o?n<o?-1:1:e.id<t.id?-1:e.id>t.id?1:0})}function Cr(d,a){if(a.length===0)return null;let e=Xn(d,a);return e.find(t=>Ni(ye(d,t)))??e[0]}function Br(d,a,e){let t=Tl(ye(d,a));return t||e}ot();ae();var me=require("obsidian");var ne=require("obsidian");ae();function Qs(d){let a=(d.dateDisplayTimezone||"").trim();return a?{timeZone:a}:{}}function at(d,a){try{return new Intl.DateTimeFormat(void 0,a).format(new Date(d))}catch{let{timeZone:e,...t}=a;return new Intl.DateTimeFormat(void 0,t).format(new Date(d))}}function We(d,a){let e=Qs(a);switch(a.dateDisplayFormat??"locale"){case"iso":return kr(d,a,!0);case"us":return at(d,{...e,month:"numeric",day:"numeric",year:"numeric",hour:"numeric",minute:"2-digit"});case"eu":return at(d,{...e,day:"numeric",month:"numeric",year:"numeric",hour:"2-digit",minute:"2-digit",hourCycle:"h23"});case"long":return at(d,{...e,dateStyle:"full",timeStyle:"short"});case"locale":default:return at(d,{...e,dateStyle:"medium",timeStyle:"short"})}}function wt(d,a){let e=Qs(a);switch(a.dateDisplayFormat??"locale"){case"iso":return kr(d,a,!1);case"us":return at(d,{...e,month:"numeric",day:"numeric",year:"numeric"});case"eu":return at(d,{...e,day:"numeric",month:"numeric",year:"numeric"});case"long":return at(d,{...e,dateStyle:"full"});case"locale":default:{let t=new Date,i=new Date(d).getFullYear()===t.getFullYear();return at(d,i?{...e,month:"short",day:"numeric"}:{...e,month:"short",day:"numeric",year:"numeric"})}}}function jt(d,a){let e=Qs(a),t=a.dateDisplayFormat==="iso"||a.dateDisplayFormat==="eu";return at(d,{...e,hour:t?"2-digit":"numeric",minute:"2-digit",...t?{hourCycle:"h23"}:{}})}function kr(d,a,e){let t=Qs(a),i=new Intl.DateTimeFormat("en-CA",{...t,year:"numeric",month:"2-digit",day:"2-digit",...e?{hour:"2-digit",minute:"2-digit",hourCycle:"h23"}:{}}).formatToParts(new Date(d)),s=o=>i.find(r=>r.type===o)?.value??"",n=`${s("year")}-${s("month")}-${s("day")}`;return e?`${n} ${s("hour")}:${s("minute")}`:n}we();ae();function ao(d,a){let e=d.basename;return a&&e.endsWith(`-${a}`)?e=e.slice(0,-(a.length+1)):a||(e=e.replace(/-[abcdefghijkmnpqrstuvwxyz23456789]{6}$/,"")),e.replace(/-/g," ").trim()||d.basename}function Ss(d,a){let e=new Set(a.discoverStashpadFolders()),t=[];for(let i of d.vault.getMarkdownFiles()){let s=i.parent?.path?.replace(/\/+$/,"")??"";if(!e.has(s))continue;let n=d.metadataCache.getFileCache(i)?.frontmatter??{},o=typeof n.id=="string"?n.id:null;if(!o||o===S)continue;let r=n.completed===!0,l=Zt(n,"task")||n.task===!0||n.completed!==void 0,c=typeof n.due=="string"||typeof n.due=="number"?String(n.due):null,A=null;if(typeof n.due=="number")Number.isFinite(n.due)&&n.due>=1e11&&(A=n.due);else if(c){let h=Date.parse(c);Number.isNaN(h)||(A=h)}!l&&!r&&A==null&&!c||t.push({file:i,folder:s,id:o,title:ao(i,o),task:l,completed:r,due:A,dueRaw:c,color:typeof n.color=="string"?n.color:null,assignedTo:Tt(n),assignedBy:rt(n.assignedBy),author:rt(n.author)})}return t}var Gr=require("obsidian");var Xe=require("obsidian");we();var Ol=0,lo=[{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"}];function bs(){return{assign:"all",person:"",folder:"all",status:"all"}}function Yi(d,a,e,t,i){let s=()=>Yi(d,a,e,t,i);d.empty(),d.addClass("stashpad-task-triage");let n=Ss(a,e),o=(e.settings.authorId??"").trim(),r=k=>!!o&&k.assignedTo.some(P=>P.id===o),l=k=>{switch(t.assign){case"mine":return r(k);case"others":return k.assignedTo.length>0&&!r(k);case"byme":return!!o&&k.assignedBy?.id===o;case"unassigned":return k.assignedTo.length===0;default:return!0}},c=k=>!t.person||k.assignedTo.some(P=>P.id===t.person)||k.author?.id===t.person||k.assignedBy?.id===t.person,A=new Map;for(let k of n){for(let P of k.assignedTo)A.set(P.id,P.name);k.assignedBy&&A.set(k.assignedBy.id,k.assignedBy.name),k.author&&A.set(k.author.id,k.author.name)}let h=[...A.entries()].map(([k,P])=>({id:k,name:P})).sort((k,P)=>k.name.localeCompare(P.name)),g=[...new Set(n.map(k=>k.folder))].sort((k,P)=>k.localeCompare(P));t.folder!=="all"&&!g.includes(t.folder)&&(t.folder="all");let u=k=>t.folder==="all"||k.folder===t.folder,f=d.createDiv({cls:"stashpad-triage-filters"}),p=f.createEl("button",{cls:"stashpad-triage-reset",attr:{"aria-label":"Reset filters"}});(0,Xe.setIcon)(p,"rotate-ccw"),p.onclick=()=>{t.assign="all",t.person="",t.folder="all",s()};let I=f.createEl("select",{cls:"stashpad-triage-select"}),m={all:"Everyone",mine:"Assigned to me",others:"Assigned to others",byme:"Assigned by me",unassigned:"Unassigned"};for(let k of["all","mine","others","byme","unassigned"]){let P=I.createEl("option",{text:m[k],value:k});t.assign===k&&(P.selected=!0)}I.onchange=()=>{t.assign=I.value,s()};let B=f.createEl("select",{cls:"stashpad-triage-select"}),C=B.createEl("option",{text:"All folders",value:"all"});t.folder==="all"&&(C.selected=!0);for(let k of g){let P=B.createEl("option",{text:k.split("/").pop()||k,value:k});t.folder===k&&(P.selected=!0)}if(B.onchange=()=>{t.folder=B.value,s()},h.length>0){let k=new Map;for(let $ of h)k.has($.name)||k.set($.name,$.id);let P=`stashpad-task-authors-${++Ol}`,O=f.createDiv({cls:"stashpad-triage-authorwrap"}),L=O.createEl("input",{cls:"stashpad-triage-authorsearch",attr:{type:"text",list:P,placeholder:"Any person\u2026",spellcheck:"false"}}),K=O.createEl("button",{cls:"stashpad-triage-authorclear",attr:{"aria-label":"Clear person filter"}});(0,Xe.setIcon)(K,"x"),K.onclick=()=>{L.value="",t.person?(t.person="",s()):L.focus()};let V=O.createEl("datalist");V.id=P;for(let $ of h)V.createEl("option",{value:$.name});t.person&&(L.value=A.get(t.person)??"");let Y=()=>{let $=L.value.trim();if($===""){t.person&&(t.person="",s());return}let j=k.get($);j&&t.person!==j&&(t.person=j,s())};L.onchange=Y,L.addEventListener("keydown",$=>{$.key==="Enter"&&Y()})}let w=Date.now(),y=new Date;y.setHours(0,0,0,0);let v=y.getTime(),E=v+864e5,Q=n.filter(k=>l(k)&&c(k)&&u(k)),b={overdue:[],today:[],upcoming:[],nodate:[],completed:[]};for(let k of Q){if(k.completed){b.completed.push(k);continue}if(k.due==null){b.nodate.push(k);continue}k.due<v?b.overdue.push(k):k.due<E?b.today.push(k):b.upcoming.push(k)}let D=(k,P)=>k.due==null&&P.due==null?k.title.localeCompare(P.title):k.due==null?1:P.due==null?-1:k.due-P.due,H=d.createDiv({cls:"stashpad-triage-chips"}),G=(k,P,O)=>{let L=H.createEl("button",{cls:"stashpad-triage-chip"});t.status===k&&L.addClass("is-active"),L.createSpan({text:P}),L.createSpan({cls:"stashpad-triage-chip-count",text:String(O)}),L.onclick=()=>{t.status=k,s()}};G("all","All",Q.length);for(let k of lo)G(k.key,k.label,b[k.key].length);if(Q.length===0){d.createDiv({cls:"stashpad-tasks-empty"}).setText(n.length===0?"No tasks yet \u2014 press G on a note to make it a task, or D to give it a due date.":"No tasks match the current filters.");return}let x=async k=>{try{await a.fileManager.processFrontMatter(k.file,P=>{P.completed=P.completed!==!0})}catch(P){new Xe.Notice(`Couldn't update task: ${P.message}`);return}s()},U=k=>{let P=k.dueRaw??(k.due!=null?new Date(k.due).toISOString():null);new Ue(a,P,O=>{a.fileManager.processFrontMatter(k.file,L=>{O.iso===null?delete L.due:(L.due=O.iso,L.task=!0)}).then(s).catch(L=>new Xe.Notice(`Couldn't snooze: ${L.message}`))},{title:"Snooze \u2014 reschedule",hideAssignees:!0,quickAdjusts:e.settings.dueQuickAdjusts}).open()},R=t.status==="all"?lo:lo.filter(k=>k.key===t.status),M=!1;for(let k of R){let P=b[k.key];if(P.length===0)continue;if(M=!0,P.sort(k.key==="completed"?(L,K)=>D(K,L):D),t.status==="all"){let L=d.createDiv({cls:`stashpad-review-section is-${k.key}`});(0,Xe.setIcon)(L.createSpan({cls:"stashpad-review-section-icon"}),k.icon),L.createSpan({cls:"stashpad-review-section-name",text:k.label}),L.createSpan({cls:"stashpad-review-section-count",text:String(P.length)})}let O=d.createDiv({cls:"stashpad-review-list"});for(let L of P)Kl(O,L,w,e,{toggleCompleted:x,snooze:U,onOpen:i.onOpen})}M||d.createDiv({cls:"stashpad-tasks-empty"}).setText("Nothing in this view.")}function Kl(d,a,e,t,i){let s=d.createDiv({cls:"stashpad-review-row"});a.completed&&s.addClass("is-completed");let n=s.createSpan({cls:"stashpad-review-check"});(0,Xe.setIcon)(n,a.completed?"check-square":"square"),a.color&&(n.style.color=a.color),n.title=a.completed?"Mark not done":"Mark done",n.onclick=()=>i.toggleCompleted(a);let o=s.createDiv({cls:"stashpad-review-main"}),r=o.createDiv({cls:"stashpad-review-title",text:a.title});r.onclick=()=>i.onOpen(a.folder,a.id);let l=o.createDiv({cls:"stashpad-review-meta"});if(l.createSpan({cls:"stashpad-review-folder",text:a.folder.split("/").pop()||a.folder}),a.author&&l.createSpan({cls:"stashpad-review-author",text:`by ${a.author.name}`}),a.due!=null){let g=a.due<e&&!a.completed,u=new Date(e);u.setHours(0,0,0,0);let f=u.getTime(),p=a.due>=f&&a.due<f+864e5,I=l.createSpan({cls:"stashpad-review-due",text:p?jt(a.due,t.settings):wt(a.due,t.settings)});g&&I.addClass("is-overdue")}else a.dueRaw?l.createSpan({cls:"stashpad-review-due",text:a.dueRaw}):l.createSpan({cls:"stashpad-review-due is-none",text:"no date"});for(let g of a.assignedTo)l.createSpan({cls:"stashpad-review-assignee",text:g.name});let c=s.createDiv({cls:"stashpad-review-actions"}),A=c.createEl("button",{cls:"stashpad-review-btn"});(0,Xe.setIcon)(A,"alarm-clock"),A.title="Snooze \u2014 reschedule",A.onclick=()=>i.snooze(a);let h=c.createEl("button",{cls:"stashpad-review-btn"});(0,Xe.setIcon)(h,"arrow-right"),h.title="Open note",h.onclick=()=>i.onOpen(a.folder,a.id)}var oi=class extends Gr.Modal{constructor(e,t){super(e);this.plugin=t;this.state=bs()}onOpen(){this.modalEl.addClass("stashpad-task-review-modal"),this.titleEl.setText("Daily task review"),Yi(this.contentEl,this.app,this.plugin,this.state,{onOpen:(e,t)=>{this.plugin.revealNoteByRef(e,t),this.close()}})}onClose(){this.contentEl.empty()}};function Et(d,a,e){let t=d.createSpan({cls:"stashpad-count-badge"});e&&t.addClass("is-expanded"),t.setText(a>99?"99+":String(a))}var zi={pinned:{label:"Pinned",icon:"pin"},shared:{label:"Shared",icon:"users"},tasks:{label:"Tasks",icon:"check-circle-2"}},Ds=class extends ne.ItemView{constructor(e,t){super(e);this.plugin=t;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(e){this.activePanel=e,this.containerEl.isConnected&&this.render()}getViewType(){return Ct}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",e=>{e&&e.view.getViewType()===z&&this.scheduleRender()}))}scheduleRender(){this.renderTimer==null&&(this.renderTimer=window.setTimeout(()=>{this.renderTimer=null,this.containerEl.isConnected&&this.render()},80))}render(){let e=this.contentEl;e.empty(),e.addClass("stashpad-panels-root");let t=e.createDiv({cls:"stashpad-panels-globals"}),i=t.createEl("button",{cls:"stashpad-panels-global-btn"});(0,ne.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=t.createEl("button",{cls:"stashpad-panels-global-btn"});(0,ne.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=t.createDiv({cls:"stashpad-panels-globals-row"}),o=n.createEl("button",{cls:"stashpad-panels-global-btn"});(0,ne.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,ne.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 l=e.createDiv({cls:"stashpad-panels-bar"});for(let A of Object.keys(zi)){let h=zi[A],g=l.createEl("button",{cls:"stashpad-panels-bar-btn"});(0,ne.setIcon)(g.createSpan({cls:"stashpad-panels-bar-btn-icon"}),h.icon),g.createSpan({cls:"stashpad-panels-bar-btn-text",text:h.label}),this.activePanel===A&&g.addClass("is-active"),g.onclick=()=>{this.activePanel!==A&&(this.activePanel=A,this.render())}}let c=e.createDiv({cls:"stashpad-panels-body"});this.activePanel==="pinned"?this.renderPinnedPanel(c):this.activePanel==="shared"?this.renderSharedPanel(c):this.activePanel==="tasks"&&this.renderTasksPanel(c)}openPinnedOptionsMenu(e){let t=this.plugin.settings.folderPanelPinnedGrouping??"pin-order",i=new ne.Menu;i.addItem(s=>s.setTitle("Sort by pin order").setChecked(t==="pin-order").onClick(()=>void this.setPinnedGrouping("pin-order"))),i.addItem(s=>s.setTitle("Group by folder").setChecked(t==="folder").onClick(()=>void this.setPinnedGrouping("folder"))),i.showAtMouseEvent(e)}async setPinnedGrouping(e){(this.plugin.settings.folderPanelPinnedGrouping??"pin-order")!==e&&(this.plugin.settings.folderPanelPinnedGrouping=e,await this.plugin.saveSettings(),this.render())}renderPinnedPanel(e){let t=e.createDiv({cls:"stashpad-panel-pinned"});(this.plugin.settings.folderPanelPinnedGrouping??"pin-order")!=="folder"&&t.addClass("is-flat");let i=t.createDiv({cls:"stashpad-pinned-headrow"}),s=i.createEl("button",{cls:"stashpad-pinned-row stashpad-pinned-home"}),n=s.createSpan({cls:"stashpad-pinned-icon"});(0,ne.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,ne.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){t.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,u)=>this.renderPinnedRow(t,g,u));return}let c=new Map;r.forEach((g,u)=>{let f=c.get(g.folder);f||(f=[],c.set(g.folder,f)),f.push({pin:g,idx:u})});let A=this.plugin.lastActiveStashpadLeaf?.view?.noteFolder,h=Array.from(c.keys());A&&c.has(A)&&(h.splice(h.indexOf(A),1),h.unshift(A));for(let g of h){let u=g.split("/").pop()||g,f=t.createDiv({cls:"stashpad-pinned-group-header"});g===A&&f.addClass("is-active-folder"),f.createSpan({cls:"stashpad-pinned-group-name",text:u});let p=c.get(g)??[];for(let{pin:I,idx:m}of p)this.renderPinnedRow(t,I,m)}}renderPinnedRow(e,t,i){let s=this.findFileFor(t);if(!s)return;let n=this.app.metadataCache.getFileCache(s)?.frontmatter??{},o=this.titleFromFile(s),r=typeof n.color=="string"?n.color:null,l=n.completed===!0,c=this.childrenOf(t.folder,t.id).length,A=c>0,h=this.expanded.has(`${t.folder}|${t.id}`),g=e.createDiv({cls:"stashpad-pinned-row"});r&&g.addClass("has-color"),l&&g.addClass("is-completed"),g.draggable=!0,g.dataset.pinIdx=String(i),g.addEventListener("dragstart",m=>{m.dataTransfer?.setData("text/plain",String(i)),m.dataTransfer&&(m.dataTransfer.effectAllowed="move"),g.addClass("is-dragging")}),g.addEventListener("dragend",()=>g.removeClass("is-dragging")),g.addEventListener("dragover",m=>{m.preventDefault(),m.dataTransfer&&(m.dataTransfer.dropEffect="move");let B=g.getBoundingClientRect(),C=m.clientY-B.top<B.height/2;g.toggleClass("drop-before",C),g.toggleClass("drop-after",!C)}),g.addEventListener("dragleave",()=>{g.removeClass("drop-before"),g.removeClass("drop-after")}),g.addEventListener("drop",m=>{m.preventDefault(),g.removeClass("drop-before"),g.removeClass("drop-after");let B=parseInt(m.dataTransfer?.getData("text/plain")??"",10);if(!Number.isFinite(B)||B===i)return;let C=g.getBoundingClientRect(),w=m.clientY-C.top<C.height/2;this.reorderPin(B,w?i:i+1)});let u=g.createSpan({cls:"stashpad-pinned-toggle"});A&&(Et(u,c,h),u.onclick=m=>{m.stopPropagation();let B=`${t.folder}|${t.id}`;this.expanded.has(B)?this.expanded.delete(B):this.expanded.add(B),this.render()});let f=g.createSpan({cls:"stashpad-pinned-icon"});(0,ne.setIcon)(f,A?"folder-tree":"file-text"),r&&(f.style.color=r);let p=g.createSpan({cls:"stashpad-pinned-label",text:o});p.onclick=()=>this.openPinFromPanel(t);let I=t.folder.split("/").pop()||t.folder;if(g.createSpan({cls:"stashpad-pinned-folder",text:I}),g.oncontextmenu=m=>{m.preventDefault();let B=new ne.Menu;B.addItem(C=>C.setTitle("Unpin from sidebar").setIcon("pin-off").onClick(()=>{this.plugin.unpinNote(t)})),B.showAtMouseEvent(m)},A&&h){let m=e.createDiv({cls:"stashpad-pinned-children"});this.renderPinnedSubtree(m,t.folder,t.id,1)}}async reorderPin(e,t){let i=this.plugin.listPinnedNotes();if(e<0||e>=i.length)return;let s=i[e],n=i.filter((A,h)=>h!==e),o=Math.max(0,Math.min(t>e?t-1:t,n.length)),r=n[o-1],l=n[o],c;!r&&!l?c=Date.now():r?l?c=(r.pinnedAt+l.pinnedAt)/2:c=r.pinnedAt+1e3:c=l.pinnedAt-1e3;try{await this.app.fileManager.processFrontMatter(s.file,A=>{A.pinnedAt=c})}catch(A){console.warn("[Stashpad] pin reorder failed",A)}this.render()}renderPinnedSubtree(e,t,i,s){let n=this.childrenOf(t,i);for(let o of n){let r=this.app.metadataCache.getFileCache(o)?.frontmatter??{},l=typeof r.id=="string"?r.id:null;if(!l)continue;let c=typeof r.color=="string"?r.color:null,A=r.completed===!0,h=this.childrenOf(t,l).length,g=h>0,u=this.expanded.has(`${t}|${l}`),f=e.createDiv({cls:"stashpad-pinned-subrow"});A&&f.addClass("is-completed"),f.style.paddingLeft=`${s*16}px`;let p=f.createSpan({cls:"stashpad-pinned-toggle"});g&&(Et(p,h,u),p.onclick=B=>{B.stopPropagation();let C=`${t}|${l}`;this.expanded.has(C)?this.expanded.delete(C):this.expanded.add(C),this.render()});let I=f.createSpan({cls:"stashpad-pinned-icon"});(0,ne.setIcon)(I,"file-text"),c&&(I.style.color=c);let m=f.createSpan({cls:"stashpad-pinned-label",text:this.titleFromFile(o)});m.onclick=()=>this.openPinFromPanel({folder:t,id:l}),g&&u&&this.renderPinnedSubtree(e,t,l,s+1)}}findFileFor(e){for(let t of this.app.vault.getMarkdownFiles()){if((t.parent?.path?.replace(/\/+$/,"")??"")!==e.folder)continue;if(this.app.metadataCache.getFileCache(t)?.frontmatter?.id===e.id)return t}return null}childrenOf(e,t){let i=[];for(let s of this.app.vault.getMarkdownFiles()){if((s.parent?.path?.replace(/\/+$/,"")??"")!==e)continue;let o=this.app.metadataCache.getFileCache(s)?.frontmatter;if(!o||typeof o.id!="string")continue;let r=o.parent;if(r===t||t===S&&(r==null||r===S)){if(o.id===S)continue;i.push(s)}}return i.sort((s,n)=>{let o=this.app.metadataCache.getFileCache(s)?.frontmatter,r=this.app.metadataCache.getFileCache(n)?.frontmatter,l=o?.created??"",c=r?.created??"";return l.localeCompare(c)}),i}titleFromFile(e){let t=this.app.metadataCache.getFileCache(e)?.frontmatter?.id;return ao(e,typeof t=="string"?t:null)}async openSearchFromPanel(){let e=await this.resolveTargetStashpad();e&&typeof e.openSearchModal=="function"&&e.openSearchModal()}async openLogFromPanel(){let e=this.app.vault.adapter,t=this.plugin.pluginPrivatePath("log.jsonl");if(!await e.exists(t)){new ne.Notice("No log yet \u2014 make some changes first.");return}let i=await e.read(t),{LogModal:s}=await Promise.resolve().then(()=>(we(),$i));new s(this.app,i,t).open()}openNotificationsFromPanel(){this.app.commands?.executeCommandById?.("stashpad:stashpad-open-notification-history")}async openHomeFromPanel(){let e=await this.resolveTargetStashpad();e&&typeof e.navigateTo=="function"&&e.navigateTo(S)}async openPinFromPanel(e){await this.plugin.revealNoteByRef(e.folder,e.id)}async resolveTargetStashpad(){let e=this.plugin.lastActiveStashpadLeaf;if(e&&e.view.getViewType()===z)return this.app.workspace.revealLeaf(e),e.view;let t=this.findActiveStashpad();if(t)return t;let i=this.app.workspace.getLeavesOfType(z);return i.length>0?(this.app.workspace.revealLeaf(i[0]),i[0].view):(await this.plugin.activateView({reveal:!0}),this.findActiveStashpad())}findActiveStashpad(){let e=this.app.workspace.activeLeaf;return e&&e.view.getViewType()===z?e.view:null}renderSharedPanel(e){let t=e.createDiv({cls:"stashpad-panel-shared"}),i=(this.plugin.settings.authorId??"").trim();if(!i){t.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 A of s){let h=A.authorId;h&&!n.has(h)&&n.set(h,A.authorDisplay||h)}let o=t.createDiv({cls:"stashpad-shared-filters"}),r=(A,h,g)=>{let u=o.createEl("button",{cls:"stashpad-shared-chip",text:A});return h&&u.addClass("is-active"),u.onclick=g,u};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 A=o.createEl("select",{cls:"stashpad-shared-author-select"}),h=A.createEl("option",{text:"Any author"});h.value="__any__";for(let[u,f]of n){let p=A.createEl("option",{text:f});p.value=u}let g=["all","mine","others"].includes(this.sharedAuthorFilter)?"__any__":this.sharedAuthorFilter;A.value=g,A.onchange=()=>{let u=A.value;u==="__any__"?this.sharedAuthorFilter="all":this.sharedAuthorFilter=u,this.render()}}let l=o.createEl("button",{cls:"stashpad-shared-chip",text:"Has contributors"});this.sharedContribOnly&&l.addClass("is-active"),l.onclick=()=>{this.sharedContribOnly=!this.sharedContribOnly,this.render()};let c=s.filter(A=>{if(this.sharedContribOnly&&A.contributorCount===0)return!1;switch(this.sharedAuthorFilter){case"all":return!0;case"mine":return A.authorId===i;case"others":return A.authorId!==i;default:return A.authorId===this.sharedAuthorFilter}});if(c.length===0){t.createDiv({cls:"stashpad-shared-empty"}).setText("No shared notes match the current filters.");return}for(let A of c){let h=t.createDiv({cls:"stashpad-pinned-row stashpad-shared-row"}),g=h.createSpan({cls:"stashpad-pinned-icon"});(0,ne.setIcon)(g,"users"),A.color&&(g.style.color=A.color);let u=h.createSpan({cls:"stashpad-pinned-label",text:A.title});u.onclick=()=>this.openSharedFromPanel(A.folder,A.id);let f=A.folder.split("/").pop()||A.folder;h.createSpan({cls:"stashpad-pinned-folder",text:f}),A.authorDisplay&&h.createSpan({cls:"stashpad-shared-meta"}).setText(A.authorId===i?`you \xB7 ${A.contributorCount} contributor${A.contributorCount===1?"":"s"}`:`by ${A.authorDisplay}${A.contributorCount>0?` \xB7 ${A.contributorCount} contributor${A.contributorCount===1?"":"s"}`:""}`)}}collectSharedNotes(e){let t=this.plugin.discoverStashpadFolders(),i=new Set(t),s=new Map;for(let o of this.app.vault.getMarkdownFiles()){let r=o.parent?.path?.replace(/\/+$/,"")??"";if(!i.has(r))continue;let l=this.app.metadataCache.getFileCache(o)?.frontmatter??{};l.id===S&&s.set(r,this.extractAuthorId(l.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 l=this.app.metadataCache.getFileCache(o)?.frontmatter??{};if(typeof l.id!="string"||l.id===S)continue;let c=this.extractAuthorId(l.author),A=Array.isArray(l.contributors)?l.contributors.filter(B=>typeof B=="string"):[],h=s.get(r)??null;if(!(A.length>0||h===e&&(c!==null&&c!==e)))continue;let I=this.titleFromFile(o),m=typeof l.color=="string"?l.color:null;n.push({file:o,folder:r,id:l.id,title:I,color:m,authorId:c,authorDisplay:this.extractAuthorDisplay(l.author)||(c??""),contributorCount:A.length})}return n.sort((o,r)=>{let l=this.app.metadataCache.getFileCache(o.file)?.frontmatter??{},c=this.app.metadataCache.getFileCache(r.file)?.frontmatter??{},A=l.modified??l.created??"";return(c.modified??c.created??"").localeCompare(A)}),n}extractAuthorId(e){if(typeof e!="string")return null;let t=e.match(/-([a-z0-9]{4,12})(?:\.md)?(?:\||\]\])/i);return t?t[1]:null}extractAuthorDisplay(e){if(typeof e!="string")return"";let t=e.match(/\|([^\]]+)\]\]/);if(t)return t[1].trim();let i=e.match(/_authors\/([^\]|]+)-[a-z0-9]{4,12}/i);return i?i[1].replace(/[-_]/g," ").trim():""}async openSharedFromPanel(e,t){await this.plugin.revealNoteByRef(e,t)}renderTasksPanel(e){let t=e.createDiv({cls:"stashpad-panel-tasks"}),s=t.createDiv({cls:"stashpad-task-review-bar"}).createEl("button",{cls:"stashpad-task-review-open"});(0,ne.setIcon)(s.createSpan({cls:"stashpad-btn-icon"}),"maximize-2"),s.createSpan({text:"Daily review"}),s.onclick=()=>new oi(this.app,this.plugin).open();let n=this.collectTasks();if(n.length===0){t.createDiv({cls:"stashpad-tasks-empty"}).setText("No tasks yet \u2014 press G on a note to mark it a task, or D to give it a due date.");return}let o=(this.plugin.settings.authorId??"").trim(),r=M=>!!o&&M.assignedTo.some(k=>k.id===o),l=M=>{let k=this.taskAssignFilter;if(k.startsWith("person:")){let P=k.slice(7);return M.assignedTo.some(O=>O.id===P)}switch(k){case"mine":return r(M);case"others":return M.assignedTo.length>0&&!r(M);case"byme":return!!o&&M.assignedBy?.id===o;case"unassigned":return M.assignedTo.length===0;default:return!0}},c=new Map;for(let M of n){for(let k of M.assignedTo)k.id!==o&&c.set(k.id,k.name);M.assignedBy&&M.assignedBy.id!==o&&c.set(M.assignedBy.id,M.assignedBy.name)}let A=[...c.entries()].map(([M,k])=>({id:M,name:k})).sort((M,k)=>M.name.localeCompare(k.name)),h=t.createDiv({cls:"stashpad-task-assign-bar"});h.createSpan({cls:"stashpad-task-assign-label",text:"Assignment"});let g=h.createEl("select",{cls:"stashpad-task-assign-select"}),u=M=>{let k={all:"Everyone",mine:"Assigned to me",others:"Assigned to others",byme:"Assigned by me",unassigned:"Unassigned"};return M.startsWith("person:")?c.get(M.slice(7))??"Person":k[M]??M},f=M=>{let k=g.createEl("option",{text:u(M),value:M});this.taskAssignFilter===M&&(k.selected=!0)};for(let M of["all","mine","others","byme","unassigned"])f(M);if(A.length>0){let M=g.createEl("optgroup");M.setAttr("label","By person");for(let k of A){let P=M.createEl("option",{text:k.name,value:`person:${k.id}`});this.taskAssignFilter===`person:${k.id}`&&(P.selected=!0)}}g.onchange=()=>{this.taskAssignFilter=g.value,this.render()};let p=[...new Set(n.map(M=>M.folder))].sort((M,k)=>M.localeCompare(k));this.taskFolderFilter!=="all"&&!p.includes(this.taskFolderFilter)&&(this.taskFolderFilter="all");let I=t.createDiv({cls:"stashpad-task-assign-bar"});I.createSpan({cls:"stashpad-task-assign-label",text:"Folder"});let m=I.createEl("select",{cls:"stashpad-task-assign-select"}),B=m.createEl("option",{text:"All folders",value:"all"});this.taskFolderFilter==="all"&&(B.selected=!0);for(let M of p){let k=m.createEl("option",{text:M.split("/").pop()||M,value:M});this.taskFolderFilter===M&&(k.selected=!0)}m.onchange=()=>{this.taskFolderFilter=m.value,this.render()};let C=M=>this.taskFolderFilter==="all"||M.folder===this.taskFolderFilter,w=n.filter(M=>l(M)&&C(M));if(w.length===0){t.createDiv({cls:"stashpad-tasks-empty"}).setText("No tasks match the current filters.");return}let y=new Date;y.setHours(0,0,0,0);let v=y.getTime(),E=v+24*60*60*1e3,Q={overdue:[],today:[],upcoming:[],nodate:[],completed:[]};for(let M of w){if(M.completed){Q.completed.push(M);continue}if(M.due==null){Q.nodate.push(M);continue}M.due<v?Q.overdue.push(M):M.due<E?Q.today.push(M):Q.upcoming.push(M)}let b=(M,k)=>M.due==null&&k.due==null?M.title.localeCompare(k.title):M.due==null?1:k.due==null?-1:M.due-k.due,D=[{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"}],H=t.createDiv({cls:"stashpad-task-filters"}),G=w.length,x=(M,k,P)=>{let O=H.createEl("button",{cls:"stashpad-task-filter"});this.taskFilter===M&&O.addClass("is-active"),O.createSpan({cls:"stashpad-task-filter-label",text:k}),O.createSpan({cls:"stashpad-task-filter-count",text:String(P)}),O.onclick=()=>{this.taskFilter=M,this.render()}};x("all","All",G),x("overdue","Overdue",Q.overdue.length),x("today","Today",Q.today.length),x("upcoming","Upcoming",Q.upcoming.length),x("nodate","No date",Q.nodate.length),x("completed","Done",Q.completed.length);let U=this.taskFilter==="all"?D:D.filter(M=>M.key===this.taskFilter),R=!1;for(let M of U){let k=Q[M.key];if(k.length!==0){if(R=!0,k.sort(M.key==="completed"?(P,O)=>b(O,P):b),this.taskFilter==="all"){let P=t.createDiv({cls:`stashpad-task-section-header is-${M.key}`});(0,ne.setIcon)(P.createSpan({cls:"stashpad-task-section-icon"}),M.icon),P.createSpan({cls:"stashpad-task-section-name",text:M.label}),P.createSpan({cls:"stashpad-task-section-count",text:String(k.length)})}for(let P of k)this.renderTaskRow(t,P,M.key==="today")}}if(!R&&this.taskFilter!=="all"){t.createDiv({cls:"stashpad-tasks-empty"}).setText(`Nothing in "${U[0]?.label??this.taskFilter}".`);return}R||t.createDiv({cls:"stashpad-tasks-empty"}).setText("No tasks to show.")}renderTaskRow(e,t,i){let s=e.createDiv({cls:"stashpad-pinned-row stashpad-task-row"});t.color&&s.addClass("has-color"),t.completed&&s.addClass("is-completed");let n=s.createSpan({cls:"stashpad-pinned-icon stashpad-task-checkbox"});(0,ne.setIcon)(n,t.completed?"check-square":"square"),t.color&&(n.style.color=t.color),n.title=t.completed?"Mark not done":"Mark done",n.onclick=l=>{l.stopPropagation(),this.toggleTaskCompleted(t)};let o=s.createSpan({cls:"stashpad-pinned-label",text:t.title});if(o.onclick=()=>this.openTaskFromPanel(t.folder,t.id),s.createSpan({cls:"stashpad-task-folder",text:t.folder.split("/").pop()||t.folder}),t.due!=null){let l=s.createSpan({cls:"stashpad-task-due",text:this.formatDueShort(t.due,i)});t.due<Date.now()&&!t.completed&&l.addClass("is-overdue")}else t.dueRaw&&s.createSpan({cls:"stashpad-task-due",text:t.dueRaw});if(t.assignedTo.length>0){let l=(this.plugin.settings.authorId??"").trim(),c=s.createSpan({cls:"stashpad-task-assignees"});for(let A of t.assignedTo){let h=c.createSpan({cls:"stashpad-task-assignee"});l&&A.id===l&&h.addClass("is-me"),h.setText(this.initials(A.name)),h.title=l&&A.id===l?`${A.name} (you)`:A.name}}let r=s.createEl("button",{cls:"stashpad-task-snooze"});(0,ne.setIcon)(r,"alarm-clock"),r.title="Snooze \u2014 reschedule due date",r.onclick=l=>{l.stopPropagation(),this.snoozeTask(t)},s.oncontextmenu=l=>{l.preventDefault();let c=new ne.Menu;c.addItem(A=>A.setTitle("Open").setIcon("arrow-right").onClick(()=>{this.openTaskFromPanel(t.folder,t.id)})),c.addItem(A=>A.setTitle("Snooze (reschedule)\u2026").setIcon("alarm-clock").onClick(()=>{this.snoozeTask(t)})),c.showAtMouseEvent(l)}}snoozeTask(e){let t=e.dueRaw??(e.due!=null?new Date(e.due).toISOString():null);new Ue(this.app,t,i=>{this.app.fileManager.processFrontMatter(e.file,s=>{i.iso===null?delete s.due:(s.due=i.iso,s.task=!0)}).then(()=>this.scheduleRender()).catch(s=>new ne.Notice(`Couldn't snooze: ${s.message}`))},{title:"Snooze \u2014 reschedule",hideAssignees:!0,quickAdjusts:this.plugin.settings.dueQuickAdjusts}).open()}formatDueShort(e,t){return t?jt(e,this.plugin.settings):wt(e,this.plugin.settings)}async openTaskFromPanel(e,t){await this.plugin.revealNoteByRef(e,t)}async toggleTaskCompleted(e){try{await this.app.fileManager.processFrontMatter(e.file,t=>{t.completed=t.completed!==!0})}catch(t){new ne.Notice(`Couldn't update task: ${t.message}`);return}this.scheduleRender()}initials(e){let t=e.trim().split(/\s+/).filter(Boolean);return t.length===0?"?":t.length===1?t[0].slice(0,2).toUpperCase():(t[0][0]+t[t.length-1][0]).toUpperCase()}collectTasks(){return Ss(this.app,this.plugin)}};async function xs(d){let a=d.workspace.getLeavesOfType(Ct);if(a.length>0){d.workspace.revealLeaf(a[0]);return}let e=d.workspace.getLeftLeaf(!1);if(!e){new ne.Notice("Stashpad: couldn't open the panels view.");return}await e.setViewState({type:Ct,active:!0}),d.workspace.revealLeaf(e)}var Aa=require("obsidian");ae();var T=require("obsidian");Wi();var Rs=require("obsidian");ae();var li=class extends Rs.AbstractInputSuggest{constructor(e,t){super(e,t);this.inputEl=t}getSuggestions(e){let t=e.toLowerCase().split(/\s+/).filter(Boolean),i=o=>t.every(r=>o.toLowerCase().includes(r)),s=[],n=o=>{if(!(o.path!=="/"&&ys.has(o.name))){o.path!=="/"&&i(o.path)&&s.push(o);for(let r of o.children)r instanceof Rs.TFolder&&n(r)}};return n(this.app.vault.getRoot()),s.slice(0,100)}renderSuggestion(e,t){t.setText(e.path)}selectSuggestion(e){this.setValue(e.path),this.inputEl.dispatchEvent(new Event("input",{bubbles:!0})),this.close()}};var ci=require("obsidian"),Us=class d extends ci.AbstractInputSuggest{constructor(e,t){super(e,t);this.inputEl=t}static norm(e){return e.replace(/^lucide-/,"")}getSuggestions(e){let t=e.toLowerCase().split(/\s+/).filter(Boolean),i=new Set,s=[];for(let r of(0,ci.getIconIds)()){let l=d.norm(r);i.has(l)||(i.add(l),s.push(l))}let n=r=>t.every(l=>r.toLowerCase().includes(l)),o=t.length?s.filter(n):s;return o.sort(),o.slice(0,t.length?50:300)}renderSuggestion(e,t){t.addClass("stashpad-icon-suggest-item");let i=t.createSpan({cls:"stashpad-icon-suggest-icon"});(0,ci.setIcon)(i,e),t.createSpan({cls:"stashpad-icon-suggest-label",text:e})}selectSuggestion(e){this.setValue(e),this.inputEl.dispatchEvent(new Event("input",{bubbles:!0})),this.close()}};ae();we();var Lt=require("obsidian"),po={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."}},zl={info:4e3,success:4e3,warning:6e3,error:1e4},$r=5e3,Gs=class{constructor(a){this.app=a;this.history=[];this.nextId=1;this.historyLimit=$r;this.changeListeners=new Set;this.muted=new Set;this.defaultAuthorId=null}setDefaultAuthorId(a){this.defaultAuthorId=a||null}show(a){let e=a.kind??"info",t=a.category??"system",i={id:this.nextId++,ts:Date.now(),message:a.message,kind:e,category:t,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(t))return null;let s=this.buildContent(a,e),n=a.duration??zl[e];return new Lt.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,e){e?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 e=this.applyLimit(a.slice());this.history=e;let t=0;for(let i of e)i.id>t&&(t=i.id);this.nextId=Math.max(this.nextId,t+1),this.emit()}setHistoryLimit(a){this.historyLimit=Number.isFinite(a)?a:$r,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(e){console.warn("[Stashpad] notification listener failed",e)}}buildContent(a,e){let t=document.createDocumentFragment(),i=document.createElement("div");i.className=`stashpad-notice stashpad-notice-${e}`;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 l=document.createElement("button");l.className="stashpad-notice-action",l.textContent=r.label,l.addEventListener("click",c=>{if(c.stopPropagation(),Promise.resolve().then(()=>r.onClick()).catch(A=>console.warn("[Stashpad] notification action failed",A)),!r.keepOpen){let A=l.closest(".notice");A&&A.parentElement&&A.parentElement.removeChild(A)}}),o.appendChild(l)}i.appendChild(o)}return t.appendChild(i),t}};function Ls(d,a,e){let t=d.vault.getAbstractFileByPath(a);if(!(t instanceof Lt.TFile))return[];let i=[{label:"Reveal",keepOpen:!0,onClick:()=>{let s=d.workspace.getLeavesOfType("file-explorer")[0];if(!s)return;d.workspace.revealLeaf(s),s.view?.revealInFolder?.(t)}}];if(!e){let s=Lt.Platform.isMacOS?"Finder":Lt.Platform.isWin?"File Explorer":"file manager";i.push({label:`Show in ${s}`,keepOpen:!0,onClick:()=>{try{let n=window.require?.("electron")?.shell,r=d.vault.adapter?.getFullPath?.(a);r&&n?.showItemInFolder&&n.showItemInFolder(r)}catch(n){console.warn("[Stashpad] showItemInFolder failed",n)}}})}return i}var Yr=require("obsidian"),go=Yr.Platform.isMacOS;function di(d){if(!d)return"(none)";let a=d.replace(/\bMod\b/g,go?"Cmd":"Ctrl");return go&&(a=a.replace(/\bAlt\b/g,"Option")),a}function zr(d,a,e={allowSingleKey:!0}){let t=d.placeholder,i=d.value;d.placeholder="Press a key\u2026 (Backspace to cancel)",d.value="",d.classList.add("is-recording");let s=!1,n=()=>{d.placeholder=t,d.classList.remove("is-recording"),s||(d.value=i),d.removeEventListener("keydown",o,!0),d.removeEventListener("blur",r)},o=l=>{if(l.key==="Control"||l.key==="Shift"||l.key==="Alt"||l.key==="Meta"||l.key==="OS")return;let c=!!l.code&&(/^Key[A-Z]$/.test(l.code)||/^Digit\d$/.test(l.code));if((l.key==="Dead"||l.key==="Process"||l.key==="Unidentified")&&!c)return;if(l.preventDefault(),l.stopPropagation(),l.key==="Backspace"&&!l.metaKey&&!l.ctrlKey&&!l.altKey&&!l.shiftKey){n();return}let A=[];go?(l.metaKey&&A.push("Mod"),l.ctrlKey&&A.push("Ctrl")):l.ctrlKey&&A.push("Mod"),l.altKey&&A.push("Alt"),l.shiftKey&&A.push("Shift");let h=Vl(l.key,l.code);if(!h||A.length===0&&!e.allowSingleKey)return;A.push(h);let g=A.join("+");s=!0,n(),a(g)},r=()=>n();return d.addEventListener("keydown",o,!0),d.addEventListener("blur",r),n}function Vl(d,a){if(!d)return"";if(a){let e=/^Key([A-Z])$/.exec(a);if(e)return e[1];let t=/^Digit(\d)$/.exec(a);if(t)return t[1]}return d.length===1?d.toUpperCase():d}ri();ot();function Ot(d,a,e,t){function i(s){return s instanceof e?s:new e(function(n){n(s)})}return new(e||(e=Promise))(function(s,n){function o(c){try{l(t.next(c))}catch(A){n(A)}}function r(c){try{l(t.throw(c))}catch(A){n(A)}}function l(c){c.done?s(c.value):i(c.value).then(o,r)}l((t=t.apply(d,a||[])).next())})}var re=class{constructor(){this.mutex=Promise.resolve()}lock(){let a=()=>{};return this.mutex=this.mutex.then(()=>new Promise(a)),new Promise(e=>{a=e})}dispatch(a){return Ot(this,void 0,void 0,function*(){let e=yield this.lock();try{return yield Promise.resolve(a())}finally{e()}})}},uo;function Wl(){return typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:global}var Co=Wl(),fo=(uo=Co.Buffer)!==null&&uo!==void 0?uo:null,Xl=Co.TextEncoder?new Co.TextEncoder:null;function _r(d,a){return(d&15)+(d>>6|d>>3&8)<<4|(a&15)+(a>>6|a>>3&8)}function ea(d,a){let e=a.length>>1;for(let t=0;t<e;t++){let i=t<<1;d[t]=_r(a.charCodeAt(i),a.charCodeAt(i+1))}}function Zl(d,a){if(d.length!==a.length*2)return!1;for(let e=0;e<a.length;e++){let t=e<<1;if(a[e]!==_r(d.charCodeAt(t),d.charCodeAt(t+1)))return!1}return!0}var Vr=87,Wr=48;function Bo(d,a,e){let t=0;for(let i=0;i<e;i++){let s=a[i]>>>4;d[t++]=s>9?s+Vr:s+Wr,s=a[i]&15,d[t++]=s>9?s+Vr:s+Wr}return String.fromCharCode.apply(null,d)}var dt=fo!==null?d=>{if(typeof d=="string"){let a=fo.from(d,"utf8");return new Uint8Array(a.buffer,a.byteOffset,a.length)}if(fo.isBuffer(d))return new Uint8Array(d.buffer,d.byteOffset,d.length);if(ArrayBuffer.isView(d))return new Uint8Array(d.buffer,d.byteOffset,d.byteLength);throw new Error("Invalid data type!")}:d=>{if(typeof d=="string")return Xl.encode(d);if(ArrayBuffer.isView(d))return new Uint8Array(d.buffer,d.byteOffset,d.byteLength);throw new Error("Invalid data type!")},Ge="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",Zi=new Uint8Array(256);for(let d=0;d<Ge.length;d++)Zi[Ge.charCodeAt(d)]=d;function Xr(d,a=!0){let e=d.length,t=e%3,i=[],s=e-t;for(let n=0;n<s;n+=3){let o=(d[n]<<16&16711680)+(d[n+1]<<8&65280)+(d[n+2]&255),r=Ge.charAt(o>>18&63)+Ge.charAt(o>>12&63)+Ge.charAt(o>>6&63)+Ge.charAt(o&63);i.push(r)}if(t===1){let n=d[e-1],o=Ge.charAt(n>>2),r=Ge.charAt(n<<4&63);i.push(`${o}${r}`),a&&i.push("==")}else if(t===2){let n=(d[e-2]<<8)+d[e-1],o=Ge.charAt(n>>10),r=Ge.charAt(n>>4&63),l=Ge.charAt(n<<2&63);i.push(`${o}${r}${l}`),a&&i.push("=")}return i.join("")}function jl(d){let a=Math.floor(d.length*.75),e=d.length;return d[e-1]==="="&&(a-=1,d[e-2]==="="&&(a-=1)),a}function _l(d){let a=jl(d),e=d.length,t=new Uint8Array(a),i=0;for(let s=0;s<e;s+=4){let n=Zi[d.charCodeAt(s)],o=Zi[d.charCodeAt(s+1)],r=Zi[d.charCodeAt(s+2)],l=Zi[d.charCodeAt(s+3)];t[i]=n<<2|o>>4,i+=1,t[i]=(o&15)<<4|r>>2,i+=1,t[i]=(r&3)<<6|l&63,i+=1}return t}var Os=16*1024,Xi=4,ec=new re,Io=new Map;function ta(d,a){return Ot(this,void 0,void 0,function*(){let e=null,t=null,i=!1;if(typeof WebAssembly>"u")throw new Error("WebAssembly is not supported in this environment!");let s=(y,v=0)=>{t.set(y,v)},n=()=>t,o=()=>e.exports,r=y=>{e.exports.Hash_SetMemorySize(y);let v=e.exports.Hash_GetBuffer(),E=e.exports.memory.buffer;t=new Uint8Array(E,v,y)},l=()=>new DataView(e.exports.memory.buffer).getUint32(e.exports.STATE_SIZE,!0),c=ec.dispatch(()=>Ot(this,void 0,void 0,function*(){if(!Io.has(d.name)){let v=_l(d.data),E=WebAssembly.compile(v);Io.set(d.name,E)}let y=yield Io.get(d.name);e=yield WebAssembly.instantiate(y,{})})),A=()=>Ot(this,void 0,void 0,function*(){e||(yield c);let y=e.exports.Hash_GetBuffer(),v=e.exports.memory.buffer;t=new Uint8Array(v,y,Os)}),h=(y=null)=>{i=!0,e.exports.Hash_Init(y)},g=y=>{let v=0;for(;v<y.length;){let E=y.subarray(v,v+Os);v+=E.length,t.set(E),e.exports.Hash_Update(E.length)}},u=y=>{if(!i)throw new Error("update() called before init()");let v=dt(y);g(v)},f=new Uint8Array(a*2),p=(y,v=null)=>{if(!i)throw new Error("digest() called before init()");return i=!1,e.exports.Hash_Final(v),y==="binary"?t.slice(0,a):Bo(f,t,a)},I=()=>{if(!i)throw new Error("save() can only be called after init() and before digest()");let y=e.exports.Hash_GetState(),v=l(),E=e.exports.memory.buffer,Q=new Uint8Array(E,y,v),b=new Uint8Array(Xi+v);return ea(b,d.hash),b.set(Q,Xi),b},m=y=>{if(!(y instanceof Uint8Array))throw new Error("load() expects an Uint8Array generated by save()");let v=e.exports.Hash_GetState(),E=l(),Q=Xi+E,b=e.exports.memory.buffer;if(y.length!==Q)throw new Error(`Bad state length (expected ${Q} bytes, got ${y.length})`);if(!Zl(d.hash,y.subarray(0,Xi)))throw new Error("This state was written by an incompatible hash implementation");let D=y.subarray(Xi);new Uint8Array(b,v,E).set(D),i=!0},B=y=>typeof y=="string"?y.length<Os/4:y.byteLength<Os,C=B;switch(d.name){case"argon2":case"scrypt":C=()=>!0;break;case"blake2b":case"blake2s":C=(y,v)=>v<=512&&B(y);break;case"blake3":C=(y,v)=>v===0&&B(y);break;case"xxhash64":case"xxhash3":case"xxhash128":case"crc64":C=()=>!1;break}let w=(y,v=null,E=null)=>{if(!C(y,v))return h(v),u(y),p("hex",E);let Q=dt(y);return t.set(Q),e.exports.Hash_Calculate(Q.length,v,E),Bo(f,t,a)};return yield A(),{getMemory:n,writeMemory:s,getExports:o,setMemorySize:r,init:h,update:u,digest:p,save:I,load:m,calculate:w,hashLength:a}})}var wA=new re;var tc="argon2",ic="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",sc="e4cdc523",nc={name:tc,data:ic,hash:sc},oc="blake2b",rc="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=",ac="c6f286e6",lc={name:oc,data:rc,hash:ac},EA=new re;function Zr(d){return!Number.isInteger(d)||d<8||d>512||d%8!==0?new Error("Invalid variant! Valid values: 8, 16, ..., 512"):null}function cc(d,a){return d|a<<16}function yo(d=512,a=null){if(Zr(d))return Promise.reject(Zr(d));let e=null,t=d;if(a!==null){if(e=dt(a),e.length>64)return Promise.reject(new Error("Max key length is 64 bytes"));t=cc(d,e.length)}let i=d/8;return ta(lc,i).then(s=>{t>512&&s.writeMemory(e),s.init(t);let n={init:t>512?()=>(s.writeMemory(e),s.init(t),n):()=>(s.init(t),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 dc(d,a,e){let t=[`m=${a.memorySize}`,`t=${a.iterations}`,`p=${a.parallelism}`].join(",");return`$argon2${a.hashType}$v=19$${t}$${Xr(d,!1)}$${Xr(e,!1)}`}var jr=new DataView(new ArrayBuffer(4));function ct(d){return jr.setInt32(0,d,!0),new Uint8Array(jr.buffer)}function mo(d,a,e){return Ot(this,void 0,void 0,function*(){if(e<=64){let r=yield yo(e*8);return r.update(ct(e)),r.update(a),r.digest("binary")}let t=Math.ceil(e/32)-2,i=new Uint8Array(e);d.init(),d.update(ct(e)),d.update(a);let s=d.digest("binary");i.set(s.subarray(0,32),0);for(let r=1;r<t;r++)d.init(),d.update(s),s=d.digest("binary"),i.set(s.subarray(0,32),r*32);let n=e-32*t,o;return n===64?(o=d,o.init()):o=yield yo(n*8),o.update(s),s=o.digest("binary"),i.set(s.subarray(0,n),t*32),i})}function Ac(d){switch(d){case"d":return 0;case"i":return 1;default:return 2}}function hc(d){return Ot(this,void 0,void 0,function*(){var a;let{parallelism:e,iterations:t,hashLength:i}=d,s=dt(d.password),n=dt(d.salt),o=19,r=Ac(d.hashType),{memorySize:l}=d,c=dt((a=d.secret)!==null&&a!==void 0?a:""),[A,h]=yield Promise.all([ta(nc,1024),yo(512)]);A.setMemorySize(l*1024+1024);let g=new Uint8Array(24),u=new DataView(g.buffer);u.setInt32(0,e,!0),u.setInt32(4,i,!0),u.setInt32(8,l,!0),u.setInt32(12,t,!0),u.setInt32(16,o,!0),u.setInt32(20,r,!0),A.writeMemory(g,l*1024),h.init(),h.update(g),h.update(ct(s.length)),h.update(s),h.update(ct(n.length)),h.update(n),h.update(ct(c.length)),h.update(c),h.update(ct(0));let p=Math.floor(l/(e*4))*4,I=new Uint8Array(72),m=h.digest("binary");I.set(m);for(let w=0;w<e;w++){I.set(ct(0),64),I.set(ct(w),68);let y=w*p,v=yield mo(h,I,1024);A.writeMemory(v,y*1024),y+=1,I.set(ct(1),64),v=yield mo(h,I,1024),A.writeMemory(v,y*1024)}let B=new Uint8Array(1024);ea(B,A.calculate(new Uint8Array([]),l));let C=yield mo(h,B,i);if(d.outputType==="hex"){let w=new Uint8Array(i*2);return Bo(w,C,i)}return d.outputType==="encoded"?dc(n,d,C):C})}var pc=d=>{var a;if(!d||typeof d!="object")throw new Error("Invalid options parameter. It requires an object.");if(!d.password)throw new Error("Password must be specified");if(d.password=dt(d.password),d.password.length<1)throw new Error("Password must be specified");if(!d.salt)throw new Error("Salt must be specified");if(d.salt=dt(d.salt),d.salt.length<8)throw new Error("Salt should be at least 8 bytes long");if(d.secret=dt((a=d.secret)!==null&&a!==void 0?a:""),!Number.isInteger(d.iterations)||d.iterations<1)throw new Error("Iterations should be a positive number");if(!Number.isInteger(d.parallelism)||d.parallelism<1)throw new Error("Parallelism should be a positive number");if(!Number.isInteger(d.hashLength)||d.hashLength<4)throw new Error("Hash length should be at least 4 bytes.");if(!Number.isInteger(d.memorySize))throw new Error("Memory size should be specified.");if(d.memorySize<8*d.parallelism)throw new Error("Memory size should be at least 8 * parallelism.");if(d.outputType===void 0&&(d.outputType="hex"),!["hex","binary","encoded"].includes(d.outputType))throw new Error(`Insupported output type ${d.outputType}. Valid values: ['hex', 'binary', 'encoded']`)};function wo(d){return Ot(this,void 0,void 0,function*(){return pc(d),hc(Object.assign(Object.assign({},d),{hashType:"id"}))})}var QA=new re;var vA=new re;var FA=new re;var kA=new re;var SA=new Uint8Array(8);var bA=new re;var DA=new re;var xA=new re;var NA=new re;var MA=new re;var TA=new re;var PA=new re;var HA=new re;var RA=new re;var UA=new re;var GA=new re;var LA=new Uint8Array(8);var OA=new re;var KA=new Uint8Array(8);var JA=new re;var qA=new Uint8Array(8);var $A=new re;var YA=new re;var zA=new re;we();var Le=new Uint8Array([83,84,65,83,72,69,78,67]),vo=2,Fo=1,ko=2,na=3,gc=32,Ai=12,Eo=32,uc=6e5,fc=47104,Ic=3,mc=1,ge=d=>d;function Me(d){if(d.length<Le.length+1)return!1;for(let a=0;a<Le.length;a++)if(d[a]!==Le[a])return!1;return!0}function ia(d,a,e){d[a]=e>>>24&255,d[a+1]=e>>>16&255,d[a+2]=e>>>8&255,d[a+3]=e&255}function sa(d,a){return d[a]*16777216+(d[a+1]<<16)+(d[a+2]<<8)+d[a+3]}async function Qo(d,a,e){if(e.id===ko)return await wo({password:d,salt:a,parallelism:e.c,iterations:e.b,memorySize:e.a,hashLength:Eo,outputType:"binary"});if(e.id===Fo){let t=await crypto.subtle.importKey("raw",ge(new TextEncoder().encode(d)),"PBKDF2",!1,["deriveBits"]),i=await crypto.subtle.deriveBits({name:"PBKDF2",salt:ge(a),iterations:e.a,hash:"SHA-256"},t,Eo*8);return new Uint8Array(i)}throw new Error(`Unsupported KDF id (${e.id}).`)}async function Ks(d){return crypto.subtle.importKey("raw",ge(d),{name:"AES-GCM"},!1,["encrypt","decrypt"])}var So={argon2id:{label:"Argon2id",strong:!0},pbkdf2:{label:"PBKDF2 (fallback)",strong:!1}};async function At(d,a){let e=crypto.getRandomValues(new Uint8Array(gc)),t=crypto.getRandomValues(new Uint8Array(Ai)),i,s,n;try{i={id:ko,a:fc,b:Ic,c:mc},n=await Qo(a,e,i),s="argon2id"}catch(A){console.warn("[Stashpad] Argon2id unavailable \u2014 encrypting with PBKDF2 fallback.",A),i={id:Fo,a:uc,b:0,c:0},n=await Qo(a,e,i),s="pbkdf2"}let o=oa(i,e,t),r=await Ks(n),l=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:ge(t),additionalData:ge(o)},r,ge(d))),c=new Uint8Array(o.length+l.length);return c.set(o,0),c.set(l,o.length),{data:c,kdf:s}}var ji=null;async function _i(){if(ji!==null)return ji;try{await wo({password:"x",salt:new Uint8Array(16),parallelism:1,iterations:1,memorySize:8,hashLength:16,outputType:"binary"}),ji=!0}catch{ji=!1}return ji}function oa(d,a,e){let t=new Uint8Array(Le.length+1+1+4+4+1+1+a.length+e.length),i=0;return t.set(Le,i),i+=Le.length,t[i++]=vo,t[i++]=d.id,ia(t,i,d.a),i+=4,ia(t,i,d.b),i+=4,t[i++]=d.c,t[i++]=a.length,t.set(a,i),i+=a.length,t.set(e,i),i+=e.length,t}async function hi(d,a){if(!Me(d))throw new Error("Not an encrypted Stashpad file.");let e=d[Le.length];if(e===1)return Cc(d,a);if(e!==vo)throw new Error(`Unsupported encrypted .stash version (${e}).`);let t=Le.length+1,i={id:d[t++],a:0,b:0,c:0};if(i.a=sa(d,t),t+=4,i.b=sa(d,t),t+=4,i.c=d[t++],i.id===ko){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===Fo&&i.a>1e7)throw new Error("Unsupported KDF parameters (file may be corrupted or malicious).");let s=d[t++];if(s<8||s>64)throw new Error("Unsupported KDF parameters (file may be corrupted or malicious).");let n=d.slice(t,t+s);t+=s;let o=d.slice(t,t+Ai);t+=Ai;let r=d.slice(0,t),l=d.slice(t),c=await Qo(a,n,i),A=await Ks(c),h=await crypto.subtle.decrypt({name:"AES-GCM",iv:ge(o),additionalData:ge(r)},A,ge(l));return new Uint8Array(h)}async function Cc(d,a){let e=Le.length+1,t=d.slice(e,e+16);e+=16;let i=d.slice(e,e+12);e+=12;let s=d.slice(e),n=await crypto.subtle.importKey("raw",ge(new TextEncoder().encode(a)),"PBKDF2",!1,["deriveKey"]),o=await crypto.subtle.deriveKey({name:"PBKDF2",salt:ge(t),iterations:21e4,hash:"SHA-256"},n,{name:"AES-GCM",length:256},!1,["decrypt"]),r=await crypto.subtle.decrypt({name:"AES-GCM",iv:ge(i)},o,ge(s));return new Uint8Array(r)}async function es(d,a){if(a.length!==Eo)throw new Error("Encryption key must be 32 bytes.");let e=crypto.getRandomValues(new Uint8Array(Ai)),i=oa({id:na,a:0,b:0,c:0},new Uint8Array(0),e),s=await Ks(a),n=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:ge(e),additionalData:ge(i)},s,ge(d))),o=new Uint8Array(i.length+n.length);return o.set(i,0),o.set(n,i.length),o}async function Oe(d,a){if(!Me(d))throw new Error("Not an encrypted Stashpad file.");let e=d[Le.length];if(e!==vo)throw new Error(`Unsupported encrypted version (${e}).`);let t=Le.length+1;if(d[t++]!==na)throw new Error("Not a raw-key (.stashenc) envelope.");t+=9;let s=d[t++];t+=s;let n=d.slice(t,t+Ai);t+=Ai;let o=d.slice(0,t),r=d.slice(t),l=await Ks(a),c=await crypto.subtle.decrypt({name:"AES-GCM",iv:ge(n),additionalData:ge(o)},l,ge(r));return new Uint8Array(c)}async function pi(d,a,e={}){if(!Me(a))return a;if(e.secretId){let i=d.secretStorage,s=null;try{s=i?.getSecret(e.secretId)??null}catch{s=null}if(s)try{return await hi(a,s)}catch{}}let t;for(;;){let i=await new Promise(s=>{new Ui(d,t,!!e.allowLater,s).open()});if(i.kind==="cancel")return null;if(i.kind==="later")return e.onLater?.(),null;try{return await hi(a,i.value)}catch{t="Wrong password or corrupted file. Try again."}}}ot();var Kt=".stashpad/keys.json",Bc=".stashpad",gi="_keys";var Js=class{constructor(a){this.app=a}get a(){return this.app.vault.adapter}validate(a){let e=a;return!!e&&e.v===2&&typeof e.keyId=="string"&&Array.isArray(e.identities)&&Array.isArray(e.slots)&&Array.isArray(e.joinRequests)}async readValid(a){try{if(!await this.a.exists(a))return null;let e=JSON.parse(await this.a.read(a));return this.validate(e)?e:null}catch{return null}}async load(){let a=await this.readValid(Kt);if(a)return a;try{let t=((await this.a.list(gi)).files||[]).filter(i=>/\/keys-\d+\.json$/.test(i)).sort();for(let i of t.reverse()){let s=await this.readValid(i);if(s)return s}}catch{}return null}async exists(){return await this.load()!==null}async hasAnyFile(){try{if(await this.a.exists(Kt))return!0}catch{}try{return((await this.a.list(gi)).files||[]).some(e=>/\/keys-\d+\.json$/.test(e))}catch{return!1}}async ensureDir(a){try{await this.a.exists(a)||await this.a.mkdir(a)}catch{}}async save(a){let e=JSON.stringify(a,null,2);await this.ensureDir(Bc);let t=`${Kt}.tmp`,i=!1;try{await this.a.write(t,e);try{await this.a.rename(t,Kt)}catch{try{await this.a.remove(Kt)}catch{}await this.a.rename(t,Kt)}i=!0}catch{try{await this.a.exists(t)&&await this.a.remove(t)}catch{}}i||await this.a.write(Kt,e),await this.ensureDir(gi);for(let s=4;s>=1;s--){let n=`${gi}/keys-${s}.json`,o=`${gi}/keys-${s+1}.json`;try{await this.a.exists(n)&&await this.a.write(o,await this.a.read(n))}catch{}}try{await this.a.write(`${gi}/keys-1.json`,e)}catch{}}};ot();var yc=".stashkey",ra=32;function bo(d){let a="";for(let e=0;e<d.length;e++)a+=String.fromCharCode(d[e]);return btoa(a)}function wc(d){let a=atob(d),e=new Uint8Array(a.length);for(let t=0;t<a.length;t++)e[t]=a.charCodeAt(t);return e}var qs=()=>new Date().toISOString(),$s=class{constructor(a){this.app=a}get a(){return this.app.vault.adapter}keyPath(a){return`${a.replace(/\/+$/,"")}/${yc}`}validate(a){let e=a;return!!e&&e.v===1&&typeof e.keyId=="string"&&typeof e.folderPath=="string"&&Array.isArray(e.slots)&&e.slots.every(t=>t&&typeof t.wrapped=="string"&&typeof t.id=="string")}async read(a){let e=this.keyPath(a);try{if(!await this.a.exists(e))return null;let t=JSON.parse(await this.a.read(e));return this.validate(t)?t:null}catch{return null}}async hasFile(a){try{return await this.a.exists(this.keyPath(a))}catch{return!1}}async write(a,e){let t=this.keyPath(a),i=JSON.stringify(e,null,2),s=`${t}.tmp`,n=!1;try{await this.a.write(s,i);try{await this.a.rename(s,t)}catch{try{await this.a.remove(t)}catch{}await this.a.rename(s,t)}n=!0}catch{try{await this.a.exists(s)&&await this.a.remove(s)}catch{}}n||await this.a.write(t,i)}async remove(a){try{await this.a.remove(this.keyPath(a))}catch{}}async create(a,e,t){if(!e)throw new Error("Password required.");let i=crypto.getRandomValues(new Uint8Array(ra)),s=await At(i,e);return{sk:{v:1,keyId:t??Ae(8),folderPath:a.replace(/\/+$/,""),slots:[{id:Ae(8),label:"Folder password",wrapped:bo(s.data),kdf:s.kdf,createdAt:qs()}],createdAt:qs()},dek:i}}async unlock(a,e){for(let t of a.slots)try{let i=await hi(wc(t.wrapped),e);if(i.length!==ra){i.fill(0);continue}return i}catch{}return null}async changePassword(a,e,t){if(!t)throw new Error("Password required.");let i=await At(e,t),s=a.slots.filter(o=>o.recovery),n={id:Ae(8),label:"Folder password",wrapped:bo(i.data),kdf:i.kdf,createdAt:qs()};return{...a,slots:[n,...s]}}async setRecovery(a,e,t){if(!t)throw new Error("Recovery password required.");let i=await At(e,t),s=a.slots.filter(o=>!o.recovery),n={id:Ae(8),label:"Recovery password",wrapped:bo(i.data),kdf:i.kdf,createdAt:qs(),recovery:!0};return{...a,slots:[...s,n]}}removeRecovery(a){return{...a,slots:a.slots.filter(e=>!e.recovery)}}hasRecovery(a){return a.slots.some(e=>e.recovery)}};var Ec="stashpad-vault-encryption";function zs(){return{}}function Qc(d){let a="";for(let e=0;e<d.length;e++)a+=String.fromCharCode(d[e]);return btoa(a)}function vc(d){let a=atob(d),e=new Uint8Array(a.length);for(let t=0;t<a.length;t++)e[t]=a.charCodeAt(t);return e}var Ys=class{constructor(a,e,t){this.app=a;this.load=e;this.save=t;this.folderSessionKeys=new Map;this.kf=null;this.folderKeyFiles=new Map;this.stashKeysIndexed=!1;this.parkedKeyMaterial=!1;this.keyfiles=new Js(a),this.folderKeystore=new $s(a)}argonProbe(){return _i()}async init(){await this.refresh(),this.parkedKeyMaterial=await this.detectParkedKeyMaterial()}async refresh(){this.kf=await this.keyfiles.load(),this.stashKeysIndexed||await this.indexStashKeys()}async detectParkedKeyMaterial(){let a=this.app.vault.adapter;try{let e=await a.list("_keys");if((e.files||[]).some(t=>/\.json$/.test(t))||(e.folders||[]).length)return!0}catch{}try{if(((await a.list(".stashpad")).folders||[]).some(t=>/\/retired-keyfile-/.test(t)))return!0}catch{}return!1}invalidateStashKeyIndex(){this.stashKeysIndexed=!1}async migrateKeyfileToStashKeys(){await this.refresh();let a=this.kf?.folderKeys;if(!a)return 0;let e=0;for(let[t,i]of Object.entries(a)){let s=this.cleanFolder(t);if(this.folderKeyFiles.has(s)||await this.folderKeystore.hasFile(s))continue;let n=(i.passwordSlots??[]).filter(r=>!r.label.startsWith("[deprecated]"));if(!n.length)continue;let o={v:1,keyId:i.keyId,folderPath:s,slots:n.map((r,l)=>({id:r.id,label:l===0?"Folder password":r.label,wrapped:r.wrapped,kdf:r.kdf,createdAt:r.createdAt})),createdAt:i.createdAt};try{await this.folderKeystore.write(s,o);let r=await this.folderKeystore.read(s);if(!r||r.slots[0]?.wrapped!==o.slots[0].wrapped){await this.folderKeystore.remove(s);continue}this.folderKeyFiles.set(s,o),e++}catch{}}return e}async indexStashKeys(){let a=new Map,e=new Set([".git",".obsidian","node_modules"]),t=async i=>{let s;try{s=await this.app.vault.adapter.list(i)}catch{return}for(let n of s.files??[])if(n===".stashkey"||n.endsWith("/.stashkey")){let o=n.includes("/")?n.slice(0,n.lastIndexOf("/")):"",r=await this.folderKeystore.read(o);r&&a.set(this.cleanFolder(o),r)}for(let n of s.folders??[])e.has(n.split("/").pop()??"")||await t(n)};await t(""),this.folderKeyFiles=a,this.stashKeysIndexed=!0}stashKeyToEntry(a,e){return{keyId:a.keyId,folderPath:this.cleanFolder(e),label:a.slots[0]?.label??"Folder password",kcId:this.folderKcId(e,a.keyId),passwordSlots:a.slots.map(t=>({id:t.id,label:t.label,wrapped:t.wrapped,kdf:t.kdf,createdAt:t.createdAt})),createdAt:a.createdAt}}secretStore(){return this.app.secretStorage??null}keychainAvailable(){return!!this.secretStore()}async parkThenSet(a,e){let t=this.secretStore();if(!t)return;let i=[a];try{let s=t.getSecret(a);if(s&&s!==e){let n=Date.now().toString(36),o=`${a.slice(0,64-(n.length+2))}-r${n}`;await t.setSecret(o,s),i.push(o)}}catch{}await t.setSecret(a,e),await this.recordKeychainIds(i)}async recordKeychainIds(a){try{let e=this.load(),t=new Set(e.knownKeychainIds??[]),i=!1;for(let s of a)s&&!t.has(s)&&(t.add(s),i=!0);i&&await this.save({...e,knownKeychainIds:[...t]})}catch{}}keychainCandidateIds(){return[...new Set(this.load().knownKeychainIds??[])]}hasAnyFolderKey(){return this.folderKeyFiles.size>0||Object.keys(this.kf?.folderKeys??{}).length>0}isConfigured(){return this.hasAnyFolderKey()}owningFolder(a){let e=this.kf?.folderKeys,t=this.cleanFolder(a);for(;t;){if(this.folderKeyFiles.has(t)||e&&Object.prototype.hasOwnProperty.call(e,t))return t;let i=t.lastIndexOf("/");if(i<0)break;t=t.slice(0,i)}return null}hasOwnFolderKey(a){let e=this.cleanFolder(a);if(this.folderKeyFiles.has(e))return!0;let t=this.kf?.folderKeys;return!!t&&Object.prototype.hasOwnProperty.call(t,e)}folderKeyEntry(a){let e=this.owningFolder(a);if(!e)return null;let t=this.folderKeyFiles.get(e);return t?this.stashKeyToEntry(t,e):this.kf?.folderKeys?.[e]??null}hasFolderKey(a){return this.owningFolder(a)!==null}folderPathByKeyId(a){for(let[e,t]of this.folderKeyFiles)if(t.keyId===a)return e;for(let[e,t]of Object.entries(this.kf?.folderKeys??{}))if(t.keyId===a)return e;return null}folderActiveSlots(a){return(a.passwordSlots??[]).filter(e=>!e.label.startsWith("[deprecated]"))}isFolderUnlocked(a){let e=this.owningFolder(a);return e?this.folderSessionKeys.has(e):!1}getFolderKey(a){let e=this.owningFolder(a);if(!e)return null;let t=this.folderSessionKeys.get(e);return t?t.slice():null}async setupFolderKey(a,e,t,i=!1){if(!e)throw new Error("Password required.");await this.refresh();let s=this.cleanFolder(a);if(this.hasOwnFolderKey(s))throw new Error("This folder already has its own key.");let n=this.owningFolder(s);if(n&&n!==s)throw new Error(`A parent folder (\u201C${n.split("/").pop()}\u201D) already has its own password; this folder inherits it.`);let{sk:o,dek:r}=await this.folderKeystore.create(s,e);await this.folderKeystore.write(s,o),this.folderKeyFiles.set(s,o),this.folderSessionKeys.set(s,r),i&&await this.rememberFolder(this.folderKcId(s,o.keyId),e)}async unlockFolder(a,e,t=!1){await this.refresh();let i=this.cleanFolder(a),s=this.folderKeyEntry(i);if(!s)return!1;for(let n of this.folderActiveSlots(s))try{let o=await hi(vc(n.wrapped),e);this.folderSessionKeys.set(s.folderPath,o);let r=this.folderKcIdFor(s);return(t||this.isFolderRemembered(r))&&await this.rememberFolder(r,e),!0}catch{}return!1}async tryAutoUnlockFolder(a){let e=this.folderKeyEntry(a);if(!e||this.isFolderUnlocked(a))return this.isFolderUnlocked(a);let t=this.folderKcIdFor(e),i=this.rememberedFolderPassword(t);if(i&&await this.unlockFolder(a,i))return!0;let s=this.secretStore();if(!s)return!1;let n=new Set(i?[i]:[]);for(let o of this.keychainCandidateIds()){if(o===t)continue;let r=null;try{r=s.getSecret(o)??null}catch{r=null}if(!(!r||n.has(r))&&(n.add(r),await this.unlockFolder(a,r)))return await this.rememberFolder(t,r),!0}return!1}async changeFolderPassword(a,e,t=!1){if(!e)throw new Error("Password required.");let i=this.cleanFolder(a);await this.refresh();let s=this.folderKeyEntry(i);if(!s)throw new Error("This folder has no key.");let n=s.folderPath,o=this.folderSessionKeys.get(n);if(!o)throw new Error("Unlock this folder first.");let r=this.folderKeyFiles.get(n);if(r){let f=await this.folderKeystore.changePassword(r,o,e);await this.folderKeystore.write(n,f),this.folderKeyFiles.set(n,f);let p=this.folderKcId(n,f.keyId);(t||this.isFolderRemembered(p))&&await this.rememberFolder(p,e);return}if(!this.kf)throw new Error("This folder has no key.");let l=s.passwordSlots.filter(f=>!f.label.startsWith("[deprecated]")),c=this.folderKcIdFor(s),A=this.rememberedFolderPassword(c);if(A&&l[0])try{await this.parkThenSet(`${c}-d-${l[0].id}`,A)}catch{}let h=await At(o,e),g=s.passwordSlots.map(f=>f.label.startsWith("[deprecated]")?f:{...f,label:`[deprecated] ${f.label}`}),u={...s,kcId:s.kcId??this.folderKcId(s.label,s.keyId),passwordSlots:[{id:Ae(8),label:"Folder password",wrapped:Qc(h.data),kdf:h.kdf,createdAt:new Date().toISOString()},...g]};this.kf.folderKeys={...this.kf.folderKeys??{},[n]:u},await this.keyfiles.save(this.kf),(t||this.isFolderRemembered(c))&&await this.rememberFolder(this.folderKcIdFor(u),e)}folderHasRecovery(a){let e=this.owningFolder(a),t=e?this.folderKeyFiles.get(e):null;return!!t&&this.folderKeystore.hasRecovery(t)}async setFolderRecoveryPassword(a,e){if(!e)throw new Error("Recovery password required.");await this.refresh();let t=this.cleanFolder(a),i=this.folderKeyEntry(t);if(!i)throw new Error("This folder has no key.");let s=i.folderPath,n=this.folderKeyFiles.get(s);if(!n)throw new Error("This folder's key predates recovery passwords \u2014 change its folder password once to upgrade it, then try again.");let o=this.folderSessionKeys.get(s);if(!o)throw new Error("Unlock this folder first.");let r=await this.folderKeystore.setRecovery(n,o,e);await this.folderKeystore.write(s,r),this.folderKeyFiles.set(s,r)}async removeFolderRecoveryPassword(a){await this.refresh();let e=this.cleanFolder(a),t=this.folderKeyEntry(e);if(!t)return;let i=t.folderPath,s=this.folderKeyFiles.get(i);if(!s||!this.folderKeystore.hasRecovery(s))return;let n=this.folderKeystore.removeRecovery(s);await this.folderKeystore.write(i,n),this.folderKeyFiles.set(i,n)}folderKcId(a,e){return(`sp-${(a||"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}`.slice(0,44)+`-${e.slice(0,6)}`).replace(/-+/g,"-")}folderKcIdFor(a){return a.kcId||`${Ec}-f-${a.keyId}`}isFolderRemembered(a){try{return!!this.secretStore()?.getSecret(a)}catch{return!1}}rememberedFolderPassword(a){try{return this.secretStore()?.getSecret(a)||null}catch{return null}}async rememberFolder(a,e){try{await this.parkThenSet(a,e)}catch(t){console.warn("[Stashpad] couldn't save folder password to keychain",t)}}async forgetFolderKeychain(a){let e=this.folderKeyEntry(a);if(!e)return;let t=this.secretStore();if(!t)return;let i=this.folderKcIdFor(e);try{if(t.getSecret(i)){await this.parkThenSet(i,"");return}}catch{}try{t.removeSecret?await t.removeSecret(i):await t.setSecret(i,"")}catch(s){console.warn("[Stashpad] couldn't clear folder keychain",s)}}lock(){for(let a of this.folderSessionKeys.values())a.fill(0);this.folderSessionKeys.clear()}lockFolder(a){let e=this.owningFolder(a)??this.cleanFolder(a),t=this.folderSessionKeys.get(e);t&&(t.fill(0),this.folderSessionKeys.delete(e))}cleanFolder(a){return(a||"").replace(/\/+$/,"")}async clear(){this.lock();try{let a=this.app.vault.adapter;for(let e of[".stashpad/keys.json"])try{await a.exists(e)&&await a.remove(e)}catch{}try{let t=((await a.list("_keys")).files||[]).filter(i=>/\/keys-\d+\.json$/.test(i));if(t.length){let s=`_keys/removed-${new Date().toISOString().slice(0,19).replace(/[:T]/g,"-")}`;try{await a.exists(s)||await a.mkdir(s)}catch{}for(let n of t){let o=n.split("/").pop();try{await a.write(`${s}/${o}`,await a.read(n)),await a.remove(n)}catch{}}}}catch{}this.stashKeysIndexed||await this.indexStashKeys();for(let e of this.folderKeyFiles.keys())try{await this.folderKeystore.remove(e)}catch{}this.folderKeyFiles.clear()}catch{}this.kf=null}async removeFolderKeyFile(a){let e=this.cleanFolder(a);await this.folderKeystore.remove(e),this.folderKeyFiles.delete(e),this.folderSessionKeys.get(e)?.fill(0),this.folderSessionKeys.delete(e)}hasLegacyKeyfile(){return!!this.kf}unmigratedKeyfileFolders(){return Object.keys(this.kf?.folderKeys??{}).filter(a=>!this.folderKeyFiles.has(this.cleanFolder(a)))}async retireLegacyKeyfile(){await this.refresh();let a=this.unmigratedKeyfileFolders();if(a.length)throw new Error(`Can't retire the old keyfile yet \u2014 these folders' keys still live only in it: ${a.map(o=>o||"(vault root)").join(", ")}. Open each folder once (or change its password) to migrate it, then try again.`);let e=this.app.vault.adapter,i=`.stashpad/retired-keyfile-${new Date().toISOString().slice(0,19).replace(/[:T]/g,"-")}`,s=0;try{await e.exists(i)||await e.mkdir(i)}catch{}let n=async(o,r)=>{try{let l=await e.read(o);return await e.write(r,l),await e.read(r)!==l?!1:(await e.remove(o),!0)}catch{return!1}};try{await e.exists(".stashpad/keys.json")&&await n(".stashpad/keys.json",`${i}/keys.json`)&&s++}catch{}try{let o=await e.list("_keys");for(let r of(o.files||[]).filter(l=>/\/keys-\d+\.json$/.test(l)))await n(r,`${i}/${r.split("/").pop()}`)&&s++}catch{}return this.kf=null,this.parkedKeyMaterial=!0,s}hasRecoverableKeyMaterial(){return!!this.kf||this.parkedKeyMaterial}async wipeLegacyKeyMaterial(){let a=this.app.vault.adapter,e=0,t=async(i,s)=>{try{await a.exists(i)&&(s?await a.rmdir(i,!0):await a.remove(i),e++)}catch{}};await t(".stashpad/keys.json",!1),await t("_keys",!0);try{let i=await a.list(".stashpad");for(let s of i.folders||[])/\/retired-keyfile-/.test(s)&&await t(s,!0)}catch{}return this.kf=null,this.parkedKeyMaterial=!1,e}dispose(){this.lock()}};var ts=null,Vs=new Set;function Ws(d){if(ts!==d){ts=d;for(let a of Vs)a()}}function ht(){return ts}function aa(d){if(ts===d){ts=null;for(let a of Vs)a()}}function la(d){return Vs.add(d),()=>Vs.delete(d)}function Fc(){return T.Platform.isMacOS?"Finder":T.Platform.isWin?"File Explorer":"file manager"}var Jt=[{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:"copyLink",label:"Copy Stashpad link",desc:"Copy an obsidian://stashpad deep link to the cursor row (or first selected note) \u2014 click it anywhere to jump back. No default chord.",defaultPrimary:""},{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 into a separate note (under a chosen parent)",desc:'Duplicate the cursor row (with its subtree) as a separate note and pick which parent it nests under. Distinct from "Fork as a version" (a draft within a sheet group). 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: G \u2014 mark the selection (or cursor row) as a task / todo, or clear it. Tasks appear in the Tasks panel.",defaultPrimary:"G"},{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",desc:"Move the selected note(s) into this folder's own archive subfolder (drops out of search; plaintext unless this folder encrypts its archive). 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 No(){let d={};for(let a of Jt)d[a.id]={primary:a.defaultPrimary,secondary:a.defaultSecondary??"",preferRight:!1,useBoth:!!a.defaultUseBoth};return d}var Qt={folder:"Stashpad",importDropFolder:"",exportFolder:"_exports",autoImport:!1,inheritObsidianExclusions:!0,folderPanelPinnedFraction:.5,folderPanelPinned:[],folderPanelDownranked:[],folderPanelHidden:[],folderPanelPinnedGrouping:"pin-order",enablePerfProfiling:!1,debugTrace:!1,writeRecoveryLinks:!0,useTemplatesFormat:!1,prefixTimestampsOnCopy:!0,splitOnLines:!1,splitMode:"lines",confirmCrossParentDrag:!0,confirmBulkDelete:!0,confirmAttachmentDelete:!0,autofocusComposerAfterSend:!0,focusComposerOnOpen:!1,searchOpensInContext:!0,popoutDuplicates:!0,encryption:zs(),encryptTrash:!1,encryptTrashFilenames:!1,migratedToggleTaskG:!1,migratedArchiveToSubfolders:!1,migratedTrashToSubfolders:!1,reEncryptWatch:[],reEncryptNudge:!1,reEncryptAfterMin:0,dueQuickAdjusts:["5m","15m","30m","1h","1d","1w"],archiveFolders:[],folderEncPrefs:{},folderIcons:{},folderSwitcherIncludePinned:!1,importExcludePrefixes:"_",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:No()},ca=JSON.parse(JSON.stringify(Qt)),xo=new Set;function X(){return ca}function is(d){ca=d;for(let a of xo)a()}function da(d){return xo.add(d),()=>xo.delete(d)}function js(d){try{let a=d.internalPlugins?.plugins?.templates;if(!a?.enabled)return null;let e=a.instance?.options??{};return{dateFormat:e.dateFormat||"YYYY-MM-DD",timeFormat:e.timeFormat||"HH:mm"}}catch{return null}}var Xs=[{id:"foldersStorage",label:"\u{1F4C1} Folders & Storage"},{id:"importExport",label:"\u{1F504} Import & Export"},{id:"datesTime",label:"\u{1F552} Dates & Time"},{id:"behaviors",label:"\u{1F39B}\uFE0F Behavior"},{id:"notifications",label:"\u{1F514} Notifications"},{id:"encryption",label:"\u{1F512} Encryption"},{id:"authorship",label:"\u2712\uFE0F Authorship"},{id:"templates",label:"\u{1F4C4} Templates"},{id:"organizationSystems",label:"\u{1F5C2}\uFE0F Organization Systems"},{id:"maintenance",label:"\u{1F6E0}\uFE0F Maintenance"},{id:"diagnostics",label:"\u{1FA7A} Diagnostics"},{id:"hotkeys",label:"\u2328\uFE0F Hotkeys"}].sort((d,a)=>{let e=t=>t.replace(/^[^\p{L}\p{N}]+/u,"");return e(d.label).localeCompare(e(a.label))}),Do=null;function kc(d,a){return Do||(Do=class extends T.SettingPage{constructor(e,t){super(),this.title=e,this._renderFn=t}display(){this.containerEl.empty(),this._renderFn(this.containerEl)}}),new Do(d,a)}var Zs=class extends T.PluginSettingTab{constructor(e,t){super(e,t);this.plugin=t;this.pfeSelected=null;this.pfeRerender=null;this.iconPickFolder=null}display(){let{containerEl:e}=this;e.empty();for(let t of Xs){new T.Setting(e).setName(t.label).setHeading();let i=this.itemsForTab(t.id);if(i)for(let s of i){let n=new T.Setting(e);typeof s.render=="function"?s.render(n):(s.name&&n.setName(s.name),s.desc&&n.setDesc(s.desc))}else this.renderTabContent(e,t.id)}}getSettingDefinitions(){return Xs.map(e=>{let t=this.itemsForTab(e.id);return t?{type:"page",name:e.label,items:t}:{type:"page",name:e.label,page:()=>kc(e.label,i=>this.renderTabContent(i,e.id))}})}itemsForTab(e){switch(e){case"hotkeys":return this.hotkeyItems();case"diagnostics":return this.diagnosticsItems();case"notifications":return this.notificationsItems();case"foldersStorage":return this.buildGeneralCategories().foldersStorage;case"importExport":return this.buildGeneralCategories().importExport;case"datesTime":return this.buildGeneralCategories().datesTime;case"maintenance":return this.buildGeneralCategories().maintenance;case"behaviors":{let t=this.buildGeneralCategories();return[this.headingDef("\u{1F4CB} List & Display"),...t.listDisplay,this.headingDef("\u2195\uFE0F Moving Notes"),...t.movingNotes,this.headingDef("\u270D\uFE0F Composer & Copying"),...t.composerCopy,this.headingDef("\u{1F5D1}\uFE0F Deleting"),...t.deleting,this.headingDef("\u{1FA9F} Windows & Tabs"),...t.windowsTabs,this.headingDef("\u2699\uFE0F Misc"),...t.misc]}case"organizationSystems":return[this.headingDef("\u{1F522} JD Index (Johnny Decimal)"),...this.jdIndexItems(),this.headingDef("\u{1F4DA} Open Knowledge Format (OKF)"),...this.okfItems()];case"encryption":return this.encryptionItems();case"authorship":return this.authorshipItems();case"templates":return this.templatesItems();default:return null}}renderTabContent(e,t){switch(t){case"authorship":this.renderAuthorshipSection(e);break;case"templates":this.renderTemplatesTab(e);break}}diagnosticsItems(){return[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.",e=>e.addToggle(t=>t.setValue(this.plugin.settings.enablePerfProfiling).onChange(async i=>{this.plugin.settings.enablePerfProfiling=i,await this.plugin.saveSettings()})),["perf","profiling","timing","slow"]),this.renderDef("Debug trace","Record low-level diagnostic lines (e.g. tap coordinates vs the row they resolve to) to an in-memory buffer while you reproduce a bug, then copy them below to share. Local only \u2014 no network, no file writes; zero overhead when off.",e=>e.addToggle(t=>t.setValue(this.plugin.settings.debugTrace).onChange(async i=>{this.plugin.settings.debugTrace=i,await this.plugin.saveSettings()})),["debug","trace","diagnostics","tap","log"]),this.renderDef("Copy / clear debug trace","Copy the captured debug lines to the clipboard (paste them back to share), or clear the buffer to start a fresh capture.",e=>{e.addButton(t=>t.setButtonText("Copy").onClick(async()=>{let i=this.plugin.getDebugTrace();if(!i){new T.Notice("Debug trace is empty \u2014 enable it and reproduce the issue first.");return}try{await navigator.clipboard.writeText(i),new T.Notice("Debug trace copied.")}catch{new T.Notice("Couldn't access clipboard.")}})),e.addButton(t=>t.setButtonText("Clear").onClick(()=>{this.plugin.clearDebugTrace(),new T.Notice("Debug trace cleared.")}))},["debug","trace","copy","clear"]),this.renderDef("Open log file","Append-only history of creates, deletes, parent changes, renames. Stored alongside the plugin's other private files.",e=>e.addButton(t=>t.setButtonText("Open log").onClick(async()=>{let i=this.app.vault.adapter,s=this.plugin.pluginPrivatePath("log.jsonl");if(!await i.exists(s)){new T.Notice("No log yet \u2014 make some changes first.");return}let n=await i.read(s);new ti(this.app,n,s).open()})),["log","history","diagnostics"])]}notificationsItems(){let e=new Set(this.plugin.settings.mutedNotificationCategories??[]),t=Object.keys(po);return[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");let n=async()=>{let o=parseInt(s.getValue(),10);if(!Number.isFinite(o)||o<0){s.setValue(String(this.plugin.settings.notificationHistoryLimit??5e3));return}this.plugin.settings.notificationHistoryLimit=o,this.plugin.notifications.setHistoryLimit(o),await this.plugin.saveSettings()};s.inputEl.addEventListener("blur",()=>void n()),s.inputEl.addEventListener("keydown",o=>{o.key==="Enter"&&n()})}),["notification","history","limit"]),{type:"group",heading:"Mute notification categories",items:t.map(i=>{let s=po[i];return this.renderDef(s.label,s.desc,n=>n.addToggle(o=>o.setValue(!e.has(i)).onChange(async r=>{let l=!r;l?e.add(i):e.delete(i),this.plugin.settings.mutedNotificationCategories=Array.from(e),this.plugin.notifications.setMuted(i,l),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 Oi(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 T.Notice("No log yet \u2014 make some changes first.");return}let l=await o.read(r);new ti(this.app,l,r).open()},this.plugin.settings.authorId||null,n=>this.plugin.lookupNoteAuthorIds(n)).open()})),["notification","history","panel"])]}renderTemplatesTab(e){this.renderColorAliasesSection(e),this.renderNoteTemplatesSection(e)}renderDef(e,t,i,s){return{name:e,desc:t,aliases:s,render:n=>{n.setName(e).setDesc(t);try{i(n)}catch(o){console.error(`[Stashpad] settings control "${e}" failed to render:`,o)}}}}sectionDef(e,t,i,s){return{name:e,desc:t,aliases:s,render:n=>{let o=n.settingEl;o.empty(),o.removeClass("setting-item"),o.addClass("stashpad-settings-section");try{i(o)}catch(r){console.error(`[Stashpad] settings section "${e}" failed to render:`,r)}}}}headingDef(e,t){return this.sectionDef(e,t??"",i=>{let s=new T.Setting(i).setName(e).setHeading();t&&s.setDesc(t)},[e.toLowerCase()])}folderKeyLabel(e){let t=new Date,i=r=>String(r).padStart(2,"0"),s=`${t.getFullYear()}${i(t.getMonth()+1)}${i(t.getDate())}-${i(t.getHours())}${i(t.getMinutes())}`,n=(this.plugin.settings.authorName||"").trim(),o=n?n.split(/\s+/).map(r=>r[0]).join(""):(this.plugin.settings.authorId||"anon").slice(0,4);return`${s} - ${e.split("/").pop()||e} - ${o}`}promptSetFolderPassword(e){new Ne(this.app,{mode:"setup",offerKeychain:!0,title:`Set password for \u201C${e.split("/").pop()}\u201D`,intro:"A separate password just for this folder. Share it with collaborators out-of-band (a password manager, Signal, in person). There is NO recovery if it's lost.",onSubmit:async({next:t,remember:i})=>{if(!t)return"Enter a password.";try{await this.plugin.encryption.setupFolderKey(e,t,this.folderKeyLabel(e),i)}catch(s){return s.message}return new T.Notice("Folder password set \u2014 share it securely."),this.update?.(),this.pfeRerender?.(),null}}).open()}promptChangeFolderPassword(e){new Ne(this.app,{mode:"setup",offerKeychain:!0,title:`Change password for \u201C${e.split("/").pop()}\u201D`,intro:"Re-wraps this folder's key under a new password. The OLD password stops working on THIS device right away (un-synced copies elsewhere keep working until they sync). To truly cut off someone who left, remove encryption and re-encrypt the folder under a fresh password.",onSubmit:async({next:t,remember:i})=>{if(!t)return"Enter a password.";try{await this.plugin.encryption.changeFolderPassword(e,t,i)}catch(s){return s.message}return new T.Notice("Folder password changed."),this.update?.(),this.pfeRerender?.(),null}}).open()}promptSetFolderRecovery(e){let t=e.split("/").pop()||e;new Ne(this.app,{mode:"setup",offerKeychain:!1,title:`Recovery password for \u201C${t}\u201D`,intro:"A SECOND password that also unlocks this folder \u2014 a backup in case the main password is lost. It wraps the same key, so it's exactly as sensitive: store it somewhere safe and separate. Setting it again replaces any existing recovery password.",onSubmit:async({next:i})=>{if(!i)return"Enter a password.";try{await this.plugin.encryption.setFolderRecoveryPassword(e,i)}catch(s){return s.message}return new T.Notice("Recovery password set \u2014 keep it somewhere safe."),this.update?.(),this.pfeRerender?.(),null}}).open()}promptRemoveFolderRecovery(e){let t=e.split("/").pop()||e;new _(this.app,`Remove recovery password for \u201C${t}\u201D?`,"The recovery password will no longer unlock this folder. The main folder password is unchanged. You can add a new recovery password later.","Remove recovery",async i=>{if(i){try{await this.plugin.encryption.removeFolderRecoveryPassword(e)}catch(s){new T.Notice(s.message);return}new T.Notice("Recovery password removed."),this.update?.(),this.pfeRerender?.()}}).open()}promptUnlockFolder(e){new Ne(this.app,{mode:"unlock",offerKeychain:!0,title:`Unlock \u201C${e.split("/").pop()}\u201D`,intro:"Enter this folder's password.",onSubmit:async({current:t,remember:i})=>await this.plugin.encryption.unlockFolder(e,t,i)?(new T.Notice("Folder unlocked."),this.update?.(),this.pfeRerender?.(),null):"Wrong password. Try again."}).open()}renderPerFolderEncryption(e){let t=this.plugin.discoverStashpadFolders();if(t.length===0){e.createEl("p",{cls:"setting-item-description"}).setText("No Stashpad folders found yet.");return}(!this.pfeSelected||!t.includes(this.pfeSelected))&&(this.pfeSelected=t[0]);let i=e.createDiv({cls:"stashpad-folderenc-panel"});this.pfeRerender=()=>{i.empty(),this.renderFolderEncPanel(i,this.pfeSelected)},new T.Setting(e).setName("Folder").setDesc("Pick a folder to configure its password, archive, and trash options. Everything below applies to the selected folder only.").setHeading().addDropdown(s=>{for(let n of t)s.addOption(n,n);s.setValue(this.pfeSelected),s.selectEl.addClass("stashpad-folderenc-picker"),s.onChange(n=>{this.pfeSelected=n,this.pfeRerender?.()})}),e.appendChild(i),this.renderFolderEncPanel(i,this.pfeSelected)}renderFolderEncPanel(e,t){let i=this.plugin.encryption,s=i.hasOwnFolderKey(t),n=i.folderKeyEntry(t)?.folderPath??null,o=!!n&&!s,r=i.isFolderUnlocked(t),l=(this.plugin.settings.folderEncPrefs??{})[t]??{},c=s?r?"Has its own password \xB7 unlocked":"Has its own password \xB7 locked":o?`Inherits \u201C${n.split("/").pop()||n}\u201D's password \xB7 ${r?"unlocked":"locked"}`:"Uses the vault password",A=new T.Setting(e).setName("Password").setDesc(c);if(o?A.addButton(f=>f.setButtonText("Manage on parent folder").onClick(()=>{this.pfeSelected=n,this.update?.(),this.pfeRerender?.()})):s?r?A.addButton(f=>f.setButtonText("Change password\u2026").onClick(()=>this.promptChangeFolderPassword(t))):A.addButton(f=>f.setButtonText("Unlock\u2026").setCta().onClick(()=>this.promptUnlockFolder(t))):A.addButton(f=>f.setButtonText("Set folder password\u2026").setCta().onClick(()=>this.promptSetFolderPassword(t))),s&&r){let f=this.plugin.encryption.folderHasRecovery(t),p=new T.Setting(e).setName("Recovery password").setDesc(f?"A second password that also unlocks this folder. Keep it somewhere safe and separate.":"Optional. Add a second password that also unlocks this folder, as a backup if the main one is lost.");p.addButton(I=>I.setButtonText(f?"Change recovery\u2026":"Add recovery\u2026").onClick(()=>this.promptSetFolderRecovery(t))),f&&p.addButton(I=>{I.setButtonText("Remove recovery").onClick(()=>this.promptRemoveFolderRecovery(t)),I.buttonEl.addClass("mod-warning")})}let h=async f=>{this.plugin.settings.folderEncPrefs={...this.plugin.settings.folderEncPrefs??{},[t]:{...(this.plugin.settings.folderEncPrefs??{})[t]??{},...f}},await this.plugin.saveSettings()};new T.Setting(e).setName("Trash handling").setDesc("Where notes deleted from this folder go.").addDropdown(f=>f.addOption("","Stashpad trash (default)").addOption("obsidian","Obsidian native trash").setValue(l.trashHandling==="obsidian"?"obsidian":"").onChange(p=>h({trashHandling:p||void 0})));let g=(f,p,I,m,B=!1)=>{new T.Setting(e).setName(f).addToggle(C=>C.setValue(!!l[p]).onChange(async w=>{if(w&&B){if(!this.plugin.encryption.hasFolderKey(t)){new T.Notice("Give this folder a password first (the \u201CSet folder password\u2026\u201D button above), then enable this."),this.pfeRerender?.();return}if(!await this.plugin.ensureFolderUnlocked(t)){this.pfeRerender?.();return}}let y={};y[p]=w,w||(y[I]=!1),await h(y),m&&await m(w),this.pfeRerender?.()})),new T.Setting(e).setName(`\u21B3 ${f} \u2014 hide filenames`).setClass("stashpad-subsetting").addToggle(C=>{C.setValue(!!l[I]),C.setDisabled(!l[p]),C.onChange(async w=>{let y={};y[I]=w,await h(y),this.pfeRerender?.()})})};g("Encrypt this folder's notes","encryptContent","encryptFilenames",async f=>{f?await this.plugin.lockFolder(t):await this.plugin.unlockFolder(t);let p=(this.plugin.settings.lockedSubtrees??[]).some(I=>(I.folder||"").replace(/\/+$/,"")===t);await h({encryptContent:p,...p?{}:{encryptFilenames:!1}})}),g("Encrypt archived notes","archiveEncryptContent","archiveEncryptFilenames",async f=>{if(!f)return;let p=this.plugin.archivedPlainNotesIn(`${t}/archive`).length;p!==0&&new _(this.app,`Encrypt the ${p} note${p===1?"":"s"} already archived?`,`\u201C${t.split("/").pop()}\u201D's archive already holds ${p} plaintext note${p===1?"":"s"}. Encrypt ${p===1?"it":"them"} now too? (Skipping leaves ${p===1?"it":"them"} readable; only notes archived from now on get encrypted.)`,"Encrypt them",async I=>{if(!I)return;let m=await this.plugin.encryptExistingArchiveNotes(t);new T.Notice(m>0?`Encrypted ${m} archived note${m===1?"":"s"}.`:"Nothing was encrypted (cancelled or already locked)."),this.pfeRerender?.()}).open()},!0),g("Encrypt trashed notes","trashEncryptContent","trashEncryptFilenames",void 0,!0),new T.Setting(e).setName("Auto re-encrypt after idle minutes").setDesc("Override the global auto-re-encrypt timer for this folder. Blank = use global; 0 = off for this folder. A cancellable countdown always shows first, and open notes are never touched.").addText(f=>{f.setPlaceholder("global"),f.setValue(l.reEncryptAfterMin==null?"":String(l.reEncryptAfterMin)),f.onChange(p=>{let I=p.trim();{let m=Number(I);I===""?h({reEncryptAfterMin:void 0}):Number.isFinite(m)&&m>=0?h({reEncryptAfterMin:Math.floor(m)}):f.setValue(l.reEncryptAfterMin==null?"":String(l.reEncryptAfterMin))}})});let u=this.plugin.discoverStashpadFolders().filter(f=>f!==t&&f.startsWith(t+"/")).sort();if(u.length){new T.Setting(e).setName("Subfolders").setDesc(`${u.length} subfolder${u.length===1?"":"s"} \u2014 they use \u201C${t.split("/").pop()}\u201D's password. Encrypt each individually.`).setHeading();for(let f of u){let p=(this.plugin.settings.folderEncPrefs??{})[f]??{},I=async C=>{this.plugin.settings.folderEncPrefs={...this.plugin.settings.folderEncPrefs??{},[f]:{...(this.plugin.settings.folderEncPrefs??{})[f]??{},...C}},await this.plugin.saveSettings()},m=(this.plugin.settings.lockedSubtrees??[]).some(C=>(C.folder||"").replace(/\/+$/,"")===f),B=f.slice(t.length+1);new T.Setting(e).setName(B).addToggle(C=>C.setValue(m).onChange(async w=>{w?await this.plugin.lockFolder(f):await this.plugin.unlockFolder(f);let y=(this.plugin.settings.lockedSubtrees??[]).some(v=>(v.folder||"").replace(/\/+$/,"")===f);await I({encryptContent:y,...y?{}:{encryptFilenames:!1}}),this.update?.(),this.pfeRerender?.()})),new T.Setting(e).setName(`\u21B3 ${B} \u2014 hide filenames`).setClass("stashpad-subsetting").addToggle(C=>{C.setValue(!!p.encryptFilenames),C.setDisabled(!m),C.onChange(w=>void I({encryptFilenames:w}))})}}}buildGeneralCategories(){let e=async()=>this.plugin.saveSettings(),t=(s,n,o,r,l)=>this.renderDef(s,n,c=>c.addToggle(A=>A.setValue(o()).onChange(async h=>{r(h),await e()})),l),i={foldersStorage:[],importExport:[],datesTime:[],listDisplay:[],movingNotes:[],deleting:[],composerCopy:[],windowsTabs:[],maintenance:[],misc:[]};i.foldersStorage.push(this.renderDef("Stashpad notes folder","Vault-relative folder where Stashpad stores its notes and attachments. Created on demand.",s=>{s.addText(n=>{new li(this.app,n.inputEl),n.setValue(this.plugin.settings.folder).setPlaceholder("Stashpad");let o=async()=>{let r=(n.getValue()||"").trim().replace(/^\/+|\/+$/g,"")||Qt.folder,l=r.split("/").filter(Boolean),c=new Set([this.plugin.settings.importDropFolder,this.plugin.settings.exportFolder,"_attachments","_processed","_authors","_deleted","archive","trash",".stashpad"].map(A=>(A??"").trim().replace(/^\/+|\/+$/g,"")).filter(Boolean));if(l.some(A=>c.has(A))){new T.Notice(`"${r}" uses a reserved Stashpad subfolder name. Pick something else.`),n.setValue(this.plugin.settings.folder);return}r!==this.plugin.settings.folder&&(this.plugin.settings.folder=r,await e())};n.inputEl.addEventListener("blur",()=>void o()),n.inputEl.addEventListener("keydown",r=>{r.key==="Enter"&&o()})})},["folder","path","location","notes"])),i.importExport.push(t("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.foldersStorage.push(t("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.foldersStorage.push(t("Include pinned notes in the folder switcher","When on, the folder switcher / creator (the folder button and the \u201COpen or switch Stashpad folder\u201D command) also lists your pinned notes, so you can jump straight to one. Off keeps the picker focused on folders.",()=>this.plugin.settings.folderSwitcherIncludePinned,s=>{this.plugin.settings.folderSwitcherIncludePinned=s},["pinned","switcher","folder","picker","jump"])),i.foldersStorage.push(this.renderDef("Folder tab icon","Give a folder its own Lucide icon (e.g. rocket, star, book-open) shown on its tab, the folder switcher, and its folder-panel row. Pick a folder, then start typing in the icon box \u2014 matching icons appear with previews; pick one. Blank = the default icon. Set per folder.",s=>{let n=this.plugin.discoverStashpadFolders();if(n.length===0){s.setDesc("No Stashpad folders found yet.");return}(!this.iconPickFolder||!n.includes(this.iconPickFolder))&&(this.iconPickFolder=n[0]);let o=null,r=s.controlEl.createSpan({cls:"stashpad-folder-icon-preview"}),l=c=>{r.empty();let A=c.trim();A&&(0,T.setIcon)(r,A)};s.addDropdown(c=>{for(let A of n)c.addOption(A,A.split("/").pop()||A);c.setValue(this.iconPickFolder),c.onChange(A=>{this.iconPickFolder=A;let h=this.plugin.getFolderIcon(A)??"";o?.setValue(h),l(h)})}),s.addText(c=>{o=c,c.setPlaceholder("type to search\u2026 (e.g. rocket)"),new Us(this.app,c.inputEl),c.setValue(this.plugin.getFolderIcon(this.iconPickFolder)??""),c.onChange(async A=>{l(A),await this.plugin.setFolderIcon(this.iconPickFolder,A.trim())})}),l(this.plugin.getFolderIcon(this.iconPickFolder)??"")},["icon","folder","tab","lucide","emoji","switcher"])),i.importExport.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 e()})),["import","subfolder"])),i.importExport.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,"")||Qt.exportFolder,await e()})),["export","stash","subfolder"])),i.importExport.push(this.renderDef("Exclude subfolders by prefix","Comma-separated name prefixes (default \u201C_\u201D). A subfolder whose name starts with any of these \u2014 at any depth \u2014 is NOT surfaced as a Stashpad folder or imported (it stays local). To encrypt such a folder, right-click it in Obsidian's file explorer \u2192 \u201C\u{1F512} Encrypt with Stashpad\u201D.",s=>s.addText(n=>n.setValue(this.plugin.settings.importExcludePrefixes??"_").setPlaceholder("_").onChange(async o=>{this.plugin.settings.importExcludePrefixes=o,await e()})),["import","exclude","prefix","subfolder","underscore","ignore"])),i.maintenance.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, rename any note whose filename slug no longer matches its body's first line, AND migrate legacy attachment filenames to the new name-first format (`photo-<id>.png`). 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{await this.plugin.runRebootstrapWithUI()}catch{}finally{n.setDisabled(!1).setButtonText("Rebootstrap now")}})),["rebootstrap","rebuild","repair","backfill","slug"])),i.maintenance.push(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.",s=>s.addToggle(n=>n.setValue(this.plugin.settings.writeRecoveryLinks).onChange(async o=>{this.plugin.settings.writeRecoveryLinks=o,await e()})),["recovery","parentlink","children","frontmatter"]));{let s=null,n=()=>{s&&s.setText(`Sample: ${We(Date.now(),this.plugin.settings)}`)};i.datesTime.push(this.renderDef("Date display format","How created / edited timestamps and due dates are shown \u2014 in the notes list, the Tasks panel, and the detail panel. Overridden by the Templates-plugin formats when the option below is on.",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 l=>{this.plugin.settings.dateDisplayFormat=l,await e(),n()})})},["date","format","display"])),i.datesTime.push(this.renderDef("Use Templates plugin date/time formats","Use the date/time formats configured in the core Templates plugin instead of the Date display format above. Off = the Date display format above is used everywhere.",o=>{o.addToggle(l=>l.setValue(this.plugin.settings.useTemplatesFormat).onChange(async c=>{this.plugin.settings.useTemplatesFormat=c,await e(),n()}));let r=js(this.app);o.descEl.createDiv({cls:"stashpad-settings-note"}).setText(r?`Templates plugin: date = "${r.dateFormat}", time = "${r.timeFormat}"`:"Templates plugin not enabled.")},["templates","date","time","format"])),i.datesTime.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 l=>{this.plugin.settings.dateDisplayTimezone=(l||"").trim(),await e(),n()})})},["timezone","tz","date","iana"])),i.datesTime.push(this.renderDef("Quick due-date adjustments","Comma-separated relative amounts shown as quick +/- buttons in the due-date and snooze pickers (e.g. 5m, 15m, 1h, 1d, 1w). Units: m=minutes, h=hours, d=days, w=weeks. A +/- flip in the picker toggles add vs subtract. Leave blank to hide the row.",o=>{o.addText(r=>{r.setPlaceholder("5m, 15m, 1h, 1d, 1w"),r.setValue((this.plugin.settings.dueQuickAdjusts??[]).join(", ")),r.onChange(async l=>{let c=l.split(",").map(A=>A.trim()).filter(A=>/^\d+\s*[mhdw]$/i.test(A)).map(A=>A.replace(/\s+/g,"").toLowerCase());this.plugin.settings.dueQuickAdjusts=c,await e()})})},["quick","adjust","snooze","due","preset","increment","decrement"])),i.datesTime.push({name:"Date sample",searchable:!1,render:o=>{let r=o.settingEl;r.empty(),r.removeClass("setting-item"),r.addClass("stashpad-settings-section"),s=r.createDiv({cls:"setting-item-description stashpad-settings-note stashpad-date-sample"}),n()}})}return i.movingNotes.push(t("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.movingNotes.push(t("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.listDisplay.push(t("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.misc.push(t("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.listDisplay.push(t("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.listDisplay.push(t("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.listDisplay.push(t("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.movingNotes.push(t("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.deleting.push(t("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.deleting.push(t("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.foldersStorage.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 T.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 l of n)this.renderFolderScopeRow(r,l)}let o=null;new T.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 l=(o?.value??"").trim().replace(/^\/+|\/+$/g,"");if(!l){new T.Notice("Enter a folder name first.");return}try{await this.plugin.createNewStashpad(l),new T.Notice(`Created Stashpad "${l}".`),o&&(o.value=""),await this.plugin.waitForStashpadFolder(l,2e3),this.update?.()}catch(c){new T.Notice(`Couldn't create: ${c.message}`)}}))},["search","scope","exclude","include","create","new","stashpad","folder"])),i.foldersStorage.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 T.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.foldersStorage.push(this.headingDef("\u{1F3F7}\uFE0F Note Titles")),i.foldersStorage.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:Ze).join(` -`);s.addTextArea(r=>{r.setValue(o),n=r.inputEl,n.rows=6,n.setCssStyles({fontFamily:"var(--font-monospace)"}),r.onChange(async l=>{this.plugin.settings.slugStopWords=(l||"").split(/\r?\n/).map(c=>c.trim().toLowerCase()).filter(Boolean),await e()})}).addExtraButton(r=>r.setIcon("rotate-ccw").setTooltip("Reset to defaults").onClick(async()=>{this.plugin.settings.slugStopWords=[...Ze],n&&(n.value=Ze.join(` -`)),await e()}))},["slug","stopwords","filename","title","note titles"])),i.composerCopy.push(t("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.composerCopy.push(t("Focus composer when opening a note","Focus the composer when you open or switch into a Stashpad view. OFF (default) focuses the LIST instead, so arrow-key navigation works right away instead of the composer grabbing focus every time. (Separate from 'after sending' above.)",()=>this.plugin.settings.focusComposerOnOpen,s=>{this.plugin.settings.focusComposerOnOpen=s},["composer","focus","open","navigate","list"])),i.windowsTabs.push(t("Search opens the note in its list (in context)","When you pick a search result, open the LIST that contains the note (focus its parent) and scroll to the note \u2014 so you see it in context instead of landing on the focused-note header. On by default.",()=>this.plugin.settings.searchOpensInContext,s=>{this.plugin.settings.searchOpensInContext=s},["search","context","list","scroll","parent"])),i.windowsTabs.push(t("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.windowsTabs.push(t("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.composerCopy.push(t("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 e=this.plugin.encryption,t=[];return t.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."});let n=i.createEl("div",{cls:"stashpad-enc-warning"});n.createEl("p").setText("\u26A0\uFE0F AI-built, NOT human-audited. This encryption was written by an AI assistant \u2014 not reviewed or security-audited by a human. Treat it as best-effort protection against a casual snoop, not a guarantee \u2014 and always keep your own unencrypted backups of anything important."),n.createEl("p").setText("There is NO recovery. If you lose a password, anything encrypted under it (notes, archived items, encrypted-trash items) is gone for good. Locking, encrypted archiving, and secure-deleting permanently remove the plaintext \u2014 the encrypted copy is the only one left. (A plaintext archive only de-indexes notes from search; it does NOT encrypt them.)"),n.createEl("p").setText("Each device unlocks with its own password (it never leaves the device); collaborators get access by device approval, not a shared password. If everyone with access loses their password, the content is unrecoverable. While encrypting or decrypting, avoid having a sync/cloud service write the vault mid-operation \u2014 it can corrupt files.");let o=i.createEl("details",{cls:"stashpad-enc-info"});o.createEl("summary",{text:"\u2139\uFE0F How Stashpad encryption works (concepts)"});let r=(c,A)=>{let h=o.createEl("p",{cls:"stashpad-enc-info-item"});h.createEl("strong",{text:`${c} \u2014 `}),h.appendText(A)};r("Per-folder passwords","Encryption is per folder: give a folder its OWN password (a separate key) and its notes lock under that key. Subfolders inherit their nearest keyed ancestor's password. A folder with no password of its own (or inherited) is not encrypted. Share a folder by handing over its password out-of-band."),r("Encrypt notes vs Hide filenames","\u201CEncrypt \u2026 notes\u201D scrambles the note body into a locked .stashenc blob (the plaintext is removed). \u201CHide filenames\u201D goes further: it replaces the on-disk name AND the placeholder title with a generic label, so a glance at the vault doesn't reveal WHAT is locked. Whether a title is hidden is decided when the note is locked."),r("Archive: plaintext vs encrypted","Every folder has its own \u201Carchive\u201D subfolder. Archiving is a plain move by default \u2014 the notes drop out of cross-folder search but stay readable. Turn on \u201CEncrypt archived notes\u201D for a folder to lock notes as they're archived instead."),r("Trash: Stashpad vs Obsidian","Deleting a note normally sends it to that folder's own \u201Ctrash\u201D subfolder \u2014 encrypted if the folder encrypts its trash \u2014 and it's recoverable from the Trash view. Set a folder's \u201CTrash handling\u201D to \u201CObsidian native trash\u201D to use Obsidian's plain deleted-files behavior instead (Stashpad can't encrypt or recover those)."),r("No recovery","There is no backdoor and no reset. If a password is lost, everything encrypted under it is gone \u2014 so keep your own unencrypted backups of anything you can't afford to lose."),e.hasAnyFolderKey()?new T.Setting(i).setName("Remove all encryption").setDesc("Decrypts everything back to plaintext and deletes every folder's password/key. If anything is still locked, you'll be offered to decrypt it (needs each folder's password) or \u2014 if a password is lost \u2014 permanently delete it. Then type the confirmation phrase.").addButton(c=>{let A=async()=>{let g=await this.plugin.encryptionStateStrict();if(g.live){let f=()=>{new _(this.app,"Delete all locked content forever?","This PERMANENTLY destroys every locked note and folder \u2014 there is NO decrypted copy and NO recovery. Only do this if you've lost the password and want to start fresh.","Delete locked content forever",async I=>{if(!I)return;let m=await this.plugin.purgeAllLockedContent();new T.Notice(`Deleted ${m} locked item${m===1?"":"s"}.`),A()},"Cancel",!0).open()},p=async()=>{if(await this.plugin.unlockAllInVault(),(await this.plugin.encryptionStateStrict()).live){new T.Notice("Some notes are still locked (decryption was cancelled or failed) \u2014 removal cancelled.",1e4);return}A()};new _(this.app,"Encrypted notes are still locked",`Some notes or folders are still encrypted (locked) and have no plaintext copy. Before removing encryption: +`}function Hs(d,a){let e=document.createDocumentFragment();e.createEl("div",{text:"Home note updated"}).setCssStyles({fontWeight:"600",marginBottom:"6px"});let i=e.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=e.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=d.vault.getAbstractFileByPath(a.previewPath);r instanceof Ce.TFile&&await d.workspace.getLeaf("tab").openFile(r)}n?.hide()},n=new Ce.Notice(e,0),n}var Ce,qr,Wi,Xi=$e(()=>{"use strict";Ce=require("obsidian");ai();le();qr=/^(\d+-\d+|\d+|[A-Za-z0-9]+(?:\.[A-Za-z0-9]+)+)\s+(.+)$/;Wi=class extends Ce.Modal{constructor(e,t,i,s,n){super(e);this.plugin=t;this.settings=i;this.indexedCount=s;this.onBuild=n;this.LARGE_BUILD=50;this.previewRan=!1;this.previewPath=null}onOpen(){let{contentEl:e,titleEl:t}=this,i=!this.settings.jdIndexHasBuilt,s=this.indexedCount>this.LARGE_BUILD;t.setText(i?"Build JD index \u2014 first time?":"Build JD index");let n=this.settings.jdIndexStashpadFolder,o=e.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."),e.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&&e.createEl("p",{cls:"setting-item-description"}).setText(`\u2713 Preview written to home note (${this.previewPath}). Open it before building if you haven't.`);let l=new Ce.Setting(e);(i||s)&&l.addButton(c=>{c.setButtonText(this.previewRan?"Re-run preview":"Run preview first"),c.setCta(),c.onClick(async()=>{try{let A=await Ps(this.app,this.plugin,this.settings);if(A.error==="no-dest"){new Ce.Notice("Set a Designated Stashpad folder for Index first.",5e3),this.close();return}if(A.error==="no-home"){new Ce.Notice(`"${this.settings.jdIndexStashpadFolder}" has no Stashpad home note. Open the folder in Stashpad first.`,7e3),this.close();return}this.previewRan=!0,this.previewPath=A.previewPath,Hs(this.app,A),this.contentEl.empty(),this.titleEl.empty(),this.onOpen()}catch(A){new Ce.Notice(`Preview failed: ${A?.message??A}`,8e3)}})}),l.addButton(c=>{c.setButtonText(i?"Build anyway":"Build"),!i&&!s&&c.setCta(),c.onClick(async()=>{this.close(),await this.onBuild()})}),l.addButton(c=>{c.setButtonText("Cancel"),c.onClick(()=>this.close())})}onClose(){this.contentEl.empty()}}});function _c(d,a){return jc(d,a||{},0,0)}function ed(d,a){return zc(d,{i:2},a&&a.out,a&&a.dictionary)}function Bn(d,a){if(a){for(var e=new de(d.length),t=0;t<d.length;++t)e[t]=d.charCodeAt(t);return e}if(Ra)return Ra.encode(d);for(var i=d.length,s=new de(d.length+(d.length>>1)),n=0,o=function(c){s[n++]=c},t=0;t<i;++t){if(n+5>s.length){var r=new de(n+8+(i-t<<1));r.set(s),s=r}var l=d.charCodeAt(t);l<128||a?o(l):l<2048?(o(192|l>>6),o(128|l&63)):l>55295&&l<57344?(l=65536+(l&1047552)|d.charCodeAt(++t)&1023,o(240|l>>18),o(128|l>>12&63),o(128|l>>6&63),o(128|l&63)):(o(224|l>>12),o(128|l>>6&63),o(128|l&63))}return cs(s,0,n)}function ir(d,a){if(a){for(var e="",t=0;t<d.length;t+=16384)e+=String.fromCharCode.apply(null,d.subarray(t,t+16384));return e}else{if(jo)return jo.decode(d);var i=id(d),s=i.s,e=i.r;return e.length&&Ee(8),s}}function za(d,a){a||(a={});var e={},t=[];Ya(d,"",e,a);var i=0,s=0;for(var n in e){var o=e[n],r=o[0],l=o[1],c=l.level==0?0:8,A=Bn(n),h=A.length,p=l.comment,u=p&&Bn(p),f=u&&u.length,g=_o(l.extra);h>65535&&Ee(11);var I=c?_c(r,l):r,m=I.length,B=Zc();B.p(r),t.push($a(l,{size:r.length,crc:B.d(),c:I,f:A,m:u,u:h!=n.length||u&&p.length!=f,o:i,compression:c})),i+=30+h+g+m,s+=76+2*(h+g)+(f||0)+m}for(var C=new de(s+22),Q=i,y=s-i,E=0;E<t.length;++E){var A=t[E];Ua(C,A.o,A,A.f,A.u,A.c.length);var w=30+A.f.length+_o(A.extra);C.set(A.c,A.o+w),Ua(C,i,A,A.f,A.u,A.c.length,A.o,A.m),i+=16+w+(A.m?A.m.length:0)}return rd(C,i,t.length,y,Q),C}function Va(d,a){for(var e={},t=d.length-22;Re(d,t)!=101010256;--t)(!t||d.length-t>65558)&&Ee(13);var i=et(d,t+8);if(!i)return{};var s=Re(d,t+16),n=Re(d,t-20)==117853008;if(n){var o=Re(d,t-12);n=Re(d,o)==101075792,n&&(i=Re(d,o+32),s=Re(d,o+48))}for(var r=a&&a.filter,l=0;l<i;++l){var c=nd(d,s,n),A=c[0],h=c[1],p=c[2],u=c[3],f=c[4],g=c[5],I=sd(d,g);s=f,(!r||r({name:u,size:h,originalSize:p,compression:A}))&&(A?A==8?e[u]=ed(d.subarray(I,I+h),{out:new de(p)}):Ee(14,"unknown compression type "+A):e[u]=cs(d,I,I+h))}return e}var de,De,er,yn,wn,Vo,Ga,La,Oa,Wo,Ka,Oc,Ta,Xo,ut,Z,tt,bt,Z,Z,Z,Z,ls,Z,Kc,Jc,qc,$c,qo,Je,$o,tr,cs,Yc,Ee,zc,ft,rs,Yo,Zo,Pa,as,Ja,Ha,Vc,qa,Wc,Xc,Zc,jc,$a,et,Re,zo,ye,Ya,Ra,jo,td,id,sd,nd,od,_o,Ua,rd,Wa=$e(()=>{de=Uint8Array,De=Uint16Array,er=Int32Array,yn=new de([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]),wn=new de([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]),Vo=new de([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),Ga=function(d,a){for(var e=new De(31),t=0;t<31;++t)e[t]=a+=1<<d[t-1];for(var i=new er(e[30]),t=1;t<30;++t)for(var s=e[t];s<e[t+1];++s)i[s]=s-e[t]<<5|t;return{b:e,r:i}},La=Ga(yn,2),Oa=La.b,Wo=La.r;Oa[28]=258,Wo[258]=28;Ka=Ga(wn,0),Oc=Ka.b,Ta=Ka.r,Xo=new De(32768);for(Z=0;Z<32768;++Z)ut=(Z&43690)>>1|(Z&21845)<<1,ut=(ut&52428)>>2|(ut&13107)<<2,ut=(ut&61680)>>4|(ut&3855)<<4,Xo[Z]=((ut&65280)>>8|(ut&255)<<8)>>1;tt=function(d,a,e){for(var t=d.length,i=0,s=new De(a);i<t;++i)d[i]&&++s[d[i]-1];var n=new De(a);for(i=1;i<a;++i)n[i]=n[i-1]+s[i-1]<<1;var o;if(e){o=new De(1<<a);var r=15-a;for(i=0;i<t;++i)if(d[i])for(var l=i<<4|d[i],c=a-d[i],A=n[d[i]-1]++<<c,h=A|(1<<c)-1;A<=h;++A)o[Xo[A]>>r]=l}else for(o=new De(t),i=0;i<t;++i)d[i]&&(o[i]=Xo[n[d[i]-1]++]>>15-d[i]);return o},bt=new de(288);for(Z=0;Z<144;++Z)bt[Z]=8;for(Z=144;Z<256;++Z)bt[Z]=9;for(Z=256;Z<280;++Z)bt[Z]=7;for(Z=280;Z<288;++Z)bt[Z]=8;ls=new de(32);for(Z=0;Z<32;++Z)ls[Z]=5;Kc=tt(bt,9,0),Jc=tt(bt,9,1),qc=tt(ls,5,0),$c=tt(ls,5,1),qo=function(d){for(var a=d[0],e=1;e<d.length;++e)d[e]>a&&(a=d[e]);return a},Je=function(d,a,e){var t=a/8|0;return(d[t]|d[t+1]<<8)>>(a&7)&e},$o=function(d,a){var e=a/8|0;return(d[e]|d[e+1]<<8|d[e+2]<<16)>>(a&7)},tr=function(d){return(d+7)/8|0},cs=function(d,a,e){return(a==null||a<0)&&(a=0),(e==null||e>d.length)&&(e=d.length),new de(d.subarray(a,e))},Yc=["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"],Ee=function(d,a,e){var t=new Error(a||Yc[d]);if(t.code=d,Error.captureStackTrace&&Error.captureStackTrace(t,Ee),!e)throw t;return t},zc=function(d,a,e,t){var i=d.length,s=t?t.length:0;if(!i||a.f&&!a.l)return e||new de(0);var n=!e,o=n||a.i!=2,r=a.i;n&&(e=new de(i*3));var l=function(ge){var xe=e.length;if(ge>xe){var ne=new de(Math.max(xe*2,ge));ne.set(e),e=ne}},c=a.f||0,A=a.p||0,h=a.b||0,p=a.l,u=a.d,f=a.m,g=a.n,I=i*8;do{if(!p){c=Je(d,A,1);var m=Je(d,A+1,3);if(A+=3,m)if(m==1)p=Jc,u=$c,f=9,g=5;else if(m==2){var y=Je(d,A,31)+257,E=Je(d,A+10,15)+4,w=y+Je(d,A+5,31)+1;A+=14;for(var v=new de(w),F=new de(19),D=0;D<E;++D)F[Vo[D]]=Je(d,A+D*3,7);A+=E*3;for(var R=qo(F),G=(1<<R)-1,x=tt(F,R,1),D=0;D<w;){var H=x[Je(d,A,G)];A+=H&15;var B=H>>4;if(B<16)v[D++]=B;else{var U=0,N=0;for(B==16?(N=3+Je(d,A,3),A+=2,U=v[D-1]):B==17?(N=3+Je(d,A,7),A+=3):B==18&&(N=11+Je(d,A,127),A+=7);N--;)v[D++]=U}}var S=v.subarray(0,y),P=v.subarray(y);f=qo(S),g=qo(P),p=tt(S,f,1),u=tt(P,g,1)}else Ee(1);else{var B=tr(A)+4,C=d[B-4]|d[B-3]<<8,Q=B+C;if(Q>i){r&&Ee(0);break}o&&l(h+C),e.set(d.subarray(B,Q),h),a.b=h+=C,a.p=A=Q*8,a.f=c;continue}if(A>I){r&&Ee(0);break}}o&&l(h+131072);for(var O=(1<<f)-1,L=(1<<g)-1,K=A;;K=A){var U=p[$o(d,A)&O],V=U>>4;if(A+=U&15,A>I){r&&Ee(0);break}if(U||Ee(2),V<256)e[h++]=V;else if(V==256){K=A,p=null;break}else{var Y=V-254;if(V>264){var D=V-257,$=yn[D];Y=Je(d,A,(1<<$)-1)+Oa[D],A+=$}var j=u[$o(d,A)&L],ce=j>>4;j||Ee(3),A+=j&15;var P=Oc[ce];if(ce>3){var $=wn[ce];P+=$o(d,A)&(1<<$)-1,A+=$}if(A>I){r&&Ee(0);break}o&&l(h+131072);var re=h+Y;if(h<P){var se=s-P,te=Math.min(P,re);for(se+h<0&&Ee(3);h<te;++h)e[h]=t[se+h]}for(;h<re;++h)e[h]=e[h-P]}}a.l=p,a.p=K,a.b=h,a.f=c,p&&(c=1,a.m=f,a.d=u,a.n=g)}while(!c);return h!=e.length&&n?cs(e,0,h):e.subarray(0,h)},ft=function(d,a,e){e<<=a&7;var t=a/8|0;d[t]|=e,d[t+1]|=e>>8},rs=function(d,a,e){e<<=a&7;var t=a/8|0;d[t]|=e,d[t+1]|=e>>8,d[t+2]|=e>>16},Yo=function(d,a){for(var e=[],t=0;t<d.length;++t)d[t]&&e.push({s:t,f:d[t]});var i=e.length,s=e.slice();if(!i)return{t:qa,l:0};if(i==1){var n=new de(e[0].s+1);return n[e[0].s]=1,{t:n,l:1}}e.sort(function(Q,y){return Q.f-y.f}),e.push({s:-1,f:25001});var o=e[0],r=e[1],l=0,c=1,A=2;for(e[0]={s:-1,f:o.f+r.f,l:o,r};c!=i-1;)o=e[e[l].f<e[A].f?l++:A++],r=e[l!=c&&e[l].f<e[A].f?l++:A++],e[c++]={s:-1,f:o.f+r.f,l:o,r};for(var h=s[0].s,t=1;t<i;++t)s[t].s>h&&(h=s[t].s);var p=new De(h+1),u=Zo(e[c-1],p,0);if(u>a){var t=0,f=0,g=u-a,I=1<<g;for(s.sort(function(y,E){return p[E.s]-p[y.s]||y.f-E.f});t<i;++t){var m=s[t].s;if(p[m]>a)f+=I-(1<<u-p[m]),p[m]=a;else break}for(f>>=g;f>0;){var B=s[t].s;p[B]<a?f-=1<<a-p[B]++-1:++t}for(;t>=0&&f;--t){var C=s[t].s;p[C]==a&&(--p[C],++f)}u=a}return{t:new de(p),l:u}},Zo=function(d,a,e){return d.s==-1?Math.max(Zo(d.l,a,e+1),Zo(d.r,a,e+1)):a[d.s]=e},Pa=function(d){for(var a=d.length;a&&!d[--a];);for(var e=new De(++a),t=0,i=d[0],s=1,n=function(r){e[t++]=r},o=1;o<=a;++o)if(d[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=d[o]}return{c:e.subarray(0,t),n:a}},as=function(d,a){for(var e=0,t=0;t<a.length;++t)e+=d[t]*a[t];return e},Ja=function(d,a,e){var t=e.length,i=tr(a+2);d[i]=t&255,d[i+1]=t>>8,d[i+2]=d[i]^255,d[i+3]=d[i+1]^255;for(var s=0;s<t;++s)d[i+s+4]=e[s];return(i+4+t)*8},Ha=function(d,a,e,t,i,s,n,o,r,l,c){ft(a,c++,e),++i[256];for(var A=Yo(i,15),h=A.t,p=A.l,u=Yo(s,15),f=u.t,g=u.l,I=Pa(h),m=I.c,B=I.n,C=Pa(f),Q=C.c,y=C.n,E=new De(19),w=0;w<m.length;++w)++E[m[w]&31];for(var w=0;w<Q.length;++w)++E[Q[w]&31];for(var v=Yo(E,7),F=v.t,D=v.l,R=19;R>4&&!F[Vo[R-1]];--R);var G=l+5<<3,x=as(i,bt)+as(s,ls)+n,H=as(i,h)+as(s,f)+n+14+3*R+as(E,F)+2*E[16]+3*E[17]+7*E[18];if(r>=0&&G<=x&&G<=H)return Ja(a,c,d.subarray(r,r+l));var U,N,S,P;if(ft(a,c,1+(H<x)),c+=2,H<x){U=tt(h,p,0),N=h,S=tt(f,g,0),P=f;var O=tt(F,D,0);ft(a,c,B-257),ft(a,c+5,y-1),ft(a,c+10,R-4),c+=14;for(var w=0;w<R;++w)ft(a,c+3*w,F[Vo[w]]);c+=3*R;for(var L=[m,Q],K=0;K<2;++K)for(var V=L[K],w=0;w<V.length;++w){var Y=V[w]&31;ft(a,c,O[Y]),c+=F[Y],Y>15&&(ft(a,c,V[w]>>5&127),c+=V[w]>>12)}}else U=Kc,N=bt,S=qc,P=ls;for(var w=0;w<o;++w){var $=t[w];if($>255){var Y=$>>18&31;rs(a,c,U[Y+257]),c+=N[Y+257],Y>7&&(ft(a,c,$>>23&31),c+=yn[Y]);var j=$&31;rs(a,c,S[j]),c+=P[j],j>3&&(rs(a,c,$>>5&8191),c+=wn[j])}else rs(a,c,U[$]),c+=N[$]}return rs(a,c,U[256]),c+N[256]},Vc=new er([65540,131080,131088,131104,262176,1048704,1048832,2114560,2117632]),qa=new de(0),Wc=function(d,a,e,t,i,s){var n=s.z||d.length,o=new de(t+n+5*(1+Math.ceil(n/7e3))+i),r=o.subarray(t,o.length-i),l=s.l,c=(s.r||0)&7;if(a){c&&(r[0]=s.r>>3);for(var A=Vc[a-1],h=A>>13,p=A&8191,u=(1<<e)-1,f=s.p||new De(32768),g=s.h||new De(u+1),I=Math.ceil(e/3),m=2*I,B=function(ve){return(d[ve]^d[ve+1]<<I^d[ve+2]<<m)&u},C=new er(25e3),Q=new De(288),y=new De(32),E=0,w=0,v=s.i||0,F=0,D=s.w||0,R=0;v+2<n;++v){var G=B(v),x=v&32767,H=g[G];if(f[x]=H,g[G]=x,D<=v){var U=n-v;if((E>7e3||F>24576)&&(U>423||!l)){c=Ha(d,r,0,C,Q,y,w,F,R,v-R,c),F=E=w=0,R=v;for(var N=0;N<286;++N)Q[N]=0;for(var N=0;N<30;++N)y[N]=0}var S=2,P=0,O=p,L=x-H&32767;if(U>2&&G==B(v-L))for(var K=Math.min(h,U)-1,V=Math.min(32767,v),Y=Math.min(258,U);L<=V&&--O&&x!=H;){if(d[v+S]==d[v+S-L]){for(var $=0;$<Y&&d[v+$]==d[v+$-L];++$);if($>S){if(S=$,P=L,$>K)break;for(var j=Math.min(L,$-2),ce=0,N=0;N<j;++N){var re=v-L+N&32767,se=f[re],te=re-se&32767;te>ce&&(ce=te,H=re)}}}x=H,H=f[x],L+=x-H&32767}if(P){C[F++]=268435456|Wo[S]<<18|Ta[P];var ge=Wo[S]&31,xe=Ta[P]&31;w+=yn[ge]+wn[xe],++Q[257+ge],++y[xe],D=v+S,++E}else C[F++]=d[v],++Q[d[v]]}}for(v=Math.max(v,D);v<n;++v)C[F++]=d[v],++Q[d[v]];c=Ha(d,r,l,C,Q,y,w,F,R,v-R,c),l||(s.r=c&7|r[c/8|0]<<3,c-=7,s.h=g,s.p=f,s.i=v,s.w=D)}else{for(var v=s.w||0;v<n+l;v+=65535){var ne=v+65535;ne>=n&&(r[c/8|0]=l,ne=n),c=Ja(r,c+1,d.subarray(v,ne))}s.i=n}return cs(o,0,t+tr(c)+i)},Xc=function(){for(var d=new Int32Array(256),a=0;a<256;++a){for(var e=a,t=9;--t;)e=(e&1&&-306674912)^e>>>1;d[a]=e}return d}(),Zc=function(){var d=-1;return{p:function(a){for(var e=d,t=0;t<a.length;++t)e=Xc[e&255^a[t]]^e>>>8;d=e},d:function(){return~d}}},jc=function(d,a,e,t,i){if(!i&&(i={l:1},a.dictionary)){var s=a.dictionary.subarray(-32768),n=new de(s.length+d.length);n.set(s),n.set(d,s.length),d=n,i.w=s.length}return Wc(d,a.level==null?6:a.level,a.mem==null?i.l?Math.ceil(Math.max(8,Math.min(13,Math.log(d.length)))*1.5):20:12+a.mem,e,t,i)},$a=function(d,a){var e={};for(var t in d)e[t]=d[t];for(var t in a)e[t]=a[t];return e},et=function(d,a){return d[a]|d[a+1]<<8},Re=function(d,a){return(d[a]|d[a+1]<<8|d[a+2]<<16|d[a+3]<<24)>>>0},zo=function(d,a){return Re(d,a)+Re(d,a+4)*4294967296},ye=function(d,a,e){for(;e;++a)d[a]=e,e>>>=8};Ya=function(d,a,e,t){for(var i in d){var s=d[i],n=a+i,o=t;Array.isArray(s)&&(o=$a(t,s[1]),s=s[0]),ArrayBuffer.isView(s)?e[n]=[s,o]:(e[n+="/"]=[new de(0),o],Ya(s,n,e,t))}},Ra=typeof TextEncoder<"u"&&new TextEncoder,jo=typeof TextDecoder<"u"&&new TextDecoder,td=0;try{jo.decode(qa,{stream:!0}),td=1}catch{}id=function(d){for(var a="",e=0;;){var t=d[e++],i=(t>127)+(t>223)+(t>239);if(e+i>d.length)return{s:a,r:cs(d,e-1)};i?i==3?(t=((t&15)<<18|(d[e++]&63)<<12|(d[e++]&63)<<6|d[e++]&63)-65536,a+=String.fromCharCode(55296|t>>10,56320|t&1023)):i&1?a+=String.fromCharCode((t&31)<<6|d[e++]&63):a+=String.fromCharCode((t&15)<<12|(d[e++]&63)<<6|d[e++]&63):a+=String.fromCharCode(t)}};sd=function(d,a){return a+30+et(d,a+26)+et(d,a+28)},nd=function(d,a,e){var t=et(d,a+28),i=et(d,a+30),s=ir(d.subarray(a+46,a+46+t),!(et(d,a+8)&2048)),n=a+46+t,o=od(d,n,i,e,Re(d,a+20),Re(d,a+24),Re(d,a+42)),r=o[0],l=o[1],c=o[2];return[et(d,a+10),r,l,s,n+i+et(d,a+32),c]},od=function(d,a,e,t,i,s,n){var o=i==4294967295,r=s==4294967295,l=n==4294967295,c=a+e,A=o+r+l;if(t&&A){for(;a+4<c;a+=4+et(d,a+2))if(et(d,a)==1)return[o?zo(d,a+4+8*r):i,r?zo(d,a+4):s,l?zo(d,a+4+8*(r+o)):n,1];t<2&&Ee(13)}return[i,s,n,0]},_o=function(d){var a=0;if(d)for(var e in d){var t=d[e].length;t>65535&&Ee(9),a+=t+4}return a},Ua=function(d,a,e,t,i,s,n,o){var r=t.length,l=e.extra,c=o&&o.length,A=_o(l);ye(d,a,n!=null?33639248:67324752),a+=4,n!=null&&(d[a++]=20,d[a++]=e.os),d[a]=20,a+=2,d[a++]=e.flag<<1|(s<0&&8),d[a++]=i&&8,d[a++]=e.compression&255,d[a++]=e.compression>>8;var h=new Date(e.mtime==null?Date.now():e.mtime),p=h.getFullYear()-1980;if((p<0||p>119)&&Ee(10),ye(d,a,p<<25|h.getMonth()+1<<21|h.getDate()<<16|h.getHours()<<11|h.getMinutes()<<5|h.getSeconds()>>1),a+=4,s!=-1&&(ye(d,a,e.crc),ye(d,a+4,s<0?-s-2:s),ye(d,a+8,e.size)),ye(d,a+12,r),ye(d,a+14,A),a+=16,n!=null&&(ye(d,a,c),ye(d,a+6,e.attrs),ye(d,a+10,n),a+=14),d.set(t,a),a+=r,A)for(var u in l){var f=l[u],g=f.length;ye(d,a,+u),ye(d,a+2,g),d.set(f,a+4),a+=4+g}return c&&(d.set(o,a),a+=c),a},rd=function(d,a,e,t,i){ye(d,a,101010256),ye(d,a+8,e),ye(d,a+10,e),ye(d,a+12,t),ye(d,a+16,i)}});var ja={};Si(ja,{bytesToStr:()=>En,unzipFiles:()=>Ei,zipFiles:()=>ds});function ld(d){return typeof d=="string"?Bn(d):d instanceof Uint8Array?d:new Uint8Array(d)}function ds(d,a=6){let e={};for(let t of d)e[t.name]=[ld(t.data),{level:a}];return Promise.resolve(za(e,{level:a}))}function En(d){return ir(d)}function Ei(d){let a=d instanceof Uint8Array?d:new Uint8Array(d),e=0,t=0,i=s=>{if(t+=1,t>Za)throw new Error(`Refusing to unzip: too many entries (>${Za}) \u2014 possible zip bomb.`);if(s.originalSize>ad)throw new Error(`Refusing to unzip: entry "${s.name}" is ${Math.round(s.originalSize/1048576)} MiB \u2014 possible zip bomb.`);if(e+=s.originalSize,e>Xa)throw new Error(`Refusing to unzip: total size >${Math.round(Xa/1048576)} MiB \u2014 possible zip bomb.`);return!0};return Promise.resolve(Va(a,{filter:i}))}var Xa,ad,Za,Qn=$e(()=>{"use strict";Wa();Xa=512*1024*1024,ad=256*1024*1024,Za=2e4});var Md={};Si(Md,{default:()=>zn});module.exports=Hl(Md);var M=require("obsidian");var bi="sheet-group",ot="sheet-order",Wt="sheet-final",Ir="sheet-label",Di="sheet-origin",xi="forked-from",Ye="fork-siblings",Zn="forked-at",jn=[bi,ot,Wt,Ir,Di,xi,Ye,Zn];function ze(d){if(!d)return null;let a=d[bi];return typeof a=="string"&&a.trim()?a:null}function Xn(d){let a=d?.[ot];return typeof a=="number"?a:null}function Ni(d){return ze(d)!==null&&Xn(d)!==null}function Mi(d){return d?.[Wt]===!0}function mr(d){return d?.[Di]===!0}function Rl(d){let a=d?.[xi];return typeof a=="string"&&a.trim()?a:null}function ys(d){return typeof d!="string"?null:d.replace(/^\[\[/,"").replace(/\]\]$/,"").split("|")[0].split("#")[0].trim()||null}function Cr(d){return ys(Rl(d))}function Ul(d){let a=d?.[Ir];return typeof a=="string"&&a.trim()?a:null}function Br(){let d=Date.now().toString(36),a=Math.floor(Math.random()*1e6).toString(36);return`s-${d}-${a}`}function we(d,a){return a.file?d.metadataCache.getFileCache(a.file)?.frontmatter:null}function _n(d,a){return a.slice().sort((e,t)=>{let i=Xn(we(d,e)),s=Xn(we(d,t));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=e.created??"",o=t.created??"";return n!==o?n<o?-1:1:e.id<t.id?-1:e.id>t.id?1:0})}function yr(d,a){if(a.length===0)return null;let e=_n(d,a);return e.find(t=>Mi(we(d,t)))??e[0]}function wr(d,a,e){let t=Ul(we(d,a));return t||e}rt();le();var Be=require("obsidian");var oe=require("obsidian");le();function vs(d){let a=(d.dateDisplayTimezone||"").trim();return a?{timeZone:a}:{}}function lt(d,a){try{return new Intl.DateTimeFormat(void 0,a).format(new Date(d))}catch{let{timeZone:e,...t}=a;return new Intl.DateTimeFormat(void 0,t).format(new Date(d))}}function Xe(d,a){let e=vs(a);switch(a.dateDisplayFormat??"locale"){case"iso":return br(d,a,!0);case"us":return lt(d,{...e,month:"numeric",day:"numeric",year:"numeric",hour:"numeric",minute:"2-digit"});case"eu":return lt(d,{...e,day:"numeric",month:"numeric",year:"numeric",hour:"2-digit",minute:"2-digit",hourCycle:"h23"});case"long":return lt(d,{...e,dateStyle:"full",timeStyle:"short"});case"locale":default:return lt(d,{...e,dateStyle:"medium",timeStyle:"short"})}}function Et(d,a){let e=vs(a);switch(a.dateDisplayFormat??"locale"){case"iso":return br(d,a,!1);case"us":return lt(d,{...e,month:"numeric",day:"numeric",year:"numeric"});case"eu":return lt(d,{...e,day:"numeric",month:"numeric",year:"numeric"});case"long":return lt(d,{...e,dateStyle:"full"});case"locale":default:{let t=new Date,i=new Date(d).getFullYear()===t.getFullYear();return lt(d,i?{...e,month:"short",day:"numeric"}:{...e,month:"short",day:"numeric",year:"numeric"})}}}function _t(d,a){let e=vs(a),t=a.dateDisplayFormat==="iso"||a.dateDisplayFormat==="eu";return lt(d,{...e,hour:t?"2-digit":"numeric",minute:"2-digit",...t?{hourCycle:"h23"}:{}})}function br(d,a,e){let t=vs(a),i=new Intl.DateTimeFormat("en-CA",{...t,year:"numeric",month:"2-digit",day:"2-digit",...e?{hour:"2-digit",minute:"2-digit",hourCycle:"h23"}:{}}).formatToParts(new Date(d)),s=o=>i.find(r=>r.type===o)?.value??"",n=`${s("year")}-${s("month")}-${s("day")}`;return e?`${n} ${s("hour")}:${s("minute")}`:n}me();le();function Ao(d,a){let e=d.basename;return a&&e.endsWith(`-${a}`)?e=e.slice(0,-(a.length+1)):a||(e=e.replace(/-[abcdefghijkmnpqrstuvwxyz23456789]{6}$/,"")),e.replace(/-/g," ").trim()||d.basename}function bs(d,a){let e=new Set(a.discoverStashpadFolders()),t=[];for(let i of d.vault.getMarkdownFiles()){let s=i.parent?.path?.replace(/\/+$/,"")??"";if(!e.has(s))continue;let n=d.metadataCache.getFileCache(i)?.frontmatter??{},o=typeof n.id=="string"?n.id:null;if(!o||o===k)continue;let r=n.completed===!0,l=jt(n,"task")||n.task===!0||n.completed!==void 0,c=typeof n.due=="string"||typeof n.due=="number"?String(n.due):null,A=null;if(typeof n.due=="number")Number.isFinite(n.due)&&n.due>=1e11&&(A=n.due);else if(c){let h=Date.parse(c);Number.isNaN(h)||(A=h)}!l&&!r&&A==null&&!c||t.push({file:i,folder:s,id:o,title:Ao(i,o),task:l,completed:r,due:A,dueRaw:c,color:typeof n.color=="string"?n.color:null,assignedTo:Pt(n),assignedBy:at(n.assignedBy),author:at(n.author)})}return t}var Kr=require("obsidian");var Ze=require("obsidian");me();var $l=0,ho=[{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"}];function Ds(){return{assign:"all",person:"",folder:"all",status:"all"}}function zi(d,a,e,t,i){let s=()=>zi(d,a,e,t,i);d.empty(),d.addClass("stashpad-task-triage");let n=bs(a,e),o=(e.settings.authorId??"").trim(),r=S=>!!o&&S.assignedTo.some(P=>P.id===o),l=S=>{switch(t.assign){case"mine":return r(S);case"others":return S.assignedTo.length>0&&!r(S);case"byme":return!!o&&S.assignedBy?.id===o;case"unassigned":return S.assignedTo.length===0;default:return!0}},c=S=>!t.person||S.assignedTo.some(P=>P.id===t.person)||S.author?.id===t.person||S.assignedBy?.id===t.person,A=new Map;for(let S of n){for(let P of S.assignedTo)A.set(P.id,P.name);S.assignedBy&&A.set(S.assignedBy.id,S.assignedBy.name),S.author&&A.set(S.author.id,S.author.name)}let h=[...A.entries()].map(([S,P])=>({id:S,name:P})).sort((S,P)=>S.name.localeCompare(P.name)),p=[...new Set(n.map(S=>S.folder))].sort((S,P)=>S.localeCompare(P));t.folder!=="all"&&!p.includes(t.folder)&&(t.folder="all");let u=S=>t.folder==="all"||S.folder===t.folder,f=d.createDiv({cls:"stashpad-triage-filters"}),g=f.createEl("button",{cls:"stashpad-triage-reset",attr:{"aria-label":"Reset filters"}});(0,Ze.setIcon)(g,"rotate-ccw"),g.onclick=()=>{t.assign="all",t.person="",t.folder="all",s()};let I=f.createEl("select",{cls:"stashpad-triage-select"}),m={all:"Everyone",mine:"Assigned to me",others:"Assigned to others",byme:"Assigned by me",unassigned:"Unassigned"};for(let S of["all","mine","others","byme","unassigned"]){let P=I.createEl("option",{text:m[S],value:S});t.assign===S&&(P.selected=!0)}I.onchange=()=>{t.assign=I.value,s()};let B=f.createEl("select",{cls:"stashpad-triage-select"}),C=B.createEl("option",{text:"All folders",value:"all"});t.folder==="all"&&(C.selected=!0);for(let S of p){let P=B.createEl("option",{text:S.split("/").pop()||S,value:S});t.folder===S&&(P.selected=!0)}if(B.onchange=()=>{t.folder=B.value,s()},h.length>0){let S=new Map;for(let $ of h)S.has($.name)||S.set($.name,$.id);let P=`stashpad-task-authors-${++$l}`,O=f.createDiv({cls:"stashpad-triage-authorwrap"}),L=O.createEl("input",{cls:"stashpad-triage-authorsearch",attr:{type:"text",list:P,placeholder:"Any person\u2026",spellcheck:"false"}}),K=O.createEl("button",{cls:"stashpad-triage-authorclear",attr:{"aria-label":"Clear person filter"}});(0,Ze.setIcon)(K,"x"),K.onclick=()=>{L.value="",t.person?(t.person="",s()):L.focus()};let V=O.createEl("datalist");V.id=P;for(let $ of h)V.createEl("option",{value:$.name});t.person&&(L.value=A.get(t.person)??"");let Y=()=>{let $=L.value.trim();if($===""){t.person&&(t.person="",s());return}let j=S.get($);j&&t.person!==j&&(t.person=j,s())};L.onchange=Y,L.addEventListener("keydown",$=>{$.key==="Enter"&&Y()})}let Q=Date.now(),y=new Date;y.setHours(0,0,0,0);let E=y.getTime(),w=E+864e5,v=n.filter(S=>l(S)&&c(S)&&u(S)),F={overdue:[],today:[],upcoming:[],nodate:[],completed:[]};for(let S of v){if(S.completed){F.completed.push(S);continue}if(S.due==null){F.nodate.push(S);continue}S.due<E?F.overdue.push(S):S.due<w?F.today.push(S):F.upcoming.push(S)}let D=(S,P)=>S.due==null&&P.due==null?S.title.localeCompare(P.title):S.due==null?1:P.due==null?-1:S.due-P.due,R=d.createDiv({cls:"stashpad-triage-chips"}),G=(S,P,O)=>{let L=R.createEl("button",{cls:"stashpad-triage-chip"});t.status===S&&L.addClass("is-active"),L.createSpan({text:P}),L.createSpan({cls:"stashpad-triage-chip-count",text:String(O)}),L.onclick=()=>{t.status=S,s()}};G("all","All",v.length);for(let S of ho)G(S.key,S.label,F[S.key].length);if(v.length===0){d.createDiv({cls:"stashpad-tasks-empty"}).setText(n.length===0?"No tasks yet \u2014 press G on a note to make it a task, or D to give it a due date.":"No tasks match the current filters.");return}let x=async S=>{try{await a.fileManager.processFrontMatter(S.file,P=>{P.completed=P.completed!==!0})}catch(P){new Ze.Notice(`Couldn't update task: ${P.message}`);return}s()},H=S=>{let P=S.dueRaw??(S.due!=null?new Date(S.due).toISOString():null);new Ge(a,P,O=>{a.fileManager.processFrontMatter(S.file,L=>{O.iso===null?delete L.due:(L.due=O.iso,L.task=!0)}).then(s).catch(L=>new Ze.Notice(`Couldn't snooze: ${L.message}`))},{title:"Snooze \u2014 reschedule",hideAssignees:!0,quickAdjusts:e.settings.dueQuickAdjusts}).open()},U=t.status==="all"?ho:ho.filter(S=>S.key===t.status),N=!1;for(let S of U){let P=F[S.key];if(P.length===0)continue;if(N=!0,P.sort(S.key==="completed"?(L,K)=>D(K,L):D),t.status==="all"){let L=d.createDiv({cls:`stashpad-review-section is-${S.key}`});(0,Ze.setIcon)(L.createSpan({cls:"stashpad-review-section-icon"}),S.icon),L.createSpan({cls:"stashpad-review-section-name",text:S.label}),L.createSpan({cls:"stashpad-review-section-count",text:String(P.length)})}let O=d.createDiv({cls:"stashpad-review-list"});for(let L of P)Yl(O,L,Q,e,{toggleCompleted:x,snooze:H,onOpen:i.onOpen})}N||d.createDiv({cls:"stashpad-tasks-empty"}).setText("Nothing in this view.")}function Yl(d,a,e,t,i){let s=d.createDiv({cls:"stashpad-review-row"});a.completed&&s.addClass("is-completed");let n=s.createSpan({cls:"stashpad-review-check"});(0,Ze.setIcon)(n,a.completed?"check-square":"square"),a.color&&(n.style.color=a.color),n.title=a.completed?"Mark not done":"Mark done",n.onclick=()=>i.toggleCompleted(a);let o=s.createDiv({cls:"stashpad-review-main"}),r=o.createDiv({cls:"stashpad-review-title",text:a.title});r.onclick=()=>i.onOpen(a.folder,a.id);let l=o.createDiv({cls:"stashpad-review-meta"});if(l.createSpan({cls:"stashpad-review-folder",text:a.folder.split("/").pop()||a.folder}),a.author&&l.createSpan({cls:"stashpad-review-author",text:`by ${a.author.name}`}),a.due!=null){let p=a.due<e&&!a.completed,u=new Date(e);u.setHours(0,0,0,0);let f=u.getTime(),g=a.due>=f&&a.due<f+864e5,I=l.createSpan({cls:"stashpad-review-due",text:g?_t(a.due,t.settings):Et(a.due,t.settings)});p&&I.addClass("is-overdue")}else a.dueRaw?l.createSpan({cls:"stashpad-review-due",text:a.dueRaw}):l.createSpan({cls:"stashpad-review-due is-none",text:"no date"});for(let p of a.assignedTo)l.createSpan({cls:"stashpad-review-assignee",text:p.name});let c=s.createDiv({cls:"stashpad-review-actions"}),A=c.createEl("button",{cls:"stashpad-review-btn"});(0,Ze.setIcon)(A,"alarm-clock"),A.title="Snooze \u2014 reschedule",A.onclick=()=>i.snooze(a);let h=c.createEl("button",{cls:"stashpad-review-btn"});(0,Ze.setIcon)(h,"arrow-right"),h.title="Open note",h.onclick=()=>i.onOpen(a.folder,a.id)}var ri=class extends Kr.Modal{constructor(e,t){super(e);this.plugin=t;this.state=Ds()}onOpen(){this.modalEl.addClass("stashpad-task-review-modal"),this.titleEl.setText("Daily task review"),zi(this.contentEl,this.app,this.plugin,this.state,{onOpen:(e,t)=>{this.plugin.revealNoteByRef(e,t),this.close()}})}onClose(){this.contentEl.empty()}};function Qt(d,a,e){let t=d.createSpan({cls:"stashpad-count-badge"});e&&t.addClass("is-expanded"),t.setText(a>99?"99+":String(a))}var Vi={pinned:{label:"Pinned",icon:"pin"},shared:{label:"Shared",icon:"users"},tasks:{label:"Tasks",icon:"check-circle-2"}},xs=class extends oe.ItemView{constructor(e,t){super(e);this.plugin=t;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(e){this.activePanel=e,this.containerEl.isConnected&&this.render()}getViewType(){return Bt}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",e=>{e&&e.view.getViewType()===z&&this.scheduleRender()}))}scheduleRender(){this.renderTimer==null&&(this.renderTimer=window.setTimeout(()=>{this.renderTimer=null,this.containerEl.isConnected&&this.render()},80))}render(){let e=this.contentEl;e.empty(),e.addClass("stashpad-panels-root");let t=e.createDiv({cls:"stashpad-panels-globals"}),i=t.createEl("button",{cls:"stashpad-panels-global-btn"});(0,oe.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=t.createEl("button",{cls:"stashpad-panels-global-btn"});(0,oe.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=t.createDiv({cls:"stashpad-panels-globals-row"}),o=n.createEl("button",{cls:"stashpad-panels-global-btn"});(0,oe.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,oe.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 l=e.createDiv({cls:"stashpad-panels-bar"});for(let A of Object.keys(Vi)){let h=Vi[A],p=l.createEl("button",{cls:"stashpad-panels-bar-btn"});(0,oe.setIcon)(p.createSpan({cls:"stashpad-panels-bar-btn-icon"}),h.icon),p.createSpan({cls:"stashpad-panels-bar-btn-text",text:h.label}),this.activePanel===A&&p.addClass("is-active"),p.onclick=()=>{this.activePanel!==A&&(this.activePanel=A,this.render())}}let c=e.createDiv({cls:"stashpad-panels-body"});this.activePanel==="pinned"?this.renderPinnedPanel(c):this.activePanel==="shared"?this.renderSharedPanel(c):this.activePanel==="tasks"&&this.renderTasksPanel(c)}openPinnedOptionsMenu(e){let t=this.plugin.settings.folderPanelPinnedGrouping??"pin-order",i=new oe.Menu;i.addItem(s=>s.setTitle("Sort by pin order").setChecked(t==="pin-order").onClick(()=>void this.setPinnedGrouping("pin-order"))),i.addItem(s=>s.setTitle("Group by folder").setChecked(t==="folder").onClick(()=>void this.setPinnedGrouping("folder"))),i.showAtMouseEvent(e)}async setPinnedGrouping(e){(this.plugin.settings.folderPanelPinnedGrouping??"pin-order")!==e&&(this.plugin.settings.folderPanelPinnedGrouping=e,await this.plugin.saveSettings(),this.render())}renderPinnedPanel(e){let t=e.createDiv({cls:"stashpad-panel-pinned"});(this.plugin.settings.folderPanelPinnedGrouping??"pin-order")!=="folder"&&t.addClass("is-flat");let i=t.createDiv({cls:"stashpad-pinned-headrow"}),s=i.createEl("button",{cls:"stashpad-pinned-row stashpad-pinned-home"}),n=s.createSpan({cls:"stashpad-pinned-icon"});(0,oe.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,oe.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){t.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,u)=>this.renderPinnedRow(t,p,u));return}let c=new Map;r.forEach((p,u)=>{let f=c.get(p.folder);f||(f=[],c.set(p.folder,f)),f.push({pin:p,idx:u})});let A=this.plugin.lastActiveStashpadLeaf?.view?.noteFolder,h=Array.from(c.keys());A&&c.has(A)&&(h.splice(h.indexOf(A),1),h.unshift(A));for(let p of h){let u=p.split("/").pop()||p,f=t.createDiv({cls:"stashpad-pinned-group-header"});p===A&&f.addClass("is-active-folder"),f.createSpan({cls:"stashpad-pinned-group-name",text:u});let g=c.get(p)??[];for(let{pin:I,idx:m}of g)this.renderPinnedRow(t,I,m)}}renderPinnedRow(e,t,i){let s=this.findFileFor(t);if(!s)return;let n=this.app.metadataCache.getFileCache(s)?.frontmatter??{},o=this.titleFromFile(s),r=typeof n.color=="string"?n.color:null,l=n.completed===!0,c=this.childrenOf(t.folder,t.id).length,A=c>0,h=this.expanded.has(`${t.folder}|${t.id}`),p=e.createDiv({cls:"stashpad-pinned-row"});r&&p.addClass("has-color"),l&&p.addClass("is-completed"),p.draggable=!0,p.dataset.pinIdx=String(i),p.addEventListener("dragstart",m=>{m.dataTransfer?.setData("text/plain",String(i)),m.dataTransfer&&(m.dataTransfer.effectAllowed="move"),p.addClass("is-dragging")}),p.addEventListener("dragend",()=>p.removeClass("is-dragging")),p.addEventListener("dragover",m=>{m.preventDefault(),m.dataTransfer&&(m.dataTransfer.dropEffect="move");let B=p.getBoundingClientRect(),C=m.clientY-B.top<B.height/2;p.toggleClass("drop-before",C),p.toggleClass("drop-after",!C)}),p.addEventListener("dragleave",()=>{p.removeClass("drop-before"),p.removeClass("drop-after")}),p.addEventListener("drop",m=>{m.preventDefault(),p.removeClass("drop-before"),p.removeClass("drop-after");let B=parseInt(m.dataTransfer?.getData("text/plain")??"",10);if(!Number.isFinite(B)||B===i)return;let C=p.getBoundingClientRect(),Q=m.clientY-C.top<C.height/2;this.reorderPin(B,Q?i:i+1)});let u=p.createSpan({cls:"stashpad-pinned-toggle"});A&&(Qt(u,c,h),u.onclick=m=>{m.stopPropagation();let B=`${t.folder}|${t.id}`;this.expanded.has(B)?this.expanded.delete(B):this.expanded.add(B),this.render()});let f=p.createSpan({cls:"stashpad-pinned-icon"});(0,oe.setIcon)(f,A?"folder-tree":"file-text"),r&&(f.style.color=r);let g=p.createSpan({cls:"stashpad-pinned-label",text:o});g.onclick=()=>this.openPinFromPanel(t);let I=t.folder.split("/").pop()||t.folder;if(p.createSpan({cls:"stashpad-pinned-folder",text:I}),p.oncontextmenu=m=>{m.preventDefault();let B=new oe.Menu;B.addItem(C=>C.setTitle("Unpin from sidebar").setIcon("pin-off").onClick(()=>{this.plugin.unpinNote(t)})),B.showAtMouseEvent(m)},A&&h){let m=e.createDiv({cls:"stashpad-pinned-children"});this.renderPinnedSubtree(m,t.folder,t.id,1)}}async reorderPin(e,t){let i=this.plugin.listPinnedNotes();if(e<0||e>=i.length)return;let s=i[e],n=i.filter((A,h)=>h!==e),o=Math.max(0,Math.min(t>e?t-1:t,n.length)),r=n[o-1],l=n[o],c;!r&&!l?c=Date.now():r?l?c=(r.pinnedAt+l.pinnedAt)/2:c=r.pinnedAt+1e3:c=l.pinnedAt-1e3;try{await this.app.fileManager.processFrontMatter(s.file,A=>{A.pinnedAt=c})}catch(A){console.warn("[Stashpad] pin reorder failed",A)}this.render()}renderPinnedSubtree(e,t,i,s){let n=this.childrenOf(t,i);for(let o of n){let r=this.app.metadataCache.getFileCache(o)?.frontmatter??{},l=typeof r.id=="string"?r.id:null;if(!l)continue;let c=typeof r.color=="string"?r.color:null,A=r.completed===!0,h=this.childrenOf(t,l).length,p=h>0,u=this.expanded.has(`${t}|${l}`),f=e.createDiv({cls:"stashpad-pinned-subrow"});A&&f.addClass("is-completed"),f.style.paddingLeft=`${s*16}px`;let g=f.createSpan({cls:"stashpad-pinned-toggle"});p&&(Qt(g,h,u),g.onclick=B=>{B.stopPropagation();let C=`${t}|${l}`;this.expanded.has(C)?this.expanded.delete(C):this.expanded.add(C),this.render()});let I=f.createSpan({cls:"stashpad-pinned-icon"});(0,oe.setIcon)(I,"file-text"),c&&(I.style.color=c);let m=f.createSpan({cls:"stashpad-pinned-label",text:this.titleFromFile(o)});m.onclick=()=>this.openPinFromPanel({folder:t,id:l}),p&&u&&this.renderPinnedSubtree(e,t,l,s+1)}}findFileFor(e){for(let t of this.app.vault.getMarkdownFiles()){if((t.parent?.path?.replace(/\/+$/,"")??"")!==e.folder)continue;if(this.app.metadataCache.getFileCache(t)?.frontmatter?.id===e.id)return t}return null}childrenOf(e,t){let i=[];for(let s of this.app.vault.getMarkdownFiles()){if((s.parent?.path?.replace(/\/+$/,"")??"")!==e)continue;let o=this.app.metadataCache.getFileCache(s)?.frontmatter;if(!o||typeof o.id!="string")continue;let r=o.parent;if(r===t||t===k&&(r==null||r===k)){if(o.id===k)continue;i.push(s)}}return i.sort((s,n)=>{let o=this.app.metadataCache.getFileCache(s)?.frontmatter,r=this.app.metadataCache.getFileCache(n)?.frontmatter,l=o?.created??"",c=r?.created??"";return l.localeCompare(c)}),i}titleFromFile(e){let t=this.app.metadataCache.getFileCache(e)?.frontmatter?.id;return Ao(e,typeof t=="string"?t:null)}async openSearchFromPanel(){let e=await this.resolveTargetStashpad();e&&typeof e.openSearchModal=="function"&&e.openSearchModal()}async openLogFromPanel(){let e=this.app.vault.adapter,t=this.plugin.pluginPrivatePath("log.jsonl");if(!await e.exists(t)){new oe.Notice("No log yet \u2014 make some changes first.");return}let i=await e.read(t),{LogModal:s}=await Promise.resolve().then(()=>(me(),Yi));new s(this.app,i,t).open()}openNotificationsFromPanel(){this.app.commands?.executeCommandById?.("stashpad:stashpad-open-notification-history")}async openHomeFromPanel(){let e=await this.resolveTargetStashpad();e&&typeof e.navigateTo=="function"&&e.navigateTo(k)}async openPinFromPanel(e){await this.plugin.revealNoteByRef(e.folder,e.id)}async resolveTargetStashpad(){let e=this.plugin.lastActiveStashpadLeaf;if(e&&e.view.getViewType()===z)return this.app.workspace.revealLeaf(e),e.view;let t=this.findActiveStashpad();if(t)return t;let i=this.app.workspace.getLeavesOfType(z);return i.length>0?(this.app.workspace.revealLeaf(i[0]),i[0].view):(await this.plugin.activateView({reveal:!0}),this.findActiveStashpad())}findActiveStashpad(){let e=this.app.workspace.activeLeaf;return e&&e.view.getViewType()===z?e.view:null}renderSharedPanel(e){let t=e.createDiv({cls:"stashpad-panel-shared"}),i=(this.plugin.settings.authorId??"").trim();if(!i){t.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 A of s){let h=A.authorId;h&&!n.has(h)&&n.set(h,A.authorDisplay||h)}let o=t.createDiv({cls:"stashpad-shared-filters"}),r=(A,h,p)=>{let u=o.createEl("button",{cls:"stashpad-shared-chip",text:A});return h&&u.addClass("is-active"),u.onclick=p,u};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 A=o.createEl("select",{cls:"stashpad-shared-author-select"}),h=A.createEl("option",{text:"Any author"});h.value="__any__";for(let[u,f]of n){let g=A.createEl("option",{text:f});g.value=u}let p=["all","mine","others"].includes(this.sharedAuthorFilter)?"__any__":this.sharedAuthorFilter;A.value=p,A.onchange=()=>{let u=A.value;u==="__any__"?this.sharedAuthorFilter="all":this.sharedAuthorFilter=u,this.render()}}let l=o.createEl("button",{cls:"stashpad-shared-chip",text:"Has contributors"});this.sharedContribOnly&&l.addClass("is-active"),l.onclick=()=>{this.sharedContribOnly=!this.sharedContribOnly,this.render()};let c=s.filter(A=>{if(this.sharedContribOnly&&A.contributorCount===0)return!1;switch(this.sharedAuthorFilter){case"all":return!0;case"mine":return A.authorId===i;case"others":return A.authorId!==i;default:return A.authorId===this.sharedAuthorFilter}});if(c.length===0){t.createDiv({cls:"stashpad-shared-empty"}).setText("No shared notes match the current filters.");return}for(let A of c){let h=t.createDiv({cls:"stashpad-pinned-row stashpad-shared-row"}),p=h.createSpan({cls:"stashpad-pinned-icon"});(0,oe.setIcon)(p,"users"),A.color&&(p.style.color=A.color);let u=h.createSpan({cls:"stashpad-pinned-label",text:A.title});u.onclick=()=>this.openSharedFromPanel(A.folder,A.id);let f=A.folder.split("/").pop()||A.folder;h.createSpan({cls:"stashpad-pinned-folder",text:f}),A.authorDisplay&&h.createSpan({cls:"stashpad-shared-meta"}).setText(A.authorId===i?`you \xB7 ${A.contributorCount} contributor${A.contributorCount===1?"":"s"}`:`by ${A.authorDisplay}${A.contributorCount>0?` \xB7 ${A.contributorCount} contributor${A.contributorCount===1?"":"s"}`:""}`)}}collectSharedNotes(e){let t=this.plugin.discoverStashpadFolders(),i=new Set(t),s=new Map;for(let o of this.app.vault.getMarkdownFiles()){let r=o.parent?.path?.replace(/\/+$/,"")??"";if(!i.has(r))continue;let l=this.app.metadataCache.getFileCache(o)?.frontmatter??{};l.id===k&&s.set(r,this.extractAuthorId(l.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 l=this.app.metadataCache.getFileCache(o)?.frontmatter??{};if(typeof l.id!="string"||l.id===k)continue;let c=this.extractAuthorId(l.author),A=Array.isArray(l.contributors)?l.contributors.filter(B=>typeof B=="string"):[],h=s.get(r)??null;if(!(A.length>0||h===e&&(c!==null&&c!==e)))continue;let I=this.titleFromFile(o),m=typeof l.color=="string"?l.color:null;n.push({file:o,folder:r,id:l.id,title:I,color:m,authorId:c,authorDisplay:this.extractAuthorDisplay(l.author)||(c??""),contributorCount:A.length})}return n.sort((o,r)=>{let l=this.app.metadataCache.getFileCache(o.file)?.frontmatter??{},c=this.app.metadataCache.getFileCache(r.file)?.frontmatter??{},A=l.modified??l.created??"";return(c.modified??c.created??"").localeCompare(A)}),n}extractAuthorId(e){if(typeof e!="string")return null;let t=e.match(/-([a-z0-9]{4,12})(?:\.md)?(?:\||\]\])/i);return t?t[1]:null}extractAuthorDisplay(e){if(typeof e!="string")return"";let t=e.match(/\|([^\]]+)\]\]/);if(t)return t[1].trim();let i=e.match(/_authors\/([^\]|]+)-[a-z0-9]{4,12}/i);return i?i[1].replace(/[-_]/g," ").trim():""}async openSharedFromPanel(e,t){await this.plugin.revealNoteByRef(e,t)}renderTasksPanel(e){let t=e.createDiv({cls:"stashpad-panel-tasks"}),s=t.createDiv({cls:"stashpad-task-review-bar"}).createEl("button",{cls:"stashpad-task-review-open"});(0,oe.setIcon)(s.createSpan({cls:"stashpad-btn-icon"}),"maximize-2"),s.createSpan({text:"Daily review"}),s.onclick=()=>new ri(this.app,this.plugin).open();let n=this.collectTasks();if(n.length===0){t.createDiv({cls:"stashpad-tasks-empty"}).setText("No tasks yet \u2014 press G on a note to mark it a task, or D to give it a due date.");return}let o=(this.plugin.settings.authorId??"").trim(),r=N=>!!o&&N.assignedTo.some(S=>S.id===o),l=N=>{let S=this.taskAssignFilter;if(S.startsWith("person:")){let P=S.slice(7);return N.assignedTo.some(O=>O.id===P)}switch(S){case"mine":return r(N);case"others":return N.assignedTo.length>0&&!r(N);case"byme":return!!o&&N.assignedBy?.id===o;case"unassigned":return N.assignedTo.length===0;default:return!0}},c=new Map;for(let N of n){for(let S of N.assignedTo)S.id!==o&&c.set(S.id,S.name);N.assignedBy&&N.assignedBy.id!==o&&c.set(N.assignedBy.id,N.assignedBy.name)}let A=[...c.entries()].map(([N,S])=>({id:N,name:S})).sort((N,S)=>N.name.localeCompare(S.name)),h=t.createDiv({cls:"stashpad-task-assign-bar"});h.createSpan({cls:"stashpad-task-assign-label",text:"Assignment"});let p=h.createEl("select",{cls:"stashpad-task-assign-select"}),u=N=>{let S={all:"Everyone",mine:"Assigned to me",others:"Assigned to others",byme:"Assigned by me",unassigned:"Unassigned"};return N.startsWith("person:")?c.get(N.slice(7))??"Person":S[N]??N},f=N=>{let S=p.createEl("option",{text:u(N),value:N});this.taskAssignFilter===N&&(S.selected=!0)};for(let N of["all","mine","others","byme","unassigned"])f(N);if(A.length>0){let N=p.createEl("optgroup");N.setAttr("label","By person");for(let S of A){let P=N.createEl("option",{text:S.name,value:`person:${S.id}`});this.taskAssignFilter===`person:${S.id}`&&(P.selected=!0)}}p.onchange=()=>{this.taskAssignFilter=p.value,this.render()};let g=[...new Set(n.map(N=>N.folder))].sort((N,S)=>N.localeCompare(S));this.taskFolderFilter!=="all"&&!g.includes(this.taskFolderFilter)&&(this.taskFolderFilter="all");let I=t.createDiv({cls:"stashpad-task-assign-bar"});I.createSpan({cls:"stashpad-task-assign-label",text:"Folder"});let m=I.createEl("select",{cls:"stashpad-task-assign-select"}),B=m.createEl("option",{text:"All folders",value:"all"});this.taskFolderFilter==="all"&&(B.selected=!0);for(let N of g){let S=m.createEl("option",{text:N.split("/").pop()||N,value:N});this.taskFolderFilter===N&&(S.selected=!0)}m.onchange=()=>{this.taskFolderFilter=m.value,this.render()};let C=N=>this.taskFolderFilter==="all"||N.folder===this.taskFolderFilter,Q=n.filter(N=>l(N)&&C(N));if(Q.length===0){t.createDiv({cls:"stashpad-tasks-empty"}).setText("No tasks match the current filters.");return}let y=new Date;y.setHours(0,0,0,0);let E=y.getTime(),w=E+24*60*60*1e3,v={overdue:[],today:[],upcoming:[],nodate:[],completed:[]};for(let N of Q){if(N.completed){v.completed.push(N);continue}if(N.due==null){v.nodate.push(N);continue}N.due<E?v.overdue.push(N):N.due<w?v.today.push(N):v.upcoming.push(N)}let F=(N,S)=>N.due==null&&S.due==null?N.title.localeCompare(S.title):N.due==null?1:S.due==null?-1:N.due-S.due,D=[{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"}],R=t.createDiv({cls:"stashpad-task-filters"}),G=Q.length,x=(N,S,P)=>{let O=R.createEl("button",{cls:"stashpad-task-filter"});this.taskFilter===N&&O.addClass("is-active"),O.createSpan({cls:"stashpad-task-filter-label",text:S}),O.createSpan({cls:"stashpad-task-filter-count",text:String(P)}),O.onclick=()=>{this.taskFilter=N,this.render()}};x("all","All",G),x("overdue","Overdue",v.overdue.length),x("today","Today",v.today.length),x("upcoming","Upcoming",v.upcoming.length),x("nodate","No date",v.nodate.length),x("completed","Done",v.completed.length);let H=this.taskFilter==="all"?D:D.filter(N=>N.key===this.taskFilter),U=!1;for(let N of H){let S=v[N.key];if(S.length!==0){if(U=!0,S.sort(N.key==="completed"?(P,O)=>F(O,P):F),this.taskFilter==="all"){let P=t.createDiv({cls:`stashpad-task-section-header is-${N.key}`});(0,oe.setIcon)(P.createSpan({cls:"stashpad-task-section-icon"}),N.icon),P.createSpan({cls:"stashpad-task-section-name",text:N.label}),P.createSpan({cls:"stashpad-task-section-count",text:String(S.length)})}for(let P of S)this.renderTaskRow(t,P,N.key==="today")}}if(!U&&this.taskFilter!=="all"){t.createDiv({cls:"stashpad-tasks-empty"}).setText(`Nothing in "${H[0]?.label??this.taskFilter}".`);return}U||t.createDiv({cls:"stashpad-tasks-empty"}).setText("No tasks to show.")}renderTaskRow(e,t,i){let s=e.createDiv({cls:"stashpad-pinned-row stashpad-task-row"});t.color&&s.addClass("has-color"),t.completed&&s.addClass("is-completed");let n=s.createSpan({cls:"stashpad-pinned-icon stashpad-task-checkbox"});(0,oe.setIcon)(n,t.completed?"check-square":"square"),t.color&&(n.style.color=t.color),n.title=t.completed?"Mark not done":"Mark done",n.onclick=l=>{l.stopPropagation(),this.toggleTaskCompleted(t)};let o=s.createSpan({cls:"stashpad-pinned-label",text:t.title});if(o.onclick=()=>this.openTaskFromPanel(t.folder,t.id),s.createSpan({cls:"stashpad-task-folder",text:t.folder.split("/").pop()||t.folder}),t.due!=null){let l=s.createSpan({cls:"stashpad-task-due",text:this.formatDueShort(t.due,i)});t.due<Date.now()&&!t.completed&&l.addClass("is-overdue")}else t.dueRaw&&s.createSpan({cls:"stashpad-task-due",text:t.dueRaw});if(t.assignedTo.length>0){let l=(this.plugin.settings.authorId??"").trim(),c=s.createSpan({cls:"stashpad-task-assignees"});for(let A of t.assignedTo){let h=c.createSpan({cls:"stashpad-task-assignee"});l&&A.id===l&&h.addClass("is-me"),h.setText(this.initials(A.name)),h.title=l&&A.id===l?`${A.name} (you)`:A.name}}let r=s.createEl("button",{cls:"stashpad-task-snooze"});(0,oe.setIcon)(r,"alarm-clock"),r.title="Snooze \u2014 reschedule due date",r.onclick=l=>{l.stopPropagation(),this.snoozeTask(t)},s.oncontextmenu=l=>{l.preventDefault();let c=new oe.Menu;c.addItem(A=>A.setTitle("Open").setIcon("arrow-right").onClick(()=>{this.openTaskFromPanel(t.folder,t.id)})),c.addItem(A=>A.setTitle("Snooze (reschedule)\u2026").setIcon("alarm-clock").onClick(()=>{this.snoozeTask(t)})),c.showAtMouseEvent(l)}}snoozeTask(e){let t=e.dueRaw??(e.due!=null?new Date(e.due).toISOString():null);new Ge(this.app,t,i=>{this.app.fileManager.processFrontMatter(e.file,s=>{i.iso===null?delete s.due:(s.due=i.iso,s.task=!0)}).then(()=>this.scheduleRender()).catch(s=>new oe.Notice(`Couldn't snooze: ${s.message}`))},{title:"Snooze \u2014 reschedule",hideAssignees:!0,quickAdjusts:this.plugin.settings.dueQuickAdjusts}).open()}formatDueShort(e,t){return t?_t(e,this.plugin.settings):Et(e,this.plugin.settings)}async openTaskFromPanel(e,t){await this.plugin.revealNoteByRef(e,t)}async toggleTaskCompleted(e){try{await this.app.fileManager.processFrontMatter(e.file,t=>{t.completed=t.completed!==!0})}catch(t){new oe.Notice(`Couldn't update task: ${t.message}`);return}this.scheduleRender()}initials(e){let t=e.trim().split(/\s+/).filter(Boolean);return t.length===0?"?":t.length===1?t[0].slice(0,2).toUpperCase():(t[0][0]+t[t.length-1][0]).toUpperCase()}collectTasks(){return bs(this.app,this.plugin)}};async function Ns(d){let a=d.workspace.getLeavesOfType(Bt);if(a.length>0){d.workspace.revealLeaf(a[0]);return}let e=d.workspace.getLeftLeaf(!1);if(!e){new oe.Notice("Stashpad: couldn't open the panels view.");return}await e.setViewState({type:Bt,active:!0}),d.workspace.revealLeaf(e)}var ga=require("obsidian");le();var T=require("obsidian");Xi();var Us=require("obsidian");le();var ci=class extends Us.AbstractInputSuggest{constructor(e,t){super(e,t);this.inputEl=t}getSuggestions(e){let t=e.toLowerCase().split(/\s+/).filter(Boolean),i=o=>t.every(r=>o.toLowerCase().includes(r)),s=[],n=o=>{if(!(o.path!=="/"&&ws.has(o.name))){o.path!=="/"&&i(o.path)&&s.push(o);for(let r of o.children)r instanceof Us.TFolder&&n(r)}};return n(this.app.vault.getRoot()),s.slice(0,100)}renderSuggestion(e,t){t.setText(e.path)}selectSuggestion(e){this.setValue(e.path),this.inputEl.dispatchEvent(new Event("input",{bubbles:!0})),this.close()}};var di=require("obsidian"),Gs=class d extends di.AbstractInputSuggest{constructor(e,t){super(e,t);this.inputEl=t}static norm(e){return e.replace(/^lucide-/,"")}getSuggestions(e){let t=e.toLowerCase().split(/\s+/).filter(Boolean),i=new Set,s=[];for(let r of(0,di.getIconIds)()){let l=d.norm(r);i.has(l)||(i.add(l),s.push(l))}let n=r=>t.every(l=>r.toLowerCase().includes(l)),o=t.length?s.filter(n):s;return o.sort(),o.slice(0,t.length?50:300)}renderSuggestion(e,t){t.addClass("stashpad-icon-suggest-item");let i=t.createSpan({cls:"stashpad-icon-suggest-icon"});(0,di.setIcon)(i,e),t.createSpan({cls:"stashpad-icon-suggest-label",text:e})}selectSuggestion(e){this.setValue(e),this.inputEl.dispatchEvent(new Event("input",{bubbles:!0})),this.close()}};le();me();var Ot=require("obsidian"),fo={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."}},Zl={info:4e3,success:4e3,warning:6e3,error:1e4},Vr=5e3,Ls=class{constructor(a){this.app=a;this.history=[];this.nextId=1;this.historyLimit=Vr;this.changeListeners=new Set;this.muted=new Set;this.defaultAuthorId=null}setDefaultAuthorId(a){this.defaultAuthorId=a||null}show(a){let e=a.kind??"info",t=a.category??"system",i={id:this.nextId++,ts:Date.now(),message:a.message,kind:e,category:t,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(t))return null;let s=this.buildContent(a,e),n=a.duration??Zl[e];return new Ot.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,e){e?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 e=this.applyLimit(a.slice());this.history=e;let t=0;for(let i of e)i.id>t&&(t=i.id);this.nextId=Math.max(this.nextId,t+1),this.emit()}setHistoryLimit(a){this.historyLimit=Number.isFinite(a)?a:Vr,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(e){console.warn("[Stashpad] notification listener failed",e)}}buildContent(a,e){let t=document.createDocumentFragment(),i=document.createElement("div");i.className=`stashpad-notice stashpad-notice-${e}`;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 l=document.createElement("button");l.className="stashpad-notice-action",l.textContent=r.label,l.addEventListener("click",c=>{if(c.stopPropagation(),Promise.resolve().then(()=>r.onClick()).catch(A=>console.warn("[Stashpad] notification action failed",A)),!r.keepOpen){let A=l.closest(".notice");A&&A.parentElement&&A.parentElement.removeChild(A)}}),o.appendChild(l)}i.appendChild(o)}return t.appendChild(i),t}};function Os(d,a,e){let t=d.vault.getAbstractFileByPath(a);if(!(t instanceof Ot.TFile))return[];let i=[{label:"Reveal",keepOpen:!0,onClick:()=>{let s=d.workspace.getLeavesOfType("file-explorer")[0];if(!s)return;d.workspace.revealLeaf(s),s.view?.revealInFolder?.(t)}}];if(!e){let s=Ot.Platform.isMacOS?"Finder":Ot.Platform.isWin?"File Explorer":"file manager";i.push({label:`Show in ${s}`,keepOpen:!0,onClick:()=>{try{let n=window.require?.("electron")?.shell,r=d.vault.adapter?.getFullPath?.(a);r&&n?.showItemInFolder&&n.showItemInFolder(r)}catch(n){console.warn("[Stashpad] showItemInFolder failed",n)}}})}return i}var Wr=require("obsidian"),Io=Wr.Platform.isMacOS;function Ai(d){if(!d)return"(none)";let a=d.replace(/\bMod\b/g,Io?"Cmd":"Ctrl");return Io&&(a=a.replace(/\bAlt\b/g,"Option")),a}function Xr(d,a,e={allowSingleKey:!0}){let t=d.placeholder,i=d.value;d.placeholder="Press a key\u2026 (Backspace to cancel)",d.value="",d.classList.add("is-recording");let s=!1,n=()=>{d.placeholder=t,d.classList.remove("is-recording"),s||(d.value=i),d.removeEventListener("keydown",o,!0),d.removeEventListener("blur",r)},o=l=>{if(l.key==="Control"||l.key==="Shift"||l.key==="Alt"||l.key==="Meta"||l.key==="OS")return;let c=!!l.code&&(/^Key[A-Z]$/.test(l.code)||/^Digit\d$/.test(l.code));if((l.key==="Dead"||l.key==="Process"||l.key==="Unidentified")&&!c)return;if(l.preventDefault(),l.stopPropagation(),l.key==="Backspace"&&!l.metaKey&&!l.ctrlKey&&!l.altKey&&!l.shiftKey){n();return}let A=[];Io?(l.metaKey&&A.push("Mod"),l.ctrlKey&&A.push("Ctrl")):l.ctrlKey&&A.push("Mod"),l.altKey&&A.push("Alt"),l.shiftKey&&A.push("Shift");let h=jl(l.key,l.code);if(!h||A.length===0&&!e.allowSingleKey)return;A.push(h);let p=A.join("+");s=!0,n(),a(p)},r=()=>n();return d.addEventListener("keydown",o,!0),d.addEventListener("blur",r),n}function jl(d,a){if(!d)return"";if(a){let e=/^Key([A-Z])$/.exec(a);if(e)return e[1];let t=/^Digit(\d)$/.exec(a);if(t)return t[1]}return d.length===1?d.toUpperCase():d}ai();rt();function Kt(d,a,e,t){function i(s){return s instanceof e?s:new e(function(n){n(s)})}return new(e||(e=Promise))(function(s,n){function o(c){try{l(t.next(c))}catch(A){n(A)}}function r(c){try{l(t.throw(c))}catch(A){n(A)}}function l(c){c.done?s(c.value):i(c.value).then(o,r)}l((t=t.apply(d,a||[])).next())})}var ae=class{constructor(){this.mutex=Promise.resolve()}lock(){let a=()=>{};return this.mutex=this.mutex.then(()=>new Promise(a)),new Promise(e=>{a=e})}dispatch(a){return Kt(this,void 0,void 0,function*(){let e=yield this.lock();try{return yield Promise.resolve(a())}finally{e()}})}},mo;function _l(){return typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:global}var wo=_l(),Co=(mo=wo.Buffer)!==null&&mo!==void 0?mo:null,ec=wo.TextEncoder?new wo.TextEncoder:null;function ia(d,a){return(d&15)+(d>>6|d>>3&8)<<4|(a&15)+(a>>6|a>>3&8)}function sa(d,a){let e=a.length>>1;for(let t=0;t<e;t++){let i=t<<1;d[t]=ia(a.charCodeAt(i),a.charCodeAt(i+1))}}function tc(d,a){if(d.length!==a.length*2)return!1;for(let e=0;e<a.length;e++){let t=e<<1;if(a[e]!==ia(d.charCodeAt(t),d.charCodeAt(t+1)))return!1}return!0}var Zr=87,jr=48;function Eo(d,a,e){let t=0;for(let i=0;i<e;i++){let s=a[i]>>>4;d[t++]=s>9?s+Zr:s+jr,s=a[i]&15,d[t++]=s>9?s+Zr:s+jr}return String.fromCharCode.apply(null,d)}var At=Co!==null?d=>{if(typeof d=="string"){let a=Co.from(d,"utf8");return new Uint8Array(a.buffer,a.byteOffset,a.length)}if(Co.isBuffer(d))return new Uint8Array(d.buffer,d.byteOffset,d.length);if(ArrayBuffer.isView(d))return new Uint8Array(d.buffer,d.byteOffset,d.byteLength);throw new Error("Invalid data type!")}:d=>{if(typeof d=="string")return ec.encode(d);if(ArrayBuffer.isView(d))return new Uint8Array(d.buffer,d.byteOffset,d.byteLength);throw new Error("Invalid data type!")},Le="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",ji=new Uint8Array(256);for(let d=0;d<Le.length;d++)ji[Le.charCodeAt(d)]=d;function _r(d,a=!0){let e=d.length,t=e%3,i=[],s=e-t;for(let n=0;n<s;n+=3){let o=(d[n]<<16&16711680)+(d[n+1]<<8&65280)+(d[n+2]&255),r=Le.charAt(o>>18&63)+Le.charAt(o>>12&63)+Le.charAt(o>>6&63)+Le.charAt(o&63);i.push(r)}if(t===1){let n=d[e-1],o=Le.charAt(n>>2),r=Le.charAt(n<<4&63);i.push(`${o}${r}`),a&&i.push("==")}else if(t===2){let n=(d[e-2]<<8)+d[e-1],o=Le.charAt(n>>10),r=Le.charAt(n>>4&63),l=Le.charAt(n<<2&63);i.push(`${o}${r}${l}`),a&&i.push("=")}return i.join("")}function ic(d){let a=Math.floor(d.length*.75),e=d.length;return d[e-1]==="="&&(a-=1,d[e-2]==="="&&(a-=1)),a}function sc(d){let a=ic(d),e=d.length,t=new Uint8Array(a),i=0;for(let s=0;s<e;s+=4){let n=ji[d.charCodeAt(s)],o=ji[d.charCodeAt(s+1)],r=ji[d.charCodeAt(s+2)],l=ji[d.charCodeAt(s+3)];t[i]=n<<2|o>>4,i+=1,t[i]=(o&15)<<4|r>>2,i+=1,t[i]=(r&3)<<6|l&63,i+=1}return t}var Ks=16*1024,Zi=4,nc=new ae,Bo=new Map;function na(d,a){return Kt(this,void 0,void 0,function*(){let e=null,t=null,i=!1;if(typeof WebAssembly>"u")throw new Error("WebAssembly is not supported in this environment!");let s=(y,E=0)=>{t.set(y,E)},n=()=>t,o=()=>e.exports,r=y=>{e.exports.Hash_SetMemorySize(y);let E=e.exports.Hash_GetBuffer(),w=e.exports.memory.buffer;t=new Uint8Array(w,E,y)},l=()=>new DataView(e.exports.memory.buffer).getUint32(e.exports.STATE_SIZE,!0),c=nc.dispatch(()=>Kt(this,void 0,void 0,function*(){if(!Bo.has(d.name)){let E=sc(d.data),w=WebAssembly.compile(E);Bo.set(d.name,w)}let y=yield Bo.get(d.name);e=yield WebAssembly.instantiate(y,{})})),A=()=>Kt(this,void 0,void 0,function*(){e||(yield c);let y=e.exports.Hash_GetBuffer(),E=e.exports.memory.buffer;t=new Uint8Array(E,y,Ks)}),h=(y=null)=>{i=!0,e.exports.Hash_Init(y)},p=y=>{let E=0;for(;E<y.length;){let w=y.subarray(E,E+Ks);E+=w.length,t.set(w),e.exports.Hash_Update(w.length)}},u=y=>{if(!i)throw new Error("update() called before init()");let E=At(y);p(E)},f=new Uint8Array(a*2),g=(y,E=null)=>{if(!i)throw new Error("digest() called before init()");return i=!1,e.exports.Hash_Final(E),y==="binary"?t.slice(0,a):Eo(f,t,a)},I=()=>{if(!i)throw new Error("save() can only be called after init() and before digest()");let y=e.exports.Hash_GetState(),E=l(),w=e.exports.memory.buffer,v=new Uint8Array(w,y,E),F=new Uint8Array(Zi+E);return sa(F,d.hash),F.set(v,Zi),F},m=y=>{if(!(y instanceof Uint8Array))throw new Error("load() expects an Uint8Array generated by save()");let E=e.exports.Hash_GetState(),w=l(),v=Zi+w,F=e.exports.memory.buffer;if(y.length!==v)throw new Error(`Bad state length (expected ${v} bytes, got ${y.length})`);if(!tc(d.hash,y.subarray(0,Zi)))throw new Error("This state was written by an incompatible hash implementation");let D=y.subarray(Zi);new Uint8Array(F,E,w).set(D),i=!0},B=y=>typeof y=="string"?y.length<Ks/4:y.byteLength<Ks,C=B;switch(d.name){case"argon2":case"scrypt":C=()=>!0;break;case"blake2b":case"blake2s":C=(y,E)=>E<=512&&B(y);break;case"blake3":C=(y,E)=>E===0&&B(y);break;case"xxhash64":case"xxhash3":case"xxhash128":case"crc64":C=()=>!1;break}let Q=(y,E=null,w=null)=>{if(!C(y,E))return h(E),u(y),g("hex",w);let v=At(y);return t.set(v),e.exports.Hash_Calculate(v.length,E,w),Eo(f,t,a)};return yield A(),{getMemory:n,writeMemory:s,getExports:o,setMemorySize:r,init:h,update:u,digest:g,save:I,load:m,calculate:Q,hashLength:a}})}var FA=new ae;var oc="argon2",rc="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",ac="e4cdc523",lc={name:oc,data:rc,hash:ac},cc="blake2b",dc="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=",Ac="c6f286e6",hc={name:cc,data:dc,hash:Ac},kA=new ae;function ea(d){return!Number.isInteger(d)||d<8||d>512||d%8!==0?new Error("Invalid variant! Valid values: 8, 16, ..., 512"):null}function pc(d,a){return d|a<<16}function Qo(d=512,a=null){if(ea(d))return Promise.reject(ea(d));let e=null,t=d;if(a!==null){if(e=At(a),e.length>64)return Promise.reject(new Error("Max key length is 64 bytes"));t=pc(d,e.length)}let i=d/8;return na(hc,i).then(s=>{t>512&&s.writeMemory(e),s.init(t);let n={init:t>512?()=>(s.writeMemory(e),s.init(t),n):()=>(s.init(t),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 gc(d,a,e){let t=[`m=${a.memorySize}`,`t=${a.iterations}`,`p=${a.parallelism}`].join(",");return`$argon2${a.hashType}$v=19$${t}$${_r(d,!1)}$${_r(e,!1)}`}var ta=new DataView(new ArrayBuffer(4));function dt(d){return ta.setInt32(0,d,!0),new Uint8Array(ta.buffer)}function yo(d,a,e){return Kt(this,void 0,void 0,function*(){if(e<=64){let r=yield Qo(e*8);return r.update(dt(e)),r.update(a),r.digest("binary")}let t=Math.ceil(e/32)-2,i=new Uint8Array(e);d.init(),d.update(dt(e)),d.update(a);let s=d.digest("binary");i.set(s.subarray(0,32),0);for(let r=1;r<t;r++)d.init(),d.update(s),s=d.digest("binary"),i.set(s.subarray(0,32),r*32);let n=e-32*t,o;return n===64?(o=d,o.init()):o=yield Qo(n*8),o.update(s),s=o.digest("binary"),i.set(s.subarray(0,n),t*32),i})}function uc(d){switch(d){case"d":return 0;case"i":return 1;default:return 2}}function fc(d){return Kt(this,void 0,void 0,function*(){var a;let{parallelism:e,iterations:t,hashLength:i}=d,s=At(d.password),n=At(d.salt),o=19,r=uc(d.hashType),{memorySize:l}=d,c=At((a=d.secret)!==null&&a!==void 0?a:""),[A,h]=yield Promise.all([na(lc,1024),Qo(512)]);A.setMemorySize(l*1024+1024);let p=new Uint8Array(24),u=new DataView(p.buffer);u.setInt32(0,e,!0),u.setInt32(4,i,!0),u.setInt32(8,l,!0),u.setInt32(12,t,!0),u.setInt32(16,o,!0),u.setInt32(20,r,!0),A.writeMemory(p,l*1024),h.init(),h.update(p),h.update(dt(s.length)),h.update(s),h.update(dt(n.length)),h.update(n),h.update(dt(c.length)),h.update(c),h.update(dt(0));let g=Math.floor(l/(e*4))*4,I=new Uint8Array(72),m=h.digest("binary");I.set(m);for(let Q=0;Q<e;Q++){I.set(dt(0),64),I.set(dt(Q),68);let y=Q*g,E=yield yo(h,I,1024);A.writeMemory(E,y*1024),y+=1,I.set(dt(1),64),E=yield yo(h,I,1024),A.writeMemory(E,y*1024)}let B=new Uint8Array(1024);sa(B,A.calculate(new Uint8Array([]),l));let C=yield yo(h,B,i);if(d.outputType==="hex"){let Q=new Uint8Array(i*2);return Eo(Q,C,i)}return d.outputType==="encoded"?gc(n,d,C):C})}var Ic=d=>{var a;if(!d||typeof d!="object")throw new Error("Invalid options parameter. It requires an object.");if(!d.password)throw new Error("Password must be specified");if(d.password=At(d.password),d.password.length<1)throw new Error("Password must be specified");if(!d.salt)throw new Error("Salt must be specified");if(d.salt=At(d.salt),d.salt.length<8)throw new Error("Salt should be at least 8 bytes long");if(d.secret=At((a=d.secret)!==null&&a!==void 0?a:""),!Number.isInteger(d.iterations)||d.iterations<1)throw new Error("Iterations should be a positive number");if(!Number.isInteger(d.parallelism)||d.parallelism<1)throw new Error("Parallelism should be a positive number");if(!Number.isInteger(d.hashLength)||d.hashLength<4)throw new Error("Hash length should be at least 4 bytes.");if(!Number.isInteger(d.memorySize))throw new Error("Memory size should be specified.");if(d.memorySize<8*d.parallelism)throw new Error("Memory size should be at least 8 * parallelism.");if(d.outputType===void 0&&(d.outputType="hex"),!["hex","binary","encoded"].includes(d.outputType))throw new Error(`Insupported output type ${d.outputType}. Valid values: ['hex', 'binary', 'encoded']`)};function vo(d){return Kt(this,void 0,void 0,function*(){return Ic(d),fc(Object.assign(Object.assign({},d),{hashType:"id"}))})}var SA=new ae;var bA=new ae;var DA=new ae;var xA=new ae;var NA=new Uint8Array(8);var MA=new ae;var TA=new ae;var PA=new ae;var HA=new ae;var RA=new ae;var UA=new ae;var GA=new ae;var LA=new ae;var OA=new ae;var KA=new ae;var JA=new ae;var qA=new Uint8Array(8);var $A=new ae;var YA=new Uint8Array(8);var zA=new ae;var VA=new Uint8Array(8);var WA=new ae;var XA=new ae;var ZA=new ae;me();var Oe=new Uint8Array([83,84,65,83,72,69,78,67]),So=2,bo=1,Do=2,aa=3,mc=32,hi=12,Fo=32,Cc=6e5,Bc=47104,yc=3,wc=1,ue=d=>d;function Me(d){if(d.length<Oe.length+1)return!1;for(let a=0;a<Oe.length;a++)if(d[a]!==Oe[a])return!1;return!0}function oa(d,a,e){d[a]=e>>>24&255,d[a+1]=e>>>16&255,d[a+2]=e>>>8&255,d[a+3]=e&255}function ra(d,a){return d[a]*16777216+(d[a+1]<<16)+(d[a+2]<<8)+d[a+3]}async function ko(d,a,e){if(e.id===Do)return await vo({password:d,salt:a,parallelism:e.c,iterations:e.b,memorySize:e.a,hashLength:Fo,outputType:"binary"});if(e.id===bo){let t=await crypto.subtle.importKey("raw",ue(new TextEncoder().encode(d)),"PBKDF2",!1,["deriveBits"]),i=await crypto.subtle.deriveBits({name:"PBKDF2",salt:ue(a),iterations:e.a,hash:"SHA-256"},t,Fo*8);return new Uint8Array(i)}throw new Error(`Unsupported KDF id (${e.id}).`)}async function Js(d){return crypto.subtle.importKey("raw",ue(d),{name:"AES-GCM"},!1,["encrypt","decrypt"])}var xo={argon2id:{label:"Argon2id",strong:!0},pbkdf2:{label:"PBKDF2 (fallback)",strong:!1}};async function ht(d,a){let e=crypto.getRandomValues(new Uint8Array(mc)),t=crypto.getRandomValues(new Uint8Array(hi)),i,s,n;try{i={id:Do,a:Bc,b:yc,c:wc},n=await ko(a,e,i),s="argon2id"}catch(A){console.warn("[Stashpad] Argon2id unavailable \u2014 encrypting with PBKDF2 fallback.",A),i={id:bo,a:Cc,b:0,c:0},n=await ko(a,e,i),s="pbkdf2"}let o=la(i,e,t),r=await Js(n),l=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:ue(t),additionalData:ue(o)},r,ue(d))),c=new Uint8Array(o.length+l.length);return c.set(o,0),c.set(l,o.length),{data:c,kdf:s}}var _i=null;async function es(){if(_i!==null)return _i;try{await vo({password:"x",salt:new Uint8Array(16),parallelism:1,iterations:1,memorySize:8,hashLength:16,outputType:"binary"}),_i=!0}catch{_i=!1}return _i}function la(d,a,e){let t=new Uint8Array(Oe.length+1+1+4+4+1+1+a.length+e.length),i=0;return t.set(Oe,i),i+=Oe.length,t[i++]=So,t[i++]=d.id,oa(t,i,d.a),i+=4,oa(t,i,d.b),i+=4,t[i++]=d.c,t[i++]=a.length,t.set(a,i),i+=a.length,t.set(e,i),i+=e.length,t}async function pi(d,a){if(!Me(d))throw new Error("Not an encrypted Stashpad file.");let e=d[Oe.length];if(e===1)return Ec(d,a);if(e!==So)throw new Error(`Unsupported encrypted .stash version (${e}).`);let t=Oe.length+1,i={id:d[t++],a:0,b:0,c:0};if(i.a=ra(d,t),t+=4,i.b=ra(d,t),t+=4,i.c=d[t++],i.id===Do){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===bo&&i.a>1e7)throw new Error("Unsupported KDF parameters (file may be corrupted or malicious).");let s=d[t++];if(s<8||s>64)throw new Error("Unsupported KDF parameters (file may be corrupted or malicious).");let n=d.slice(t,t+s);t+=s;let o=d.slice(t,t+hi);t+=hi;let r=d.slice(0,t),l=d.slice(t),c=await ko(a,n,i),A=await Js(c),h=await crypto.subtle.decrypt({name:"AES-GCM",iv:ue(o),additionalData:ue(r)},A,ue(l));return new Uint8Array(h)}async function Ec(d,a){let e=Oe.length+1,t=d.slice(e,e+16);e+=16;let i=d.slice(e,e+12);e+=12;let s=d.slice(e),n=await crypto.subtle.importKey("raw",ue(new TextEncoder().encode(a)),"PBKDF2",!1,["deriveKey"]),o=await crypto.subtle.deriveKey({name:"PBKDF2",salt:ue(t),iterations:21e4,hash:"SHA-256"},n,{name:"AES-GCM",length:256},!1,["decrypt"]),r=await crypto.subtle.decrypt({name:"AES-GCM",iv:ue(i)},o,ue(s));return new Uint8Array(r)}async function ts(d,a){if(a.length!==Fo)throw new Error("Encryption key must be 32 bytes.");let e=crypto.getRandomValues(new Uint8Array(hi)),i=la({id:aa,a:0,b:0,c:0},new Uint8Array(0),e),s=await Js(a),n=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:ue(e),additionalData:ue(i)},s,ue(d))),o=new Uint8Array(i.length+n.length);return o.set(i,0),o.set(n,i.length),o}async function Ke(d,a){if(!Me(d))throw new Error("Not an encrypted Stashpad file.");let e=d[Oe.length];if(e!==So)throw new Error(`Unsupported encrypted version (${e}).`);let t=Oe.length+1;if(d[t++]!==aa)throw new Error("Not a raw-key (.stashenc) envelope.");t+=9;let s=d[t++];t+=s;let n=d.slice(t,t+hi);t+=hi;let o=d.slice(0,t),r=d.slice(t),l=await Js(a),c=await crypto.subtle.decrypt({name:"AES-GCM",iv:ue(n),additionalData:ue(o)},l,ue(r));return new Uint8Array(c)}async function gi(d,a,e={}){if(!Me(a))return a;if(e.secretId){let i=d.secretStorage,s=null;try{s=i?.getSecret(e.secretId)??null}catch{s=null}if(s)try{return await pi(a,s)}catch{}}let t;for(;;){let i=await new Promise(s=>{new Gi(d,t,!!e.allowLater,s).open()});if(i.kind==="cancel")return null;if(i.kind==="later")return e.onLater?.(),null;try{return await pi(a,i.value)}catch{t="Wrong password or corrupted file. Try again."}}}rt();var Jt=".stashpad/keys.json",Qc=".stashpad",ui="_keys";var qs=class{constructor(a){this.app=a}get a(){return this.app.vault.adapter}validate(a){let e=a;return!!e&&e.v===2&&typeof e.keyId=="string"&&Array.isArray(e.identities)&&Array.isArray(e.slots)&&Array.isArray(e.joinRequests)}async readValid(a){try{if(!await this.a.exists(a))return null;let e=JSON.parse(await this.a.read(a));return this.validate(e)?e:null}catch{return null}}async load(){let a=await this.readValid(Jt);if(a)return a;try{let t=((await this.a.list(ui)).files||[]).filter(i=>/\/keys-\d+\.json$/.test(i)).sort();for(let i of t.reverse()){let s=await this.readValid(i);if(s)return s}}catch{}return null}async exists(){return await this.load()!==null}async hasAnyFile(){try{if(await this.a.exists(Jt))return!0}catch{}try{return((await this.a.list(ui)).files||[]).some(e=>/\/keys-\d+\.json$/.test(e))}catch{return!1}}async ensureDir(a){try{await this.a.exists(a)||await this.a.mkdir(a)}catch{}}async save(a){let e=JSON.stringify(a,null,2);await this.ensureDir(Qc);let t=`${Jt}.tmp`,i=!1;try{await this.a.write(t,e);try{await this.a.rename(t,Jt)}catch{try{await this.a.remove(Jt)}catch{}await this.a.rename(t,Jt)}i=!0}catch{try{await this.a.exists(t)&&await this.a.remove(t)}catch{}}i||await this.a.write(Jt,e),await this.ensureDir(ui);for(let s=4;s>=1;s--){let n=`${ui}/keys-${s}.json`,o=`${ui}/keys-${s+1}.json`;try{await this.a.exists(n)&&await this.a.write(o,await this.a.read(n))}catch{}}try{await this.a.write(`${ui}/keys-1.json`,e)}catch{}}};rt();var vc=".stashkey",ca=32;function No(d){let a="";for(let e=0;e<d.length;e++)a+=String.fromCharCode(d[e]);return btoa(a)}function Fc(d){let a=atob(d),e=new Uint8Array(a.length);for(let t=0;t<a.length;t++)e[t]=a.charCodeAt(t);return e}var $s=()=>new Date().toISOString(),Ys=class{constructor(a){this.app=a}get a(){return this.app.vault.adapter}keyPath(a){return`${a.replace(/\/+$/,"")}/${vc}`}validate(a){let e=a;return!!e&&e.v===1&&typeof e.keyId=="string"&&typeof e.folderPath=="string"&&Array.isArray(e.slots)&&e.slots.every(t=>t&&typeof t.wrapped=="string"&&typeof t.id=="string")}async read(a){let e=this.keyPath(a);try{if(!await this.a.exists(e))return null;let t=JSON.parse(await this.a.read(e));return this.validate(t)?t:null}catch{return null}}async hasFile(a){try{return await this.a.exists(this.keyPath(a))}catch{return!1}}async write(a,e){let t=this.keyPath(a),i=JSON.stringify(e,null,2),s=`${t}.tmp`,n=!1;try{await this.a.write(s,i);try{await this.a.rename(s,t)}catch{try{await this.a.remove(t)}catch{}await this.a.rename(s,t)}n=!0}catch{try{await this.a.exists(s)&&await this.a.remove(s)}catch{}}n||await this.a.write(t,i)}async remove(a){try{await this.a.remove(this.keyPath(a))}catch{}}async create(a,e,t){if(!e)throw new Error("Password required.");let i=crypto.getRandomValues(new Uint8Array(ca)),s=await ht(i,e);return{sk:{v:1,keyId:t??he(8),folderPath:a.replace(/\/+$/,""),slots:[{id:he(8),label:"Folder password",wrapped:No(s.data),kdf:s.kdf,createdAt:$s()}],createdAt:$s()},dek:i}}async unlock(a,e){for(let t of a.slots)try{let i=await pi(Fc(t.wrapped),e);if(i.length!==ca){i.fill(0);continue}return i}catch{}return null}async changePassword(a,e,t){if(!t)throw new Error("Password required.");let i=await ht(e,t),s=a.slots.filter(o=>o.recovery),n={id:he(8),label:"Folder password",wrapped:No(i.data),kdf:i.kdf,createdAt:$s()};return{...a,slots:[n,...s]}}async setRecovery(a,e,t){if(!t)throw new Error("Recovery password required.");let i=await ht(e,t),s=a.slots.filter(o=>!o.recovery),n={id:he(8),label:"Recovery password",wrapped:No(i.data),kdf:i.kdf,createdAt:$s(),recovery:!0};return{...a,slots:[...s,n]}}removeRecovery(a){return{...a,slots:a.slots.filter(e=>!e.recovery)}}hasRecovery(a){return a.slots.some(e=>e.recovery)}};var kc="stashpad-vault-encryption";function Vs(){return{}}function Sc(d){let a="";for(let e=0;e<d.length;e++)a+=String.fromCharCode(d[e]);return btoa(a)}function bc(d){let a=atob(d),e=new Uint8Array(a.length);for(let t=0;t<a.length;t++)e[t]=a.charCodeAt(t);return e}var zs=class{constructor(a,e,t){this.app=a;this.load=e;this.save=t;this.folderSessionKeys=new Map;this.kf=null;this.folderKeyFiles=new Map;this.stashKeysIndexed=!1;this.parkedKeyMaterial=!1;this.keyfiles=new qs(a),this.folderKeystore=new Ys(a)}argonProbe(){return es()}async init(){await this.refresh(),this.parkedKeyMaterial=await this.detectParkedKeyMaterial()}async refresh(){this.kf=await this.keyfiles.load(),this.stashKeysIndexed||await this.indexStashKeys()}async detectParkedKeyMaterial(){let a=this.app.vault.adapter;try{let e=await a.list("_keys");if((e.files||[]).some(t=>/\.json$/.test(t))||(e.folders||[]).length)return!0}catch{}try{if(((await a.list(".stashpad")).folders||[]).some(t=>/\/retired-keyfile-/.test(t)))return!0}catch{}return!1}invalidateStashKeyIndex(){this.stashKeysIndexed=!1}async migrateKeyfileToStashKeys(){await this.refresh();let a=this.kf?.folderKeys;if(!a)return 0;let e=0;for(let[t,i]of Object.entries(a)){let s=this.cleanFolder(t);if(this.folderKeyFiles.has(s)||await this.folderKeystore.hasFile(s))continue;let n=(i.passwordSlots??[]).filter(r=>!r.label.startsWith("[deprecated]"));if(!n.length)continue;let o={v:1,keyId:i.keyId,folderPath:s,slots:n.map((r,l)=>({id:r.id,label:l===0?"Folder password":r.label,wrapped:r.wrapped,kdf:r.kdf,createdAt:r.createdAt})),createdAt:i.createdAt};try{await this.folderKeystore.write(s,o);let r=await this.folderKeystore.read(s);if(!r||r.slots[0]?.wrapped!==o.slots[0].wrapped){await this.folderKeystore.remove(s);continue}this.folderKeyFiles.set(s,o),e++}catch{}}return e}async indexStashKeys(){let a=new Map,e=new Set([".git",".obsidian","node_modules"]),t=async i=>{let s;try{s=await this.app.vault.adapter.list(i)}catch{return}for(let n of s.files??[])if(n===".stashkey"||n.endsWith("/.stashkey")){let o=n.includes("/")?n.slice(0,n.lastIndexOf("/")):"",r=await this.folderKeystore.read(o);r&&a.set(this.cleanFolder(o),r)}for(let n of s.folders??[])e.has(n.split("/").pop()??"")||await t(n)};await t(""),this.folderKeyFiles=a,this.stashKeysIndexed=!0}stashKeyToEntry(a,e){return{keyId:a.keyId,folderPath:this.cleanFolder(e),label:a.slots[0]?.label??"Folder password",kcId:this.folderKcId(e,a.keyId),passwordSlots:a.slots.map(t=>({id:t.id,label:t.label,wrapped:t.wrapped,kdf:t.kdf,createdAt:t.createdAt})),createdAt:a.createdAt}}secretStore(){return this.app.secretStorage??null}keychainAvailable(){return!!this.secretStore()}async parkThenSet(a,e){let t=this.secretStore();if(!t)return;let i=[a];try{let s=t.getSecret(a);if(s&&s!==e){let n=Date.now().toString(36),o=`${a.slice(0,64-(n.length+2))}-r${n}`;await t.setSecret(o,s),i.push(o)}}catch{}await t.setSecret(a,e),await this.recordKeychainIds(i)}async recordKeychainIds(a){try{let e=this.load(),t=new Set(e.knownKeychainIds??[]),i=!1;for(let s of a)s&&!t.has(s)&&(t.add(s),i=!0);i&&await this.save({...e,knownKeychainIds:[...t]})}catch{}}keychainCandidateIds(){return[...new Set(this.load().knownKeychainIds??[])]}hasAnyFolderKey(){return this.folderKeyFiles.size>0||Object.keys(this.kf?.folderKeys??{}).length>0}isConfigured(){return this.hasAnyFolderKey()}owningFolder(a){let e=this.kf?.folderKeys,t=this.cleanFolder(a);for(;t;){if(this.folderKeyFiles.has(t)||e&&Object.prototype.hasOwnProperty.call(e,t))return t;let i=t.lastIndexOf("/");if(i<0)break;t=t.slice(0,i)}return null}hasOwnFolderKey(a){let e=this.cleanFolder(a);if(this.folderKeyFiles.has(e))return!0;let t=this.kf?.folderKeys;return!!t&&Object.prototype.hasOwnProperty.call(t,e)}folderKeyEntry(a){let e=this.owningFolder(a);if(!e)return null;let t=this.folderKeyFiles.get(e);return t?this.stashKeyToEntry(t,e):this.kf?.folderKeys?.[e]??null}hasFolderKey(a){return this.owningFolder(a)!==null}folderPathByKeyId(a){for(let[e,t]of this.folderKeyFiles)if(t.keyId===a)return e;for(let[e,t]of Object.entries(this.kf?.folderKeys??{}))if(t.keyId===a)return e;return null}folderActiveSlots(a){return(a.passwordSlots??[]).filter(e=>!e.label.startsWith("[deprecated]"))}isFolderUnlocked(a){let e=this.owningFolder(a);return e?this.folderSessionKeys.has(e):!1}getFolderKey(a){let e=this.owningFolder(a);if(!e)return null;let t=this.folderSessionKeys.get(e);return t?t.slice():null}async setupFolderKey(a,e,t,i=!1){if(!e)throw new Error("Password required.");await this.refresh();let s=this.cleanFolder(a);if(this.hasOwnFolderKey(s))throw new Error("This folder already has its own key.");let n=this.owningFolder(s);if(n&&n!==s)throw new Error(`A parent folder (\u201C${n.split("/").pop()}\u201D) already has its own password; this folder inherits it.`);let{sk:o,dek:r}=await this.folderKeystore.create(s,e);await this.folderKeystore.write(s,o),this.folderKeyFiles.set(s,o),this.folderSessionKeys.set(s,r),i&&await this.rememberFolder(this.folderKcId(s,o.keyId),e)}async unlockFolder(a,e,t=!1){await this.refresh();let i=this.cleanFolder(a),s=this.folderKeyEntry(i);if(!s)return!1;for(let n of this.folderActiveSlots(s))try{let o=await pi(bc(n.wrapped),e);this.folderSessionKeys.set(s.folderPath,o);let r=this.folderKcIdFor(s);return(t||this.isFolderRemembered(r))&&await this.rememberFolder(r,e),!0}catch{}return!1}async tryAutoUnlockFolder(a){let e=this.folderKeyEntry(a);if(!e||this.isFolderUnlocked(a))return this.isFolderUnlocked(a);let t=this.folderKcIdFor(e),i=this.rememberedFolderPassword(t);if(i&&await this.unlockFolder(a,i))return!0;let s=this.secretStore();if(!s)return!1;let n=new Set(i?[i]:[]);for(let o of this.keychainCandidateIds()){if(o===t)continue;let r=null;try{r=s.getSecret(o)??null}catch{r=null}if(!(!r||n.has(r))&&(n.add(r),await this.unlockFolder(a,r)))return await this.rememberFolder(t,r),!0}return!1}async changeFolderPassword(a,e,t=!1){if(!e)throw new Error("Password required.");let i=this.cleanFolder(a);await this.refresh();let s=this.folderKeyEntry(i);if(!s)throw new Error("This folder has no key.");let n=s.folderPath,o=this.folderSessionKeys.get(n);if(!o)throw new Error("Unlock this folder first.");let r=this.folderKeyFiles.get(n);if(r){let f=await this.folderKeystore.changePassword(r,o,e);await this.folderKeystore.write(n,f),this.folderKeyFiles.set(n,f);let g=this.folderKcId(n,f.keyId);(t||this.isFolderRemembered(g))&&await this.rememberFolder(g,e);return}if(!this.kf)throw new Error("This folder has no key.");let l=s.passwordSlots.filter(f=>!f.label.startsWith("[deprecated]")),c=this.folderKcIdFor(s),A=this.rememberedFolderPassword(c);if(A&&l[0])try{await this.parkThenSet(`${c}-d-${l[0].id}`,A)}catch{}let h=await ht(o,e),p=s.passwordSlots.map(f=>f.label.startsWith("[deprecated]")?f:{...f,label:`[deprecated] ${f.label}`}),u={...s,kcId:s.kcId??this.folderKcId(s.label,s.keyId),passwordSlots:[{id:he(8),label:"Folder password",wrapped:Sc(h.data),kdf:h.kdf,createdAt:new Date().toISOString()},...p]};this.kf.folderKeys={...this.kf.folderKeys??{},[n]:u},await this.keyfiles.save(this.kf),(t||this.isFolderRemembered(c))&&await this.rememberFolder(this.folderKcIdFor(u),e)}folderHasRecovery(a){let e=this.owningFolder(a),t=e?this.folderKeyFiles.get(e):null;return!!t&&this.folderKeystore.hasRecovery(t)}async setFolderRecoveryPassword(a,e){if(!e)throw new Error("Recovery password required.");await this.refresh();let t=this.cleanFolder(a),i=this.folderKeyEntry(t);if(!i)throw new Error("This folder has no key.");let s=i.folderPath,n=this.folderKeyFiles.get(s);if(!n)throw new Error("This folder's key predates recovery passwords \u2014 change its folder password once to upgrade it, then try again.");let o=this.folderSessionKeys.get(s);if(!o)throw new Error("Unlock this folder first.");let r=await this.folderKeystore.setRecovery(n,o,e);await this.folderKeystore.write(s,r),this.folderKeyFiles.set(s,r)}async removeFolderRecoveryPassword(a){await this.refresh();let e=this.cleanFolder(a),t=this.folderKeyEntry(e);if(!t)return;let i=t.folderPath,s=this.folderKeyFiles.get(i);if(!s||!this.folderKeystore.hasRecovery(s))return;let n=this.folderKeystore.removeRecovery(s);await this.folderKeystore.write(i,n),this.folderKeyFiles.set(i,n)}folderKcId(a,e){return(`sp-${(a||"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}`.slice(0,44)+`-${e.slice(0,6)}`).replace(/-+/g,"-")}folderKcIdFor(a){return a.kcId||`${kc}-f-${a.keyId}`}isFolderRemembered(a){try{return!!this.secretStore()?.getSecret(a)}catch{return!1}}rememberedFolderPassword(a){try{return this.secretStore()?.getSecret(a)||null}catch{return null}}async rememberFolder(a,e){try{await this.parkThenSet(a,e)}catch(t){console.warn("[Stashpad] couldn't save folder password to keychain",t)}}async forgetFolderKeychain(a){let e=this.folderKeyEntry(a);if(!e)return;let t=this.secretStore();if(!t)return;let i=this.folderKcIdFor(e);try{if(t.getSecret(i)){await this.parkThenSet(i,"");return}}catch{}try{t.removeSecret?await t.removeSecret(i):await t.setSecret(i,"")}catch(s){console.warn("[Stashpad] couldn't clear folder keychain",s)}}lock(){for(let a of this.folderSessionKeys.values())a.fill(0);this.folderSessionKeys.clear()}lockFolder(a){let e=this.owningFolder(a)??this.cleanFolder(a),t=this.folderSessionKeys.get(e);t&&(t.fill(0),this.folderSessionKeys.delete(e))}cleanFolder(a){return(a||"").replace(/\/+$/,"")}async clear(){this.lock();try{let a=this.app.vault.adapter;for(let e of[".stashpad/keys.json"])try{await a.exists(e)&&await a.remove(e)}catch{}try{let t=((await a.list("_keys")).files||[]).filter(i=>/\/keys-\d+\.json$/.test(i));if(t.length){let s=`_keys/removed-${new Date().toISOString().slice(0,19).replace(/[:T]/g,"-")}`;try{await a.exists(s)||await a.mkdir(s)}catch{}for(let n of t){let o=n.split("/").pop();try{await a.write(`${s}/${o}`,await a.read(n)),await a.remove(n)}catch{}}}}catch{}this.stashKeysIndexed||await this.indexStashKeys();for(let e of this.folderKeyFiles.keys())try{await this.folderKeystore.remove(e)}catch{}this.folderKeyFiles.clear()}catch{}this.kf=null}async removeFolderKeyFile(a){let e=this.cleanFolder(a);await this.folderKeystore.remove(e),this.folderKeyFiles.delete(e),this.folderSessionKeys.get(e)?.fill(0),this.folderSessionKeys.delete(e)}hasLegacyKeyfile(){return!!this.kf}unmigratedKeyfileFolders(){return Object.keys(this.kf?.folderKeys??{}).filter(a=>!this.folderKeyFiles.has(this.cleanFolder(a)))}async retireLegacyKeyfile(){await this.refresh();let a=this.unmigratedKeyfileFolders();if(a.length)throw new Error(`Can't retire the old keyfile yet \u2014 these folders' keys still live only in it: ${a.map(o=>o||"(vault root)").join(", ")}. Open each folder once (or change its password) to migrate it, then try again.`);let e=this.app.vault.adapter,i=`.stashpad/retired-keyfile-${new Date().toISOString().slice(0,19).replace(/[:T]/g,"-")}`,s=0;try{await e.exists(i)||await e.mkdir(i)}catch{}let n=async(o,r)=>{try{let l=await e.read(o);return await e.write(r,l),await e.read(r)!==l?!1:(await e.remove(o),!0)}catch{return!1}};try{await e.exists(".stashpad/keys.json")&&await n(".stashpad/keys.json",`${i}/keys.json`)&&s++}catch{}try{let o=await e.list("_keys");for(let r of(o.files||[]).filter(l=>/\/keys-\d+\.json$/.test(l)))await n(r,`${i}/${r.split("/").pop()}`)&&s++}catch{}return this.kf=null,this.parkedKeyMaterial=!0,s}hasRecoverableKeyMaterial(){return!!this.kf||this.parkedKeyMaterial}async wipeLegacyKeyMaterial(){let a=this.app.vault.adapter,e=0,t=async(i,s)=>{try{await a.exists(i)&&(s?await a.rmdir(i,!0):await a.remove(i),e++)}catch{}};await t(".stashpad/keys.json",!1),await t("_keys",!0);try{let i=await a.list(".stashpad");for(let s of i.folders||[])/\/retired-keyfile-/.test(s)&&await t(s,!0)}catch{}return this.kf=null,this.parkedKeyMaterial=!1,e}dispose(){this.lock()}};var is=null,Ws=new Set;function Xs(d){if(is!==d){is=d;for(let a of Ws)a()}}function pt(){return is}function da(d){if(is===d){is=null;for(let a of Ws)a()}}function Aa(d){return Ws.add(d),()=>Ws.delete(d)}function Dc(){return T.Platform.isMacOS?"Finder":T.Platform.isWin?"File Explorer":"file manager"}var qt=[{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:"copyLink",label:"Copy Stashpad link",desc:"Copy an obsidian://stashpad deep link to the cursor row (or first selected note) \u2014 click it anywhere to jump back. No default chord.",defaultPrimary:""},{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 into a separate note (under a chosen parent)",desc:'Duplicate the cursor row (with its subtree) as a separate note and pick which parent it nests under. Distinct from "Fork as a version" (a draft within a sheet group). 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: G \u2014 mark the selection (or cursor row) as a task / todo, or clear it. Tasks appear in the Tasks panel.",defaultPrimary:"G"},{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",desc:"Move the selected note(s) into this folder's own archive subfolder (drops out of search; plaintext unless this folder encrypts its archive). 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 Po(){let d={};for(let a of qt)d[a.id]={primary:a.defaultPrimary,secondary:a.defaultSecondary??"",preferRight:!1,useBoth:!!a.defaultUseBoth};return d}var vt={folder:"Stashpad",importDropFolder:"",exportFolder:"_exports",autoImport:!1,inheritObsidianExclusions:!0,folderPanelPinnedFraction:.5,folderPanelPinned:[],folderPanelDownranked:[],folderPanelHidden:[],folderPanelPinnedGrouping:"pin-order",enablePerfProfiling:!1,debugTrace:!1,writeRecoveryLinks:!0,useTemplatesFormat:!1,prefixTimestampsOnCopy:!0,splitOnLines:!1,splitMode:"lines",confirmCrossParentDrag:!0,confirmBulkDelete:!0,confirmAttachmentDelete:!0,autofocusComposerAfterSend:!0,focusComposerOnOpen:!1,searchOpensInContext:!0,popoutDuplicates:!0,encryption:Vs(),encryptTrash:!1,encryptTrashFilenames:!1,migratedToggleTaskG:!1,migratedArchiveToSubfolders:!1,migratedTrashToSubfolders:!1,reEncryptWatch:[],reEncryptNudge:!1,reEncryptAfterMin:0,dueQuickAdjusts:["5m","15m","30m","1h","1d","1w"],archiveFolders:[],folderEncPrefs:{},folderIcons:{},folderSwitcherIncludePinned:!1,importExcludePrefixes:"_",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:Po()},ha=JSON.parse(JSON.stringify(vt)),To=new Set;function X(){return ha}function ss(d){ha=d;for(let a of To)a()}function pa(d){return To.add(d),()=>To.delete(d)}function _s(d){try{let a=d.internalPlugins?.plugins?.templates;if(!a?.enabled)return null;let e=a.instance?.options??{};return{dateFormat:e.dateFormat||"YYYY-MM-DD",timeFormat:e.timeFormat||"HH:mm"}}catch{return null}}var Zs=[{id:"foldersStorage",label:"\u{1F4C1} Folders & Storage"},{id:"importExport",label:"\u{1F504} Import & Export"},{id:"datesTime",label:"\u{1F552} Dates & Time"},{id:"behaviors",label:"\u{1F39B}\uFE0F Behavior"},{id:"notifications",label:"\u{1F514} Notifications"},{id:"encryption",label:"\u{1F512} Encryption"},{id:"authorship",label:"\u2712\uFE0F Authorship"},{id:"templates",label:"\u{1F4C4} Templates"},{id:"organizationSystems",label:"\u{1F5C2}\uFE0F Organization Systems"},{id:"maintenance",label:"\u{1F6E0}\uFE0F Maintenance"},{id:"diagnostics",label:"\u{1FA7A} Diagnostics"},{id:"hotkeys",label:"\u2328\uFE0F Hotkeys"}].sort((d,a)=>{let e=t=>t.replace(/^[^\p{L}\p{N}]+/u,"");return e(d.label).localeCompare(e(a.label))}),Mo=null;function xc(d,a){return Mo||(Mo=class extends T.SettingPage{constructor(e,t){super(),this.title=e,this._renderFn=t}display(){this.containerEl.empty(),this._renderFn(this.containerEl)}}),new Mo(d,a)}var js=class extends T.PluginSettingTab{constructor(e,t){super(e,t);this.plugin=t;this.pfeSelected=null;this.pfeRerender=null;this.iconPickFolder=null}display(){let{containerEl:e}=this;e.empty();for(let t of Zs){new T.Setting(e).setName(t.label).setHeading();let i=this.itemsForTab(t.id);if(i)for(let s of i){let n=new T.Setting(e);typeof s.render=="function"?s.render(n):(s.name&&n.setName(s.name),s.desc&&n.setDesc(s.desc))}else this.renderTabContent(e,t.id)}}getSettingDefinitions(){return Zs.map(e=>{let t=this.itemsForTab(e.id);return t?{type:"page",name:e.label,items:t}:{type:"page",name:e.label,page:()=>xc(e.label,i=>this.renderTabContent(i,e.id))}})}itemsForTab(e){switch(e){case"hotkeys":return this.hotkeyItems();case"diagnostics":return this.diagnosticsItems();case"notifications":return this.notificationsItems();case"foldersStorage":return this.buildGeneralCategories().foldersStorage;case"importExport":return this.buildGeneralCategories().importExport;case"datesTime":return this.buildGeneralCategories().datesTime;case"maintenance":return this.buildGeneralCategories().maintenance;case"behaviors":{let t=this.buildGeneralCategories();return[this.headingDef("\u{1F4CB} List & Display"),...t.listDisplay,this.headingDef("\u2195\uFE0F Moving Notes"),...t.movingNotes,this.headingDef("\u270D\uFE0F Composer & Copying"),...t.composerCopy,this.headingDef("\u{1F5D1}\uFE0F Deleting"),...t.deleting,this.headingDef("\u{1FA9F} Windows & Tabs"),...t.windowsTabs,this.headingDef("\u2699\uFE0F Misc"),...t.misc]}case"organizationSystems":return[this.headingDef("\u{1F522} JD Index (Johnny Decimal)"),...this.jdIndexItems(),this.headingDef("\u{1F4DA} Open Knowledge Format (OKF)"),...this.okfItems()];case"encryption":return this.encryptionItems();case"authorship":return this.authorshipItems();case"templates":return this.templatesItems();default:return null}}renderTabContent(e,t){switch(t){case"authorship":this.renderAuthorshipSection(e);break;case"templates":this.renderTemplatesTab(e);break}}diagnosticsItems(){return[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.",e=>e.addToggle(t=>t.setValue(this.plugin.settings.enablePerfProfiling).onChange(async i=>{this.plugin.settings.enablePerfProfiling=i,await this.plugin.saveSettings()})),["perf","profiling","timing","slow"]),this.renderDef("Debug trace","Record low-level diagnostic lines (e.g. tap coordinates vs the row they resolve to) to an in-memory buffer while you reproduce a bug, then copy them below to share. Local only \u2014 no network, no file writes; zero overhead when off.",e=>e.addToggle(t=>t.setValue(this.plugin.settings.debugTrace).onChange(async i=>{this.plugin.settings.debugTrace=i,await this.plugin.saveSettings()})),["debug","trace","diagnostics","tap","log"]),this.renderDef("Copy / clear debug trace","Copy the captured debug lines to the clipboard (paste them back to share), or clear the buffer to start a fresh capture.",e=>{e.addButton(t=>t.setButtonText("Copy").onClick(async()=>{let i=this.plugin.getDebugTrace();if(!i){new T.Notice("Debug trace is empty \u2014 enable it and reproduce the issue first.");return}try{await navigator.clipboard.writeText(i),new T.Notice("Debug trace copied.")}catch{new T.Notice("Couldn't access clipboard.")}})),e.addButton(t=>t.setButtonText("Clear").onClick(()=>{this.plugin.clearDebugTrace(),new T.Notice("Debug trace cleared.")}))},["debug","trace","copy","clear"]),this.renderDef("Open log file","Append-only history of creates, deletes, parent changes, renames. Stored alongside the plugin's other private files.",e=>e.addButton(t=>t.setButtonText("Open log").onClick(async()=>{let i=this.app.vault.adapter,s=this.plugin.pluginPrivatePath("log.jsonl");if(!await i.exists(s)){new T.Notice("No log yet \u2014 make some changes first.");return}let n=await i.read(s);new ii(this.app,n,s).open()})),["log","history","diagnostics"])]}notificationsItems(){let e=new Set(this.plugin.settings.mutedNotificationCategories??[]),t=Object.keys(fo);return[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");let n=async()=>{let o=parseInt(s.getValue(),10);if(!Number.isFinite(o)||o<0){s.setValue(String(this.plugin.settings.notificationHistoryLimit??5e3));return}this.plugin.settings.notificationHistoryLimit=o,this.plugin.notifications.setHistoryLimit(o),await this.plugin.saveSettings()};s.inputEl.addEventListener("blur",()=>void n()),s.inputEl.addEventListener("keydown",o=>{o.key==="Enter"&&n()})}),["notification","history","limit"]),{type:"group",heading:"Mute notification categories",items:t.map(i=>{let s=fo[i];return this.renderDef(s.label,s.desc,n=>n.addToggle(o=>o.setValue(!e.has(i)).onChange(async r=>{let l=!r;l?e.add(i):e.delete(i),this.plugin.settings.mutedNotificationCategories=Array.from(e),this.plugin.notifications.setMuted(i,l),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 Ki(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 T.Notice("No log yet \u2014 make some changes first.");return}let l=await o.read(r);new ii(this.app,l,r).open()},this.plugin.settings.authorId||null,n=>this.plugin.lookupNoteAuthorIds(n)).open()})),["notification","history","panel"])]}renderTemplatesTab(e){this.renderColorAliasesSection(e),this.renderNoteTemplatesSection(e)}renderDef(e,t,i,s){return{name:e,desc:t,aliases:s,render:n=>{n.setName(e).setDesc(t);try{i(n)}catch(o){console.error(`[Stashpad] settings control "${e}" failed to render:`,o)}}}}sectionDef(e,t,i,s){return{name:e,desc:t,aliases:s,render:n=>{let o=n.settingEl;o.empty(),o.removeClass("setting-item"),o.addClass("stashpad-settings-section");try{i(o)}catch(r){console.error(`[Stashpad] settings section "${e}" failed to render:`,r)}}}}headingDef(e,t){return this.sectionDef(e,t??"",i=>{let s=new T.Setting(i).setName(e).setHeading();t&&s.setDesc(t)},[e.toLowerCase()])}folderKeyLabel(e){let t=new Date,i=r=>String(r).padStart(2,"0"),s=`${t.getFullYear()}${i(t.getMonth()+1)}${i(t.getDate())}-${i(t.getHours())}${i(t.getMinutes())}`,n=(this.plugin.settings.authorName||"").trim(),o=n?n.split(/\s+/).map(r=>r[0]).join(""):(this.plugin.settings.authorId||"anon").slice(0,4);return`${s} - ${e.split("/").pop()||e} - ${o}`}promptSetFolderPassword(e){new Ne(this.app,{mode:"setup",offerKeychain:!0,title:`Set password for \u201C${e.split("/").pop()}\u201D`,intro:"A separate password just for this folder. Share it with collaborators out-of-band (a password manager, Signal, in person). There is NO recovery if it's lost.",onSubmit:async({next:t,remember:i})=>{if(!t)return"Enter a password.";try{await this.plugin.encryption.setupFolderKey(e,t,this.folderKeyLabel(e),i)}catch(s){return s.message}return new T.Notice("Folder password set \u2014 share it securely."),this.update?.(),this.pfeRerender?.(),null}}).open()}promptChangeFolderPassword(e){new Ne(this.app,{mode:"setup",offerKeychain:!0,title:`Change password for \u201C${e.split("/").pop()}\u201D`,intro:"Re-wraps this folder's key under a new password. The OLD password stops working on THIS device right away (un-synced copies elsewhere keep working until they sync). To truly cut off someone who left, remove encryption and re-encrypt the folder under a fresh password.",onSubmit:async({next:t,remember:i})=>{if(!t)return"Enter a password.";try{await this.plugin.encryption.changeFolderPassword(e,t,i)}catch(s){return s.message}return new T.Notice("Folder password changed."),this.update?.(),this.pfeRerender?.(),null}}).open()}promptSetFolderRecovery(e){let t=e.split("/").pop()||e;new Ne(this.app,{mode:"setup",offerKeychain:!1,title:`Recovery password for \u201C${t}\u201D`,intro:"A SECOND password that also unlocks this folder \u2014 a backup in case the main password is lost. It wraps the same key, so it's exactly as sensitive: store it somewhere safe and separate. Setting it again replaces any existing recovery password.",onSubmit:async({next:i})=>{if(!i)return"Enter a password.";try{await this.plugin.encryption.setFolderRecoveryPassword(e,i)}catch(s){return s.message}return new T.Notice("Recovery password set \u2014 keep it somewhere safe."),this.update?.(),this.pfeRerender?.(),null}}).open()}promptRemoveFolderRecovery(e){let t=e.split("/").pop()||e;new _(this.app,`Remove recovery password for \u201C${t}\u201D?`,"The recovery password will no longer unlock this folder. The main folder password is unchanged. You can add a new recovery password later.","Remove recovery",async i=>{if(i){try{await this.plugin.encryption.removeFolderRecoveryPassword(e)}catch(s){new T.Notice(s.message);return}new T.Notice("Recovery password removed."),this.update?.(),this.pfeRerender?.()}}).open()}promptUnlockFolder(e){new Ne(this.app,{mode:"unlock",offerKeychain:!0,title:`Unlock \u201C${e.split("/").pop()}\u201D`,intro:"Enter this folder's password.",onSubmit:async({current:t,remember:i})=>await this.plugin.encryption.unlockFolder(e,t,i)?(new T.Notice("Folder unlocked."),this.update?.(),this.pfeRerender?.(),null):"Wrong password. Try again."}).open()}renderPerFolderEncryption(e){let t=this.plugin.discoverStashpadFolders();if(t.length===0){e.createEl("p",{cls:"setting-item-description"}).setText("No Stashpad folders found yet.");return}(!this.pfeSelected||!t.includes(this.pfeSelected))&&(this.pfeSelected=t[0]);let i=e.createDiv({cls:"stashpad-folderenc-panel"});this.pfeRerender=()=>{i.empty(),this.renderFolderEncPanel(i,this.pfeSelected)},new T.Setting(e).setName("Folder").setDesc("Pick a folder to configure its password, archive, and trash options. Everything below applies to the selected folder only.").setHeading().addDropdown(s=>{for(let n of t)s.addOption(n,n);s.setValue(this.pfeSelected),s.selectEl.addClass("stashpad-folderenc-picker"),s.onChange(n=>{this.pfeSelected=n,this.pfeRerender?.()})}),e.appendChild(i),this.renderFolderEncPanel(i,this.pfeSelected)}renderFolderEncPanel(e,t){let i=this.plugin.encryption,s=i.hasOwnFolderKey(t),n=i.folderKeyEntry(t)?.folderPath??null,o=!!n&&!s,r=i.isFolderUnlocked(t),l=(this.plugin.settings.folderEncPrefs??{})[t]??{},c=s?r?"Has its own password \xB7 unlocked":"Has its own password \xB7 locked":o?`Inherits \u201C${n.split("/").pop()||n}\u201D's password \xB7 ${r?"unlocked":"locked"}`:"Uses the vault password",A=new T.Setting(e).setName("Password").setDesc(c);if(o?A.addButton(f=>f.setButtonText("Manage on parent folder").onClick(()=>{this.pfeSelected=n,this.update?.(),this.pfeRerender?.()})):s?r?A.addButton(f=>f.setButtonText("Change password\u2026").onClick(()=>this.promptChangeFolderPassword(t))):A.addButton(f=>f.setButtonText("Unlock\u2026").setCta().onClick(()=>this.promptUnlockFolder(t))):A.addButton(f=>f.setButtonText("Set folder password\u2026").setCta().onClick(()=>this.promptSetFolderPassword(t))),s&&r){let f=this.plugin.encryption.folderHasRecovery(t),g=new T.Setting(e).setName("Recovery password").setDesc(f?"A second password that also unlocks this folder. Keep it somewhere safe and separate.":"Optional. Add a second password that also unlocks this folder, as a backup if the main one is lost.");g.addButton(I=>I.setButtonText(f?"Change recovery\u2026":"Add recovery\u2026").onClick(()=>this.promptSetFolderRecovery(t))),f&&g.addButton(I=>{I.setButtonText("Remove recovery").onClick(()=>this.promptRemoveFolderRecovery(t)),I.buttonEl.addClass("mod-warning")})}let h=async f=>{this.plugin.settings.folderEncPrefs={...this.plugin.settings.folderEncPrefs??{},[t]:{...(this.plugin.settings.folderEncPrefs??{})[t]??{},...f}},await this.plugin.saveSettings()};new T.Setting(e).setName("Trash handling").setDesc("Where notes deleted from this folder go.").addDropdown(f=>f.addOption("","Stashpad trash (default)").addOption("obsidian","Obsidian native trash").setValue(l.trashHandling==="obsidian"?"obsidian":"").onChange(g=>h({trashHandling:g||void 0})));let p=(f,g,I,m,B=!1)=>{new T.Setting(e).setName(f).addToggle(C=>C.setValue(!!l[g]).onChange(async Q=>{if(Q&&B){if(!this.plugin.encryption.hasFolderKey(t)){new T.Notice("Give this folder a password first (the \u201CSet folder password\u2026\u201D button above), then enable this."),this.pfeRerender?.();return}if(!await this.plugin.ensureFolderUnlocked(t)){this.pfeRerender?.();return}}let y={};y[g]=Q,Q||(y[I]=!1),await h(y),m&&await m(Q),this.pfeRerender?.()})),new T.Setting(e).setName(`\u21B3 ${f} \u2014 hide filenames`).setClass("stashpad-subsetting").addToggle(C=>{C.setValue(!!l[I]),C.setDisabled(!l[g]),C.onChange(async Q=>{let y={};y[I]=Q,await h(y),this.pfeRerender?.()})})};p("Encrypt this folder's notes","encryptContent","encryptFilenames",async f=>{f?await this.plugin.lockFolder(t):await this.plugin.unlockFolder(t);let g=(this.plugin.settings.lockedSubtrees??[]).some(I=>(I.folder||"").replace(/\/+$/,"")===t);await h({encryptContent:g,...g?{}:{encryptFilenames:!1}})}),p("Encrypt archived notes","archiveEncryptContent","archiveEncryptFilenames",async f=>{if(!f)return;let g=this.plugin.archivedPlainNotesIn(`${t}/archive`).length;g!==0&&new _(this.app,`Encrypt the ${g} note${g===1?"":"s"} already archived?`,`\u201C${t.split("/").pop()}\u201D's archive already holds ${g} plaintext note${g===1?"":"s"}. Encrypt ${g===1?"it":"them"} now too? (Skipping leaves ${g===1?"it":"them"} readable; only notes archived from now on get encrypted.)`,"Encrypt them",async I=>{if(!I)return;let m=await this.plugin.encryptExistingArchiveNotes(t);new T.Notice(m>0?`Encrypted ${m} archived note${m===1?"":"s"}.`:"Nothing was encrypted (cancelled or already locked)."),this.pfeRerender?.()}).open()},!0),p("Encrypt trashed notes","trashEncryptContent","trashEncryptFilenames",void 0,!0),new T.Setting(e).setName("Auto re-encrypt after idle minutes").setDesc("Override the global auto-re-encrypt timer for this folder. Blank = use global; 0 = off for this folder. A cancellable countdown always shows first, and open notes are never touched.").addText(f=>{f.setPlaceholder("global"),f.setValue(l.reEncryptAfterMin==null?"":String(l.reEncryptAfterMin)),f.onChange(g=>{let I=g.trim();{let m=Number(I);I===""?h({reEncryptAfterMin:void 0}):Number.isFinite(m)&&m>=0?h({reEncryptAfterMin:Math.floor(m)}):f.setValue(l.reEncryptAfterMin==null?"":String(l.reEncryptAfterMin))}})});let u=this.plugin.discoverStashpadFolders().filter(f=>f!==t&&f.startsWith(t+"/")).sort();if(u.length){new T.Setting(e).setName("Subfolders").setDesc(`${u.length} subfolder${u.length===1?"":"s"} \u2014 they use \u201C${t.split("/").pop()}\u201D's password. Encrypt each individually.`).setHeading();for(let f of u){let g=(this.plugin.settings.folderEncPrefs??{})[f]??{},I=async C=>{this.plugin.settings.folderEncPrefs={...this.plugin.settings.folderEncPrefs??{},[f]:{...(this.plugin.settings.folderEncPrefs??{})[f]??{},...C}},await this.plugin.saveSettings()},m=(this.plugin.settings.lockedSubtrees??[]).some(C=>(C.folder||"").replace(/\/+$/,"")===f),B=f.slice(t.length+1);new T.Setting(e).setName(B).addToggle(C=>C.setValue(m).onChange(async Q=>{Q?await this.plugin.lockFolder(f):await this.plugin.unlockFolder(f);let y=(this.plugin.settings.lockedSubtrees??[]).some(E=>(E.folder||"").replace(/\/+$/,"")===f);await I({encryptContent:y,...y?{}:{encryptFilenames:!1}}),this.update?.(),this.pfeRerender?.()})),new T.Setting(e).setName(`\u21B3 ${B} \u2014 hide filenames`).setClass("stashpad-subsetting").addToggle(C=>{C.setValue(!!g.encryptFilenames),C.setDisabled(!m),C.onChange(Q=>void I({encryptFilenames:Q}))})}}}buildGeneralCategories(){let e=async()=>this.plugin.saveSettings(),t=(s,n,o,r,l)=>this.renderDef(s,n,c=>c.addToggle(A=>A.setValue(o()).onChange(async h=>{r(h),await e()})),l),i={foldersStorage:[],importExport:[],datesTime:[],listDisplay:[],movingNotes:[],deleting:[],composerCopy:[],windowsTabs:[],maintenance:[],misc:[]};i.foldersStorage.push(this.renderDef("Stashpad notes folder","Vault-relative folder where Stashpad stores its notes and attachments. Created on demand.",s=>{s.addText(n=>{new ci(this.app,n.inputEl),n.setValue(this.plugin.settings.folder).setPlaceholder("Stashpad");let o=async()=>{let r=(n.getValue()||"").trim().replace(/^\/+|\/+$/g,"")||vt.folder,l=r.split("/").filter(Boolean),c=new Set([this.plugin.settings.importDropFolder,this.plugin.settings.exportFolder,"_attachments","_processed","_authors","_deleted","archive","trash",".stashpad"].map(A=>(A??"").trim().replace(/^\/+|\/+$/g,"")).filter(Boolean));if(l.some(A=>c.has(A))){new T.Notice(`"${r}" uses a reserved Stashpad subfolder name. Pick something else.`),n.setValue(this.plugin.settings.folder);return}r!==this.plugin.settings.folder&&(this.plugin.settings.folder=r,await e())};n.inputEl.addEventListener("blur",()=>void o()),n.inputEl.addEventListener("keydown",r=>{r.key==="Enter"&&o()})})},["folder","path","location","notes"])),i.importExport.push(t("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.foldersStorage.push(t("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.foldersStorage.push(t("Include pinned notes in the folder switcher","When on, the folder switcher / creator (the folder button and the \u201COpen or switch Stashpad folder\u201D command) also lists your pinned notes, so you can jump straight to one. Off keeps the picker focused on folders.",()=>this.plugin.settings.folderSwitcherIncludePinned,s=>{this.plugin.settings.folderSwitcherIncludePinned=s},["pinned","switcher","folder","picker","jump"])),i.foldersStorage.push(this.renderDef("Folder tab icon","Give a folder its own Lucide icon (e.g. rocket, star, book-open) shown on its tab, the folder switcher, and its folder-panel row. Pick a folder, then start typing in the icon box \u2014 matching icons appear with previews; pick one. Blank = the default icon. Set per folder.",s=>{let n=this.plugin.discoverStashpadFolders();if(n.length===0){s.setDesc("No Stashpad folders found yet.");return}(!this.iconPickFolder||!n.includes(this.iconPickFolder))&&(this.iconPickFolder=n[0]);let o=null,r=s.controlEl.createSpan({cls:"stashpad-folder-icon-preview"}),l=c=>{r.empty();let A=c.trim();A&&(0,T.setIcon)(r,A)};s.addDropdown(c=>{for(let A of n)c.addOption(A,A.split("/").pop()||A);c.setValue(this.iconPickFolder),c.onChange(A=>{this.iconPickFolder=A;let h=this.plugin.getFolderIcon(A)??"";o?.setValue(h),l(h)})}),s.addText(c=>{o=c,c.setPlaceholder("type to search\u2026 (e.g. rocket)"),new Gs(this.app,c.inputEl),c.setValue(this.plugin.getFolderIcon(this.iconPickFolder)??""),c.onChange(async A=>{l(A),await this.plugin.setFolderIcon(this.iconPickFolder,A.trim())})}),l(this.plugin.getFolderIcon(this.iconPickFolder)??"")},["icon","folder","tab","lucide","emoji","switcher"])),i.importExport.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 e()})),["import","subfolder"])),i.importExport.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,"")||vt.exportFolder,await e()})),["export","stash","subfolder"])),i.importExport.push(this.renderDef("Exclude subfolders by prefix","Comma-separated name prefixes (default \u201C_\u201D). A subfolder whose name starts with any of these \u2014 at any depth \u2014 is NOT surfaced as a Stashpad folder or imported (it stays local). To encrypt such a folder, right-click it in Obsidian's file explorer \u2192 \u201C\u{1F512} Encrypt with Stashpad\u201D.",s=>s.addText(n=>n.setValue(this.plugin.settings.importExcludePrefixes??"_").setPlaceholder("_").onChange(async o=>{this.plugin.settings.importExcludePrefixes=o,await e()})),["import","exclude","prefix","subfolder","underscore","ignore"])),i.maintenance.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, rename any note whose filename slug no longer matches its body's first line, AND migrate legacy attachment filenames to the new name-first format (`photo-<id>.png`). 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{await this.plugin.runRebootstrapWithUI()}catch{}finally{n.setDisabled(!1).setButtonText("Rebootstrap now")}})),["rebootstrap","rebuild","repair","backfill","slug"])),i.maintenance.push(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.",s=>s.addToggle(n=>n.setValue(this.plugin.settings.writeRecoveryLinks).onChange(async o=>{this.plugin.settings.writeRecoveryLinks=o,await e()})),["recovery","parentlink","children","frontmatter"]));{let s=null,n=()=>{s&&s.setText(`Sample: ${Xe(Date.now(),this.plugin.settings)}`)};i.datesTime.push(this.renderDef("Date display format","How created / edited timestamps and due dates are shown \u2014 in the notes list, the Tasks panel, and the detail panel. Overridden by the Templates-plugin formats when the option below is on.",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 l=>{this.plugin.settings.dateDisplayFormat=l,await e(),n()})})},["date","format","display"])),i.datesTime.push(this.renderDef("Use Templates plugin date/time formats","Use the date/time formats configured in the core Templates plugin instead of the Date display format above. Off = the Date display format above is used everywhere.",o=>{o.addToggle(l=>l.setValue(this.plugin.settings.useTemplatesFormat).onChange(async c=>{this.plugin.settings.useTemplatesFormat=c,await e(),n()}));let r=_s(this.app);o.descEl.createDiv({cls:"stashpad-settings-note"}).setText(r?`Templates plugin: date = "${r.dateFormat}", time = "${r.timeFormat}"`:"Templates plugin not enabled.")},["templates","date","time","format"])),i.datesTime.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 l=>{this.plugin.settings.dateDisplayTimezone=(l||"").trim(),await e(),n()})})},["timezone","tz","date","iana"])),i.datesTime.push(this.renderDef("Quick due-date adjustments","Comma-separated relative amounts shown as quick +/- buttons in the due-date and snooze pickers (e.g. 5m, 15m, 1h, 1d, 1w). Units: m=minutes, h=hours, d=days, w=weeks. A +/- flip in the picker toggles add vs subtract. Leave blank to hide the row.",o=>{o.addText(r=>{r.setPlaceholder("5m, 15m, 1h, 1d, 1w"),r.setValue((this.plugin.settings.dueQuickAdjusts??[]).join(", ")),r.onChange(async l=>{let c=l.split(",").map(A=>A.trim()).filter(A=>/^\d+\s*[mhdw]$/i.test(A)).map(A=>A.replace(/\s+/g,"").toLowerCase());this.plugin.settings.dueQuickAdjusts=c,await e()})})},["quick","adjust","snooze","due","preset","increment","decrement"])),i.datesTime.push({name:"Date sample",searchable:!1,render:o=>{let r=o.settingEl;r.empty(),r.removeClass("setting-item"),r.addClass("stashpad-settings-section"),s=r.createDiv({cls:"setting-item-description stashpad-settings-note stashpad-date-sample"}),n()}})}return i.movingNotes.push(t("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.movingNotes.push(t("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.listDisplay.push(t("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.misc.push(t("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.listDisplay.push(t("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.listDisplay.push(t("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.listDisplay.push(t("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.movingNotes.push(t("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.deleting.push(t("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.deleting.push(t("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.foldersStorage.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 T.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 l of n)this.renderFolderScopeRow(r,l)}let o=null;new T.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 l=(o?.value??"").trim().replace(/^\/+|\/+$/g,"");if(!l){new T.Notice("Enter a folder name first.");return}try{await this.plugin.createNewStashpad(l),new T.Notice(`Created Stashpad "${l}".`),o&&(o.value=""),await this.plugin.waitForStashpadFolder(l,2e3),this.update?.()}catch(c){new T.Notice(`Couldn't create: ${c.message}`)}}))},["search","scope","exclude","include","create","new","stashpad","folder"])),i.foldersStorage.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 T.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.foldersStorage.push(this.headingDef("\u{1F3F7}\uFE0F Note Titles")),i.foldersStorage.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:je).join(` +`);s.addTextArea(r=>{r.setValue(o),n=r.inputEl,n.rows=6,n.setCssStyles({fontFamily:"var(--font-monospace)"}),r.onChange(async l=>{this.plugin.settings.slugStopWords=(l||"").split(/\r?\n/).map(c=>c.trim().toLowerCase()).filter(Boolean),await e()})}).addExtraButton(r=>r.setIcon("rotate-ccw").setTooltip("Reset to defaults").onClick(async()=>{this.plugin.settings.slugStopWords=[...je],n&&(n.value=je.join(` +`)),await e()}))},["slug","stopwords","filename","title","note titles"])),i.composerCopy.push(t("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.composerCopy.push(t("Focus composer when opening a note","Focus the composer when you open or switch into a Stashpad view. OFF (default) focuses the LIST instead, so arrow-key navigation works right away instead of the composer grabbing focus every time. (Separate from 'after sending' above.)",()=>this.plugin.settings.focusComposerOnOpen,s=>{this.plugin.settings.focusComposerOnOpen=s},["composer","focus","open","navigate","list"])),i.windowsTabs.push(t("Search opens the note in its list (in context)","When you pick a search result, open the LIST that contains the note (focus its parent) and scroll to the note \u2014 so you see it in context instead of landing on the focused-note header. On by default.",()=>this.plugin.settings.searchOpensInContext,s=>{this.plugin.settings.searchOpensInContext=s},["search","context","list","scroll","parent"])),i.windowsTabs.push(t("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.windowsTabs.push(t("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.composerCopy.push(t("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 e=this.plugin.encryption,t=[];return t.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."});let n=i.createEl("div",{cls:"stashpad-enc-warning"});n.createEl("p").setText("\u26A0\uFE0F AI-built, NOT human-audited. This encryption was written by an AI assistant \u2014 not reviewed or security-audited by a human. Treat it as best-effort protection against a casual snoop, not a guarantee \u2014 and always keep your own unencrypted backups of anything important."),n.createEl("p").setText("There is NO recovery. If you lose a password, anything encrypted under it (notes, archived items, encrypted-trash items) is gone for good. Locking, encrypted archiving, and secure-deleting permanently remove the plaintext \u2014 the encrypted copy is the only one left. (A plaintext archive only de-indexes notes from search; it does NOT encrypt them.)"),n.createEl("p").setText("Each device unlocks with its own password (it never leaves the device); collaborators get access by device approval, not a shared password. If everyone with access loses their password, the content is unrecoverable. While encrypting or decrypting, avoid having a sync/cloud service write the vault mid-operation \u2014 it can corrupt files.");let o=i.createEl("details",{cls:"stashpad-enc-info"});o.createEl("summary",{text:"\u2139\uFE0F How Stashpad encryption works (concepts)"});let r=(c,A)=>{let h=o.createEl("p",{cls:"stashpad-enc-info-item"});h.createEl("strong",{text:`${c} \u2014 `}),h.appendText(A)};r("Per-folder passwords","Encryption is per folder: give a folder its OWN password (a separate key) and its notes lock under that key. Subfolders inherit their nearest keyed ancestor's password. A folder with no password of its own (or inherited) is not encrypted. Share a folder by handing over its password out-of-band."),r("Encrypt notes vs Hide filenames","\u201CEncrypt \u2026 notes\u201D scrambles the note body into a locked .stashenc blob (the plaintext is removed). \u201CHide filenames\u201D goes further: it replaces the on-disk name AND the placeholder title with a generic label, so a glance at the vault doesn't reveal WHAT is locked. Whether a title is hidden is decided when the note is locked."),r("Archive: plaintext vs encrypted","Every folder has its own \u201Carchive\u201D subfolder. Archiving is a plain move by default \u2014 the notes drop out of cross-folder search but stay readable. Turn on \u201CEncrypt archived notes\u201D for a folder to lock notes as they're archived instead."),r("Trash: Stashpad vs Obsidian","Deleting a note normally sends it to that folder's own \u201Ctrash\u201D subfolder \u2014 encrypted if the folder encrypts its trash \u2014 and it's recoverable from the Trash view. Set a folder's \u201CTrash handling\u201D to \u201CObsidian native trash\u201D to use Obsidian's plain deleted-files behavior instead (Stashpad can't encrypt or recover those)."),r("No recovery","There is no backdoor and no reset. If a password is lost, everything encrypted under it is gone \u2014 so keep your own unencrypted backups of anything you can't afford to lose."),e.hasAnyFolderKey()?new T.Setting(i).setName("Remove all encryption").setDesc("Decrypts everything back to plaintext and deletes every folder's password/key. If anything is still locked, you'll be offered to decrypt it (needs each folder's password) or \u2014 if a password is lost \u2014 permanently delete it. Then type the confirmation phrase.").addButton(c=>{let A=async()=>{let p=await this.plugin.encryptionStateStrict();if(p.live){let f=()=>{new _(this.app,"Delete all locked content forever?","This PERMANENTLY destroys every locked note and folder \u2014 there is NO decrypted copy and NO recovery. Only do this if you've lost the password and want to start fresh.","Delete locked content forever",async I=>{if(!I)return;let m=await this.plugin.purgeAllLockedContent();new T.Notice(`Deleted ${m} locked item${m===1?"":"s"}.`),A()},"Cancel",!0).open()},g=async()=>{if(await this.plugin.unlockAllInVault(),(await this.plugin.encryptionStateStrict()).live){new T.Notice("Some notes are still locked (decryption was cancelled or failed) \u2014 removal cancelled.",1e4);return}A()};new _(this.app,"Encrypted notes are still locked",`Some notes or folders are still encrypted (locked) and have no plaintext copy. Before removing encryption: \u2022 Decrypt everything \u2014 unlock them back to normal notes (needs your password). -\u2022 Delete locked content \u2014 permanently destroy them (only if you've lost the password).`,"Decrypt everything",I=>{I?p():f()},"Delete locked content").open();return}let u=(f,p)=>{new ni(this.app,{title:"Remove encryption?",body:`This erases the encryption key for this vault. No locked notes/folders exist, so your live content is safe.${f} You'll need to set a new password to encrypt again later, and anything previously exported with this key stays locked to its passphrase.`,phrase:"REMOVE ENCRYPTION",confirmText:"Remove encryption",onConfirm:async()=>{let I=await this.plugin.encryptionStateStrict();if(I.live){new T.Notice("Locked notes appeared while this dialog was open \u2014 removal cancelled. Decrypt everything first.",1e4);return}if(I.trash&&!p){new T.Notice("Encrypted trash appeared while this dialog was open \u2014 removal cancelled. Re-open Remove encryption to handle it.",1e4);return}let m=await this.plugin.listDeletedTrash();for(let B of m)await this.plugin.purgeDeletedAt(B.blob);await e.clear(),new T.Notice("Encryption removed."),this.update?.()}}).open()};if(g.trash){let f=async()=>{let I=await this.plugin.restoreAllTrash();if((await this.plugin.encryptionStateStrict()).trash){new T.Notice("Some encrypted-trash items couldn't be decrypted \u2014 removal cancelled. Check the trash tab and try again.",1e4);return}u(I>0?` (${I} trash item${I===1?"":"s"} were decrypted back to their folders.)`:"",!0)},p=()=>{new _(this.app,"Discard encrypted trash?","The encrypted-trash items will be PERMANENTLY lost the moment the key is erased \u2014 there is no recovery. Continue?","Confirm",I=>{I&&u(" \u26A0\uFE0F The encrypted trash is being permanently discarded.",!0)},"Cancel",!0).open()};new _(this.app,"Encrypted notes in the trash",`There are encrypted, deleted notes in the trash. Removing encryption makes them PERMANENTLY unreadable. +\u2022 Delete locked content \u2014 permanently destroy them (only if you've lost the password).`,"Decrypt everything",I=>{I?g():f()},"Delete locked content").open();return}let u=(f,g)=>{new oi(this.app,{title:"Remove encryption?",body:`This erases the encryption key for this vault. No locked notes/folders exist, so your live content is safe.${f} You'll need to set a new password to encrypt again later, and anything previously exported with this key stays locked to its passphrase.`,phrase:"REMOVE ENCRYPTION",confirmText:"Remove encryption",onConfirm:async()=>{let I=await this.plugin.encryptionStateStrict();if(I.live){new T.Notice("Locked notes appeared while this dialog was open \u2014 removal cancelled. Decrypt everything first.",1e4);return}if(I.trash&&!g){new T.Notice("Encrypted trash appeared while this dialog was open \u2014 removal cancelled. Re-open Remove encryption to handle it.",1e4);return}let m=await this.plugin.listDeletedTrash();for(let B of m)await this.plugin.purgeDeletedAt(B.blob);await e.clear(),new T.Notice("Encryption removed."),this.update?.()}}).open()};if(p.trash){let f=async()=>{let I=await this.plugin.restoreAllTrash();if((await this.plugin.encryptionStateStrict()).trash){new T.Notice("Some encrypted-trash items couldn't be decrypted \u2014 removal cancelled. Check the trash tab and try again.",1e4);return}u(I>0?` (${I} trash item${I===1?"":"s"} were decrypted back to their folders.)`:"",!0)},g=()=>{new _(this.app,"Discard encrypted trash?","The encrypted-trash items will be PERMANENTLY lost the moment the key is erased \u2014 there is no recovery. Continue?","Confirm",I=>{I&&u(" \u26A0\uFE0F The encrypted trash is being permanently discarded.",!0)},"Cancel",!0).open()};new _(this.app,"Encrypted notes in the trash",`There are encrypted, deleted notes in the trash. Removing encryption makes them PERMANENTLY unreadable. \u2022 Decrypt Trash \u2014 restore them to their original folders first (recommended). -\u2022 Discard trash \u2014 let them be permanently erased with the key.`,"Decrypt Trash",I=>{I?f():p()},"Discard trash").open();return}u("",!1)},h=!1;c.setButtonText("Remove\u2026").onClick(async()=>{if(!h){h=!0,c.setDisabled(!0),c.buttonEl.addClass("stashpad-btn-loading");try{await A()}finally{h=!1,c.setDisabled(!1),c.buttonEl.removeClass("stashpad-btn-loading")}}}),c.buttonEl.addClass("mod-warning")}):new T.Setting(i).setName("Remove all encryption").setDesc("Nothing is encrypted in this vault yet. Give a folder a password under \u201CPer-Folder Passwords\u201D below to start.");let l=()=>{new ni(this.app,{title:"Permanently delete the old key material?",body:"This PERMANENTLY deletes the old central keyfile (.stashpad/keys.json), its _keys/ backups, and any retired-keyfile backups \u2014 with NO copy kept and NO way to recover them. It does NOT touch your per-folder passwords or currently-encrypted content (use \u201CRemove all encryption\u201D above for those). Only do this if you're sure you'll never need the old key material back.",phrase:"DELETE KEY MATERIAL",confirmText:"Permanently delete",onConfirm:async()=>{let c=await e.wipeLegacyKeyMaterial();new T.Notice(c>0?`Permanently deleted the old key material (${c} item${c===1?"":"s"}). Not recoverable.`:"No old key material found to delete.",9e3),this.update?.()}}).open()};e.hasLegacyKeyfile()?new T.Setting(i).setName("Retire the old encryption keyfile").setDesc("This vault still has the old central keyfile (.stashpad/keys.json), kept only as a read-only backup now that encryption is per-folder. \u201CRetire\u201D MOVES it and its _keys/ backups into .stashpad/retired-keyfile-<date>/ \u2014 reversible, and a recoverable copy is KEPT (nothing is deleted). \u201CPermanently delete\u201D instead removes all old key material with no backup. Retire is blocked if any folder's key still lives only in the old keyfile.").addButton(c=>c.setButtonText("Retire (keep backup)").onClick(async()=>{try{let A=await e.retireLegacyKeyfile();new T.Notice(`Retired the old keyfile \u2014 ${A} file${A===1?"":"s"} moved into .stashpad/retired-keyfile-\u2026 Reversible; a copy is kept.`,9e3),this.update?.()}catch(A){new T.Notice(A.message,12e3)}})).addButton(c=>{c.setButtonText("Permanently delete\u2026").onClick(l),c.buttonEl.addClass("mod-warning")}):e.hasRecoverableKeyMaterial()&&new T.Setting(i).setName("Delete retired keyfile backups").setDesc("The old keyfile was retired, but a recoverable backup is still on disk (.stashpad/retired-keyfile-\u2026 / _keys/). Permanently delete it if you no longer want it recoverable. Doesn't touch your per-folder passwords or encrypted content.").addButton(c=>{c.setButtonText("Permanently delete\u2026").onClick(l),c.buttonEl.addClass("mod-warning")})},["encryption","encrypt","password","passphrase","lock","unlock","key","security","private","folder","share","keyfile","retire"])),t.push(this.headingDef("Encrypted-note defaults","Global defaults for previously-encrypted notes. Per-folder encryption + trash options live under \u201CPer-Folder Passwords\u201D below.")),t.push(this.renderDef("Remind me about unlocked encrypted notes","On startup, if notes that WERE encrypted are still sitting plaintext (you unlocked them, or restored them from the trash), show a notice with a Review button that opens the \u201CPreviously encrypted\u201D view. Nothing is ever re-encrypted automatically.",i=>i.addToggle(s=>s.setValue(this.plugin.settings.reEncryptNudge??!1).onChange(async n=>{this.plugin.settings.reEncryptNudge=n,await this.plugin.saveSettings()})),["remind","nudge","re-encrypt","watchlist","unlocked","sweep"])),t.push(this.renderDef("Auto re-encrypt after idle minutes (global)","0 = OFF (default). After an unlocked, previously-encrypted note sits idle this long, Stashpad shows a \u201CRe-encrypting in 10s\u2026 [Keep unlocked]\u201D countdown you can cancel, then re-locks it. It NEVER re-encrypts a note you have open in an editor. Set per-folder overrides under \u201CPer-Folder Passwords\u201D; per-note in the \u201CPreviously encrypted\u201D view.",i=>i.addText(s=>s.setValue(String(this.plugin.settings.reEncryptAfterMin??0)).onChange(async n=>{{let o=Number(n.trim());if(n.trim()==="")this.plugin.settings.reEncryptAfterMin=0;else if(Number.isFinite(o)&&o>=0)this.plugin.settings.reEncryptAfterMin=Math.floor(o);else{s.setValue(String(this.plugin.settings.reEncryptAfterMin??0));return}await this.plugin.saveSettings()}})),["auto","re-encrypt","idle","timer","peek","lock"])),t.push(this.headingDef("Archive","Every folder has its own \u201Carchive\u201D subfolder: \u201CMove selection to archive\u201D tucks notes into it, archived notes drop out of search, and everything shows up in the aggregated Archived view. Whether a folder's archive is encrypted is set per folder under \u201CPer-Folder Passwords\u201D below (\u201CEncrypt archived notes\u201D).")),t.push(this.sectionDef("Per-Folder Passwords","Give a folder its own password (a separate key) so you can share just that folder with collaborators. Folders without their own password use the vault password.",i=>{this.renderPerFolderEncryption(i)},["folder","per-folder","password","encrypt","key","share","collaborator","archive","unlock","lock"])),t}hotkeyItems(){let e={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},t=Jt.map(i=>({name:i.label,desc:i.desc,aliases:["hotkey","shortcut","keybind","binding","key"],render:s=>this.renderBindingRow(s,i)}));return[e,...t]}renderJdIndexSection(e){let t=new T.Setting(e).setName("JD Index Builder").setHeading();t.settingEl.id="stashpad-jd-index-section";let i=e.createEl("div",{cls:"stashpad-settings-section"}).createEl("p",{cls:"setting-item-description"});i.appendText("Builds a Johnny-Decimal-style index inside a designated Stashpad folder. Two commands:"),i.createEl("br"),i.createEl("strong",{text:"Preview"}),i.appendText(" overwrites the designated folder\u2019s HOME note body with the would-be hierarchy + everything that didn\u2019t match. Frontmatter is preserved; everything below it is replaced."),i.createEl("br"),i.createEl("strong",{text:"Build"}),i.appendText(" creates an actual hierarchy of Stashpad notes (one per prefix), with child\u2192parent relationships matching the dotted segments."),i.createEl("br"),i.appendText("Matches strict prefixes only: all-digits ("),i.createEl("code",{text:"10 Life"}),i.appendText(") or alphanumeric-with-dots ("),i.createEl("code",{text:"1.2 Family"}),i.appendText(", "),i.createEl("code",{text:"animal.duck.yellow Eggs"}),i.appendText("). Mixed schemes sort numbers first, then alphabetically.");let s=this.plugin.discoverStashpadFolders();new T.Setting(e).setName("Scope").setDesc("Scan the whole vault, or restrict to a single folder + its descendants.").addDropdown(l=>{l.addOption("vault","Entire vault"),l.addOption("folder","Single folder"),l.setValue(this.plugin.settings.jdIndexScope??"vault"),l.onChange(async c=>{this.plugin.settings.jdIndexScope=c==="folder"?"folder":"vault",await this.plugin.saveSettings(),this.display()})}),(this.plugin.settings.jdIndexScope??"vault")==="folder"&&new T.Setting(e).setName("Scope folder").setDesc("Vault-relative path. Leave empty to fall back to the entire vault.").addText(l=>{new li(this.app,l.inputEl),l.setPlaceholder("Path/To/Folder"),l.setValue(this.plugin.settings.jdIndexScopeFolder??""),l.onChange(async c=>{this.plugin.settings.jdIndexScopeFolder=(c||"").trim().replace(/^\/+|\/+$/g,""),await this.plugin.saveSettings()})}),new T.Setting(e).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(l=>{l.setValue(this.plugin.settings.jdIndexIncludeStashpadFolders===!0),l.onChange(async c=>{this.plugin.settings.jdIndexIncludeStashpadFolders=c,await this.plugin.saveSettings(),this.display()})}),new T.Setting(e).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(l=>{new li(this.app,l.inputEl),l.setPlaceholder(s[0]??"(pick a Stashpad folder)"),l.setValue(this.plugin.settings.jdIndexStashpadFolder??""),l.onChange(async c=>{this.plugin.settings.jdIndexStashpadFolder=(c||"").trim().replace(/^\/+|\/+$/g,""),await this.plugin.saveSettings()})}),new T.Setting(e).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(l=>{l.addOption("natural","Natural (numeric \u2192 alphabetical)"),l.addOption("created","By creation time"),l.setValue(this.plugin.settings.jdIndexSort??"natural"),l.onChange(async c=>{this.plugin.settings.jdIndexSort=c==="created"?"created":"natural",await this.plugin.saveSettings()})});let n=ai(this.app,this.plugin,this.plugin.settings),o=e.createEl("div",{cls:"stashpad-settings-section"}).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 T.Setting(e).setName("Actions").setClass("stashpad-jd-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(l=>{l.setButtonText("Preview"),l.setTooltip("Overwrites the designated Stashpad folder's HOME note body with the preview."),l.onClick(async()=>{try{let c=await Ts(this.app,this.plugin,this.plugin.settings);if(c.error==="no-dest"){new T.Notice("Set a Designated Stashpad folder for Index first.",5e3);return}if(c.error==="no-home"){new T.Notice(`"${this.plugin.settings.jdIndexStashpadFolder}" doesn't have a Stashpad home note. Open the folder in Stashpad first (it creates one automatically).`,7e3);return}Ps(this.app,c),this.display()}catch(c){console.error("[stashpad] preview failed",c),new T.Notice(`Preview failed: ${c?.message??c}`,8e3)}})}).addButton(l=>{l.setButtonText("Build Stashpad notes"),l.setCta(),l.setTooltip("Create the Stashpad-note hierarchy. Existing notes with matching jdPrefix are updated."),l.onClick(()=>{if(!(this.plugin.settings.jdIndexStashpadFolder??"").trim().replace(/^\/+|\/+$/g,"")){new T.Notice("Set a Designated Stashpad folder for Index first.",5e3);return}new Vi(this.app,this.plugin,this.plugin.settings,n.indexed.length,async()=>{try{let h=await Ao(this.app,this.plugin,this.plugin.settings);if(h.error==="no-dest"){new T.Notice("Set a Designated Stashpad folder for Index first.",5e3);return}if(h.error==="dest-not-stashpad"){new T.Notice(`"${h.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 T.Notice(`Built: ${h.created} created, ${h.updated} updated, ${h.skipped} skipped \u2192 ${h.destFolder}`,6e3),this.display()}catch(h){console.error("[stashpad] build failed",h),new T.Notice(`Build failed: ${h?.message??h}`,8e3)}}).open()})}).addButton(l=>{l.setButtonText(`Reveal in ${Fc()}`),l.setTooltip("Open the designated Stashpad folder in your OS file browser."),l.onClick(async()=>{let c=(this.plugin.settings.jdIndexStashpadFolder??"").trim().replace(/^\/+|\/+$/g,"");if(!c){new T.Notice("Set a Designated Stashpad folder for Index first.",5e3);return}if(!this.app.vault.getAbstractFileByPath(c)){new T.Notice(`Folder "${c}" doesn't exist yet.`,5e3);return}try{let h=this.app.vault.adapter.basePath;if(h){let{shell:g}=window.require?.("electron")??{},u=`${h}/${c}`;g?.openPath?.(u)}else new T.Notice("Reveal in file system not supported on this platform.",4e3)}catch(h){new T.Notice(`Couldn't open folder: ${h?.message??h}`,5e3)}})})}renderColorAliasesSection(e){let t=this.plugin.discoverStashpadFolders();if(t.length===0){new T.Setting(e).setName("Color aliases per Stashpad").setDesc("No Stashpads discovered yet \u2014 create one above first.");return}let i=(()=>{let o=ht()?.noteFolder;return o&&t.includes(o)?o:t[0]})();new T.Setting(e).setName("Color aliases per Stashpad").setDesc("Which Stashpad's colors to label.").addDropdown(o=>{for(let r of t)o.addOption(r,r);o.setValue(i),o.onChange(r=>{i=r,n()})}),e.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=e.createDiv({cls:"stashpad-color-aliases-list"}),n=()=>{s.empty();let o=this.plugin.collectColorsInFolder(i),r=new Map(o.map(h=>[h.hex,h.count])),l=this.plugin.settings.colorAliases?.[i.replace(/\/+$/,"")]??{},c=new Set([...r.keys(),...Object.keys(l)]);if(c.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 A=[...c].map(h=>({hex:h,count:r.get(h)??0}));A.sort((h,g)=>g.count-h.count||h.hex.localeCompare(g.hex));for(let h of A)this.renderColorAliasRow(s,i,h.hex,h.count,n)};n()}authorshipItems(){let e=[];e.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 o=>{this.plugin.settings.authorName=o.trim(),this.plugin.settings.authorName&&!this.plugin.settings.authorId&&(this.plugin.settings.authorId=Ae()),await this.plugin.saveSettings()});let n=()=>void this.plugin.syncAuthorFilesToName();s.inputEl.addEventListener("blur",n),s.inputEl.addEventListener("keydown",o=>{o.key==="Enter"&&n()})}),["author","name","identity","stamp"])),e.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"])),e.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 o=>{this.plugin.settings.authorRole=o.trim(),await this.plugin.saveSettings()});let n=()=>void this.plugin.syncAuthorFilesToName();s.inputEl.addEventListener("blur",n),s.inputEl.addEventListener("keydown",o=>{o.key==="Enter"&&n()})}),["role","title","job"])),e.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 o=>{this.plugin.settings.authorDepartment=o.trim(),await this.plugin.saveSettings()});let n=()=>void this.plugin.syncAuthorFilesToName();s.inputEl.addEventListener("blur",n),s.inputEl.addEventListener("keydown",o=>{o.key==="Enter"&&n()})}),["department","team"]));let t=(i,s,n,o)=>this.renderDef(i,"",r=>r.addToggle(l=>l.setValue(s()).onChange(async c=>{n(c),await this.plugin.saveSettings()})),o);return e.push(t("Show author in note footer",()=>this.plugin.settings.showAuthor,i=>{this.plugin.settings.showAuthor=i},["author","footer","show"])),e.push(t("Show contributors in note footer",()=>this.plugin.settings.showContributors,i=>{this.plugin.settings.showContributors=i},["contributors","footer","show"])),e.push(t("Show last edit time in note footer",()=>this.plugin.settings.showLastEdit,i=>{this.plugin.settings.showLastEdit=i},["last edit","modified","footer","time"])),e.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"])),e.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"])),e}renderAuthoredFolders(e){new T.Setting(e).setName("Folders you've worked in").setHeading();let t=this.plugin.collectAuthoredFolders();if(t.length===0){e.createEl("p",{cls:"setting-item-description",text:"No authored or contributed folders yet."});return}let i=e.createDiv({cls:"stashpad-authored-folders-list"});for(let s of t){let n=i.createDiv({cls:"stashpad-authored-folder-row"}),o=n.createEl("a",{cls:"stashpad-authored-folder-link",text:s.folder});o.onclick=l=>{l.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.",e=>this.renderColorAliasesSection(e),["color","colour","alias","name","swatch","palette","label"]),this.sectionDef("Note Templates","Per-Stashpad note templates \u2014 content stamped into new notes.",e=>this.renderNoteTemplatesSection(e),["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.",e=>this.renderJdIndexSection(e),["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.",e=>this.renderOkfSection(e),["okf","open knowledge format","knowledge","catalog","index","export","bundle","tarball","agent","google"])]}appendCode(e,t){t.split(/`([^`]+)`/g).forEach((i,s)=>{s%2===1?e.createEl("code",{text:i}):i&&e.appendText(i)})}codeDesc(e){let t=document.createDocumentFragment();return this.appendCode(t,e),t}renderOkfSection(e){if(e.createDiv({cls:"stashpad-beta-row"}).createEl("span",{cls:"stashpad-beta-badge",text:"BETA"}),new T.Setting(e).setName("Enable OKF").setDesc(this.codeDesc("Master switch. When on, you choose which folders use OKF by assigning the OKF template to them in Stashpad's own Templates section (the \u{1F4C4} Templates settings here \u2014 NOT Obsidian's core Templates plugin) \u2014 all / some / none, 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 T.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=e.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 Stashpad's \u{1F4C4} Templates section (here in Stashpad's settings \u2014 not Obsidian's core Templates plugin) 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=e.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 T.Setting(e).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 l;try{l=await this.plugin.ensureOkfTemplate()}catch(c){new T.Notice(`Couldn't create the OKF template: ${c.message}`);return}new T.Notice(`OKF template ready at "${l}" \u2014 set a folder's template to that path.`),this.update?.(),this.openSettingsPage("Templates")})}),new T.Setting(e).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 l=await this.plugin.rebuildAllOkf();new T.Notice(l.folders===0?"No folders use the OKF template yet \u2014 assign it in Templates first.":`OKF: updated ${l.written} of ${l.checked} notes across ${l.folders} folder${l.folders===1?"":"s"}.`),this.update?.()}))}let t=new T.Setting(e).setName("Learn about OKF").setDesc("Google's open, vendor-neutral spec for sharing curated knowledge with agents.");t.addButton(i=>i.setButtonText("Spec / repo").onClick(()=>window.open("https://github.com/GoogleCloudPlatform/knowledge-catalog/tree/main/okf"))),t.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(e){let t=()=>new T.Notice(`Open Settings \u2192 Stashpad \u2192 ${e}.`);try{let i=this.app.setting;if(!i?.openTabById){t();return}i.openTabById("stashpad"),window.setTimeout(()=>{let s=i.modalEl?.querySelector(".vertical-tab-content");if(!s){t();return}let o=Array.from(s.querySelectorAll("*")).find(r=>r.childElementCount===0&&r.textContent?.trim()===e&&!r.closest(".vertical-tab-header"))?.closest("[class*='nav'], .setting-item, button, a");o&&!o.closest(".vertical-tab-header")?o.click():t()},60)}catch{t()}}renderAuthorshipSection(e){new T.Setting(e).setName("Authorship").setHeading(),e.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 T.Setting(e).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=Ae()),await this.plugin.saveSettings(),await this.plugin.syncAuthorFilesToName()})}),new T.Setting(e).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 T.Setting(e).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 T.Setting(e).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 T.Setting(e).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 T.Setting(e).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 T.Setting(e).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 t=this.plugin.collectAuthoredFolders();if(t.length>0){new T.Setting(e).setName("Folders You've Worked In").setHeading();let i=e.createDiv({cls:"stashpad-authored-folders-list"});for(let s of t){let n=i.createDiv({cls:"stashpad-authored-folder-row"}),o=n.createEl("a",{cls:"stashpad-authored-folder-link",text:s.folder});o.onclick=l=>{l.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(e)}renderKnownAuthorsSection(e){new T.Setting(e).setName("Known Authors (registry)").setHeading(),e.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 T.Setting(e).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 T.Notice(`Author registry rebuilt: ${n.total} author(s).`)}catch(n){new T.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 T.Notice(n.created>0?`Restored ${n.created} author page(s).`:"No missing author pages.")}catch(n){new T.Notice(`Restore failed: ${n.message}`)}s.setDisabled(!1).setButtonText("Restore missing pages")}));let t=this.plugin.authorRegistry.all();if(t.length===0){e.createEl("div",{cls:"setting-item-description",text:"No authors recorded yet. Rebuild to scan the vault."});return}let i=e.createDiv({cls:"stashpad-known-authors-list"});for(let s of t){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 l=n.createDiv({cls:"stashpad-known-author-history"}),c=s.renames.map(A=>`${A.from} \u2192 ${A.to}`).join(", ");l.setText(`Renamed: ${c}`)}}}renderNoteTemplatesSection(e){let t=this.plugin.discoverStashpadFolders();if(t.length===0)return;if(new T.Setting(e).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(e.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=e.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 c=r.createDiv({cls:"stashpad-note-template-input-wrap"}),A=c.createEl("input",{type:"text",cls:"stashpad-note-template-input",attr:{placeholder:"path/to/template.md (leave blank to disable)"}});A.value=(this.plugin.settings.noteTemplates??{})[o]??"";let h=c.createDiv({cls:"stashpad-note-template-suggest"});h.setCssStyles({display:"none"});let g=[],u=[],f=-1,p=()=>h.style.display!=="none"&&g.length>0,I=Q=>{f=Q,u.forEach((b,D)=>b.toggleClass("is-active",D===Q)),Q>=0&&u[Q]&&u[Q].scrollIntoView({block:"nearest"})},m=()=>{h.setCssStyles({display:"none"}),f=-1},B=async Q=>{A.value=Q,await v(),m()},C=r.createDiv({cls:"stashpad-note-template-warn"});C.setCssStyles({display:"none"});let w=()=>this.app.vault.getMarkdownFiles().map(Q=>Q.path).filter(Q=>!/\/(_imports|_exports|_attachments|\.stashpad)\//.test(Q)).sort(),y=()=>{h.empty(),u=[];let Q=A.value.trim().toLowerCase().split(/\s+/).filter(Boolean),b=D=>{let H=D.toLowerCase();return Q.every(G=>H.includes(G))};if(g=w().filter(D=>b(D)).slice(0,12),g.length===0){m();return}h.setCssStyles({display:""}),g.forEach((D,H)=>{let G=h.createDiv({cls:"stashpad-note-template-suggest-item",text:D});u.push(G),G.addEventListener("mousemove",()=>I(H)),G.addEventListener("mousedown",async x=>{x.preventDefault(),await B(D)})}),f=f>=0&&f<g.length?f:-1,f>=0&&I(f)},v=async()=>{let Q=A.value.trim(),b={...this.plugin.settings.noteTemplates??{}};Q?b[o]=Q:delete b[o],this.plugin.settings.noteTemplates=b,await this.plugin.saveSettings(),E()},E=()=>{C.empty(),C.setCssStyles({display:"none"});let Q=A.value.trim();if(!Q)return;let b=this.app.vault.getAbstractFileByPath(Q);if(!b||b.extension!=="md"){C.setCssStyles({display:""}),C.setText(`\u26A0 "${Q}" is not a markdown file in this vault.`);return}let D=this.app.metadataCache.getFileCache(b)?.frontmatter??{},G=ze.filter(x=>{let U=D[x];return!(U==null||typeof U=="string"&&U.trim()===""||Array.isArray(U)&&U.length===0)});G.length!==0&&(C.setCssStyles({display:""}),C.setText(`\u26A0 Template defines ${G.join(", ")} \u2014 Stashpad always sets ${G.length===1?"this":"these"} on new notes, so the template value${G.length===1?"":"s"} will be ignored.`))};A.addEventListener("focus",y),A.addEventListener("input",()=>{f=-1,y()}),A.addEventListener("blur",()=>{setTimeout(m,150)}),A.addEventListener("change",()=>{v()}),A.addEventListener("keydown",Q=>{if(Q.key==="ArrowDown")Q.preventDefault(),p()?I((f+1)%g.length):(y(),g.length&&I(0));else if(Q.key==="ArrowUp"){if(!p())return;Q.preventDefault(),I((f-1+g.length)%g.length)}else if(Q.key==="Enter")p()&&f>=0&&(Q.preventDefault(),B(g[f]));else if(Q.key==="Escape")p()&&(Q.preventDefault(),m());else if(Q.key==="Tab"&&!Q.shiftKey){if(!p())return;let b=g[f>=0?f:0],D=A.value,H;if(b.toLowerCase().startsWith(D.toLowerCase())){let G=b.indexOf("/",D.length);H=G>=0?b.slice(0,G+1):b}else H=b;H&&H!==D&&(Q.preventDefault(),A.value=H,f=-1,y(),g.length===1&&I(0))}}),E()};for(let n of t)s(n)}renderColorAliasRow(e,t,i,s,n){let o=e.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 h=this.plugin.settings.customPalette??[];new Gt(this.app,i,h,async g=>{if((g??null)===null&&s===0){await this.plugin.setColorAlias(t,i,""),n();return}if(g&&g.toLowerCase()===i){n();return}let u=await this.plugin.recolorAllInFolder(t,i,g??null);if(u>0)new T.Notice(`Recolored ${u} note${u===1?"":"s"}.`);else if(s===0){let f=this.plugin.getColorAlias(t,i);f&&(await this.plugin.setColorAlias(t,i,""),g&&await this.plugin.setColorAlias(t,g,f))}n()},async g=>{let u=(this.plugin.settings.customPalette??[]).filter(f=>f.toLowerCase()!==g.toLowerCase());return this.plugin.settings.customPalette=u,await this.plugin.saveSettings(),u}).open()};let l=o.createDiv({cls:"stashpad-color-alias-meta"});l.createSpan({cls:"stashpad-color-alias-hex",text:i}),l.createSpan({cls:"stashpad-color-alias-count",text:s===0?"\xB7 unused":`\xB7 ${s} note${s===1?"":"s"}`});let c=o.createEl("input",{type:"text",cls:"stashpad-color-alias-input",attr:{placeholder:"Alias (optional)"}});c.value=this.plugin.getColorAlias(t,i)??"",c.onchange=async()=>{await this.plugin.setColorAlias(t,i,c.value),!c.value.trim()&&s===0&&n()};let A=o.createEl("button",{cls:"stashpad-color-alias-del",text:"\xD7",attr:{title:"Delete alias"}});c.value||A.setCssStyles({visibility:"hidden"}),A.onclick=async()=>{await this.plugin.setColorAlias(t,i,""),s===0?n():(c.value="",A.setCssStyles({visibility:"hidden"}))}}renderFolderScopeRow(e,t){let i=e.createDiv({cls:"stashpad-folder-row"});i.createSpan({cls:"stashpad-folder-row-label",text:t});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(t),l=()=>{let A=r();n.toggleClass("is-right",A),n.setAttribute("aria-checked",String(A)),o.setText(A?"X":"\u2713"),s.setText(A?"Excluded":"Included"),s.toggleClass("is-excluded",A),n.title=A?"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."},c=async()=>{let A=new Set(this.plugin.settings.searchExcludedFolders??[]);A.has(t)?A.delete(t):A.add(t),this.plugin.settings.searchExcludedFolders=[...A].sort(),l(),await this.plugin.saveSettings()};n.onclick=()=>void c(),n.onkeydown=A=>{(A.key===" "||A.key==="Enter")&&(A.preventDefault(),c())},l()}renderFolderPlacementList(e){let t=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=>(t[o.key]??[]).length>0)){e.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=>{t.folderPanelPinned=(t.folderPanelPinned??[]).filter(r=>r!==o),t.folderPanelDownranked=(t.folderPanelDownranked??[]).filter(r=>r!==o),t.folderPanelHidden=(t.folderPanelHidden??[]).filter(r=>r!==o),await this.plugin.saveSettings(),this.update?.()};for(let o of i){let r=[...t[o.key]??[]].sort();if(r.length===0)continue;e.createEl("div",{cls:"stashpad-folder-placement-group",text:`${o.label} (${r.length})`});let l=e.createDiv({cls:"stashpad-folder-list"});for(let c of r){let A=l.createDiv({cls:"stashpad-folder-row"});A.createSpan({cls:"stashpad-folder-row-label",text:c});let h=A.createEl("button",{text:o.action});h.onclick=()=>void n(c)}}}renderBindingRow(e,t){e.setName(t.label).setDesc(t.desc),e.settingEl.addClass("stashpad-binding-row");let i=()=>this.plugin.settings.bindings[t.id],s,n,o=()=>{},r=async g=>{},l=e.controlEl.createDiv({cls:"stashpad-binding-seg",attr:{role:"group","aria-label":"Active binding"}}),c={left:l.createEl("button",{cls:"stashpad-binding-seg-btn",text:"Left"}),both:l.createEl("button",{cls:"stashpad-binding-seg-btn",text:"Both"}),right:l.createEl("button",{cls:"stashpad-binding-seg-btn",text:"Right"})};["left","both","right"].forEach(g=>{c[g].onclick=()=>void r(g)});let A=e.controlEl.createDiv({cls:"stashpad-binding-slots"}),h=g=>{let u=A.createDiv({cls:"stashpad-binding-slot"}),f=u.createEl("input",{type:"text"});f.readOnly=!0,f.placeholder="Click & press a key",f.value=di(i()[g]),f.classList.add("stashpad-binding-input");let p=()=>{f.size=Math.max(3,f.value.length||f.placeholder.length)};p();let I=g==="primary"?t.defaultPrimary:t.defaultSecondary??"";f.onclick=()=>{zr(f,async y=>{let v=Jt.find(E=>{if(E.id===t.id)return!1;let Q=this.plugin.settings.bindings[E.id];return!!Q&&(Q.primary===y||Q.secondary===y)});v&&new T.Notice(`Note: ${di(y)} is also bound to "${v.label}". Both will trigger; the first match wins.`,6e3),this.plugin.settings.bindings[t.id][g]=y,f.value=di(y),p(),await this.plugin.saveSettings(),o(),w()})};let m=u.createDiv({cls:"stashpad-binding-slot-btns"}),B=m.createEl("button",{cls:"stashpad-binding-clear",text:"\xD7"});B.title="Clear this slot",B.onclick=async()=>{this.plugin.settings.bindings[t.id][g]="",f.value="",p(),await this.plugin.saveSettings(),o(),w()};let C=m.createEl("button",{cls:"stashpad-binding-revert"});(0,T.setIcon)(C,"rotate-ccw");let w=()=>{let v=i()[g]!==I;C.toggleClass("is-hidden",!v),C.title=I?`Revert to default (${di(I)})`:"Revert to default (no binding)"};return C.onclick=async()=>{this.plugin.settings.bindings[t.id][g]=I,f.value=di(I),p(),await this.plugin.saveSettings(),o(),w()},w(),f};s=h("primary"),n=h("secondary"),r=async g=>{let u=this.plugin.settings.bindings[t.id];u.primary&&u.secondary&&(g==="both"?u.useBoth=!0:(u.useBoth=!1,u.preferRight=g==="right"),await this.plugin.saveSettings(),o())},o=()=>{let g=i(),u=!!(g.primary&&g.secondary),f=g.useBoth?"both":g.preferRight?"right":"left";["left","both","right"].forEach(p=>{c[p].toggleClass("is-active",u&&p===f),c[p].disabled=!u}),l.toggleClass("is-disabled",!u),l.title=u?"Which binding is active \u2014 Left, Both, or Right":"Bind both slots to choose Left / Both / Right"},o()}};var ui=class{constructor(a,e){this.app=a;this.ta=e;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 e=()=>{this.indexBuilt=!1},t=this.app.vault;t.on("create",e),t.on("delete",e),t.on("rename",e),this.vaultListeners.push(()=>t.off("create",e),()=>t.off("delete",e),()=>t.off("rename",e))}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=X().inheritObsidianExclusions,e=a?this.app.vault.getConfig?.("userIgnoreFilters"):void 0;this.fileIndex=this.app.vault.getFiles().filter(i=>!Qr(i.path)&&!vr(i.path)&&!(a&&Fr(i.path,e))).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 t=this.app.metadataCache.getTags?.()??{};this.tagIndex=Object.keys(t).sort((i,s)=>(t[s]||0)-(t[i]||0)),this.indexBuilt=!0}detectTrigger(){let a=this.ta.value,e=this.ta.selectionStart;if(e==null)return null;let t=a.slice(0,e),i=t.match(/\[\[([^\]\[\n]*)$/);if(i){let n=i[1];return{kind:"link",query:n,replaceStart:e-n.length-2,replaceEnd:e}}let s=t.match(/(^|\s)#([A-Za-z0-9_/\-]+)$/);if(s){let n=s[2];return{kind:"tag",query:n,replaceStart:e-n.length-1,replaceEnd:e}}return null}buildItems(a){this.buildIndex();let e=a.query.toLowerCase().trim(),t=e?e.split(/\s+/).filter(Boolean):[],i=s=>{if(!t.length)return!0;for(let n of t)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 Aa.Scope(this.app.scope);a.register([],"Escape",e=>(e.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 e=this.ta.ownerDocument??document;this.popupEl=e.body.createDiv({cls:"stashpad-composer-suggest"}),this.popupEl.tabIndex=-1,this.popupEl.addEventListener("mousedown",t=>t.preventDefault())}let a=this.popupEl;a.empty();for(let e=0;e<this.items.length;e++){let t=this.items[e],i=a.createDiv({cls:"stashpad-composer-suggest-row"});e===this.activeIdx&&i.addClass("is-active"),i.createSpan({cls:"stashpad-composer-suggest-label",text:t.label}),t.subtitle&&i.createSpan({cls:"stashpad-composer-suggest-sub",text:t.subtitle}),i.onmousedown=s=>{s.preventDefault(),this.activeIdx=e,this.commit()}}this.position()}refreshActive(){if(!this.popupEl)return;let a=this.popupEl.children;for(let t=0;t<a.length;t++)a[t].toggleClass("is-active",t===this.activeIdx);let e=a[this.activeIdx];e&&e.scrollIntoView({block:"nearest"})}position(){if(!this.popupEl)return;let a=this.ta.getBoundingClientRect(),e=this.popupEl.offsetHeight||200,t=a.top-e-4,i=a.left;this.popupEl.style.left=`${Math.max(8,i)}px`,this.popupEl.style.top=`${Math.max(8,t)}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 e=this.ta.value.slice(0,this.state.replaceStart),t=this.ta.value.slice(this.state.replaceEnd),i=a.insert;this.ta.value=e+i+t;let s=e.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()}};ae();function ha(d){return/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(d)}var _s=class extends me.ItemView{constructor(e,t){super(e);this.plugin=t;this.displayedPath=null;this.bodyComponent=null;this.unsubscribeSelection=null;this.renderTimer=null;this.renderToken=0;this.expanded=new Set;this.composerAutocomplete=null;this.composerInputEl=null;this.composerDraft="";this.composerDraftForId=null;this.displayedId=null;this.unsubscribeContent=null}getViewType(){return xt}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",e=>{!e||e===this.leaf||e.view?.getViewType?.()===z&&this.scheduleRender()})),this.registerEvent(this.app.vault.on("modify",e=>{this.displayedPath&&e.path===this.displayedPath&&this.scheduleRender()})),this.registerEvent(this.app.vault.on("rename",(e,t)=>{this.displayedPath&&t===this.displayedPath&&(this.displayedPath=e.path,this.scheduleRender())})),this.registerEvent(this.app.metadataCache.on("changed",e=>{this.displayedPath&&e.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 i=this.plugin.lastActiveStashpadLeaf?.view;if(i?.getViewType?.()===z&&i.tree?.get){let s=i.tree.get(this.displayedId);if(s?.file)return{folder:i.noteFolder,id:this.displayedId,file:s.file}}this.displayedId=null}let e=this.plugin.getActiveStashpadSelection();if(e)return this.displayedId=e.id,e;let t=this.plugin.lastActiveStashpadLeaf?.view;if(t?.getViewType?.()===z&&t.tree?.get&&t.focusId){let i=t.tree.get(t.focusId);if(i?.file)return{folder:t.noteFolder,id:t.focusId,file:i.file}}return null}async render(){let e=++this.renderToken,t=this.contentEl,i=!!this.composerInputEl&&document.activeElement===this.composerInputEl,s=this.composerInputEl?.selectionStart??null;this.composerAutocomplete?.detach(),this.composerAutocomplete=null,this.composerInputEl=null,t.empty(),t.addClass("stashpad-detail-root");let n=this.resolveDisplayed();if(!n){this.displayedPath=null;let p=t.createDiv({cls:"stashpad-detail-empty"});(0,me.setIcon)(p.createSpan({cls:"stashpad-detail-empty-icon"}),"panel-right"),p.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 o=n.file;this.displayedPath=o.path;let r=this.app.metadataCache.getFileCache(o)?.frontmatter??{},l=t.createDiv({cls:"stashpad-detail-scroll"}),c=l.createDiv({cls:"stashpad-detail-header"}),A=c.createDiv({cls:"stashpad-detail-titlerow"});A.createDiv({cls:"stashpad-detail-title",text:this.titleFor(o)});let h=A.createEl("button",{cls:"stashpad-detail-open-btn",attr:{"aria-label":"Open in Stashpad tab"}});(0,me.setIcon)(h,"arrow-up-right"),h.title="Open this note in a new Stashpad tab",h.onclick=()=>{this.openInStashpad(n.folder,n.id)};let g=c.createDiv({cls:"stashpad-detail-metarow"});if(n.folder&&g.createSpan({cls:"stashpad-detail-meta-chip",text:n.folder.split("/").pop()||n.folder}),typeof r.color=="string"&&ha(r.color)){let p=g.createSpan({cls:"stashpad-detail-meta-color"});p.style.background=r.color,p.title=r.color}if(r.completed===!0&&g.createSpan({cls:"stashpad-detail-meta-chip is-completed",text:"\u2713 completed"}),typeof r.due=="string"||typeof r.due=="number"){let p=Date.parse(String(r.due)),I=Number.isNaN(p)?String(r.due):We(p,this.plugin.settings);g.createSpan({cls:"stashpad-detail-meta-chip is-due",text:`due ${I}`})}if(Array.isArray(r.tags))for(let p of r.tags.filter(I=>typeof I=="string"))g.createSpan({cls:"stashpad-detail-meta-tag",text:`#${p.replace(/^#/,"")}`});let u=l.createDiv({cls:"stashpad-detail-body"});try{let p=await this.app.vault.cachedRead(o),I=this.stripFrontmatter(p);this.bodyComponent&&(this.removeChild(this.bodyComponent),this.bodyComponent=null);let m=new me.Component;this.addChild(m),this.bodyComponent=m,await me.MarkdownRenderer.render(this.app,I,u,o.path,m)}catch(p){u.createDiv({cls:"stashpad-detail-error",text:`Couldn't read \`${o.path}\`: ${p.message}`})}if(e!==this.renderToken)return;this.renderFooterMeta(l,o,r,n),this.renderChildren(l,n.folder,n.id),this.renderComposer(t,n);let f=this.composerInputEl;if(i&&f&&(f.focus(),s!=null)){let p=Math.min(s,f.value.length);try{f.setSelectionRange(p,p)}catch{}}}renderComposer(e,t){let i=e.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===t.id?s.value=this.composerDraft:(this.composerDraft="",this.composerDraftForId=t.id),s.addEventListener("input",()=>{this.composerDraft=s.value,this.composerDraftForId=t.id}),s.addEventListener("keydown",o=>{if(o.key==="Enter"&&!o.shiftKey&&!o.isComposing){if(this.composerAutocomplete?.isOpen?.())return;o.preventDefault(),this.submitComposer(t)}});let n=i.createEl("button",{cls:"stashpad-detail-composer-send",attr:{"aria-label":"Add child note"}});(0,me.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(t),this.composerAutocomplete=new ui(this.app,s),this.composerAutocomplete.attach()}async submitComposer(e){let t=(this.composerInputEl?.value??"").trim();if(!t)return;let i=this.plugin.lastActiveStashpadLeaf?.view;if(!i||i.getViewType?.()!==z||typeof i.createNoteUnder!="function"){new me.Notice("Open a Stashpad view to add notes.");return}try{await i.createNoteUnder(t,e.id)}catch(s){new me.Notice(`Couldn't add note: ${s.message}`);return}this.composerDraft="",this.composerDraftForId=e.id,this.composerInputEl&&(this.composerInputEl.value=""),await this.render(),setTimeout(()=>this.composerInputEl?.focus(),0)}renderChildren(e,t,i){let s=this.plugin.lastActiveStashpadLeaf?.view;if(!s||s.getViewType?.()!==z)return;let n=s.tree;if(!n?.getChildren)return;let o=n.getChildren(i);if(!o||o.length===0)return;let r=e.createDiv({cls:"stashpad-detail-children"});r.createDiv({cls:"stashpad-detail-children-header",text:`Children (${o.length})`});let l=r.createDiv({cls:"stashpad-detail-children-list"});for(let c of o)c.file&&this.renderDetailChildRow(l,s,n,t,c,0)}renderDetailChildRow(e,t,i,s,n,o,r=new Set){if(!n.file||r.has(n.id))return;let l=this.app.metadataCache.getFileCache(n.file)?.frontmatter??{},c=typeof l.color=="string"&&ha(l.color)?l.color:null,A=l.completed===!0,h=i.getChildren(n.id),g=h.length>0,u=`${s}|${n.id}`,f=this.expanded.has(u),p=e.createDiv({cls:"stashpad-detail-child-row"});A&&p.addClass("is-completed"),o>0&&(p.style.paddingLeft=`${o*16}px`),p.draggable=!0,p.dataset.id=n.id,p.addEventListener("dragstart",w=>{w.dataTransfer?.setData("text/plain",n.id),w.dataTransfer&&(w.dataTransfer.effectAllowed="move"),p.addClass("is-dragging")}),p.addEventListener("dragend",()=>p.removeClass("is-dragging")),p.addEventListener("dragover",w=>{w.preventDefault(),w.dataTransfer&&(w.dataTransfer.dropEffect="move");let y=p.getBoundingClientRect(),v=w.clientY-y.top<y.height/2;p.toggleClass("drop-before",v),p.toggleClass("drop-after",!v)}),p.addEventListener("dragleave",()=>{p.removeClass("drop-before"),p.removeClass("drop-after")}),p.addEventListener("drop",w=>{w.preventDefault(),p.removeClass("drop-before"),p.removeClass("drop-after");let y=w.dataTransfer?.getData("text/plain");if(!y||y===n.id)return;let v=p.getBoundingClientRect(),E=w.clientY-v.top<v.height/2;typeof t.reorderToTarget=="function"&&t.reorderToTarget([y],n.id,E?"before":"after")}),p.oncontextmenu=w=>{w.preventDefault();let y=i.get(n.id);y&&typeof t.openNoteMenu=="function"&&t.openNoteMenu(w,y)};let I=p.createSpan({cls:"stashpad-detail-child-toggle"});if(g&&(Et(I,h.length,f),I.onclick=w=>{w.stopPropagation(),this.expanded.has(u)?this.expanded.delete(u):this.expanded.add(u),this.render()}),Zt(l,"task")||l.task===!0||l.completed!==void 0){let w=p.createSpan({cls:"stashpad-detail-child-checkbox"});(0,me.setIcon)(w,A?"check-square":"square"),w.title=A?"Mark not done":"Mark done",w.addEventListener("mousedown",y=>y.stopPropagation()),w.addEventListener("dblclick",y=>{y.preventDefault(),y.stopPropagation()}),w.onclick=y=>{y.preventDefault(),y.stopPropagation();let v=i.get(n.id);v&&typeof t.toggleCompletedForNode=="function"&&t.toggleCompletedForNode(v)}}let B=p.createSpan({cls:"stashpad-detail-child-icon"});(0,me.setIcon)(B,g?"folder-tree":"file-text"),c&&(B.style.color=c);let C=p.createSpan({cls:"stashpad-detail-child-title",text:this.titleFor(n.file)});if(C.onclick=()=>{t?.navigateTo&&t.navigateTo(n.id)},g&&f){let w=new Set(r).add(n.id);for(let y of h)this.renderDetailChildRow(e,t,i,s,y,o+1,w)}}renderFooterMeta(e,t,i,s){let n=e.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(l=>typeof l=="string").map(l=>this.stripWikiLink(l));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:t.path}),o.push({label:"ID",value:s.id}),o.length===0){n.remove();return}for(let r of o){let l=n.createDiv({cls:"stashpad-detail-meta-line"});l.createSpan({cls:"stashpad-detail-meta-key",text:r.label}),l.createSpan({cls:"stashpad-detail-meta-val",text:r.value})}}titleFor(e){return e.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ")}stripFrontmatter(e){if(!e.startsWith("---"))return e;let t=e.indexOf(` ----`,3);return t<0?e:e.slice(t+4).replace(/^\n+/,"")}stripWikiLink(e){let t=e.match(/^\[\[(.+?)(?:\|(.+))?\]\]$/);return t?t[2]??(t[1].split("/").pop()??t[1]).replace(/\.md$/,""):e}formatTime(e){let t=Date.parse(e);return Number.isFinite(t)?We(t,this.plugin.settings):e}async openInStashpad(e,t){try{let i=await this.plugin.activateViewForFolder(e);t!==S&&this.plugin.navigateLeafTo(i,e,t)}catch(i){new me.Notice(`Couldn't open: ${i.message}`)}}};async function en(d){let a=d.workspace.getLeavesOfType(xt);if(a.length>0){d.workspace.revealLeaf(a[0]);return}let e=d.workspace.getRightLeaf(!1);if(!e){new me.Notice("Stashpad: couldn't open the detail panel.");return}await e.setViewState({type:xt,active:!0}),d.workspace.revealLeaf(e)}var F=require("obsidian");ae();var vt=require("obsidian");ae();function Sc(d,a){let e=d.vault.getAbstractFileByPath(a);if(!(e instanceof vt.TFolder))return[];let t=[],i=[e];for(;i.length;){let s=i.pop();for(let n of s.children)n instanceof vt.TFile?n.extension==="md"&&t.push(n):n instanceof vt.TFolder&&(Er(n.name)||i.push(n))}return t}var tn=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(S,{id:S,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 e=this.currentFolder,t=this.byPath,i=this.nodes;this.nodes=new Map,this.byPath=new Map,this.nodes.set(S,{id:S,parent:null,children:[],file:null,created:""});let s=e?Sc(this.app,e):this.app.vault.getMarkdownFiles();for(let n of s){let o=this.app.metadataCache.getFileCache(n)?.frontmatter,r=o?.id;if(!r){let c=t.get(n.path),A=c?i.get(c):void 0,h=this.synthetic.get(n.path),g=A??h;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===S){let c=this.nodes.get(S);c.file=n,c.created=o?.created??"",this.byPath.set(n.path,S);continue}let l=o?.parent??null;l===r&&(l=null),this.nodes.set(r,{id:r,parent:l??S,children:[],file:n,created:o?.created??""}),this.byPath.set(n.path,r)}for(let n of this.nodes.values()){if(n.id===S)continue;let o=new Set([n.id]),r=n.parent??S;for(;r!==S&&this.nodes.has(r);){if(o.has(r)){n.parent=S;break}o.add(r),r=this.nodes.get(r).parent??S}}for(let n of this.nodes.values()){if(n.id===S)continue;let o=n.parent??S;(this.nodes.get(o)??this.nodes.get(S)).children.push(n.id)}for(let n of this.nodes.values())if(n.children.sort((o,r)=>{let l=this.nodes.get(o),c=this.nodes.get(r);return(l.created||"").localeCompare(c.created||"")}),this.orderProvider){let o=this.orderProvider(n.id);if(o.length>0){let r=new Map;o.forEach((l,c)=>r.set(l,c)),n.children.sort((l,c)=>{let A=r.has(l)?r.get(l):1/0,h=r.has(c)?r.get(c):1/0;return A===h?0:A-h})}}this.emit()}insertSynthetic(a){if(!a.file)return;let e=a.file.path;this.synthetic.set(e,a),this.nodes.set(a.id,a),this.byPath.set(e,a.id);let t=a.parent??S,i=this.nodes.get(t);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(S)}getChildren(a){let e=this.nodes.get(a);return e?e.children.map(t=>this.nodes.get(t)).filter(t=>!!t):[]}fileBackedCount(){let a=0;for(let e of this.nodes.values())e.file&&a++;return a}pathTo(a){let e=[],t=new Set,i=this.nodes.get(a);for(;i&&i.id!==S&&!t.has(i.id);)t.add(i.id),e.unshift(i),i=i.parent?this.nodes.get(i.parent):void 0;return e}idForPath(a){return this.byPath.get(a)}snapshot(){let a={};for(let e of this.nodes.values())e.id===S||!e.file||(a[e.id]={parent:e.parent===S?null:e.parent,path:e.file.path});return a}hookMetadataCache(a){let e=l=>{let c=this.currentFolder;return c?typeof l!="string"?!1:l===c||l.startsWith(c+"/"):!0},t=!1,i=()=>{t=!0,this.coalesceTimer==null&&(this.coalesceTimer=window.setTimeout(()=>{this.coalesceTimer=null,t&&(t=!1,this.emit(),a())},16))},s=l=>{l instanceof vt.TFile&&e(l.path)&&l.extension==="md"&&(this.applyChange(l),i())},n=l=>{l instanceof vt.TFile&&e(l.path)&&l.extension==="md"&&this.applyChange(l)&&i()},o=l=>{let c=l?.path;typeof c=="string"&&e(c)&&this.applyDelete(c)&&i()},r=(l,c)=>{if(!(l instanceof vt.TFile))return;let A=typeof c=="string"?c:null;!e(l.path)&&!e(A)||this.applyRename(l,A??"")&&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(Nt(a.path))return this.byPath.has(a.path)?this.applyDelete(a.path):!1;let e=this.app.metadataCache.getFileCache(a)?.frontmatter,t=e?.id,i=this.byPath.get(a.path);if(!t){if(i){let c=this.nodes.get(i);if(c&&c.file!==a)return c.file=a,!0}return!1}if(this.synthetic.delete(a.path),t===S){let c=this.nodes.get(S),A=e?.created??"",h=!1;return c.file!==a&&(c.file=a,h=!0),c.created!==A&&(c.created=A,h=!0),this.byPath.get(a.path)!==S&&(this.byPath.set(a.path,S),h=!0),h}let s=e?.parent??S;s===t&&(s=S);let n=e?.created??"";if(!(s===S||this.nodes.has(s)))return this.rebuild(),!0;if(i&&i!==t)return this.rebuild(),!0;let r=this.nodes.get(t);if(!r){let c={id:t,parent:s,children:[],file:a,created:n};return this.nodes.set(t,c),this.byPath.set(a.path,t),this.attachToParent(c),this.resortChildrenOf(s),!0}let l=!1;if(r.file!==a&&(r.file=a,l=!0),r.created!==n&&(r.created=n,this.resortChildrenOf(r.parent??S),l=!0),r.parent!==s){let c=r.parent??S;this.detachFromParent(r),r.parent=s,this.attachToParent(r),this.resortChildrenOf(c),this.resortChildrenOf(s),l=!0}return l}applyDelete(a){let e=this.byPath.get(a);if(!e)return!1;let t=this.nodes.get(e);if(!t)return this.byPath.delete(a),this.synthetic.delete(a),!0;this.detachFromParent(t);let i=this.nodes.get(S);for(let s of t.children){let n=this.nodes.get(s);n&&(n.parent=S,i.children.includes(s)||i.children.push(s))}return t.children.length>0&&this.resortChildrenOf(S),this.nodes.delete(e),this.byPath.delete(a),this.synthetic.delete(a),!0}applyRename(a,e){let t=this.currentFolder,i=!t||e===t||e.startsWith(t+"/"),s=!t||a.path===t||a.path.startsWith(t+"/");if(!i&&!s)return!1;if(i&&!s)return this.applyDelete(e);if(!i&&s)return this.applyChange(a);if(Nt(a.path))return this.byPath.has(e)?this.applyDelete(e):!1;let n=this.byPath.get(e);if(!n)return this.applyChange(a);this.byPath.delete(e),this.byPath.set(a.path,n);let o=this.nodes.get(n);return o&&(o.file=a),!0}detachFromParent(a){let e=this.nodes.get(a.parent??S);if(!e)return;let t=e.children.indexOf(a.id);t>=0&&e.children.splice(t,1)}attachToParent(a){let e=this.nodes.get(a.parent??S);e||(e=this.nodes.get(S)),e.children.includes(a.id)||e.children.push(a.id)}resortChildrenOf(a){let e=this.nodes.get(a);if(e&&(e.children.sort((t,i)=>{let s=this.nodes.get(t),n=this.nodes.get(i);return(s.created||"").localeCompare(n.created||"")}),this.orderProvider)){let t=this.orderProvider(a);if(t.length>0){let i=new Map;t.forEach((s,n)=>i.set(s,n)),e.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 Mo=class{constructor(){this.enabled=!1;this.buckets=new Map}record(a,e){if(!this.enabled)return;let t=this.buckets.get(a);t||(t={count:0,total:0,max:0},this.buckets.set(a,t)),t.count+=1,t.total+=e,e>t.max&&(t.max=e)}time(a,e){if(!this.enabled)return e();let t=performance.now();try{return e()}finally{this.record(a,performance.now()-t)}}async timeAsync(a,e){if(!this.enabled)return e();let t=performance.now();try{return await e()}finally{this.record(a,performance.now()-t)}}reset(){this.buckets.clear()}hasData(){return this.buckets.size>0}report(){let a=[...this.buckets.entries()].map(([t,i])=>({label:t,...i,avg:i.total/i.count})).sort((t,i)=>i.total-t.total);if(a.length===0)return"Stashpad perf: no samples (enable profiling, then use the app).";let e=["**Stashpad performance profile**","","| label | count | total (ms) | avg (ms) | max (ms) |","| --- | ---: | ---: | ---: | ---: |"];for(let t of a)e.push(`| \`${t.label}\` | ${t.count} | ${t.total.toFixed(0)} | ${t.avg.toFixed(1)} | ${t.max.toFixed(0)} |`);return e.join(` -`)}},ke=new Mo;var Ft={min:6e4,minute:6e4,m:6e4,h:36e5,hr:36e5,hour:36e5,d:864e5,day:864e5,w:6048e5,wk:6048e5,week:6048e5};function To(d){if(typeof d=="number")return d>0?d:null;if(!d)return null;let a=String(d).trim().toLowerCase().match(/^(\d+(?:\.\d+)?)\s*([a-z]+)?$/);if(!a)return null;let e=parseFloat(a[1]),t=(a[2]||"min").replace(/s$/,""),i=Ft[t];return i&&e>0?e*i:null}var pa=["sunday","monday","tuesday","wednesday","thursday","friday","saturday"];function ga(d,a){let e=new Date(d),t=e.getDate();return e.setMonth(e.getMonth()+a),e.getDate()<t&&e.setDate(0),e.getTime()}function ua(d,a){let e=new Date(d);return e.setFullYear(e.getFullYear()+a),e.getTime()}function bc(d,a){let e=new Date(d);do e.setDate(e.getDate()+1);while(e.getDay()!==a);return e.getTime()}function Dc(d){let a=new Date(d);do a.setDate(a.getDate()+1);while(a.getDay()===0||a.getDay()===6);return a.getTime()}function sn(d){if(!d)return null;let a=String(d).trim().toLowerCase();if(!a)return null;let e="due";/\b(when done|after completion|on completion|from completion)\b/.test(a)&&(e="completion",a=a.replace(/\b(when done|after completion|on completion|from completion)\b/g,"").trim()),a=a.replace(/^every\s+/,"").replace(/\s+/g," ").trim();let t=(n,o)=>({next:n,anchor:e,label:o});if(/^(first|1st) of (the )?month$/.test(a))return t(n=>{let o=new Date(n);return o.setMonth(o.getMonth()+1,1),o.getTime()},"first of the month");let i=pa.indexOf(a.replace(/s$/,""));if(i>=0)return t(n=>bc(n,i),`every ${pa[i]}`);if(a==="weekday"||a==="weekdays"||a==="business day"||a==="business days")return t(Dc,"every weekday");if(a==="daily"||a==="day")return t(n=>n+Ft.day,"every day");if(a==="weekly"||a==="week")return t(n=>n+Ft.week,"every week");if(a==="monthly"||a==="month")return t(n=>ga(n,1),"every month");if(a==="yearly"||a==="annually"||a==="year")return t(n=>ua(n,1),"every year");if(a==="hourly"||a==="hour")return t(n=>n+Ft.h,"every hour");let s=a.match(/^(\d+)\s*([a-z]+)$/);if(s){let n=parseInt(s[1],10),o=s[2].replace(/s$/,"");if(n>0){if(o==="day")return t(r=>r+n*Ft.day,`every ${n} days`);if(o==="week"||o==="wk")return t(r=>r+n*Ft.week,`every ${n} weeks`);if(o==="month"||o==="mo")return t(r=>ga(r,n),`every ${n} months`);if(o==="year"||o==="yr")return t(r=>ua(r,n),`every ${n} years`);if(o==="hour"||o==="hr"||o==="h")return t(r=>r+n*Ft.h,`every ${n} hours`);if(o==="min"||o==="minute"||o==="m")return t(r=>r+n*Ft.min,`every ${n} minutes`)}}return null}function nn(d,a,e){let t=d.anchor==="completion"?e:a??e,i=d.next(t),s=0;for(;i<=e&&s++<5e3;)i=d.next(i);if(i<=e){i=d.next(e);let n=0;for(;i<=e&&n++<5e3;)i=d.next(i)}return i}var fa=".stashpad-order.json",fi=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 e=`${a}/${fa}`,t=this.app.vault.adapter,i={};try{if(await t.exists(e)){let s=await t.read(e),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(l=>typeof l=="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 e=this.pendingTimers.get(a);e!=null&&(window.clearTimeout(e),this.pendingTimers.delete(a)),await this.writeNow(a)}scheduleWrite(a){let e=this.pendingTimers.get(a);e!=null&&window.clearTimeout(e);let t=window.setTimeout(()=>{this.pendingTimers.delete(a),this.writeNow(a)},150);this.pendingTimers.set(a,t)}async writeNow(a){let t=(this.writeInFlight.get(a)??Promise.resolve()).then(()=>this.doWrite(a));this.writeInFlight.set(a,t);try{await t}finally{this.writeInFlight.get(a)===t&&this.writeInFlight.delete(a)}}async doWrite(a){let e=this.cache.get(a)??{},t=`${a}/${fa}`,i=this.app.vault.adapter;try{if(await i.exists(t)){let n=JSON.parse(await i.read(t));if(n&&typeof n=="object"&&!Array.isArray(n))for(let[o,r]of Object.entries(n))!(o in e)&&Array.isArray(r)&&r.every(l=>typeof l=="string")&&(e[o]=r)}}catch{}let s={};for(let[n,o]of Object.entries(e))o.length>0&&(s[n]=o);this.cache.set(a,s);try{if(Object.keys(s).length===0)try{await i.remove(t)}catch{}else await i.write(t,JSON.stringify(s,null,2))}catch(n){console.warn("Stashpad: order save failed",n)}}getOrder(a,e){return this.cache.get(a)?.[e]?.slice()??[]}setOrder(a,e,t){let i=this.cache.get(a)??{};i[e]=t.slice(),this.cache.set(a,i)}appendChild(a,e,t){let i=this.cache.get(a)??{},s=i[e]??[];s.includes(t)||s.push(t),i[e]=s,this.cache.set(a,i)}removeChild(a,e){let t=this.cache.get(a);if(t)for(let i of Object.values(t)){let s=i.indexOf(e);s>=0&&i.splice(s,1)}}invalidate(a){this.cache.delete(a)}};var Ii={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"},Po=["manual","created-asc","created-desc","modified-asc","modified-desc","title-az","title-za"],Ia=new Set(Po),ma=".stashpad-sort.json",on=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 e=`${a}/${ma}`,t=this.app.vault.adapter,i={};try{if(await t.exists(e)){let s=JSON.parse(await t.read(e));if(s&&typeof s=="object"&&!Array.isArray(s))for(let[n,o]of Object.entries(s))typeof o=="string"&&Ia.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 e=this.pendingTimers.get(a);e!=null&&(window.clearTimeout(e),this.pendingTimers.delete(a)),await this.writeNow(a)}scheduleWrite(a){let e=this.pendingTimers.get(a);e!=null&&window.clearTimeout(e);let t=window.setTimeout(()=>{this.pendingTimers.delete(a),this.writeNow(a)},150);this.pendingTimers.set(a,t)}async writeNow(a){let t=(this.writeInFlight.get(a)??Promise.resolve()).then(()=>this.doWrite(a));this.writeInFlight.set(a,t);try{await t}finally{this.writeInFlight.get(a)===t&&this.writeInFlight.delete(a)}}async doWrite(a){let e=this.cache.get(a)??{},t=`${a}/${ma}`,i=this.app.vault.adapter;try{if(await i.exists(t)){let s=JSON.parse(await i.read(t));if(s&&typeof s=="object"&&!Array.isArray(s))for(let[n,o]of Object.entries(s))!(n in e)&&typeof o=="string"&&Ia.has(o)&&(e[n]=o)}}catch{}try{if(Object.keys(e).length===0)try{await i.remove(t)}catch{}else await i.write(t,JSON.stringify(e,null,2))}catch(s){console.warn("Stashpad: sort save failed",s)}}getMode(a,e){return this.cache.get(a)?.[e]??"manual"}setMode(a,e,t){let i=this.cache.get(a)??{};t==="manual"?delete i[e]:i[e]=t,this.cache.set(a,i)}removeParent(a,e){let t=this.cache.get(a);t&&delete t[e]}invalidate(a){this.cache.delete(a)}};ae();var kt="parentLink",mi="children";var ln=class ln{constructor(a,e){this.app=a;this.getTree=e;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 e of this.activityListeners)try{e(a)}catch(t){console.warn("[Stashpad] fmSync activity listener failed",t)}}schedule(a){if(!a||!X().writeRecoveryLinks)return;let e=this.pending.size;this.pending.add(a),this.pending.size!==e&&this.emitActivity(),this.kick()}scheduleParentChange(a,e,t){this.schedule(a),e&&this.schedule(e),this.schedule(t)}scheduleSubtree(a){let e=this.getTree(),t=i=>{this.schedule(i);for(let s of e.getChildren(i))t(s.id)};t(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,e){for(let t of this.errorListeners)try{t(a,e)}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(),ln.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(e){console.warn("[Stashpad] frontmatter sync tick failed",e)}this.pending.size>0&&this.kick()}}wouldWrite(a){let t=this.getTree().get(a);if(!t||!t.file)return!1;let i=this.computeParentLink(t),s=this.computeChildrenLinks(t),n=this.app.metadataCache.getFileCache(t.file)?.frontmatter,o=n&&typeof n[kt]=="string"?n[kt]:null,r=n?.[mi],l=Array.isArray(r)?r.filter(c=>typeof c=="string"):[];if((o??null)!==(i??null)||l.length!==s.length)return!0;for(let c=0;c<l.length;c++)if(l[c]!==s[c])return!0;return!1}async syncOne(a){let t=this.getTree().get(a);if(!t||!t.file||!this.wouldWrite(a))return;let i=this.computeParentLink(t),s=this.computeChildrenLinks(t);try{await ke.timeAsync("write.fmSync",()=>this.app.fileManager.processFrontMatter(t.file,n=>{i?n[kt]=i:delete n[kt],s.length>0?n[mi]=s:delete n[mi]}))}catch(n){console.warn("[Stashpad] frontmatter sync failed",t.file?.path,n),this.emitError(t.file.path,n)}}computeParentLink(a){if(a.id===S)return null;let e=this.getTree();if(!a.parent||a.parent===S){let i=e.getRoot();return i&&i.id!==a.id&&i.file?rn(i.file.path):null}let t=e.get(a.parent);return t?.file?rn(t.file.path):null}computeChildrenLinks(a){return this.getTree().getChildren(a.id).filter(t=>!!t.file).map(t=>rn(t.file.path))}};ln.PACING_MS=100;var an=ln;async function Ci(d,a){let e=a.endsWith("/")?a:a+"/",t=new Map,i=new Map;for(let c of d.vault.getMarkdownFiles()){if(c.path!==a&&!c.path.startsWith(e))continue;let A=d.metadataCache.getFileCache(c)?.frontmatter,h=typeof A?.id=="string"?A.id:null;if(!h)continue;let g=typeof A?.parent=="string"?A.parent:S;t.set(h,{file:c,id:h,parent:g});let u=i.get(g)??[];u.push(h),i.set(g,u)}let s=c=>rn(c.file.path),n=c=>{if(c.id===S)return null;if(c.parent===S||!c.parent){let h=t.get(S);return h?s(h):null}let A=t.get(c.parent);return A?s(A):null},o=c=>{let A=i.get(c.id)??[],h=[];for(let g of A){let u=t.get(g);u&&h.push(s(u))}return h},r=0,l=0;for(let c of t.values()){r+=1;let A=n(c),h=o(c),g=d.metadataCache.getFileCache(c.file)?.frontmatter,u=g&&typeof g[kt]=="string"?g[kt]:null,f=g?.[mi],p=Array.isArray(f)?f.filter(B=>typeof B=="string"):[],I=(u??null)===(A??null),m=p.length===h.length&&p.every((B,C)=>B===h[C]);if(!(I&&m))try{await d.fileManager.processFrontMatter(c.file,B=>{A?B[kt]=A:delete B[kt],h.length>0?B[mi]=h:delete B[mi]}),l+=1,await new Promise(B=>setTimeout(B,50))}catch(B){console.warn("[Stashpad] rebootstrap fm sync failed",c.file.path,B)}}return{checked:r,written:l}}function rn(d){return`[[${d.replace(/\.md$/i,"")}]]`}ri();var cn=class{constructor(a,e){this.tree=a;this.log=e;this.sweepChain=Promise.resolve()}async sweep(a){let e=this.sweepChain.then(()=>this.doSweep(a),()=>this.doSweep(a));return this.sweepChain=e.catch(()=>{}),e}async doSweep(a){let e=await this.log.readState(),t=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(t)){let r=e[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(e))!t[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(e))i(o.path)||(s[n]=o);for(let[n,o]of Object.entries(t))s[n]=o;await this.log.writeState(s)}};var he=require("obsidian");ae();so();var fe=he.moment;function Ho(d){let a=d.trim().toLowerCase();if(!a)return null;let e=Date.now(),t=f=>fe(f).startOf("day").valueOf(),i=/\b(\d{1,2})(?::(\d{2}))?\s*(am|pm)?\b/gi,s=0,n=!1,o=a,r=null;for(let f=i.exec(a);f!=null;f=i.exec(a))if(f[3]||f[2]){r=f;break}if(r){let f=parseInt(r[1],10),p=r[2]?parseInt(r[2],10):0,I=r[3]?.toLowerCase();I==="pm"&&f<12&&(f+=12),I==="am"&&f===12&&(f=0),f>=0&&f<24&&p>=0&&p<60&&(s=(f*3600+p*60)*1e3,n=!0,o=a.replace(r[0]," ").replace(/\s+/g," ").trim())}let l=f=>n?f+s:f;if(o===""||o==="today")return l(t(e));if(o==="yesterday")return l(fe(e).startOf("day").subtract(1,"day").valueOf());if(o==="tomorrow")return l(fe(e).startOf("day").add(1,"day").valueOf());let c=["sunday","monday","tuesday","wednesday","thursday","friday","saturday"],A=["sun","mon","tue","wed","thu","fri","sat"],h=c.indexOf(o)>=0?c.indexOf(o):A.indexOf(o);if(h>=0){let f=fe().startOf("day"),I=(f.day()-h+7)%7;return l(f.subtract(I,"days").valueOf())}let g=/^(\d+)\s*([dwmy])$/.exec(o);if(g){let f=parseInt(g[1],10),p={d:"days",w:"weeks",m:"months",y:"years"}[g[2]];return l(fe().subtract(f,p).startOf("day").valueOf())}let u=fe(o,["YYYY-MM-DD","YYYY/MM/DD","MM-DD-YYYY","MM/DD/YYYY","M-D-YYYY","M/D/YYYY"],!0);return u.isValid()?l(u.startOf("day").valueOf()):null}function Ro(d){let a={text:[],filters:{}},e=(d||"").trim();if(!e)return a;let t=/(?<![\w-])(in|before|after|on):\s*(?:\[([^\]]*)\]|([^]*?)(?=\s+(?:in|before|after|on):|$))/gi,i=e.split(""),s;for(;(s=t.exec(e))!=null;){let n=s[1].toLowerCase(),o=(s[2]!==void 0?s[2]:s[3]??"").trim();if(!o)continue;let r=!1;if(n==="in")a.filters.in=o.toLowerCase(),r=!0;else if(n==="before"){let l=Ho(o);l!=null&&(a.filters.before=l,r=!0)}else if(n==="after"){let l=Ho(o);l!=null&&(a.filters.after=l,r=!0)}else if(n==="on"){let l=Ho(o);if(l!=null)if(r=!0,/\b\d{1,2}:\d{2}\b|\b\d{1,2}\s*(?:am|pm)\b/i.test(o))a.filters.on={start:l-6e4,end:l+6e4};else{let A=fe(l).startOf("day");a.filters.on={start:A.valueOf(),end:A.clone().add(1,"day").valueOf()}}}if(r)for(let l=s.index;l<s.index+s[0].length;l++)i[l]=" "}for(let n of i.join("").split(/\s+/))n&&a.text.push(n.toLowerCase());return a}var je=class d extends he.SuggestModal{constructor(e,t,i,s){super(e);this.tree=t;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 e=this.pendingCleanups.pop();try{e&&e()}catch{}}try{this.opts.onClose?.()}catch{}}loadAll(){let e=this.tree.getRoot(),t=e.file?.parent?.name?.trim()??"",i=t?`Home \u2014 ${t}`:"Home",s=(n,o)=>{let r=this.tree.get(n);r?.file&&n!==S?this.notes.push({node:r,title:`${" ".repeat(o)}${this.titleFn(r)}`,body:""}):r?.file&&n===S&&this.notes.push({node:r,title:i,body:""});for(let l of this.tree.getChildren(n))s(l.id,o+1)};e.file&&this.notes.push({node:e,title:i,body:""});for(let n of this.tree.getChildren(S))s(n.id,1);if(this.opts.lockedNotes)for(let n of this.opts.lockedNotes()){let o=(this.opts.hideLockedTitles??!1)||!n.title;this.notes.push({node:null,title:o?"Locked note":n.title,body:"",locked:n})}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(e){if(e.node?.created){let t=Date.parse(e.node.created);if(!Number.isNaN(t))return t}if(e.locked?.created){let t=Date.parse(e.locked.created);if(!Number.isNaN(t))return t}return e.cross?.file?.stat?.ctime!=null?e.cross.file.stat.ctime:null}stripFm(e){if(!e.startsWith("---"))return e;let t=e.indexOf(` ----`,3);return t===-1?e:e.slice(t+4).replace(/^\r?\n/,"")}getSuggestions(e){let t=e.trim().toLowerCase(),i=Ro(e),s=i.text,n=m=>{if(!s.length)return!0;for(let B of s)if(!m.includes(B))return!1;return!0},o=null,r=null;if(i.filters.in){let m=i.filters.in.split(/\s+/).filter(Boolean);o=new Set,r=new Map;let B=y=>m.every(v=>y.toLowerCase().includes(v)),C=y=>{if(!o.has(y)){o.add(y);for(let v of this.tree.getChildren(y))C(v.id)}};for(let y of this.notes)!y.node||y.cross||B(y.title)&&C(y.node.id);let w=new Map;for(let y of this.notes){if(!y.cross)continue;let v=w.get(y.cross.folder)??[];v.push(y),w.set(y.cross.folder,v)}for(let[y,v]of w){let E=new Map;for(let D of v){let H=D.cross?.parentId??null;if(!H)continue;let G=E.get(H)??[];G.push(D.cross.id),E.set(H,G)}let Q=new Set;r.set(y,Q);let b=D=>{if(!Q.has(D)){Q.add(D);for(let H of E.get(D)??[])b(H)}};for(let D of v)B(D.title)&&b(D.cross.id)}}let l=m=>{let B=i.filters;if(o||r)if(m.cross){let C=r?.get(m.cross.folder);if(!C||!C.has(m.cross.id))return!1}else if(m.node){if(!o||!o.has(m.node.id))return!1}else return!1;if(B.before||B.after||B.on){let C=this.createdMsFor(m);if(C==null||B.before!=null&&C>=B.before||B.after!=null&&C<=B.after||B.on&&(C<B.on.start||C>=B.on.end))return!1}return!0},c=m=>n(m.toLowerCase()),A=this.notes.filter(m=>!m.cross),h=this.notes.filter(m=>m.cross),g=(m,B)=>({id:m.locked?`locked:${m.locked.blob}`:m.cross?`cross:${m.cross.folder}:${m.cross.id}`:m.node.id,label:m.title,node:m.node,kind:"note",bodyPreview:this.previewFromBody(m.body,B),matchLine:B,crossFolder:m.cross?.folder,crossFile:m.cross?.file,crossId:m.cross?.id,locked:m.locked}),u=m=>{let B=[];for(let C of m)if(l(C))if(this.opts.mode==="search"){if(!t){B.push(g(C,-1));continue}let w=n(C.title.toLowerCase()),y=C.body.split(/\r?\n/),v=[];for(let Q=0;Q<y.length;Q++)c(y[Q])&&v.push(Q);let E=v.length>0||n(C.body.toLowerCase());if(!w&&!E)continue;if(v.length===0)B.push(g(C,-1));else{let Q=[],b=-100;for(let H of v)H-b>5&&Q.push(H),b=H;let D=5;for(let H of Q.slice(0,D))B.push(g(C,H))}}else{if(t&&!n(C.title.toLowerCase())&&!n(C.body.toLowerCase()))continue;B.push(g(C,-1))}return B},f=u(A),p=[...f];if(this.opts.mode==="search"?t?!0:f.length<10:!!t){let m=u(h);this.opts.mode==="search"&&!t&&(p.length=Math.min(p.length,50)),p.push(...m)}if(this.opts.folderResults){let m=this.opts.folderResults(),B={id:"__folder_picker__",label:"Open folder in a new tab\u2026",node:null,kind:"folder-open"};m.length>0&&(t?m.some(C=>{let w=C.split("/").pop()??C;return n(`${C.toLowerCase()} ${w.toLowerCase()}`)})&&p.push(B):p.unshift(B))}if(this.opts.allowCreate&&t&&!p.some(m=>m.label.trim().toLowerCase()===t)&&p.push({id:"__create__",label:`Create new: "${e}"`,node:null,kind:"create"}),i.text.join("").length>=3){let m=C=>C.kind==="note"&&(C.id===S||C.crossId===S)&&n(C.label.toLowerCase()),B=p.filter(m);if(B.length>0){let C=p.filter(w=>!m(w));p.splice(0,p.length,...B,...C)}}return this.opts.excludedFolderNotes&&!this.includeExcluded&&p.push({id:"__search_excluded__",label:"Search excluded Stashpad folders",node:null,kind:"search-excluded"}),p}loadExcludedNotes(){if(this.includeExcluded||!this.opts.excludedFolderNotes)return;this.includeExcluded=!0;for(let t of this.opts.excludedFolderNotes())this.notes.push({node:null,title:t.title,body:t.body,cross:t});this.crossFolderIndex=null;for(let t of this.notes)!t.cross||t.body||!t.cross.file||this.app.vault.cachedRead(t.cross.file).then(i=>{t.body=this.stripFm(i)});let e=this.inputEl;e&&(e.dispatchEvent(new Event("input",{bubbles:!0})),setTimeout(()=>e.dispatchEvent(new Event("input",{bubbles:!0})),250))}previewFromBody(e,t){let i=e.split(/\r?\n/);if(t<0)return i.filter(r=>r.trim().length>0).slice(0,3).join(` +\u2022 Discard trash \u2014 let them be permanently erased with the key.`,"Decrypt Trash",I=>{I?f():g()},"Discard trash").open();return}u("",!1)},h=!1;c.setButtonText("Remove\u2026").onClick(async()=>{if(!h){h=!0,c.setDisabled(!0),c.buttonEl.addClass("stashpad-btn-loading");try{await A()}finally{h=!1,c.setDisabled(!1),c.buttonEl.removeClass("stashpad-btn-loading")}}}),c.buttonEl.addClass("mod-warning")}):new T.Setting(i).setName("Remove all encryption").setDesc("Nothing is encrypted in this vault yet. Give a folder a password under \u201CPer-Folder Passwords\u201D below to start.");let l=()=>{new oi(this.app,{title:"Permanently delete the old key material?",body:"This PERMANENTLY deletes the old central keyfile (.stashpad/keys.json), its _keys/ backups, and any retired-keyfile backups \u2014 with NO copy kept and NO way to recover them. It does NOT touch your per-folder passwords or currently-encrypted content (use \u201CRemove all encryption\u201D above for those). Only do this if you're sure you'll never need the old key material back.",phrase:"DELETE KEY MATERIAL",confirmText:"Permanently delete",onConfirm:async()=>{let c=await e.wipeLegacyKeyMaterial();new T.Notice(c>0?`Permanently deleted the old key material (${c} item${c===1?"":"s"}). Not recoverable.`:"No old key material found to delete.",9e3),this.update?.()}}).open()};e.hasLegacyKeyfile()?new T.Setting(i).setName("Retire the old encryption keyfile").setDesc("This vault still has the old central keyfile (.stashpad/keys.json), kept only as a read-only backup now that encryption is per-folder. \u201CRetire\u201D MOVES it and its _keys/ backups into .stashpad/retired-keyfile-<date>/ \u2014 reversible, and a recoverable copy is KEPT (nothing is deleted). \u201CPermanently delete\u201D instead removes all old key material with no backup. Retire is blocked if any folder's key still lives only in the old keyfile.").addButton(c=>c.setButtonText("Retire (keep backup)").onClick(async()=>{try{let A=await e.retireLegacyKeyfile();new T.Notice(`Retired the old keyfile \u2014 ${A} file${A===1?"":"s"} moved into .stashpad/retired-keyfile-\u2026 Reversible; a copy is kept.`,9e3),this.update?.()}catch(A){new T.Notice(A.message,12e3)}})).addButton(c=>{c.setButtonText("Permanently delete\u2026").onClick(l),c.buttonEl.addClass("mod-warning")}):e.hasRecoverableKeyMaterial()&&new T.Setting(i).setName("Delete retired keyfile backups").setDesc("The old keyfile was retired, but a recoverable backup is still on disk (.stashpad/retired-keyfile-\u2026 / _keys/). Permanently delete it if you no longer want it recoverable. Doesn't touch your per-folder passwords or encrypted content.").addButton(c=>{c.setButtonText("Permanently delete\u2026").onClick(l),c.buttonEl.addClass("mod-warning")})},["encryption","encrypt","password","passphrase","lock","unlock","key","security","private","folder","share","keyfile","retire"])),t.push(this.headingDef("Encrypted-note defaults","Global defaults for previously-encrypted notes. Per-folder encryption + trash options live under \u201CPer-Folder Passwords\u201D below.")),t.push(this.renderDef("Remind me about unlocked encrypted notes","On startup, if notes that WERE encrypted are still sitting plaintext (you unlocked them, or restored them from the trash), show a notice with a Review button that opens the \u201CPreviously encrypted\u201D view. Nothing is ever re-encrypted automatically.",i=>i.addToggle(s=>s.setValue(this.plugin.settings.reEncryptNudge??!1).onChange(async n=>{this.plugin.settings.reEncryptNudge=n,await this.plugin.saveSettings()})),["remind","nudge","re-encrypt","watchlist","unlocked","sweep"])),t.push(this.renderDef("Auto re-encrypt after idle minutes (global)","0 = OFF (default). After an unlocked, previously-encrypted note sits idle this long, Stashpad shows a \u201CRe-encrypting in 10s\u2026 [Keep unlocked]\u201D countdown you can cancel, then re-locks it. It NEVER re-encrypts a note you have open in an editor. Set per-folder overrides under \u201CPer-Folder Passwords\u201D; per-note in the \u201CPreviously encrypted\u201D view.",i=>i.addText(s=>s.setValue(String(this.plugin.settings.reEncryptAfterMin??0)).onChange(async n=>{{let o=Number(n.trim());if(n.trim()==="")this.plugin.settings.reEncryptAfterMin=0;else if(Number.isFinite(o)&&o>=0)this.plugin.settings.reEncryptAfterMin=Math.floor(o);else{s.setValue(String(this.plugin.settings.reEncryptAfterMin??0));return}await this.plugin.saveSettings()}})),["auto","re-encrypt","idle","timer","peek","lock"])),t.push(this.headingDef("Archive","Every folder has its own \u201Carchive\u201D subfolder: \u201CMove selection to archive\u201D tucks notes into it, archived notes drop out of search, and everything shows up in the aggregated Archived view. Whether a folder's archive is encrypted is set per folder under \u201CPer-Folder Passwords\u201D below (\u201CEncrypt archived notes\u201D).")),t.push(this.sectionDef("Per-Folder Passwords","Give a folder its own password (a separate key) so you can share just that folder with collaborators. Folders without their own password use the vault password.",i=>{this.renderPerFolderEncryption(i)},["folder","per-folder","password","encrypt","key","share","collaborator","archive","unlock","lock"])),t}hotkeyItems(){let e={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},t=qt.map(i=>({name:i.label,desc:i.desc,aliases:["hotkey","shortcut","keybind","binding","key"],render:s=>this.renderBindingRow(s,i)}));return[e,...t]}renderJdIndexSection(e){let t=new T.Setting(e).setName("JD Index Builder").setHeading();t.settingEl.id="stashpad-jd-index-section";let i=e.createEl("div",{cls:"stashpad-settings-section"}).createEl("p",{cls:"setting-item-description"});i.appendText("Builds a Johnny-Decimal-style index inside a designated Stashpad folder. Two commands:"),i.createEl("br"),i.createEl("strong",{text:"Preview"}),i.appendText(" overwrites the designated folder\u2019s HOME note body with the would-be hierarchy + everything that didn\u2019t match. Frontmatter is preserved; everything below it is replaced."),i.createEl("br"),i.createEl("strong",{text:"Build"}),i.appendText(" creates an actual hierarchy of Stashpad notes (one per prefix), with child\u2192parent relationships matching the dotted segments."),i.createEl("br"),i.appendText("Matches strict prefixes only: all-digits ("),i.createEl("code",{text:"10 Life"}),i.appendText(") or alphanumeric-with-dots ("),i.createEl("code",{text:"1.2 Family"}),i.appendText(", "),i.createEl("code",{text:"animal.duck.yellow Eggs"}),i.appendText("). Mixed schemes sort numbers first, then alphabetically.");let s=this.plugin.discoverStashpadFolders();new T.Setting(e).setName("Scope").setDesc("Scan the whole vault, or restrict to a single folder + its descendants.").addDropdown(l=>{l.addOption("vault","Entire vault"),l.addOption("folder","Single folder"),l.setValue(this.plugin.settings.jdIndexScope??"vault"),l.onChange(async c=>{this.plugin.settings.jdIndexScope=c==="folder"?"folder":"vault",await this.plugin.saveSettings(),this.display()})}),(this.plugin.settings.jdIndexScope??"vault")==="folder"&&new T.Setting(e).setName("Scope folder").setDesc("Vault-relative path. Leave empty to fall back to the entire vault.").addText(l=>{new ci(this.app,l.inputEl),l.setPlaceholder("Path/To/Folder"),l.setValue(this.plugin.settings.jdIndexScopeFolder??""),l.onChange(async c=>{this.plugin.settings.jdIndexScopeFolder=(c||"").trim().replace(/^\/+|\/+$/g,""),await this.plugin.saveSettings()})}),new T.Setting(e).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(l=>{l.setValue(this.plugin.settings.jdIndexIncludeStashpadFolders===!0),l.onChange(async c=>{this.plugin.settings.jdIndexIncludeStashpadFolders=c,await this.plugin.saveSettings(),this.display()})}),new T.Setting(e).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(l=>{new ci(this.app,l.inputEl),l.setPlaceholder(s[0]??"(pick a Stashpad folder)"),l.setValue(this.plugin.settings.jdIndexStashpadFolder??""),l.onChange(async c=>{this.plugin.settings.jdIndexStashpadFolder=(c||"").trim().replace(/^\/+|\/+$/g,""),await this.plugin.saveSettings()})}),new T.Setting(e).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(l=>{l.addOption("natural","Natural (numeric \u2192 alphabetical)"),l.addOption("created","By creation time"),l.setValue(this.plugin.settings.jdIndexSort??"natural"),l.onChange(async c=>{this.plugin.settings.jdIndexSort=c==="created"?"created":"natural",await this.plugin.saveSettings()})});let n=li(this.app,this.plugin,this.plugin.settings),o=e.createEl("div",{cls:"stashpad-settings-section"}).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 T.Setting(e).setName("Actions").setClass("stashpad-jd-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(l=>{l.setButtonText("Preview"),l.setTooltip("Overwrites the designated Stashpad folder's HOME note body with the preview."),l.onClick(async()=>{try{let c=await Ps(this.app,this.plugin,this.plugin.settings);if(c.error==="no-dest"){new T.Notice("Set a Designated Stashpad folder for Index first.",5e3);return}if(c.error==="no-home"){new T.Notice(`"${this.plugin.settings.jdIndexStashpadFolder}" doesn't have a Stashpad home note. Open the folder in Stashpad first (it creates one automatically).`,7e3);return}Hs(this.app,c),this.display()}catch(c){console.error("[stashpad] preview failed",c),new T.Notice(`Preview failed: ${c?.message??c}`,8e3)}})}).addButton(l=>{l.setButtonText("Build Stashpad notes"),l.setCta(),l.setTooltip("Create the Stashpad-note hierarchy. Existing notes with matching jdPrefix are updated."),l.onClick(()=>{if(!(this.plugin.settings.jdIndexStashpadFolder??"").trim().replace(/^\/+|\/+$/g,"")){new T.Notice("Set a Designated Stashpad folder for Index first.",5e3);return}new Wi(this.app,this.plugin,this.plugin.settings,n.indexed.length,async()=>{try{let h=await go(this.app,this.plugin,this.plugin.settings);if(h.error==="no-dest"){new T.Notice("Set a Designated Stashpad folder for Index first.",5e3);return}if(h.error==="dest-not-stashpad"){new T.Notice(`"${h.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 T.Notice(`Built: ${h.created} created, ${h.updated} updated, ${h.skipped} skipped \u2192 ${h.destFolder}`,6e3),this.display()}catch(h){console.error("[stashpad] build failed",h),new T.Notice(`Build failed: ${h?.message??h}`,8e3)}}).open()})}).addButton(l=>{l.setButtonText(`Reveal in ${Dc()}`),l.setTooltip("Open the designated Stashpad folder in your OS file browser."),l.onClick(async()=>{let c=(this.plugin.settings.jdIndexStashpadFolder??"").trim().replace(/^\/+|\/+$/g,"");if(!c){new T.Notice("Set a Designated Stashpad folder for Index first.",5e3);return}if(!this.app.vault.getAbstractFileByPath(c)){new T.Notice(`Folder "${c}" doesn't exist yet.`,5e3);return}try{let h=this.app.vault.adapter.basePath;if(h){let{shell:p}=window.require?.("electron")??{},u=`${h}/${c}`;p?.openPath?.(u)}else new T.Notice("Reveal in file system not supported on this platform.",4e3)}catch(h){new T.Notice(`Couldn't open folder: ${h?.message??h}`,5e3)}})})}renderColorAliasesSection(e){let t=this.plugin.discoverStashpadFolders();if(t.length===0){new T.Setting(e).setName("Color aliases per Stashpad").setDesc("No Stashpads discovered yet \u2014 create one above first.");return}let i=(()=>{let o=pt()?.noteFolder;return o&&t.includes(o)?o:t[0]})();new T.Setting(e).setName("Color aliases per Stashpad").setDesc("Which Stashpad's colors to label.").addDropdown(o=>{for(let r of t)o.addOption(r,r);o.setValue(i),o.onChange(r=>{i=r,n()})}),e.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=e.createDiv({cls:"stashpad-color-aliases-list"}),n=()=>{s.empty();let o=this.plugin.collectColorsInFolder(i),r=new Map(o.map(h=>[h.hex,h.count])),l=this.plugin.settings.colorAliases?.[i.replace(/\/+$/,"")]??{},c=new Set([...r.keys(),...Object.keys(l)]);if(c.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 A=[...c].map(h=>({hex:h,count:r.get(h)??0}));A.sort((h,p)=>p.count-h.count||h.hex.localeCompare(p.hex));for(let h of A)this.renderColorAliasRow(s,i,h.hex,h.count,n)};n()}authorshipItems(){let e=[];e.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 o=>{this.plugin.settings.authorName=o.trim(),this.plugin.settings.authorName&&!this.plugin.settings.authorId&&(this.plugin.settings.authorId=he()),await this.plugin.saveSettings()});let n=()=>void this.plugin.syncAuthorFilesToName();s.inputEl.addEventListener("blur",n),s.inputEl.addEventListener("keydown",o=>{o.key==="Enter"&&n()})}),["author","name","identity","stamp"])),e.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"])),e.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 o=>{this.plugin.settings.authorRole=o.trim(),await this.plugin.saveSettings()});let n=()=>void this.plugin.syncAuthorFilesToName();s.inputEl.addEventListener("blur",n),s.inputEl.addEventListener("keydown",o=>{o.key==="Enter"&&n()})}),["role","title","job"])),e.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 o=>{this.plugin.settings.authorDepartment=o.trim(),await this.plugin.saveSettings()});let n=()=>void this.plugin.syncAuthorFilesToName();s.inputEl.addEventListener("blur",n),s.inputEl.addEventListener("keydown",o=>{o.key==="Enter"&&n()})}),["department","team"]));let t=(i,s,n,o)=>this.renderDef(i,"",r=>r.addToggle(l=>l.setValue(s()).onChange(async c=>{n(c),await this.plugin.saveSettings()})),o);return e.push(t("Show author in note footer",()=>this.plugin.settings.showAuthor,i=>{this.plugin.settings.showAuthor=i},["author","footer","show"])),e.push(t("Show contributors in note footer",()=>this.plugin.settings.showContributors,i=>{this.plugin.settings.showContributors=i},["contributors","footer","show"])),e.push(t("Show last edit time in note footer",()=>this.plugin.settings.showLastEdit,i=>{this.plugin.settings.showLastEdit=i},["last edit","modified","footer","time"])),e.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"])),e.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"])),e}renderAuthoredFolders(e){new T.Setting(e).setName("Folders you've worked in").setHeading();let t=this.plugin.collectAuthoredFolders();if(t.length===0){e.createEl("p",{cls:"setting-item-description",text:"No authored or contributed folders yet."});return}let i=e.createDiv({cls:"stashpad-authored-folders-list"});for(let s of t){let n=i.createDiv({cls:"stashpad-authored-folder-row"}),o=n.createEl("a",{cls:"stashpad-authored-folder-link",text:s.folder});o.onclick=l=>{l.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.",e=>this.renderColorAliasesSection(e),["color","colour","alias","name","swatch","palette","label"]),this.sectionDef("Note Templates","Per-Stashpad note templates \u2014 content stamped into new notes.",e=>this.renderNoteTemplatesSection(e),["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.",e=>this.renderJdIndexSection(e),["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.",e=>this.renderOkfSection(e),["okf","open knowledge format","knowledge","catalog","index","export","bundle","tarball","agent","google"])]}appendCode(e,t){t.split(/`([^`]+)`/g).forEach((i,s)=>{s%2===1?e.createEl("code",{text:i}):i&&e.appendText(i)})}codeDesc(e){let t=document.createDocumentFragment();return this.appendCode(t,e),t}renderOkfSection(e){if(e.createDiv({cls:"stashpad-beta-row"}).createEl("span",{cls:"stashpad-beta-badge",text:"BETA"}),new T.Setting(e).setName("Enable OKF").setDesc(this.codeDesc("Master switch. When on, you choose which folders use OKF by assigning the OKF template to them in Stashpad's own Templates section (the \u{1F4C4} Templates settings here \u2014 NOT Obsidian's core Templates plugin) \u2014 all / some / none, 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 T.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=e.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 Stashpad's \u{1F4C4} Templates section (here in Stashpad's settings \u2014 not Obsidian's core Templates plugin) 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=e.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 T.Setting(e).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 l;try{l=await this.plugin.ensureOkfTemplate()}catch(c){new T.Notice(`Couldn't create the OKF template: ${c.message}`);return}new T.Notice(`OKF template ready at "${l}" \u2014 set a folder's template to that path.`),this.update?.(),this.openSettingsPage("Templates")})}),new T.Setting(e).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 l=await this.plugin.rebuildAllOkf();new T.Notice(l.folders===0?"No folders use the OKF template yet \u2014 assign it in Templates first.":`OKF: updated ${l.written} of ${l.checked} notes across ${l.folders} folder${l.folders===1?"":"s"}.`),this.update?.()}))}let t=new T.Setting(e).setName("Learn about OKF").setDesc("Google's open, vendor-neutral spec for sharing curated knowledge with agents.");t.addButton(i=>i.setButtonText("Spec / repo").onClick(()=>window.open("https://github.com/GoogleCloudPlatform/knowledge-catalog/tree/main/okf"))),t.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(e){let t=()=>new T.Notice(`Open Settings \u2192 Stashpad \u2192 ${e}.`);try{let i=this.app.setting;if(!i?.openTabById){t();return}i.openTabById("stashpad"),window.setTimeout(()=>{let s=i.modalEl?.querySelector(".vertical-tab-content");if(!s){t();return}let o=Array.from(s.querySelectorAll("*")).find(r=>r.childElementCount===0&&r.textContent?.trim()===e&&!r.closest(".vertical-tab-header"))?.closest("[class*='nav'], .setting-item, button, a");o&&!o.closest(".vertical-tab-header")?o.click():t()},60)}catch{t()}}renderAuthorshipSection(e){new T.Setting(e).setName("Authorship").setHeading(),e.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 T.Setting(e).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=he()),await this.plugin.saveSettings(),await this.plugin.syncAuthorFilesToName()})}),new T.Setting(e).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 T.Setting(e).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 T.Setting(e).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 T.Setting(e).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 T.Setting(e).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 T.Setting(e).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 t=this.plugin.collectAuthoredFolders();if(t.length>0){new T.Setting(e).setName("Folders You've Worked In").setHeading();let i=e.createDiv({cls:"stashpad-authored-folders-list"});for(let s of t){let n=i.createDiv({cls:"stashpad-authored-folder-row"}),o=n.createEl("a",{cls:"stashpad-authored-folder-link",text:s.folder});o.onclick=l=>{l.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(e)}renderKnownAuthorsSection(e){new T.Setting(e).setName("Known Authors (registry)").setHeading(),e.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 T.Setting(e).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 T.Notice(`Author registry rebuilt: ${n.total} author(s).`)}catch(n){new T.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 T.Notice(n.created>0?`Restored ${n.created} author page(s).`:"No missing author pages.")}catch(n){new T.Notice(`Restore failed: ${n.message}`)}s.setDisabled(!1).setButtonText("Restore missing pages")}));let t=this.plugin.authorRegistry.all();if(t.length===0){e.createEl("div",{cls:"setting-item-description",text:"No authors recorded yet. Rebuild to scan the vault."});return}let i=e.createDiv({cls:"stashpad-known-authors-list"});for(let s of t){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 l=n.createDiv({cls:"stashpad-known-author-history"}),c=s.renames.map(A=>`${A.from} \u2192 ${A.to}`).join(", ");l.setText(`Renamed: ${c}`)}}}renderNoteTemplatesSection(e){let t=this.plugin.discoverStashpadFolders();if(t.length===0)return;if(new T.Setting(e).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(e.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=e.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 c=r.createDiv({cls:"stashpad-note-template-input-wrap"}),A=c.createEl("input",{type:"text",cls:"stashpad-note-template-input",attr:{placeholder:"path/to/template.md (leave blank to disable)"}});A.value=(this.plugin.settings.noteTemplates??{})[o]??"";let h=c.createDiv({cls:"stashpad-note-template-suggest"});h.setCssStyles({display:"none"});let p=[],u=[],f=-1,g=()=>h.style.display!=="none"&&p.length>0,I=v=>{f=v,u.forEach((F,D)=>F.toggleClass("is-active",D===v)),v>=0&&u[v]&&u[v].scrollIntoView({block:"nearest"})},m=()=>{h.setCssStyles({display:"none"}),f=-1},B=async v=>{A.value=v,await E(),m()},C=r.createDiv({cls:"stashpad-note-template-warn"});C.setCssStyles({display:"none"});let Q=()=>this.app.vault.getMarkdownFiles().map(v=>v.path).filter(v=>!/\/(_imports|_exports|_attachments|\.stashpad)\//.test(v)).sort(),y=()=>{h.empty(),u=[];let v=A.value.trim().toLowerCase().split(/\s+/).filter(Boolean),F=D=>{let R=D.toLowerCase();return v.every(G=>R.includes(G))};if(p=Q().filter(D=>F(D)).slice(0,12),p.length===0){m();return}h.setCssStyles({display:""}),p.forEach((D,R)=>{let G=h.createDiv({cls:"stashpad-note-template-suggest-item",text:D});u.push(G),G.addEventListener("mousemove",()=>I(R)),G.addEventListener("mousedown",async x=>{x.preventDefault(),await B(D)})}),f=f>=0&&f<p.length?f:-1,f>=0&&I(f)},E=async()=>{let v=A.value.trim(),F={...this.plugin.settings.noteTemplates??{}};v?F[o]=v:delete F[o],this.plugin.settings.noteTemplates=F,await this.plugin.saveSettings(),w()},w=()=>{C.empty(),C.setCssStyles({display:"none"});let v=A.value.trim();if(!v)return;let F=this.app.vault.getAbstractFileByPath(v);if(!F||F.extension!=="md"){C.setCssStyles({display:""}),C.setText(`\u26A0 "${v}" is not a markdown file in this vault.`);return}let D=this.app.metadataCache.getFileCache(F)?.frontmatter??{},G=Ve.filter(x=>{let H=D[x];return!(H==null||typeof H=="string"&&H.trim()===""||Array.isArray(H)&&H.length===0)});G.length!==0&&(C.setCssStyles({display:""}),C.setText(`\u26A0 Template defines ${G.join(", ")} \u2014 Stashpad always sets ${G.length===1?"this":"these"} on new notes, so the template value${G.length===1?"":"s"} will be ignored.`))};A.addEventListener("focus",y),A.addEventListener("input",()=>{f=-1,y()}),A.addEventListener("blur",()=>{setTimeout(m,150)}),A.addEventListener("change",()=>{E()}),A.addEventListener("keydown",v=>{if(v.key==="ArrowDown")v.preventDefault(),g()?I((f+1)%p.length):(y(),p.length&&I(0));else if(v.key==="ArrowUp"){if(!g())return;v.preventDefault(),I((f-1+p.length)%p.length)}else if(v.key==="Enter")g()&&f>=0&&(v.preventDefault(),B(p[f]));else if(v.key==="Escape")g()&&(v.preventDefault(),m());else if(v.key==="Tab"&&!v.shiftKey){if(!g())return;let F=p[f>=0?f:0],D=A.value,R;if(F.toLowerCase().startsWith(D.toLowerCase())){let G=F.indexOf("/",D.length);R=G>=0?F.slice(0,G+1):F}else R=F;R&&R!==D&&(v.preventDefault(),A.value=R,f=-1,y(),p.length===1&&I(0))}}),w()};for(let n of t)s(n)}renderColorAliasRow(e,t,i,s,n){let o=e.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 h=this.plugin.settings.customPalette??[];new Lt(this.app,i,h,async p=>{if((p??null)===null&&s===0){await this.plugin.setColorAlias(t,i,""),n();return}if(p&&p.toLowerCase()===i){n();return}let u=await this.plugin.recolorAllInFolder(t,i,p??null);if(u>0)new T.Notice(`Recolored ${u} note${u===1?"":"s"}.`);else if(s===0){let f=this.plugin.getColorAlias(t,i);f&&(await this.plugin.setColorAlias(t,i,""),p&&await this.plugin.setColorAlias(t,p,f))}n()},async p=>{let u=(this.plugin.settings.customPalette??[]).filter(f=>f.toLowerCase()!==p.toLowerCase());return this.plugin.settings.customPalette=u,await this.plugin.saveSettings(),u}).open()};let l=o.createDiv({cls:"stashpad-color-alias-meta"});l.createSpan({cls:"stashpad-color-alias-hex",text:i}),l.createSpan({cls:"stashpad-color-alias-count",text:s===0?"\xB7 unused":`\xB7 ${s} note${s===1?"":"s"}`});let c=o.createEl("input",{type:"text",cls:"stashpad-color-alias-input",attr:{placeholder:"Alias (optional)"}});c.value=this.plugin.getColorAlias(t,i)??"",c.onchange=async()=>{await this.plugin.setColorAlias(t,i,c.value),!c.value.trim()&&s===0&&n()};let A=o.createEl("button",{cls:"stashpad-color-alias-del",text:"\xD7",attr:{title:"Delete alias"}});c.value||A.setCssStyles({visibility:"hidden"}),A.onclick=async()=>{await this.plugin.setColorAlias(t,i,""),s===0?n():(c.value="",A.setCssStyles({visibility:"hidden"}))}}renderFolderScopeRow(e,t){let i=e.createDiv({cls:"stashpad-folder-row"});i.createSpan({cls:"stashpad-folder-row-label",text:t});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(t),l=()=>{let A=r();n.toggleClass("is-right",A),n.setAttribute("aria-checked",String(A)),o.setText(A?"X":"\u2713"),s.setText(A?"Excluded":"Included"),s.toggleClass("is-excluded",A),n.title=A?"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."},c=async()=>{let A=new Set(this.plugin.settings.searchExcludedFolders??[]);A.has(t)?A.delete(t):A.add(t),this.plugin.settings.searchExcludedFolders=[...A].sort(),l(),await this.plugin.saveSettings()};n.onclick=()=>void c(),n.onkeydown=A=>{(A.key===" "||A.key==="Enter")&&(A.preventDefault(),c())},l()}renderFolderPlacementList(e){let t=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=>(t[o.key]??[]).length>0)){e.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=>{t.folderPanelPinned=(t.folderPanelPinned??[]).filter(r=>r!==o),t.folderPanelDownranked=(t.folderPanelDownranked??[]).filter(r=>r!==o),t.folderPanelHidden=(t.folderPanelHidden??[]).filter(r=>r!==o),await this.plugin.saveSettings(),this.update?.()};for(let o of i){let r=[...t[o.key]??[]].sort();if(r.length===0)continue;e.createEl("div",{cls:"stashpad-folder-placement-group",text:`${o.label} (${r.length})`});let l=e.createDiv({cls:"stashpad-folder-list"});for(let c of r){let A=l.createDiv({cls:"stashpad-folder-row"});A.createSpan({cls:"stashpad-folder-row-label",text:c});let h=A.createEl("button",{text:o.action});h.onclick=()=>void n(c)}}}renderBindingRow(e,t){e.setName(t.label).setDesc(t.desc),e.settingEl.addClass("stashpad-binding-row");let i=()=>this.plugin.settings.bindings[t.id],s,n,o=()=>{},r=async p=>{},l=e.controlEl.createDiv({cls:"stashpad-binding-seg",attr:{role:"group","aria-label":"Active binding"}}),c={left:l.createEl("button",{cls:"stashpad-binding-seg-btn",text:"Left"}),both:l.createEl("button",{cls:"stashpad-binding-seg-btn",text:"Both"}),right:l.createEl("button",{cls:"stashpad-binding-seg-btn",text:"Right"})};["left","both","right"].forEach(p=>{c[p].onclick=()=>void r(p)});let A=e.controlEl.createDiv({cls:"stashpad-binding-slots"}),h=p=>{let u=A.createDiv({cls:"stashpad-binding-slot"}),f=u.createEl("input",{type:"text"});f.readOnly=!0,f.placeholder="Click & press a key",f.value=Ai(i()[p]),f.classList.add("stashpad-binding-input");let g=()=>{f.size=Math.max(3,f.value.length||f.placeholder.length)};g();let I=p==="primary"?t.defaultPrimary:t.defaultSecondary??"";f.onclick=()=>{Xr(f,async y=>{let E=qt.find(w=>{if(w.id===t.id)return!1;let v=this.plugin.settings.bindings[w.id];return!!v&&(v.primary===y||v.secondary===y)});E&&new T.Notice(`Note: ${Ai(y)} is also bound to "${E.label}". Both will trigger; the first match wins.`,6e3),this.plugin.settings.bindings[t.id][p]=y,f.value=Ai(y),g(),await this.plugin.saveSettings(),o(),Q()})};let m=u.createDiv({cls:"stashpad-binding-slot-btns"}),B=m.createEl("button",{cls:"stashpad-binding-clear",text:"\xD7"});B.title="Clear this slot",B.onclick=async()=>{this.plugin.settings.bindings[t.id][p]="",f.value="",g(),await this.plugin.saveSettings(),o(),Q()};let C=m.createEl("button",{cls:"stashpad-binding-revert"});(0,T.setIcon)(C,"rotate-ccw");let Q=()=>{let E=i()[p]!==I;C.toggleClass("is-hidden",!E),C.title=I?`Revert to default (${Ai(I)})`:"Revert to default (no binding)"};return C.onclick=async()=>{this.plugin.settings.bindings[t.id][p]=I,f.value=Ai(I),g(),await this.plugin.saveSettings(),o(),Q()},Q(),f};s=h("primary"),n=h("secondary"),r=async p=>{let u=this.plugin.settings.bindings[t.id];u.primary&&u.secondary&&(p==="both"?u.useBoth=!0:(u.useBoth=!1,u.preferRight=p==="right"),await this.plugin.saveSettings(),o())},o=()=>{let p=i(),u=!!(p.primary&&p.secondary),f=p.useBoth?"both":p.preferRight?"right":"left";["left","both","right"].forEach(g=>{c[g].toggleClass("is-active",u&&g===f),c[g].disabled=!u}),l.toggleClass("is-disabled",!u),l.title=u?"Which binding is active \u2014 Left, Both, or Right":"Bind both slots to choose Left / Both / Right"},o()}};var fi=class{constructor(a,e){this.app=a;this.ta=e;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 e=()=>{this.indexBuilt=!1},t=this.app.vault;t.on("create",e),t.on("delete",e),t.on("rename",e),this.vaultListeners.push(()=>t.off("create",e),()=>t.off("delete",e),()=>t.off("rename",e))}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=X().inheritObsidianExclusions,e=a?this.app.vault.getConfig?.("userIgnoreFilters"):void 0;this.fileIndex=this.app.vault.getFiles().filter(i=>!Fr(i.path)&&!kr(i.path)&&!(a&&Sr(i.path,e))).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 t=this.app.metadataCache.getTags?.()??{};this.tagIndex=Object.keys(t).sort((i,s)=>(t[s]||0)-(t[i]||0)),this.indexBuilt=!0}detectTrigger(){let a=this.ta.value,e=this.ta.selectionStart;if(e==null)return null;let t=a.slice(0,e),i=t.match(/\[\[([^\]\[\n]*)$/);if(i){let n=i[1];return{kind:"link",query:n,replaceStart:e-n.length-2,replaceEnd:e}}let s=t.match(/(^|\s)#([A-Za-z0-9_/\-]+)$/);if(s){let n=s[2];return{kind:"tag",query:n,replaceStart:e-n.length-1,replaceEnd:e}}return null}buildItems(a){this.buildIndex();let e=a.query.toLowerCase().trim(),t=e?e.split(/\s+/).filter(Boolean):[],i=s=>{if(!t.length)return!0;for(let n of t)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 ga.Scope(this.app.scope);a.register([],"Escape",e=>(e.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 e=this.ta.ownerDocument??document;this.popupEl=e.body.createDiv({cls:"stashpad-composer-suggest"}),this.popupEl.tabIndex=-1,this.popupEl.addEventListener("mousedown",t=>t.preventDefault())}let a=this.popupEl;a.empty();for(let e=0;e<this.items.length;e++){let t=this.items[e],i=a.createDiv({cls:"stashpad-composer-suggest-row"});e===this.activeIdx&&i.addClass("is-active"),i.createSpan({cls:"stashpad-composer-suggest-label",text:t.label}),t.subtitle&&i.createSpan({cls:"stashpad-composer-suggest-sub",text:t.subtitle}),i.onmousedown=s=>{s.preventDefault(),this.activeIdx=e,this.commit()}}this.position()}refreshActive(){if(!this.popupEl)return;let a=this.popupEl.children;for(let t=0;t<a.length;t++)a[t].toggleClass("is-active",t===this.activeIdx);let e=a[this.activeIdx];e&&e.scrollIntoView({block:"nearest"})}position(){if(!this.popupEl)return;let a=this.ta.getBoundingClientRect(),e=this.popupEl.offsetHeight||200,t=a.top-e-4,i=a.left;this.popupEl.style.left=`${Math.max(8,i)}px`,this.popupEl.style.top=`${Math.max(8,t)}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 e=this.ta.value.slice(0,this.state.replaceStart),t=this.ta.value.slice(this.state.replaceEnd),i=a.insert;this.ta.value=e+i+t;let s=e.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()}};le();function ua(d){return/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(d)}var en=class extends Be.ItemView{constructor(e,t){super(e);this.plugin=t;this.displayedPath=null;this.bodyComponent=null;this.unsubscribeSelection=null;this.renderTimer=null;this.renderToken=0;this.expanded=new Set;this.composerAutocomplete=null;this.composerInputEl=null;this.composerDraft="";this.composerDraftForId=null;this.displayedId=null;this.unsubscribeContent=null}getViewType(){return Nt}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",e=>{!e||e===this.leaf||e.view?.getViewType?.()===z&&this.scheduleRender()})),this.registerEvent(this.app.vault.on("modify",e=>{this.displayedPath&&e.path===this.displayedPath&&this.scheduleRender()})),this.registerEvent(this.app.vault.on("rename",(e,t)=>{this.displayedPath&&t===this.displayedPath&&(this.displayedPath=e.path,this.scheduleRender())})),this.registerEvent(this.app.metadataCache.on("changed",e=>{this.displayedPath&&e.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 i=this.plugin.lastActiveStashpadLeaf?.view;if(i?.getViewType?.()===z&&i.tree?.get){let s=i.tree.get(this.displayedId);if(s?.file)return{folder:i.noteFolder,id:this.displayedId,file:s.file}}this.displayedId=null}let e=this.plugin.getActiveStashpadSelection();if(e)return this.displayedId=e.id,e;let t=this.plugin.lastActiveStashpadLeaf?.view;if(t?.getViewType?.()===z&&t.tree?.get&&t.focusId){let i=t.tree.get(t.focusId);if(i?.file)return{folder:t.noteFolder,id:t.focusId,file:i.file}}return null}async render(){let e=++this.renderToken,t=this.contentEl,i=!!this.composerInputEl&&document.activeElement===this.composerInputEl,s=this.composerInputEl?.selectionStart??null;this.composerAutocomplete?.detach(),this.composerAutocomplete=null,this.composerInputEl=null,t.empty(),t.addClass("stashpad-detail-root");let n=this.resolveDisplayed();if(!n){this.displayedPath=null;let g=t.createDiv({cls:"stashpad-detail-empty"});(0,Be.setIcon)(g.createSpan({cls:"stashpad-detail-empty-icon"}),"panel-right"),g.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 o=n.file;this.displayedPath=o.path;let r=this.app.metadataCache.getFileCache(o)?.frontmatter??{},l=t.createDiv({cls:"stashpad-detail-scroll"}),c=l.createDiv({cls:"stashpad-detail-header"}),A=c.createDiv({cls:"stashpad-detail-titlerow"});A.createDiv({cls:"stashpad-detail-title",text:this.titleFor(o)});let h=A.createEl("button",{cls:"stashpad-detail-open-btn",attr:{"aria-label":"Open in Stashpad tab"}});(0,Be.setIcon)(h,"arrow-up-right"),h.title="Open this note in a new Stashpad tab",h.onclick=()=>{this.openInStashpad(n.folder,n.id)};let p=c.createDiv({cls:"stashpad-detail-metarow"});if(n.folder&&p.createSpan({cls:"stashpad-detail-meta-chip",text:n.folder.split("/").pop()||n.folder}),typeof r.color=="string"&&ua(r.color)){let g=p.createSpan({cls:"stashpad-detail-meta-color"});g.style.background=r.color,g.title=r.color}if(r.completed===!0&&p.createSpan({cls:"stashpad-detail-meta-chip is-completed",text:"\u2713 completed"}),typeof r.due=="string"||typeof r.due=="number"){let g=Date.parse(String(r.due)),I=Number.isNaN(g)?String(r.due):Xe(g,this.plugin.settings);p.createSpan({cls:"stashpad-detail-meta-chip is-due",text:`due ${I}`})}if(Array.isArray(r.tags))for(let g of r.tags.filter(I=>typeof I=="string"))p.createSpan({cls:"stashpad-detail-meta-tag",text:`#${g.replace(/^#/,"")}`});let u=l.createDiv({cls:"stashpad-detail-body"});try{let g=await this.app.vault.cachedRead(o),I=this.stripFrontmatter(g);this.bodyComponent&&(this.removeChild(this.bodyComponent),this.bodyComponent=null);let m=new Be.Component;this.addChild(m),this.bodyComponent=m,await Be.MarkdownRenderer.render(this.app,I,u,o.path,m)}catch(g){u.createDiv({cls:"stashpad-detail-error",text:`Couldn't read \`${o.path}\`: ${g.message}`})}if(e!==this.renderToken)return;this.renderFooterMeta(l,o,r,n),this.renderChildren(l,n.folder,n.id),this.renderComposer(t,n);let f=this.composerInputEl;if(i&&f&&(f.focus(),s!=null)){let g=Math.min(s,f.value.length);try{f.setSelectionRange(g,g)}catch{}}}renderComposer(e,t){let i=e.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===t.id?s.value=this.composerDraft:(this.composerDraft="",this.composerDraftForId=t.id),s.addEventListener("input",()=>{this.composerDraft=s.value,this.composerDraftForId=t.id}),s.addEventListener("keydown",o=>{if(o.key==="Enter"&&!o.shiftKey&&!o.isComposing){if(this.composerAutocomplete?.isOpen?.())return;o.preventDefault(),this.submitComposer(t)}});let n=i.createEl("button",{cls:"stashpad-detail-composer-send",attr:{"aria-label":"Add child note"}});(0,Be.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(t),this.composerAutocomplete=new fi(this.app,s),this.composerAutocomplete.attach()}async submitComposer(e){let t=(this.composerInputEl?.value??"").trim();if(!t)return;let i=this.plugin.lastActiveStashpadLeaf?.view;if(!i||i.getViewType?.()!==z||typeof i.createNoteUnder!="function"){new Be.Notice("Open a Stashpad view to add notes.");return}try{await i.createNoteUnder(t,e.id)}catch(s){new Be.Notice(`Couldn't add note: ${s.message}`);return}this.composerDraft="",this.composerDraftForId=e.id,this.composerInputEl&&(this.composerInputEl.value=""),await this.render(),setTimeout(()=>this.composerInputEl?.focus(),0)}renderChildren(e,t,i){let s=this.plugin.lastActiveStashpadLeaf?.view;if(!s||s.getViewType?.()!==z)return;let n=s.tree;if(!n?.getChildren)return;let o=n.getChildren(i);if(!o||o.length===0)return;let r=e.createDiv({cls:"stashpad-detail-children"});r.createDiv({cls:"stashpad-detail-children-header",text:`Children (${o.length})`});let l=r.createDiv({cls:"stashpad-detail-children-list"});for(let c of o)c.file&&this.renderDetailChildRow(l,s,n,t,c,0)}renderDetailChildRow(e,t,i,s,n,o,r=new Set){if(!n.file||r.has(n.id))return;let l=this.app.metadataCache.getFileCache(n.file)?.frontmatter??{},c=typeof l.color=="string"&&ua(l.color)?l.color:null,A=l.completed===!0,h=i.getChildren(n.id),p=h.length>0,u=`${s}|${n.id}`,f=this.expanded.has(u),g=e.createDiv({cls:"stashpad-detail-child-row"});A&&g.addClass("is-completed"),o>0&&(g.style.paddingLeft=`${o*16}px`),g.draggable=!0,g.dataset.id=n.id,g.addEventListener("dragstart",Q=>{Q.dataTransfer?.setData("text/plain",n.id),Q.dataTransfer&&(Q.dataTransfer.effectAllowed="move"),g.addClass("is-dragging")}),g.addEventListener("dragend",()=>g.removeClass("is-dragging")),g.addEventListener("dragover",Q=>{Q.preventDefault(),Q.dataTransfer&&(Q.dataTransfer.dropEffect="move");let y=g.getBoundingClientRect(),E=Q.clientY-y.top<y.height/2;g.toggleClass("drop-before",E),g.toggleClass("drop-after",!E)}),g.addEventListener("dragleave",()=>{g.removeClass("drop-before"),g.removeClass("drop-after")}),g.addEventListener("drop",Q=>{Q.preventDefault(),g.removeClass("drop-before"),g.removeClass("drop-after");let y=Q.dataTransfer?.getData("text/plain");if(!y||y===n.id)return;let E=g.getBoundingClientRect(),w=Q.clientY-E.top<E.height/2;typeof t.reorderToTarget=="function"&&t.reorderToTarget([y],n.id,w?"before":"after")}),g.oncontextmenu=Q=>{Q.preventDefault();let y=i.get(n.id);y&&typeof t.openNoteMenu=="function"&&t.openNoteMenu(Q,y)};let I=g.createSpan({cls:"stashpad-detail-child-toggle"});if(p&&(Qt(I,h.length,f),I.onclick=Q=>{Q.stopPropagation(),this.expanded.has(u)?this.expanded.delete(u):this.expanded.add(u),this.render()}),jt(l,"task")||l.task===!0||l.completed!==void 0){let Q=g.createSpan({cls:"stashpad-detail-child-checkbox"});(0,Be.setIcon)(Q,A?"check-square":"square"),Q.title=A?"Mark not done":"Mark done",Q.addEventListener("mousedown",y=>y.stopPropagation()),Q.addEventListener("dblclick",y=>{y.preventDefault(),y.stopPropagation()}),Q.onclick=y=>{y.preventDefault(),y.stopPropagation();let E=i.get(n.id);E&&typeof t.toggleCompletedForNode=="function"&&t.toggleCompletedForNode(E)}}let B=g.createSpan({cls:"stashpad-detail-child-icon"});(0,Be.setIcon)(B,p?"folder-tree":"file-text"),c&&(B.style.color=c);let C=g.createSpan({cls:"stashpad-detail-child-title",text:this.titleFor(n.file)});if(C.onclick=()=>{t?.navigateTo&&t.navigateTo(n.id)},p&&f){let Q=new Set(r).add(n.id);for(let y of h)this.renderDetailChildRow(e,t,i,s,y,o+1,Q)}}renderFooterMeta(e,t,i,s){let n=e.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(l=>typeof l=="string").map(l=>this.stripWikiLink(l));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:t.path}),o.push({label:"ID",value:s.id}),o.length===0){n.remove();return}for(let r of o){let l=n.createDiv({cls:"stashpad-detail-meta-line"});l.createSpan({cls:"stashpad-detail-meta-key",text:r.label}),l.createSpan({cls:"stashpad-detail-meta-val",text:r.value})}}titleFor(e){return e.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ")}stripFrontmatter(e){if(!e.startsWith("---"))return e;let t=e.indexOf(` +---`,3);return t<0?e:e.slice(t+4).replace(/^\n+/,"")}stripWikiLink(e){let t=e.match(/^\[\[(.+?)(?:\|(.+))?\]\]$/);return t?t[2]??(t[1].split("/").pop()??t[1]).replace(/\.md$/,""):e}formatTime(e){let t=Date.parse(e);return Number.isFinite(t)?Xe(t,this.plugin.settings):e}async openInStashpad(e,t){try{let i=await this.plugin.activateViewForFolder(e);t!==k&&this.plugin.navigateLeafTo(i,e,t)}catch(i){new Be.Notice(`Couldn't open: ${i.message}`)}}};async function tn(d){let a=d.workspace.getLeavesOfType(Nt);if(a.length>0){d.workspace.revealLeaf(a[0]);return}let e=d.workspace.getRightLeaf(!1);if(!e){new Be.Notice("Stashpad: couldn't open the detail panel.");return}await e.setViewState({type:Nt,active:!0}),d.workspace.revealLeaf(e)}var b=require("obsidian");le();var Ft=require("obsidian");le();function Nc(d,a){let e=d.vault.getAbstractFileByPath(a);if(!(e instanceof Ft.TFolder))return[];let t=[],i=[e];for(;i.length;){let s=i.pop();for(let n of s.children)n instanceof Ft.TFile?n.extension==="md"&&t.push(n):n instanceof Ft.TFolder&&(vr(n.name)||i.push(n))}return t}var sn=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(k,{id:k,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 e=this.currentFolder,t=this.byPath,i=this.nodes;this.nodes=new Map,this.byPath=new Map,this.nodes.set(k,{id:k,parent:null,children:[],file:null,created:""});let s=e?Nc(this.app,e):this.app.vault.getMarkdownFiles();for(let n of s){let o=this.app.metadataCache.getFileCache(n)?.frontmatter,r=o?.id;if(!r){let c=t.get(n.path),A=c?i.get(c):void 0,h=this.synthetic.get(n.path),p=A??h;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===k){let c=this.nodes.get(k);c.file=n,c.created=o?.created??"",this.byPath.set(n.path,k);continue}let l=o?.parent??null;l===r&&(l=null),this.nodes.set(r,{id:r,parent:l??k,children:[],file:n,created:o?.created??""}),this.byPath.set(n.path,r)}for(let n of this.nodes.values()){if(n.id===k)continue;let o=new Set([n.id]),r=n.parent??k;for(;r!==k&&this.nodes.has(r);){if(o.has(r)){n.parent=k;break}o.add(r),r=this.nodes.get(r).parent??k}}for(let n of this.nodes.values()){if(n.id===k)continue;let o=n.parent??k;(this.nodes.get(o)??this.nodes.get(k)).children.push(n.id)}for(let n of this.nodes.values())if(n.children.sort((o,r)=>{let l=this.nodes.get(o),c=this.nodes.get(r);return(l.created||"").localeCompare(c.created||"")}),this.orderProvider){let o=this.orderProvider(n.id);if(o.length>0){let r=new Map;o.forEach((l,c)=>r.set(l,c)),n.children.sort((l,c)=>{let A=r.has(l)?r.get(l):1/0,h=r.has(c)?r.get(c):1/0;return A===h?0:A-h})}}this.emit()}insertSynthetic(a){if(!a.file)return;let e=a.file.path;this.synthetic.set(e,a),this.nodes.set(a.id,a),this.byPath.set(e,a.id);let t=a.parent??k,i=this.nodes.get(t);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(k)}getChildren(a){let e=this.nodes.get(a);return e?e.children.map(t=>this.nodes.get(t)).filter(t=>!!t):[]}fileBackedCount(){let a=0;for(let e of this.nodes.values())e.file&&a++;return a}pathTo(a){let e=[],t=new Set,i=this.nodes.get(a);for(;i&&i.id!==k&&!t.has(i.id);)t.add(i.id),e.unshift(i),i=i.parent?this.nodes.get(i.parent):void 0;return e}idForPath(a){return this.byPath.get(a)}snapshot(){let a={};for(let e of this.nodes.values())e.id===k||!e.file||(a[e.id]={parent:e.parent===k?null:e.parent,path:e.file.path});return a}hookMetadataCache(a){let e=l=>{let c=this.currentFolder;return c?typeof l!="string"?!1:l===c||l.startsWith(c+"/"):!0},t=!1,i=()=>{t=!0,this.coalesceTimer==null&&(this.coalesceTimer=window.setTimeout(()=>{this.coalesceTimer=null,t&&(t=!1,this.emit(),a())},16))},s=l=>{l instanceof Ft.TFile&&e(l.path)&&l.extension==="md"&&(this.applyChange(l),i())},n=l=>{l instanceof Ft.TFile&&e(l.path)&&l.extension==="md"&&this.applyChange(l)&&i()},o=l=>{let c=l?.path;typeof c=="string"&&e(c)&&this.applyDelete(c)&&i()},r=(l,c)=>{if(!(l instanceof Ft.TFile))return;let A=typeof c=="string"?c:null;!e(l.path)&&!e(A)||this.applyRename(l,A??"")&&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(Mt(a.path))return this.byPath.has(a.path)?this.applyDelete(a.path):!1;let e=this.app.metadataCache.getFileCache(a)?.frontmatter,t=e?.id,i=this.byPath.get(a.path);if(!t){if(i){let c=this.nodes.get(i);if(c&&c.file!==a)return c.file=a,!0}return!1}if(this.synthetic.delete(a.path),t===k){let c=this.nodes.get(k),A=e?.created??"",h=!1;return c.file!==a&&(c.file=a,h=!0),c.created!==A&&(c.created=A,h=!0),this.byPath.get(a.path)!==k&&(this.byPath.set(a.path,k),h=!0),h}let s=e?.parent??k;s===t&&(s=k);let n=e?.created??"";if(!(s===k||this.nodes.has(s)))return this.rebuild(),!0;if(i&&i!==t)return this.rebuild(),!0;let r=this.nodes.get(t);if(!r){let c={id:t,parent:s,children:[],file:a,created:n};return this.nodes.set(t,c),this.byPath.set(a.path,t),this.attachToParent(c),this.resortChildrenOf(s),!0}let l=!1;if(r.file!==a&&(r.file=a,l=!0),r.created!==n&&(r.created=n,this.resortChildrenOf(r.parent??k),l=!0),r.parent!==s){let c=r.parent??k;this.detachFromParent(r),r.parent=s,this.attachToParent(r),this.resortChildrenOf(c),this.resortChildrenOf(s),l=!0}return l}applyDelete(a){let e=this.byPath.get(a);if(!e)return!1;let t=this.nodes.get(e);if(!t)return this.byPath.delete(a),this.synthetic.delete(a),!0;this.detachFromParent(t);let i=this.nodes.get(k);for(let s of t.children){let n=this.nodes.get(s);n&&(n.parent=k,i.children.includes(s)||i.children.push(s))}return t.children.length>0&&this.resortChildrenOf(k),this.nodes.delete(e),this.byPath.delete(a),this.synthetic.delete(a),!0}applyRename(a,e){let t=this.currentFolder,i=!t||e===t||e.startsWith(t+"/"),s=!t||a.path===t||a.path.startsWith(t+"/");if(!i&&!s)return!1;if(i&&!s)return this.applyDelete(e);if(!i&&s)return this.applyChange(a);if(Mt(a.path))return this.byPath.has(e)?this.applyDelete(e):!1;let n=this.byPath.get(e);if(!n)return this.applyChange(a);this.byPath.delete(e),this.byPath.set(a.path,n);let o=this.nodes.get(n);return o&&(o.file=a),!0}detachFromParent(a){let e=this.nodes.get(a.parent??k);if(!e)return;let t=e.children.indexOf(a.id);t>=0&&e.children.splice(t,1)}attachToParent(a){let e=this.nodes.get(a.parent??k);e||(e=this.nodes.get(k)),e.children.includes(a.id)||e.children.push(a.id)}resortChildrenOf(a){let e=this.nodes.get(a);if(e&&(e.children.sort((t,i)=>{let s=this.nodes.get(t),n=this.nodes.get(i);return(s.created||"").localeCompare(n.created||"")}),this.orderProvider)){let t=this.orderProvider(a);if(t.length>0){let i=new Map;t.forEach((s,n)=>i.set(s,n)),e.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 Ho=class{constructor(){this.enabled=!1;this.buckets=new Map}record(a,e){if(!this.enabled)return;let t=this.buckets.get(a);t||(t={count:0,total:0,max:0},this.buckets.set(a,t)),t.count+=1,t.total+=e,e>t.max&&(t.max=e)}time(a,e){if(!this.enabled)return e();let t=performance.now();try{return e()}finally{this.record(a,performance.now()-t)}}async timeAsync(a,e){if(!this.enabled)return e();let t=performance.now();try{return await e()}finally{this.record(a,performance.now()-t)}}reset(){this.buckets.clear()}hasData(){return this.buckets.size>0}report(){let a=[...this.buckets.entries()].map(([t,i])=>({label:t,...i,avg:i.total/i.count})).sort((t,i)=>i.total-t.total);if(a.length===0)return"Stashpad perf: no samples (enable profiling, then use the app).";let e=["**Stashpad performance profile**","","| label | count | total (ms) | avg (ms) | max (ms) |","| --- | ---: | ---: | ---: | ---: |"];for(let t of a)e.push(`| \`${t.label}\` | ${t.count} | ${t.total.toFixed(0)} | ${t.avg.toFixed(1)} | ${t.max.toFixed(0)} |`);return e.join(` +`)}},ke=new Ho;var kt={min:6e4,minute:6e4,m:6e4,h:36e5,hr:36e5,hour:36e5,d:864e5,day:864e5,w:6048e5,wk:6048e5,week:6048e5};function Ro(d){if(typeof d=="number")return d>0?d:null;if(!d)return null;let a=String(d).trim().toLowerCase().match(/^(\d+(?:\.\d+)?)\s*([a-z]+)?$/);if(!a)return null;let e=parseFloat(a[1]),t=(a[2]||"min").replace(/s$/,""),i=kt[t];return i&&e>0?e*i:null}var fa=["sunday","monday","tuesday","wednesday","thursday","friday","saturday"];function Ia(d,a){let e=new Date(d),t=e.getDate();return e.setMonth(e.getMonth()+a),e.getDate()<t&&e.setDate(0),e.getTime()}function ma(d,a){let e=new Date(d);return e.setFullYear(e.getFullYear()+a),e.getTime()}function Mc(d,a){let e=new Date(d);do e.setDate(e.getDate()+1);while(e.getDay()!==a);return e.getTime()}function Tc(d){let a=new Date(d);do a.setDate(a.getDate()+1);while(a.getDay()===0||a.getDay()===6);return a.getTime()}function nn(d){if(!d)return null;let a=String(d).trim().toLowerCase();if(!a)return null;let e="due";/\b(when done|after completion|on completion|from completion)\b/.test(a)&&(e="completion",a=a.replace(/\b(when done|after completion|on completion|from completion)\b/g,"").trim()),a=a.replace(/^every\s+/,"").replace(/\s+/g," ").trim();let t=(n,o)=>({next:n,anchor:e,label:o});if(/^(first|1st) of (the )?month$/.test(a))return t(n=>{let o=new Date(n);return o.setMonth(o.getMonth()+1,1),o.getTime()},"first of the month");let i=fa.indexOf(a.replace(/s$/,""));if(i>=0)return t(n=>Mc(n,i),`every ${fa[i]}`);if(a==="weekday"||a==="weekdays"||a==="business day"||a==="business days")return t(Tc,"every weekday");if(a==="daily"||a==="day")return t(n=>n+kt.day,"every day");if(a==="weekly"||a==="week")return t(n=>n+kt.week,"every week");if(a==="monthly"||a==="month")return t(n=>Ia(n,1),"every month");if(a==="yearly"||a==="annually"||a==="year")return t(n=>ma(n,1),"every year");if(a==="hourly"||a==="hour")return t(n=>n+kt.h,"every hour");let s=a.match(/^(\d+)\s*([a-z]+)$/);if(s){let n=parseInt(s[1],10),o=s[2].replace(/s$/,"");if(n>0){if(o==="day")return t(r=>r+n*kt.day,`every ${n} days`);if(o==="week"||o==="wk")return t(r=>r+n*kt.week,`every ${n} weeks`);if(o==="month"||o==="mo")return t(r=>Ia(r,n),`every ${n} months`);if(o==="year"||o==="yr")return t(r=>ma(r,n),`every ${n} years`);if(o==="hour"||o==="hr"||o==="h")return t(r=>r+n*kt.h,`every ${n} hours`);if(o==="min"||o==="minute"||o==="m")return t(r=>r+n*kt.min,`every ${n} minutes`)}}return null}function on(d,a,e){let t=d.anchor==="completion"?e:a??e,i=d.next(t),s=0;for(;i<=e&&s++<5e3;)i=d.next(i);if(i<=e){i=d.next(e);let n=0;for(;i<=e&&n++<5e3;)i=d.next(i)}return i}var Ca=".stashpad-order.json",Ii=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 e=`${a}/${Ca}`,t=this.app.vault.adapter,i={};try{if(await t.exists(e)){let s=await t.read(e),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(l=>typeof l=="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 e=this.pendingTimers.get(a);e!=null&&(window.clearTimeout(e),this.pendingTimers.delete(a)),await this.writeNow(a)}scheduleWrite(a){let e=this.pendingTimers.get(a);e!=null&&window.clearTimeout(e);let t=window.setTimeout(()=>{this.pendingTimers.delete(a),this.writeNow(a)},150);this.pendingTimers.set(a,t)}async writeNow(a){let t=(this.writeInFlight.get(a)??Promise.resolve()).then(()=>this.doWrite(a));this.writeInFlight.set(a,t);try{await t}finally{this.writeInFlight.get(a)===t&&this.writeInFlight.delete(a)}}async doWrite(a){let e=this.cache.get(a)??{},t=`${a}/${Ca}`,i=this.app.vault.adapter;try{if(await i.exists(t)){let n=JSON.parse(await i.read(t));if(n&&typeof n=="object"&&!Array.isArray(n))for(let[o,r]of Object.entries(n))!(o in e)&&Array.isArray(r)&&r.every(l=>typeof l=="string")&&(e[o]=r)}}catch{}let s={};for(let[n,o]of Object.entries(e))o.length>0&&(s[n]=o);this.cache.set(a,s);try{if(Object.keys(s).length===0)try{await i.remove(t)}catch{}else await i.write(t,JSON.stringify(s,null,2))}catch(n){console.warn("Stashpad: order save failed",n)}}getOrder(a,e){return this.cache.get(a)?.[e]?.slice()??[]}setOrder(a,e,t){let i=this.cache.get(a)??{};i[e]=t.slice(),this.cache.set(a,i)}appendChild(a,e,t){let i=this.cache.get(a)??{},s=i[e]??[];s.includes(t)||s.push(t),i[e]=s,this.cache.set(a,i)}removeChild(a,e){let t=this.cache.get(a);if(t)for(let i of Object.values(t)){let s=i.indexOf(e);s>=0&&i.splice(s,1)}}invalidate(a){this.cache.delete(a)}};var mi={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"},Uo=["manual","created-asc","created-desc","modified-asc","modified-desc","title-az","title-za"],Ba=new Set(Uo),ya=".stashpad-sort.json",rn=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 e=`${a}/${ya}`,t=this.app.vault.adapter,i={};try{if(await t.exists(e)){let s=JSON.parse(await t.read(e));if(s&&typeof s=="object"&&!Array.isArray(s))for(let[n,o]of Object.entries(s))typeof o=="string"&&Ba.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 e=this.pendingTimers.get(a);e!=null&&(window.clearTimeout(e),this.pendingTimers.delete(a)),await this.writeNow(a)}scheduleWrite(a){let e=this.pendingTimers.get(a);e!=null&&window.clearTimeout(e);let t=window.setTimeout(()=>{this.pendingTimers.delete(a),this.writeNow(a)},150);this.pendingTimers.set(a,t)}async writeNow(a){let t=(this.writeInFlight.get(a)??Promise.resolve()).then(()=>this.doWrite(a));this.writeInFlight.set(a,t);try{await t}finally{this.writeInFlight.get(a)===t&&this.writeInFlight.delete(a)}}async doWrite(a){let e=this.cache.get(a)??{},t=`${a}/${ya}`,i=this.app.vault.adapter;try{if(await i.exists(t)){let s=JSON.parse(await i.read(t));if(s&&typeof s=="object"&&!Array.isArray(s))for(let[n,o]of Object.entries(s))!(n in e)&&typeof o=="string"&&Ba.has(o)&&(e[n]=o)}}catch{}try{if(Object.keys(e).length===0)try{await i.remove(t)}catch{}else await i.write(t,JSON.stringify(e,null,2))}catch(s){console.warn("Stashpad: sort save failed",s)}}getMode(a,e){return this.cache.get(a)?.[e]??"manual"}setMode(a,e,t){let i=this.cache.get(a)??{};t==="manual"?delete i[e]:i[e]=t,this.cache.set(a,i)}removeParent(a,e){let t=this.cache.get(a);t&&delete t[e]}invalidate(a){this.cache.delete(a)}};le();var St="parentLink",Ci="children";var cn=class cn{constructor(a,e){this.app=a;this.getTree=e;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 e of this.activityListeners)try{e(a)}catch(t){console.warn("[Stashpad] fmSync activity listener failed",t)}}schedule(a){if(!a||!X().writeRecoveryLinks)return;let e=this.pending.size;this.pending.add(a),this.pending.size!==e&&this.emitActivity(),this.kick()}scheduleParentChange(a,e,t){this.schedule(a),e&&this.schedule(e),this.schedule(t)}scheduleSubtree(a){let e=this.getTree(),t=i=>{this.schedule(i);for(let s of e.getChildren(i))t(s.id)};t(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,e){for(let t of this.errorListeners)try{t(a,e)}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(),cn.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(e){console.warn("[Stashpad] frontmatter sync tick failed",e)}this.pending.size>0&&this.kick()}}wouldWrite(a){let t=this.getTree().get(a);if(!t||!t.file)return!1;let i=this.computeParentLink(t),s=this.computeChildrenLinks(t),n=this.app.metadataCache.getFileCache(t.file)?.frontmatter,o=n&&typeof n[St]=="string"?n[St]:null,r=n?.[Ci],l=Array.isArray(r)?r.filter(c=>typeof c=="string"):[];if((o??null)!==(i??null)||l.length!==s.length)return!0;for(let c=0;c<l.length;c++)if(l[c]!==s[c])return!0;return!1}async syncOne(a){let t=this.getTree().get(a);if(!t||!t.file||!this.wouldWrite(a))return;let i=this.computeParentLink(t),s=this.computeChildrenLinks(t);try{await ke.timeAsync("write.fmSync",()=>this.app.fileManager.processFrontMatter(t.file,n=>{i?n[St]=i:delete n[St],s.length>0?n[Ci]=s:delete n[Ci]}))}catch(n){console.warn("[Stashpad] frontmatter sync failed",t.file?.path,n),this.emitError(t.file.path,n)}}computeParentLink(a){if(a.id===k)return null;let e=this.getTree();if(!a.parent||a.parent===k){let i=e.getRoot();return i&&i.id!==a.id&&i.file?an(i.file.path):null}let t=e.get(a.parent);return t?.file?an(t.file.path):null}computeChildrenLinks(a){return this.getTree().getChildren(a.id).filter(t=>!!t.file).map(t=>an(t.file.path))}};cn.PACING_MS=100;var ln=cn;async function Bi(d,a){let e=a.endsWith("/")?a:a+"/",t=new Map,i=new Map;for(let c of d.vault.getMarkdownFiles()){if(c.path!==a&&!c.path.startsWith(e))continue;let A=d.metadataCache.getFileCache(c)?.frontmatter,h=typeof A?.id=="string"?A.id:null;if(!h)continue;let p=typeof A?.parent=="string"?A.parent:k;t.set(h,{file:c,id:h,parent:p});let u=i.get(p)??[];u.push(h),i.set(p,u)}let s=c=>an(c.file.path),n=c=>{if(c.id===k)return null;if(c.parent===k||!c.parent){let h=t.get(k);return h?s(h):null}let A=t.get(c.parent);return A?s(A):null},o=c=>{let A=i.get(c.id)??[],h=[];for(let p of A){let u=t.get(p);u&&h.push(s(u))}return h},r=0,l=0;for(let c of t.values()){r+=1;let A=n(c),h=o(c),p=d.metadataCache.getFileCache(c.file)?.frontmatter,u=p&&typeof p[St]=="string"?p[St]:null,f=p?.[Ci],g=Array.isArray(f)?f.filter(B=>typeof B=="string"):[],I=(u??null)===(A??null),m=g.length===h.length&&g.every((B,C)=>B===h[C]);if(!(I&&m))try{await d.fileManager.processFrontMatter(c.file,B=>{A?B[St]=A:delete B[St],h.length>0?B[Ci]=h:delete B[Ci]}),l+=1,await new Promise(B=>setTimeout(B,50))}catch(B){console.warn("[Stashpad] rebootstrap fm sync failed",c.file.path,B)}}return{checked:r,written:l}}function an(d){return`[[${d.replace(/\.md$/i,"")}]]`}ai();var dn=class{constructor(a,e){this.tree=a;this.log=e;this.sweepChain=Promise.resolve()}async sweep(a){let e=this.sweepChain.then(()=>this.doSweep(a),()=>this.doSweep(a));return this.sweepChain=e.catch(()=>{}),e}async doSweep(a){let e=await this.log.readState(),t=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(t)){let r=e[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(e))!t[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(e))i(o.path)||(s[n]=o);for(let[n,o]of Object.entries(t))s[n]=o;await this.log.writeState(s)}};var pe=require("obsidian");le();ro();var Ie=pe.moment;function Go(d){let a=d.trim().toLowerCase();if(!a)return null;let e=Date.now(),t=f=>Ie(f).startOf("day").valueOf(),i=/\b(\d{1,2})(?::(\d{2}))?\s*(am|pm)?\b/gi,s=0,n=!1,o=a,r=null;for(let f=i.exec(a);f!=null;f=i.exec(a))if(f[3]||f[2]){r=f;break}if(r){let f=parseInt(r[1],10),g=r[2]?parseInt(r[2],10):0,I=r[3]?.toLowerCase();I==="pm"&&f<12&&(f+=12),I==="am"&&f===12&&(f=0),f>=0&&f<24&&g>=0&&g<60&&(s=(f*3600+g*60)*1e3,n=!0,o=a.replace(r[0]," ").replace(/\s+/g," ").trim())}let l=f=>n?f+s:f;if(o===""||o==="today")return l(t(e));if(o==="yesterday")return l(Ie(e).startOf("day").subtract(1,"day").valueOf());if(o==="tomorrow")return l(Ie(e).startOf("day").add(1,"day").valueOf());let c=["sunday","monday","tuesday","wednesday","thursday","friday","saturday"],A=["sun","mon","tue","wed","thu","fri","sat"],h=c.indexOf(o)>=0?c.indexOf(o):A.indexOf(o);if(h>=0){let f=Ie().startOf("day"),I=(f.day()-h+7)%7;return l(f.subtract(I,"days").valueOf())}let p=/^(\d+)\s*([dwmy])$/.exec(o);if(p){let f=parseInt(p[1],10),g={d:"days",w:"weeks",m:"months",y:"years"}[p[2]];return l(Ie().subtract(f,g).startOf("day").valueOf())}let u=Ie(o,["YYYY-MM-DD","YYYY/MM/DD","MM-DD-YYYY","MM/DD/YYYY","M-D-YYYY","M/D/YYYY"],!0);return u.isValid()?l(u.startOf("day").valueOf()):null}function Lo(d){let a={text:[],filters:{}},e=(d||"").trim();if(!e)return a;let t=/(?<![\w-])(in|before|after|on):\s*(?:\[([^\]]*)\]|([^]*?)(?=\s+(?:in|before|after|on):|$))/gi,i=e.split(""),s;for(;(s=t.exec(e))!=null;){let n=s[1].toLowerCase(),o=(s[2]!==void 0?s[2]:s[3]??"").trim();if(!o)continue;let r=!1;if(n==="in")a.filters.in=o.toLowerCase(),r=!0;else if(n==="before"){let l=Go(o);l!=null&&(a.filters.before=l,r=!0)}else if(n==="after"){let l=Go(o);l!=null&&(a.filters.after=l,r=!0)}else if(n==="on"){let l=Go(o);if(l!=null)if(r=!0,/\b\d{1,2}:\d{2}\b|\b\d{1,2}\s*(?:am|pm)\b/i.test(o))a.filters.on={start:l-6e4,end:l+6e4};else{let A=Ie(l).startOf("day");a.filters.on={start:A.valueOf(),end:A.clone().add(1,"day").valueOf()}}}if(r)for(let l=s.index;l<s.index+s[0].length;l++)i[l]=" "}for(let n of i.join("").split(/\s+/))n&&a.text.push(n.toLowerCase());return a}var _e=class d extends pe.SuggestModal{constructor(e,t,i,s){super(e);this.tree=t;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 e=this.pendingCleanups.pop();try{e&&e()}catch{}}try{this.opts.onClose?.()}catch{}}loadAll(){let e=this.tree.getRoot(),t=e.file?.parent?.name?.trim()??"",i=t?`Home \u2014 ${t}`:"Home",s=(n,o)=>{let r=this.tree.get(n);r?.file&&n!==k?this.notes.push({node:r,title:`${" ".repeat(o)}${this.titleFn(r)}`,body:""}):r?.file&&n===k&&this.notes.push({node:r,title:i,body:""});for(let l of this.tree.getChildren(n))s(l.id,o+1)};e.file&&this.notes.push({node:e,title:i,body:""});for(let n of this.tree.getChildren(k))s(n.id,1);if(this.opts.lockedNotes)for(let n of this.opts.lockedNotes()){let o=(this.opts.hideLockedTitles??!1)||!n.title;this.notes.push({node:null,title:o?"Locked note":n.title,body:"",locked:n})}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(e){if(e.node?.created){let t=Date.parse(e.node.created);if(!Number.isNaN(t))return t}if(e.locked?.created){let t=Date.parse(e.locked.created);if(!Number.isNaN(t))return t}return e.cross?.file?.stat?.ctime!=null?e.cross.file.stat.ctime:null}stripFm(e){if(!e.startsWith("---"))return e;let t=e.indexOf(` +---`,3);return t===-1?e:e.slice(t+4).replace(/^\r?\n/,"")}getSuggestions(e){let t=e.trim().toLowerCase(),i=Lo(e),s=i.text,n=y=>{if(!s.length)return!0;for(let E of s)if(!y.includes(E))return!1;return!0},o=null,r=null;if(i.filters.in){let y=i.filters.in.split(/\s+/).filter(Boolean);o=new Set,r=new Map;let E=F=>y.every(D=>F.toLowerCase().includes(D)),w=F=>{if(!o.has(F)){o.add(F);for(let D of this.tree.getChildren(F))w(D.id)}};for(let F of this.notes)!F.node||F.cross||E(F.title)&&w(F.node.id);let v=new Map;for(let F of this.notes){if(!F.cross)continue;let D=v.get(F.cross.folder)??[];D.push(F),v.set(F.cross.folder,D)}for(let[F,D]of v){let R=new Map;for(let H of D){let U=H.cross?.parentId??null;if(!U)continue;let N=R.get(U)??[];N.push(H.cross.id),R.set(U,N)}let G=new Set;r.set(F,G);let x=H=>{if(!G.has(H)){G.add(H);for(let U of R.get(H)??[])x(U)}};for(let H of D)E(H.title)&&x(H.cross.id)}}let l=y=>{let E=i.filters;if(o||r)if(y.cross){let w=r?.get(y.cross.folder);if(!w||!w.has(y.cross.id))return!1}else if(y.node){if(!o||!o.has(y.node.id))return!1}else return!1;if(E.before||E.after||E.on){let w=this.createdMsFor(y);if(w==null||E.before!=null&&w>=E.before||E.after!=null&&w<=E.after||E.on&&(w<E.on.start||w>=E.on.end))return!1}return!0},c=y=>n(y.toLowerCase()),A=this.notes.filter(y=>!y.cross),h=this.notes.filter(y=>y.cross),p=(y,E)=>({id:y.locked?`locked:${y.locked.blob}`:y.cross?`cross:${y.cross.folder}:${y.cross.id}`:y.node.id,label:y.title,node:y.node,kind:"note",bodyPreview:this.previewFromBody(y.body,E),matchLine:E,crossFolder:y.cross?.folder,crossFile:y.cross?.file,crossId:y.cross?.id,locked:y.locked}),u=y=>y.node?.file?.stat?.mtime??y.cross?.file?.stat?.mtime??0,f=y=>y.node?.id===k||y.cross?.id===k,g=this.opts.mode==="pick",I=y=>{let E;if(!t)E=0;else{let w=y.title.toLowerCase(),v=y.body.toLowerCase();w===t?E=6:w.startsWith(t)?E=5:w.includes(t)?E=4:s.every(F=>w.includes(F))?E=3:v.includes(t)?E=2:E=1}return g&&f(y)&&(E+=.5),E},m=y=>{let E=[];for(let F of y)if(l(F))if(this.opts.mode==="search"){if(!t){E.push({n:F,matchLines:[]});continue}let D=n(F.title.toLowerCase()),R=F.body.split(/\r?\n/),G=[];for(let H=0;H<R.length;H++)c(R[H])&&G.push(H);let x=G.length>0||n(F.body.toLowerCase());if(!D&&!x)continue;E.push({n:F,matchLines:G})}else{if(t&&!n(F.title.toLowerCase())&&!n(F.body.toLowerCase()))continue;E.push({n:F,matchLines:[]})}let w=E.map(F=>({...F,band:I(F.n),mtime:u(F.n)}));w.sort((F,D)=>D.band-F.band||D.mtime-F.mtime);let v=[];for(let{n:F,matchLines:D}of w)if(this.opts.mode==="search"&&t&&D.length>0){let R=[],G=-100;for(let H of D)H-G>5&&R.push(H),G=H;let x=5;for(let H of R.slice(0,x))v.push(p(F,H))}else v.push(p(F,-1));return v},B=m(A),C=[...B];if(this.opts.mode==="search"?t?!0:B.length<10:!!t){let y=m(h);this.opts.mode==="search"&&!t&&(C.length=Math.min(C.length,50)),C.push(...y)}if(this.opts.folderResults){let y=this.opts.folderResults(),E={id:"__folder_picker__",label:"Open folder in a new tab\u2026",node:null,kind:"folder-open"};y.length>0&&(t?y.some(w=>{let v=w.split("/").pop()??w;return n(`${w.toLowerCase()} ${v.toLowerCase()}`)})&&C.push(E):C.unshift(E))}if(this.opts.allowCreate&&t&&!C.some(y=>y.label.trim().toLowerCase()===t)&&C.push({id:"__create__",label:`Create new: "${e}"`,node:null,kind:"create"}),i.text.join("").length>=3){let y=w=>w.kind==="note"&&(w.id===k||w.crossId===k)&&n(w.label.toLowerCase()),E=C.filter(y);if(E.length>0){let w=C.filter(v=>!y(v));C.splice(0,C.length,...E,...w)}}return this.opts.excludedFolderNotes&&!this.includeExcluded&&C.push({id:"__search_excluded__",label:"Search excluded Stashpad folders",node:null,kind:"search-excluded"}),C}loadExcludedNotes(){if(this.includeExcluded||!this.opts.excludedFolderNotes)return;this.includeExcluded=!0;for(let t of this.opts.excludedFolderNotes())this.notes.push({node:null,title:t.title,body:t.body,cross:t});this.crossFolderIndex=null;for(let t of this.notes)!t.cross||t.body||!t.cross.file||this.app.vault.cachedRead(t.cross.file).then(i=>{t.body=this.stripFm(i)});let e=this.inputEl;e&&(e.dispatchEvent(new Event("input",{bubbles:!0})),setTimeout(()=>e.dispatchEvent(new Event("input",{bubbles:!0})),250))}previewFromBody(e,t){let i=e.split(/\r?\n/);if(t<0)return i.filter(r=>r.trim().length>0).slice(0,3).join(` `);let s=Math.max(0,t-2),n=Math.min(i.length,t+3);return i.slice(s,n).filter(o=>o.trim().length>0).join(` -`)}renderSuggestion(e,t){if(t.addClass("stashpad-suggest-item"),e.kind==="create"){t.createDiv({cls:"stashpad-suggest-create",text:e.label});return}if(e.kind==="folder-open"){t.addClass("is-folder-open"),t.createDiv({cls:"stashpad-suggest-title",text:e.label}),e.folder?t.createDiv({cls:"stashpad-suggest-preview",text:e.folder}):t.createDiv({cls:"stashpad-suggest-preview",text:"Click to choose a folder\u2026"});return}if(e.kind==="search-excluded"){t.addClass("is-search-excluded");let u=t.createDiv({cls:"stashpad-suggest-title stashpad-search-excluded-row"}),f=u.createSpan({cls:"stashpad-search-excluded-icon"});(0,he.setIcon)(f,"folder-search"),u.createSpan({text:e.label}),t.createDiv({cls:"stashpad-suggest-preview",text:"Include folders you've excluded from search (e.g. to move a note there)."});return}if(e.locked){t.addClass("stashpad-suggest-row","is-locked");let u=t.createDiv({cls:"stashpad-suggest-body"}),f=u.createDiv({cls:"stashpad-suggest-title stashpad-suggest-locked"});(0,he.setIcon)(f.createSpan({cls:"stashpad-suggest-locked-icon"}),"lock");let p=Ro(this.inputEl?.value??"").text;this.highlightInto(f.createSpan(),e.label,p),u.createDiv({cls:"stashpad-suggest-preview",text:e.locked.count>1?`${e.locked.count} notes \xB7 locked`:"Encrypted \u2014 locked"});return}e.crossFolder&&t.addClass("is-cross-folder"),t.addClass("stashpad-suggest-row");let i=t.createDiv({cls:"stashpad-suggest-body"}),s=this.notes.find(u=>e.crossFolder?u.cross?.folder===e.crossFolder&&u.cross?.id===e.crossId:u.node?.id===e.id),n=Ro(this.inputEl?.value??"").text,o=this.firstLineOfBody(s?.body??"")||e.label.trim(),r=i.createDiv({cls:"stashpad-suggest-title"});this.highlightInto(r,o,n);let l=e.crossFolder??this.opts.localFolder??null;if(e.bodyPreview&&e.matchLine!=null&&e.matchLine>=0){let u=i.createDiv({cls:"stashpad-suggest-preview stashpad-suggest-snippet"});this.highlightInto(u,e.bodyPreview,n)}let c="";if(e.crossFolder?c=s?.cross?.parentBlurb??"":c=this.parentBlurbFor(e.node),c){let u=i.createDiv({cls:"stashpad-suggest-preview"});u.appendText("Parent: "),this.highlightInto(u,c,n)}let A=e.crossFolder?this.buildCrossBreadcrumb(e):this.buildLocalBreadcrumb(e.node),h=e.crossFolder??this.opts.localFolder??null;if(h||A){let u=i.createDiv({cls:"stashpad-suggest-breadcrumb"}),p=[h?h.split("/").pop()||h:"",A].filter(I=>I&&I.length>0).join(" \u203A ");p&&u.setText(p)}let g=s?this.createdMsFor(s):null;if(g!=null||l){let u=t.createDiv({cls:"stashpad-suggest-rail"});if(g!=null){let f=u.createDiv({cls:"stashpad-suggest-time"});f.setText(this.formatRelativeTime(g)),f.title=fe(g).format("YYYY-MM-DD HH:mm")}l&&u.createDiv({cls:"stashpad-suggest-folder-badge",text:l.split("/").pop()||l})}}formatRelativeTime(e){let t=fe(e),i=fe().startOf("day").diff(fe(e).startOf("day"),"days");return i===0?t.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?t.format("MMM D"):t.format("MMM D, YYYY")}highlightInto(e,t,i){if(!t)return;let s=i.filter(c=>c&&c.length>0);if(!s.length){e.appendText(t);return}let n=t.toLowerCase(),o=[];for(let c of s){let A=0;for(;(A=n.indexOf(c,A))!==-1;)o.push([A,A+c.length]),A+=1}if(!o.length){e.appendText(t);return}o.sort((c,A)=>c[0]-A[0]);let r=[];for(let c of o){let A=r[r.length-1];A&&c[0]<=A[1]?A[1]=Math.max(A[1],c[1]):r.push([c[0],c[1]])}let l=0;for(let[c,A]of r)c>l&&e.appendText(t.slice(l,c)),e.createSpan({cls:"stashpad-suggest-match",text:t.slice(c,A)}),l=A;l<t.length&&e.appendText(t.slice(l))}buildLocalBreadcrumb(e){if(!e||!e.parent||e.parent===S)return"";let t=[],i=new Set([e.id]),s=this.tree.get(e.parent);for(;s&&s.id!==S&&!i.has(s.id);)i.add(s.id),t.unshift(this.titleFn(s)),s=s.parent&&s.parent!==S?this.tree.get(s.parent):void 0;return t.join(" \u203A ")}buildCrossBreadcrumb(e){if(!e.crossFolder)return"";if(!this.crossFolderIndex){this.crossFolderIndex=new Map;for(let l of this.notes){if(!l.cross)continue;let c=this.crossFolderIndex.get(l.cross.folder);c||(c=new Map,this.crossFolderIndex.set(l.cross.folder,c)),c.set(l.cross.id,l.cross)}}let t=this.crossFolderIndex.get(e.crossFolder);if(!t)return"";let i=e.crossId??e.id.replace(/^cross:/,""),s=t.get(i);if(!s)return"";let n=[],o=new Set([s.id]),r=s.parentId?t.get(s.parentId):null;for(;r&&!o.has(r.id);)o.add(r.id),n.unshift(r.title),r=r.parentId?t.get(r.parentId):null;return n.join(" \u203A ")}firstLineOfBody(e){if(!e)return"";let t=e.split(/\r?\n/);for(let i of t){let s=i.trim();if(s)return s}return""}parentBlurbFor(e){if(!e||!e.parent||e.parent===S)return"";let t=this.tree.get(e.parent);if(!t||!t.file)return"";let i=this.notes.find(s=>s.node?.id===t.id);return i?this.firstLineOfBody(i.body):""}onOpen(){if(super.onOpen(),this.opts.showFilterChips&&!he.Platform.isMobile){let e=this.inputEl,t=this.resultContainerEl;if(!e||!t)return;this.mountFilterChipRow(e,t);return}if(he.Platform.isMobile){let e=this.inputEl;e&&e.focus()}}mountFilterChipRow(e,t){e.addEventListener("keydown",c=>{if(c.key==="["){c.preventDefault();let A=e.selectionStart??e.value.length,h=e.selectionEnd??A,g=e.value.slice(0,A),u=e.value.slice(A,h),f=e.value.slice(h);e.value=`${g}[${u}]${f}`;let p=A+1+u.length;e.setSelectionRange(p,p),e.dispatchEvent(new Event("input",{bubbles:!0}));return}if(c.key==="]"){let A=e.selectionStart??-1;A>=0&&e.value[A]==="]"&&(c.preventDefault(),e.setSelectionRange(A+1,A+1));return}if(c.key==="Backspace"&&!c.metaKey&&!c.ctrlKey&&!c.altKey&&e.selectionStart===e.selectionEnd){let A=e.selectionStart??-1;if(A>0&&e.value[A-1]==="["&&e.value[A]==="]"){c.preventDefault();let h=e.value.slice(0,A-1),g=e.value.slice(A+1);e.value=`${h}${g}`,e.setSelectionRange(A-1,A-1),e.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",c=>{c.preventDefault()}),n.addEventListener("click",c=>{c.preventDefault(),this.appendFilterToInput(e,"in","")}),n.addEventListener("keydown",c=>{(c.key==="Enter"||c.key===" ")&&(c.preventDefault(),c.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",c=>{c.preventDefault()}),o.addEventListener("click",c=>{c.preventDefault(),this.toggleWhenBuilder(e,i)}),o.addEventListener("keydown",c=>{(c.key==="Enter"||c.key===" ")&&(c.preventDefault(),c.stopPropagation(),o.click())}),i.appendChild(o),t.parentElement?.insertBefore(i,t);let r=new he.Scope(this.scope),l=c=>{let A=document.activeElement;return A?.classList?.contains("stashpad-search-filter-chip")?(c.preventDefault(),A.click(),!1):c.key==="Enter"&&!c.isComposing?(c.preventDefault(),this.selectActiveSuggestion?.(c),!1):!0};r.register([],"Enter",l),r.register([]," ",l),r.register(["Mod"],"f",c=>{c.preventDefault();let A=this.inputEl;return A&&(A.focus(),A.select()),!1}),r.register([],"Tab",c=>{let A=this.modalEl,h=this.inputEl;if(!A)return!0;let g=Array.from(A.querySelectorAll('input, button, select, textarea, a[href], [tabindex]:not([tabindex="-1"])')).filter(p=>!p.hasAttribute("disabled")&&p.tabIndex!==-1&&p.offsetParent!==null);if(g.length===0)return!0;let u=document.activeElement,f=u?g.indexOf(u):-1;if(c.shiftKey){if(f<=0)return c.preventDefault(),g[g.length-1].focus(),!1}else if(f===g.length-1)return c.preventDefault(),(h??g[0]).focus(),!1;return!0}),this.app.keymap?.pushScope(r),this.pendingCleanups.push(()=>{try{this.app.keymap?.popScope(r)}catch{}})}appendFilterToInput(e,t,i){let s=e.value,o=`${s.length>0&&!/\s$/.test(s)?" ":""}${t}: [`,r="]",l=i;e.value=`${s}${o}${l}${r}`;let c=s.length+o.length+l.length;if(e.setSelectionRange(c,c+0),!l){let A=s.length+o.length;e.setSelectionRange(A,A)}e.focus(),e.dispatchEvent(new Event("input",{bubbles:!0}))}toggleWhenBuilder(e,t){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 p of o){let I=document.createElement("button");I.type="button",I.className="stashpad-when-tab",I.textContent=p.label,this.whenMode===p.id&&I.addClass("is-active"),I.addEventListener("mousedown",m=>m.preventDefault()),I.addEventListener("click",m=>{if(m.preventDefault(),this.whenMode===p.id)return;let B=this.whenMode;B!=="between"&&p.id==="between"?this.whenBetweenEndText="":B==="between"&&p.id!=="between"&&(!this.whenSingleText&&this.whenBetweenEndText&&(this.whenSingleText=this.whenBetweenEndText),this.whenBetweenEndText=""),this.whenMode=p.id;for(let C in r)r[C].toggleClass("is-active",C===p.id);f()}),r[p.id]=I,n.appendChild(I)}s.appendChild(n);let l=document.createElement("div");l.className="stashpad-when-body",s.appendChild(l);let c=(p,I,m="single")=>{let B=fe().format("YYYY-MM-DD"),C=!I||I===B;if(m==="betweenStart")return"00:00";if(m==="betweenEnd")return"23:59";switch(p){case"after":return"00:00";case"on":return C?fe().format("HH:mm"):"23:59";case"before":return C?fe().format("HH:mm"):"23:59";default:return"23:59"}},A=(p,I)=>{p.addEventListener("keydown",m=>{m.key==="Enter"?(m.preventDefault(),m.stopPropagation(),I()):m.key==="Escape"&&(m.preventDefault(),m.stopPropagation(),this.closeWhenBuilder())})},h=(p,I)=>{let m=p.selectionStart??p.value.length,B=p.selectionEnd??p.value.length,w=`${m>0&&!/\s$/.test(p.value.slice(0,m))?" ":""}${I}`,y=p.value.slice(0,m)+w+p.value.slice(B);p.value=y;let v=m+w.length;p.setSelectionRange(v,v),p.focus(),p.dispatchEvent(new Event("input",{bubbles:!0}))},g=(p,I)=>{let B=p.slice(0,I).match(/(\d{4}-\d{2}-\d{2})(?!.*\d{4}-\d{2}-\d{2})/);return B?B[1]:null},u=(p,I,m,B)=>{let C=l.createDiv({cls:"stashpad-when-input-wrap has-icons"}),w=C.createDiv({cls:"stashpad-when-icon-slot"}),y=w.createEl("button",{cls:"stashpad-when-icon stashpad-when-icon-cal"});y.type="button",y.title="Pick date",(0,he.setIcon)(y,"calendar-days");let v=w.createEl("input",{cls:"stashpad-when-native",attr:{type:"date"}});v.tabIndex=-1;let E=C.createDiv({cls:"stashpad-when-icon-slot"}),Q=E.createEl("button",{cls:"stashpad-when-icon stashpad-when-icon-clock"});Q.type="button",Q.title="Pick time",(0,he.setIcon)(Q,"clock");let b=C.createDiv({cls:"stashpad-when-icon-slot"}),D=b.createEl("button",{cls:"stashpad-when-icon stashpad-when-icon-day"});D.type="button",D.title="Pick day",(0,he.setIcon)(D,"calendar");let H=C.createDiv({cls:"stashpad-when-icon-slot"}),G=H.createEl("button",{cls:"stashpad-when-icon stashpad-when-icon-tf"});G.type="button",G.title="Pick timeframe",(0,he.setIcon)(G,"history");let x=C.createEl("input",{cls:"stashpad-when-input",attr:{type:"text",placeholder:p}});x.value=I(),x.addEventListener("input",()=>m(x.value));let U=C.createEl("button",{cls:"stashpad-when-clear"});U.type="button",U.textContent="\xD7",U.title="Clear";for(let O of[y,Q,D,G,U])O.addEventListener("mousedown",L=>L.preventDefault());let R=null,M=(O,L)=>{R&&R();let K=O.createDiv({cls:"stashpad-when-popover"}),V=O.ownerDocument??document,Y=new he.Scope(this.scope),$=null,j=te=>{$=te},le=!1,oe=te=>{!K.contains(te.target)&&te.target!==O&&!O.contains(te.target)&&ie()},ie=()=>{if(!le){le=!0,K.remove(),V.removeEventListener("mousedown",oe,!0);try{this.app.keymap?.popScope(Y)}catch{}R===ie&&(R=null)}};R=ie,Y.register([],"Escape",te=>(te.preventDefault(),ie(),!1)),Y.register([],"Enter",te=>(te.preventDefault(),$&&$(),!1));try{L(K,ie,j)}catch(te){console.error("[stashpad] popover fill threw:",te),K.remove(),R=null;return}this.app.keymap?.pushScope(Y),this.pendingCleanups.push(ie),setTimeout(()=>V.addEventListener("mousedown",oe,!0),0)};G.addEventListener("click",O=>{O.preventDefault(),M(H,(L,K,V)=>{let Y=this.whenMode==="on",$=(se,ve)=>{if(!Y)return`${se}${ve}`;let Dt={d:"days",w:"weeks",m:"months",y:"years"}[ve];return fe().subtract(se,Dt).format("YYYY-MM-DD")},j=L.createDiv({cls:"stashpad-when-pop-row"}),le=[{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 se of le){let ve=j.createEl("button",{cls:"stashpad-when-pop-chip",text:se.label});ve.type="button",ve.addEventListener("mousedown",Dt=>Dt.preventDefault()),ve.addEventListener("click",Dt=>{Dt.preventDefault(),h(x,$(se.n,se.unit)),K()})}let oe=L.createDiv({cls:"stashpad-when-pop-row stashpad-when-pop-builder"});oe.createSpan({text:"Last",cls:"stashpad-when-pop-label"});let ie=oe.createEl("input",{cls:"stashpad-when-pop-number",attr:{type:"number",min:"1",max:"999",value:"7"}}),te=oe.createEl("select",{cls:"stashpad-when-pop-unit"});for(let se of[{v:"d",label:"days"},{v:"w",label:"weeks"},{v:"m",label:"months"},{v:"y",label:"years"}]){let ve=te.createEl("option",{text:se.label});ve.value=se.v}let pe=oe.createEl("button",{cls:"stashpad-when-pop-chip stashpad-when-pop-go",text:"Insert"});pe.type="button";let xe=()=>{let se=parseInt(ie.value,10);!Number.isFinite(se)||se<1||(h(x,$(se,te.value)),K())};pe.addEventListener("mousedown",se=>se.preventDefault()),pe.addEventListener("click",se=>{se.preventDefault(),xe()}),V(xe),ie.focus(),ie.select()})});let k=(O,L,K,V,Y)=>{M(L,($,j,le)=>{vs($,{seedH:K,seedM:V,seedPeriod:Y,close:j,setOnEnter:le,onFinalize:oe=>h(O,Tr(oe))})})};D.addEventListener("click",O=>{O.preventDefault(),M(b,(L,K,V)=>{let Y=L.createDiv({cls:"stashpad-when-pop-row"});for(let ie of["Today","Yesterday"]){let te=Y.createEl("button",{cls:"stashpad-when-pop-chip",text:ie});te.type="button",te.addEventListener("mousedown",pe=>pe.preventDefault()),te.addEventListener("click",pe=>{pe.preventDefault(),h(x,ie),K()})}let $=L.createDiv({cls:"stashpad-when-pop-row stashpad-when-pop-days"}),j=["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],oe=(fe().day()+6)%7;for(let ie=0;ie<j.length;ie++){let te=j[ie],pe=$.createEl("button",{cls:"stashpad-when-pop-chip",text:te.slice(0,3)});pe.type="button",pe.title=te,ie===oe&&pe.addClass("is-today"),pe.addEventListener("mousedown",xe=>xe.preventDefault()),pe.addEventListener("click",xe=>{if(xe.preventDefault(),B==="betweenEnd"){let se=ie,ve=fe().startOf("day"),Dt=(ve.day()+6)%7,$n=(se-Dt+7)%7;$n===0&&($n=7);let kl=ve.clone().add($n,"days").format("YYYY-MM-DD");h(x,kl)}else h(x,te);K()})}})});let P=(O,L)=>{O.value||(O.value=L);let K=O;if(typeof K.showPicker=="function")try{K.showPicker();return}catch{}O.focus(),O.click()};return y.addEventListener("click",O=>{O.preventDefault(),P(v,fe().format("YYYY-MM-DD"))}),v.addEventListener("change",()=>{v.value&&h(x,v.value)}),Q.addEventListener("click",O=>{O.preventDefault();let L=x.selectionStart??x.value.length,K=g(x.value,L),V=c(this.whenMode,K,B),[Y,$]=V.split(":"),j=parseInt(Y,10),le=parseInt($,10),oe=j%12;oe===0&&(oe=12);let ie=j>=12?"pm":"am";k(x,E,oe,le,ie)}),U.addEventListener("click",O=>{O.preventDefault(),x.value="",m(""),x.focus()}),x},f=()=>{if(l.empty(),this.whenMode==="between"){let p=u("start (date / day / timeframe)",()=>this.whenSingleText,y=>{this.whenSingleText=y},"betweenStart"),I=u("end (date / day / timeframe)",()=>this.whenBetweenEndText,y=>{this.whenBetweenEndText=y},"betweenEnd"),m=l.createDiv({cls:"stashpad-when-actions"}),B=m.createEl("button",{cls:"stashpad-when-insert",text:"Insert"});B.type="button",B.addEventListener("mousedown",y=>y.preventDefault());let C=()=>{let y=p.value.trim(),v=I.value.trim();y&&this.appendFilterToInput(e,"after",y),v&&this.appendFilterToInput(e,"before",v),this.closeWhenBuilder()};B.addEventListener("click",y=>{y.preventDefault(),C()});let w=m.createEl("button",{cls:"stashpad-when-cancel",text:"Cancel"});w.type="button",w.addEventListener("mousedown",y=>y.preventDefault()),w.addEventListener("click",y=>{y.preventDefault(),this.closeWhenBuilder()}),A(p,C),A(I,C),p.focus(),p.setSelectionRange(p.value.length,p.value.length)}else{let p=u("date / day / timeframe",()=>this.whenSingleText,w=>{this.whenSingleText=w},"single"),I=l.createDiv({cls:"stashpad-when-actions"}),m=I.createEl("button",{cls:"stashpad-when-insert",text:"Insert"});m.type="button",m.addEventListener("mousedown",w=>w.preventDefault());let B=()=>{let w=p.value.trim();w&&this.appendFilterToInput(e,this.whenMode,w),this.closeWhenBuilder()};m.addEventListener("click",w=>{w.preventDefault(),B()});let C=I.createEl("button",{cls:"stashpad-when-cancel",text:"Cancel"});C.type="button",C.addEventListener("mousedown",w=>w.preventDefault()),C.addEventListener("click",w=>{w.preventDefault(),this.closeWhenBuilder()}),A(p,B),p.focus(),p.setSelectionRange(p.value.length,p.value.length)}};f(),t.parentElement?.insertBefore(s,t.nextSibling),this.whenBuilderEl=s}closeWhenBuilder(){if(!this.whenBuilderEl)return;this.whenBuilderEl.remove(),this.whenBuilderEl=null,this.modalEl?.removeClass("is-when-builder-open")}selectSuggestion(e,t){if(e&&e.kind==="search-excluded"){this.loadExcludedNotes();return}super.selectSuggestion(e,t)}onChooseSuggestion(e){if(e.kind==="create"&&this.opts.onCreate){let t=this.inputEl?.value??"",i=t.replace(/(?<![\w-])(in|before|after|on):\s*(?:\[[^\]]*\]|[^]*?(?=\s+(?:in|before|after|on):|$))/gi," ").replace(/\s+/g," ").trim();this.opts.onCreate(i||t);return}if(e.kind==="folder-open"&&e.id==="__folder_picker__"){let t=this.opts.folderResults?.()??[];if(!t.length)return;let i=this.inputEl?.value??"",s=!1,n=g=>{s=!0;let u=g.split("/").pop()??g;this.opts.onPick({id:`folder:${g}`,label:`Open folder \u201C${u}\u201D in a new tab`,node:null,kind:"folder-open",folder:g})},o=new Uo(this.app,t,n),r=o.onClose.bind(o),l=this.tree,c=this.titleFn,A=this.opts,h=this.app;o.onClose=()=>{r(),setTimeout(()=>{if(s)return;let g=new d(h,l,c,A);g.open(),setTimeout(()=>{let u=g.inputEl;u&&(i&&(u.value=i,u.dispatchEvent(new Event("input",{bubbles:!0}))),u.focus(),u.setSelectionRange(u.value.length,u.value.length))},0)},0)},o.open();return}if(e.node?.file&&!this.app.vault.getAbstractFileByPath(e.node.file.path)){new he.Notice("That note no longer exists.");return}this.opts.onPick(e)}},Uo=class extends he.FuzzySuggestModal{constructor(e,t,i){super(e);this.folders=t;this.onChosen=i;this.setPlaceholder("Open which folder?")}getItems(){return this.folders}getItemText(e){let t=e.split("/").pop()??e;return t===e?e:`${t} \u2014 ${e}`}onChooseItem(e){this.onChosen(e)}};var ss="stashpad";function Go(d){let a=[];d.vault&&a.push(`vault=${encodeURIComponent(d.vault)}`),a.push(`folder=${encodeURIComponent(d.folder)}`),d.note&&a.push(`note=${encodeURIComponent(d.note)}`);let e=d.run&&d.run.length?d.run:["reveal"];return a.push(`run=${encodeURIComponent(e.join(","))}`),`obsidian://${ss}?${a.join("&")}`}function Ca(d){let a=(d||"").trim();if(!a)return null;let e;if(/^obsidian:\/\//i.test(a)){let c=a.match(/^obsidian:\/\/([^?]*)(?:\?(.*))?$/i);if(!c||decodeURIComponent(c[1].replace(/\/+$/,"")).toLowerCase()!==ss)return null;e=c[2]??""}else e=a.replace(/^\?/,"");let t=new URLSearchParams(e),i=t.get("folder");if(!i)return null;let s={folder:i},n=t.get("vault");n&&(s.vault=n);let o=t.get("note");o&&(s.note=o);let r=t.get("run");r&&(s.run=r);let l=t.get("action");return l&&(s.action=l),s}function Ba(d){let a=d.run;!a&&d.action&&d.action!==ss&&(a=d.action);let e=(a||"reveal").split(",").map(t=>t.trim().toLowerCase()).filter(Boolean);return e.length?e:["reveal"]}var ya=require("obsidian");ae();var dn=class extends ya.SuggestModal{constructor(a){super(a),this.setPlaceholder("Run a Stashpad command\u2026");let e=this.app.commands?.commands??{};this.commands=Object.keys(e).filter(t=>t.startsWith("stashpad:")).filter(t=>t!=="stashpad:stashpad-command-palette").map(t=>({id:t,name:xc(e[t]?.name??t)})).sort((t,i)=>t.name.localeCompare(i.name))}getSuggestions(a){return this.commands.filter(e=>Es(a,e.name))}renderSuggestion(a,e){e.createDiv({text:a.name,cls:"stashpad-cmd-palette-name"})}onChooseSuggestion(a){this.app.commands?.executeCommandById?.(a.id)}};function xc(d){return d.replace(/^(?:\s*Stashpad:\s*)+/i,"").trim()||d}we();var Lo=require("obsidian");function wa(d){let a=d.code||"",e=/^Key([A-Z])$/.exec(a);if(e)return e[1].toLowerCase();let t=/^Digit(\d)$/.exec(a);return t?t[1]:(d.key||"").toLowerCase()}function Nc(d,a){return!a||d.metaKey||d.ctrlKey||d.altKey?!1:a.length===1&&!/[a-z0-9]/i.test(a)?d.key===a:wa(d)===a.toLowerCase()}function Bi(d,a){return a?a.includes("+")?Mc(d,a):Nc(d,a):!1}function q(d,a){if(!a)return!1;let{primary:e,secondary:t,preferRight:i,useBoth:s}=a;return e&&t?s?Bi(d,e)||Bi(d,t):i?Bi(d,t):Bi(d,e):Bi(d,e)||Bi(d,t)}function ns(d){if(!d)return"";let a=Lo.Platform.isMacOS;return d.split("+").map(e=>{let t=e.trim();return t?t.toLowerCase()==="mod"?a?"Cmd":"Ctrl":t.toLowerCase()==="alt"?a?"Opt":"Alt":t.length===1?t.toUpperCase():t:""}).filter(Boolean).join("+")}function Mc(d,a){if(!a)return!1;let e=a.split("+").map(h=>h.trim()).filter(Boolean);if(e.length<2)return!1;let t=e[e.length-1].toLowerCase(),i=new Set(e.slice(0,-1).map(h=>h.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"),l=i.has("shift"),A=Lo.Platform.isMacOS?d.metaKey:d.ctrlKey;return s&&!A||n&&!d.ctrlKey||o&&!d.metaKey||r!==d.altKey||l!==d.shiftKey||!s&&(!n&&d.ctrlKey||!o&&d.metaKey)?!1:wa(d)===t}var Ce=require("obsidian");ae();var Ea=require("obsidian"),Tc="byfolder";function An(d,a,e,t){let i=d.createDiv({cls:"stashpad-trash-modes"}),s=i.createEl("button",{cls:"stashpad-agg-reset",attr:{"aria-label":"Reset to default view"}});(0,Ea.setIcon)(s,"rotate-ccw"),s.onclick=()=>t(Tc);let n=[{key:"byfolder",label:"By folder",count:e.total},{key:"separated",label:"Separated",count:e.total},{key:"mixed",label:"Mixed (by date)",count:e.total},{key:"encrypted",label:"Encrypted",count:e.enc},{key:"unencrypted",label:"Unencrypted",count:e.dec}];for(let o of n){let r=i.createEl("button",{cls:"stashpad-triage-chip"});a===o.key&&r.addClass("is-active"),r.createSpan({text:o.label}),r.createSpan({cls:"stashpad-triage-chip-count",text:String(o.count)}),r.onclick=()=>t(o.key)}}function pt(d,a,e,t){if(!e||e===a)return;let i=o=>{let r=!1;return d.iterateAllLeaves(l=>{l===o&&(r=!0)}),r},s=a,n=d.on("active-leaf-change",()=>{if(i(a)){s=d.activeLeaf??s;return}d.offref(n),s===a&&i(e)&&(d.setActiveLeaf(e,{focus:!0}),d.revealLeaf(e))});t?.(n)}var hn=Ce.moment,pn=class extends Ce.ItemView{constructor(e,t){super(e);this.plugin=t;this.mode="encrypted";this.taskState=bs();this.archiveSubMode="byfolder";this.renderPending=!1;this.watchFolderFilter="";this.watchViaFilter="";this.watchQuery=""}getViewType(){return Xt}getDisplayText(){return this.mode==="archived"?"All archived":this.mode==="tasks"?"All tasks":this.mode==="watch"?"Previously encrypted":"All encrypted"}getIcon(){return this.mode==="archived"?"archive":this.mode==="tasks"?"check-square":this.mode==="watch"?"history":"lock"}getState(){return{...super.getState(),mode:this.mode}}async setState(e,t){(e?.mode==="archived"||e?.mode==="encrypted"||e?.mode==="tasks"||e?.mode==="watch")&&(this.mode=e.mode),await super.setState(e,t),await this.render()}async onOpen(){this.containerEl.addClass("stashpad-aggregate-view");let e=s=>s.endsWith(".stashenc")&&!s.startsWith("_deleted/"),t=s=>s.endsWith(".md")&&/(^|\/)archive\//.test(s),i=s=>e(s)||t(s);this.registerEvent(this.app.vault.on("create",s=>{i(s.path)&&this.scheduleRender()})),this.registerEvent(this.app.vault.on("delete",s=>{i(s.path)&&this.scheduleRender()})),this.registerEvent(this.app.vault.on("rename",(s,n)=>{(i(s.path)||i(n))&&this.scheduleRender()})),await this.render()}scheduleRender(){this.renderPending||(this.renderPending=!0,window.setTimeout(()=>{this.renderPending=!1,this.render()},150))}cleanFolder(e){return(e||"").replace(/\/+$/,"")}archiveFolders(){let e=new Set;for(let i of this.plugin.discoverStashpadFolders()){let s=yt(i);this.plugin.app.vault.getAbstractFileByPath(s)&&e.add(s)}for(let i of this.plugin.settings.archiveFolders??[])e.add(this.cleanFolder(i));let t=this.plugin.settings.folderEncPrefs??{};for(let[i,s]of Object.entries(t))s?.archive&&e.add(this.cleanFolder(i));return[...e].sort((i,s)=>i.localeCompare(s))}async render(){let e=this.contentEl;e.empty(),e.addClass("stashpad-aggregate-body");let t=e.createDiv({cls:"stashpad-aggregate-header"});t.createEl("h3",{text:this.getDisplayText()});let i=t.createEl("button",{cls:"stashpad-trash-iconbtn"});if((0,Ce.setIcon)(i,"refresh-cw"),i.setAttr("aria-label","Refresh"),i.onclick=()=>void this.render(),this.mode==="tasks"){Yi(e.createDiv(),this.app,this.plugin,this.taskState,{onOpen:(s,n)=>void this.plugin.revealNoteByRef(s,n)});return}if(this.mode==="archived"){this.renderArchived(e);return}if(this.mode==="watch"){this.renderWatch(e);return}this.renderEncrypted(e)}renderEncrypted(e){let t=this.plugin.settings.lockedSubtrees??[];if(t.length===0){e.createDiv({cls:"stashpad-trash-empty",text:"Nothing is encrypted yet. Lock a note or folder and it shows up here."});return}let i=new Map;for(let n of t){let o=this.cleanFolder(n.folder)||"(vault root)";(i.get(o)??i.set(o,[]).get(o)).push(n)}let s=[...i.keys()].sort((n,o)=>n.localeCompare(o));e.createDiv({cls:"stashpad-aggregate-sub",text:`${t.length} locked ${t.length===1?"item":"items"} in ${s.length} ${s.length===1?"folder":"folders"}.`});for(let n of s){let o=e.createDiv({cls:"stashpad-trash-group"}),r=o.createDiv({cls:"stashpad-trash-group-head"});(0,Ce.setIcon)(r.createSpan({cls:"stashpad-trash-group-icon"}),"folder"),r.createSpan({text:n.split("/").pop()||n}),r.createSpan({cls:"stashpad-trash-group-count",text:String(i.get(n).length)});let l=r.createEl("button",{cls:"stashpad-trash-iconbtn",text:"Open"});l.onclick=()=>void this.plugin.activateViewForFolder(n);for(let c of i.get(n)){let A=o.createDiv({cls:"stashpad-trash-row"}),h=A.createDiv({cls:"stashpad-trash-row-main"});h.createSpan({cls:"stashpad-trash-title",text:c.title||"Locked note"});let g=c.created?`locked ${hn(c.created).fromNow()}`:"locked",u=c.count>1?` \xB7 ${c.count} notes`:"";h.createSpan({cls:"stashpad-trash-sub",text:g+u});let f=A.createEl("button",{cls:"stashpad-trash-iconbtn",text:"Export"});f.setAttr("aria-label","Export to .stash (encrypted with a password you choose)"),f.onclick=()=>void this.plugin.exportLockedSubtree(c.blob);let p=A.createSpan({cls:"stashpad-aggregate-lockbadge"});(0,Ce.setIcon)(p,"lock")}}}renderArchived(e){let t=this.archiveFolders();if(t.length===0){e.createDiv({cls:"stashpad-trash-empty",text:"No archive folders yet. Toggle Archive on a folder to collect it here."});return}let i=new Set(t),s=this.plugin.settings.lockedSubtrees??[],n=new Map;for(let p of s){let I=this.cleanFolder(p.folder);i.has(I)&&(n.get(I)??n.set(I,[]).get(I)).push(p)}let o=new Map,r=0;for(let p of t){let I=this.plugin.archivedPlainNotesIn(p);o.set(p,I),r+=I.length}let l=[...n.values()].reduce((p,I)=>p+I.length,0),c=r+l,A=t.flatMap(p=>o.get(p)??[]),h=t.flatMap(p=>n.get(p)??[]);e.createDiv({cls:"stashpad-aggregate-sub",text:`${t.length} archive ${t.length===1?"folder":"folders"}, ${c} archived ${c===1?"item":"items"} (${r} plain \xB7 ${l} locked).`}),An(e,this.archiveSubMode,{total:c,enc:l,dec:r},p=>{this.archiveSubMode=p,this.render()});let g=this.archiveSubMode;if(g==="mixed"){let p=[];for(let m of A)p.push({ts:m.stat.mtime||0,kind:"plain",f:m});for(let m of h)p.push({ts:m.created&&Date.parse(m.created)||0,kind:"locked",e:m});p.sort((m,B)=>B.ts-m.ts);let I=e.createDiv({cls:"stashpad-trash-group"});for(let m of p)m.kind==="plain"&&m.f?this.archivePlainRow(I,m.f):m.e&&this.archiveLockedRow(I,m.e);return}if(g==="byfolder"){for(let p of t){let I=n.get(p)??[],m=o.get(p)??[],B=e.createDiv({cls:"stashpad-trash-group"}),C=B.createDiv({cls:"stashpad-trash-group-head"});(0,Ce.setIcon)(C.createSpan({cls:"stashpad-trash-group-icon"}),"archive"),C.createSpan({text:p.split("/").pop()||p}),C.createSpan({cls:"stashpad-trash-group-count",text:String(I.length+m.length)});let w=C.createEl("button",{cls:"stashpad-trash-iconbtn",text:"Open"});if(w.onclick=()=>void this.plugin.activateViewForFolder(p),I.length===0&&m.length===0){B.createDiv({cls:"stashpad-trash-sub",text:"No archived items."});continue}for(let y of m)this.archivePlainRow(B,y);for(let y of I)this.archiveLockedRow(B,y)}return}let u=g!=="encrypted"&&A.length>0,f=g!=="unencrypted"&&h.length>0;if(!u&&!f){e.createDiv({cls:"stashpad-trash-empty",text:"Nothing in this view."});return}if(u){let p=e.createDiv({cls:"stashpad-trash-group"}),I=p.createDiv({cls:"stashpad-trash-group-head"});(0,Ce.setIcon)(I.createSpan({cls:"stashpad-trash-group-icon"}),"file-text"),I.createSpan({text:"Plain notes"}),I.createSpan({cls:"stashpad-trash-group-count",text:String(A.length)});for(let m of A)this.archivePlainRow(p,m)}if(f){let p=e.createDiv({cls:"stashpad-trash-group"}),I=p.createDiv({cls:"stashpad-trash-group-head"});(0,Ce.setIcon)(I.createSpan({cls:"stashpad-trash-group-icon"}),"lock"),I.createSpan({text:"Locked (encrypted)"}),I.createSpan({cls:"stashpad-trash-group-count",text:String(h.length)});for(let m of h)this.archiveLockedRow(p,m)}}archivePlainRow(e,t){let i=e.createDiv({cls:"stashpad-trash-row"}),s=i.createDiv({cls:"stashpad-trash-row-main"});s.createSpan({cls:"stashpad-trash-title",text:t.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||t.basename}),s.createSpan({cls:"stashpad-trash-sub",text:`archived ${hn(t.stat.mtime).fromNow()}`});let n=i.createEl("button",{cls:"stashpad-trash-restore",text:"Restore"});(0,Ce.setIcon)(n.createSpan({cls:"stashpad-btn-icon"}),"rotate-ccw"),n.onclick=async()=>{n.disabled=!0,await this.plugin.unarchiveNote(t)?this.render():n.disabled=!1}}archiveLockedRow(e,t){let i=e.createDiv({cls:"stashpad-trash-row"}),s=i.createDiv({cls:"stashpad-trash-row-main"});s.createSpan({cls:"stashpad-trash-title",text:t.title||"Locked note"});let n=t.created?`archived ${hn(t.created).fromNow()}`:"archived",o=(t.count??0)>1?` \xB7 ${t.count} notes`:"";s.createSpan({cls:"stashpad-trash-sub",text:n+o});let r=i.createEl("button",{cls:"stashpad-trash-restore",text:"Restore"});(0,Ce.setIcon)(r.createSpan({cls:"stashpad-btn-icon"}),"rotate-ccw"),r.setAttr("aria-label","Unlock and restore (needs the password)"),r.onclick=async()=>{r.disabled=!0;let A=t.blob.split("/"),h=A.lastIndexOf("archive"),g=h>0?A.slice(0,h).join("/"):void 0;await this.plugin.unlockBundleAt(t.blob,g?{destFolder:g}:{})?this.render():r.disabled=!1};let l=i.createEl("button",{cls:"stashpad-trash-iconbtn",text:"Export"});l.setAttr("aria-label","Export to .stash (encrypted with a password you choose)"),l.onclick=()=>void this.plugin.exportLockedSubtree(t.blob);let c=i.createSpan({cls:"stashpad-aggregate-lockbadge"});(0,Ce.setIcon)(c,"lock")}renderWatch(e){this.plugin.pruneReEncryptWatch()&&this.plugin.saveSettings();let t=this.plugin.settings.reEncryptWatch??[],i=t.filter(p=>!p.removed),s=t.filter(p=>p.removed);if(t.length===0){e.createDiv({cls:"stashpad-trash-empty",text:"Nothing here yet. When you unlock an encrypted note (or restore one from the trash), it shows up here so you can re-encrypt it later."});return}let n=e.createDiv({cls:"stashpad-trash-modes"}),o=n.createEl("select",{cls:"dropdown"});o.createEl("option",{value:"",text:"All folders"});for(let p of[...new Set(i.map(I=>I.folder))].sort())o.createEl("option",{value:p,text:p});o.value=this.watchFolderFilter,o.onchange=()=>{this.watchFolderFilter=o.value,this.render()};let r=n.createEl("select",{cls:"dropdown"});r.createEl("option",{value:"",text:"Unlocked + restored"}),r.createEl("option",{value:"unlock",text:"Unlocked"}),r.createEl("option",{value:"restore",text:"Restored from trash"}),r.value=this.watchViaFilter,r.onchange=()=>{this.watchViaFilter=r.value,this.render()};let l=n.createEl("input",{type:"text",attr:{placeholder:"Search\u2026"}});l.value=this.watchQuery,l.oninput=()=>{this.watchQuery=l.value,f()};let c=(p,I)=>p.toLowerCase().split(/\s+/).filter(Boolean).every(m=>I.toLowerCase().includes(m)),A=p=>(!this.watchFolderFilter||p.folder===this.watchFolderFilter)&&(!this.watchViaFilter||p.via===this.watchViaFilter)&&(!this.watchQuery.trim()||c(this.watchQuery,`${p.title} ${p.folder}`)),h=async()=>{await this.plugin.saveSettings(),this.render()},g=(p,I,m)=>{let B=p.createDiv({cls:"stashpad-trash-row"}),C=B.createDiv({cls:"stashpad-trash-row-main"});C.createSpan({cls:"stashpad-trash-title",text:this.plugin.reEncryptDisplayTitle(I)});let w=hn(I.unlockedAt).fromNow(),y=I.count>1?` \xB7 ${I.count} notes`:"";if(C.createSpan({cls:"stashpad-trash-sub",text:`${I.via==="restore"?"restored":"unlocked"} ${w} \xB7 ${I.folder.split("/").pop()||I.folder}${y}`}),m){let v=B.createEl("button",{cls:"stashpad-trash-iconbtn",text:"Un-remove"});v.onclick=()=>{delete I.removed,delete I.removedAt,h()}}else{let v=B.createEl("button",{cls:"stashpad-trash-restore",text:"Re-encrypt"});(0,Ce.setIcon)(v.createSpan({cls:"stashpad-btn-icon"}),"lock"),v.onclick=async()=>{v.disabled=!0,await this.plugin.lockNoteSubtree(I.folder,I.rootId,null,{})||(v.disabled=!1),this.render()};let E=B.createEl("input",{type:"number",cls:"stashpad-watch-peek",attr:{placeholder:"auto",title:"Auto re-encrypt after N idle minutes (blank = folder/global default, 0 = off)",min:"0"}});E.value=I.peekMin==null?"":String(I.peekMin),E.onchange=()=>{let b=E.value.trim(),D=Number(b);if(b==="")delete I.peekMin;else if(Number.isFinite(D)&&D>=0)I.peekMin=Math.floor(D);else{E.value=I.peekMin==null?"":String(I.peekMin);return}this.plugin.saveSettings()};let Q=B.createEl("button",{cls:"stashpad-trash-iconbtn"});(0,Ce.setIcon)(Q,"x"),Q.setAttr("aria-label","Remove from watchlist (recoverable below)"),Q.onclick=()=>{I.removed=!0,I.removedAt=new Date().toISOString(),h()}}},u=e.createDiv(),f=()=>{u.empty();let p=i.filter(A).sort((B,C)=>(C.unlockedAt||"").localeCompare(B.unlockedAt||"")),I=u.createDiv({cls:"stashpad-trash-group-head"});if((0,Ce.setIcon)(I.createSpan({cls:"stashpad-trash-group-icon"}),"history"),I.createSpan({text:"Watching"}),I.createSpan({cls:"stashpad-trash-group-count",text:String(p.length)}),i.length>0){let B=I.createEl("button",{cls:"stashpad-trash-iconbtn",text:"Re-encrypt all applicable"});B.onclick=()=>void this.plugin.encryptEverythingApplicable()}p.length===0&&u.createDiv({cls:"stashpad-trash-sub",text:i.length?"No matches for the current filters.":"Nothing being watched."});let m=u.createDiv({cls:"stashpad-trash-group"});for(let B of p)g(m,B,!1);if(s.length>0){let B=u.createEl("details",{cls:"stashpad-watch-removed"});B.createEl("summary",{text:`Removed from watchlist (${s.length})`});let C=B.createDiv({cls:"stashpad-trash-group"});for(let w of s.filter(A))g(C,w,!0)}};f()}async onClose(){this.contentEl.empty()}};async function Te(d,a){let{workspace:e}=d.app,t=e.getLeavesOfType(Xt).find(n=>n.getViewState()?.state?.mode===a);if(t){e.revealLeaf(t);return}let i=e.getMostRecentLeaf(),s=e.getLeaf("tab");await s.setViewState({type:Xt,active:!0,state:{mode:a}}),e.revealLeaf(s),pt(e,s,i,n=>d.registerEvent(n))}var qt=require("obsidian");we();var Pe=class Pe{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(),e=(this.host.plugin.settings.authorId??"").trim();if(!a||!e)return null;let t=a.replace(/[^\w\- ]+/g,"").trim().replace(/\s+/g,"-")||"author",i=`${this.host.noteFolder}/_authors/${t}-${e}.md`,s=a.replace(/[\[\]|]/g,"").trim()||t;return{link:`[[${i}|${s}]]`,path:i,name:a,id:e}}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(e=>{let t=e.parent?.path?.replace(/\/+$/,"")??"";if(t!==a&&!t.startsWith(a+"/")||e.path.includes("/_authors/"))return!1;let i=this.host.app.metadataCache.getFileCache(e)?.frontmatter;return typeof i?.id=="string"&&!!i.id})}async pacedFrontmatter(a,e){for(let s=0;s<a.length;s++){let n=this.host.app.vault.getAbstractFileByPath(a[s]);if(n instanceof qt.TFile){this.recentSelfWrites.set(n.path,Date.now());try{await this.host.app.fileManager.processFrontMatter(n,o=>e(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 e=this.currentAuthorLink();if(!e){new qt.Notice("Set your author name in Stashpad settings first.");return}let t=`-${e.id}`,i=a.scope==="selection"?this.host.getActionTargets().map(g=>g.file).filter(g=>!!g):this.fileBackedNotesInFolder();if(i.length===0){new qt.Notice(a.scope==="selection"?"No notes selected.":"No notes in this folder.");return}let s=[],n=[];for(let g of i){let u=this.host.app.metadataCache.getFileCache(g)?.frontmatter,f=typeof u?.author=="string"?u.author:"";if(!f.trim()){s.push(g.path);continue}if(f.includes(t)||!a.contributorMode)continue;(Array.isArray(u?.contributors)?u.contributors.filter(I=>typeof I=="string"):[]).some(I=>I.includes(t))||n.push(g.path)}let o=s.length+n.length;if(o===0){new qt.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(f=>{new _(this.host.app,"Claim authorship",`${g.join(" ")}? -Existing authors are never overwritten. This can be undone.`,"Claim",f).open()}))return}let r=this.host.noteFolder,l=e.link,c=new Set,A=async()=>{await this.pacedFrontmatter(s,(g,u)=>{typeof g.author=="string"&&g.author.trim()||(g.author=l),Array.isArray(g.contributors)&&g.contributors.some(f=>typeof f=="string"&&f.includes(t))&&(g.contributors=g.contributors.filter(f=>!(typeof f=="string"&&f.includes(t))),c.add(u))}),await this.pacedFrontmatter(n,g=>{let u=Array.isArray(g.contributors)?g.contributors.filter(f=>typeof f=="string"):[];u.some(f=>f.includes(t))||u.push(l),g.contributors=u})};this.ensureAuthorFile(e),await A(),this.host.plugin.getUndoStack(r).push({label:`Claim authorship (${o} note${o===1?"":"s"})`,undo:async()=>{await this.pacedFrontmatter(s,(g,u)=>{if(typeof g.author=="string"&&g.author.includes(t)&&delete g.author,c.has(u)){let f=Array.isArray(g.contributors)?g.contributors.filter(p=>typeof p=="string"):[];f.some(p=>p.includes(t))||f.push(l),g.contributors=f}}),await this.pacedFrontmatter(n,g=>{Array.isArray(g.contributors)&&(g.contributors=g.contributors.filter(u=>!(typeof u=="string"&&u.includes(t))))}),this.host.debouncedRender()},redo:async()=>{c.clear(),await A(),this.host.debouncedRender()}});let h=[];s.length&&h.push(`authored ${s.length}`),n.length&&h.push(`contributing to ${n.length}`),new qt.Notice(`Claimed authorship: ${h.join(", ")}. Undo available.`),this.host.debouncedRender()}async ensureAuthorFile(a){try{a.id&&this.host.plugin.authorRegistry.record({id:a.id,name:a.name});let e=`${this.host.noteFolder}/_authors`;if(await this.host.ensureFolder(e),await this.host.app.vault.adapter.exists(a.path))return;let t=a.id===(this.host.plugin.settings.authorId??"").trim(),i=this.host.plugin.buildAuthorStub({id:a.id,name:a.name,role:t?this.host.plugin.settings.authorRole:void 0,department:t?this.host.plugin.settings.authorDepartment:void 0},new Date().toISOString());await this.host.app.vault.create(a.path,i)}catch(e){console.warn("[Stashpad] ensureAuthorFile failed",e)}}collectAuthorIds(a){let e=new Set,t=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=t(s.author);if(n&&e.add(n),Array.isArray(s.contributors))for(let o of s.contributors){let r=t(o);r&&e.add(r)}}return Array.from(e)}pruneContribMaps(){let a=Date.now(),e=Pe.EXTERNAL_WRITE_GRACE_MS*20,t=Pe.EXTERNAL_QUIESCENCE_MS*12;for(let[i,s]of this.recentSelfWrites)a-s>e&&this.recentSelfWrites.delete(i);for(let[i,s]of this.lastExternalModify)a-s>t&&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 e=Date.now(),t=this.recentSelfWrites.get(a.path);t!==void 0&&e-t<Pe.EXTERNAL_WRITE_GRACE_MS||this.lastExternalModify.set(a.path,e),this.scheduleContribution(a)}scheduleContribution(a){let e=this.contribTimers.get(a.path);e&&clearTimeout(e);let t=this.isFileActivelyEdited(a),i=Pe.CONTRIB_DEBOUNCE_MS+(t?Pe.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<Pe.EXTERNAL_QUIESCENCE_MS){this.scheduleContribution(a);return}this.maybeRecordContribution(a)},i);this.contribTimers.set(a.path,s)}isFileActivelyEdited(a){try{let e=this.host.app.workspace.activeLeaf;if(!e)return!1;let t=e.view;if(!t||t.getViewType?.()!=="markdown"||t.file?.path!==a.path)return!1;let i=t.containerEl??null;return!!i&&i.contains(document.activeElement)}catch{return!1}}async maybeRecordContribution(a){let e="";try{e=await this.host.app.vault.cachedRead(a)}catch{return}let t=this.host.stripFrontmatter(e),i=this.knownBodies.get(a.path);if(this.knownBodies.set(a.path,t),i===void 0||i===t||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:"",l=Array.isArray(o.contributors)?o.contributors.filter(g=>typeof g=="string"):[],c=`-${s.id}`,A=r.includes(c),h=l.some(g=>g.includes(c));!A&&!h&&l.push(s.link),o.contributors=l})}catch(o){console.warn("[Stashpad] maybeRecordContribution failed",o)}}};Pe.CONTRIB_DEBOUNCE_MS=4e3,Pe.CONTRIB_ACTIVE_EDITOR_BONUS_MS=2e3,Pe.EXTERNAL_WRITE_GRACE_MS=1500,Pe.EXTERNAL_QUIESCENCE_MS=5e3;var gn=Pe;var un=class{constructor(a){this.host=a;this.dragSourceIds=null;this.dragPlaceholder=null;this.dragRowHeight=0}attachRowDnD(a,e,t){a.addEventListener("dragstart",i=>{let s=this.host.selection.has(e.id)&&this.host.selection.size>1?[...this.host.selection]:[e.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,l=this.dragPlaceholder.previousElementSibling;this.removeDragPlaceholder();let c,A="before";r&&r.classList.contains("stashpad-note")?(c=r.dataset.id,A="before"):l&&l.classList.contains("stashpad-note")&&(c=l.dataset.id,A="after"),c&&this.host.reorderToTarget(o,c,A)}),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,e.id,"into"):this.host.reorderToTarget(s,e.id,n==="drop-above"?"before":"after")})}attachListDnD(a){a.addEventListener("dragover",e=>{if(!this.dragSourceIds)return;let t=e.target;if(t&&t.closest&&t.closest(".stashpad-note"))return;e.preventDefault(),e.dataTransfer&&(e.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(e.clientY<n.top+n.height/2){this.placePlaceholder(s,"before");return}}this.placePlaceholder(i[i.length-1],"after")}}),a.addEventListener("drop",e=>{if(!this.dragSourceIds)return;e.preventDefault();let t=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(t,n,"before")}else if(s&&s.classList.contains("stashpad-note")){let n=s.dataset.id;n&&this.host.reorderToTarget(t,n,"after")}})}placePlaceholder(a,e){if(!this.dragPlaceholder||!this.host.listEl)return;let t=e==="before"?a:a.nextSibling;if(e==="before"&&this.dragPlaceholder.nextSibling===a||e==="after"&&this.dragPlaceholder.previousSibling===a)return;let i=!!this.dragPlaceholder.parentElement;this.host.listEl.insertBefore(this.dragPlaceholder,t),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,e){let t=e.getBoundingClientRect(),i=a.clientY-t.top;return i<t.height*.3?"drop-above":i>t.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 Qa=require("obsidian");var fn=class{constructor(a,e,t){this.host=a;this.component=e;this.bodyObserver=null;this.lazyBodies=new WeakMap;this.renderCache=t??new Map}async getOrComputeRender(a){let e=this.renderCache.get(a.path);if(e&&e.mtime===a.stat.mtime)return ke.record("render.row.cacheHit",0),e;let t=await ke.timeAsync("render.row.read",()=>this.host.app.vault.cachedRead(a)),i=this.host.stripFrontmatter(t),{text:s,attachments:n}=this.splitAttachments(i),o=createDiv({cls:"stashpad-note-text"});await ke.timeAsync("render.row.markdown",()=>Qa.MarkdownRenderer.render(this.host.app,s,o,a.path,this.component));let r=o.innerHTML,l={mtime:a.stat.mtime,text:s,attachments:n,html:r};return this.renderCache.set(a.path,l),l}arm(){this.bodyObserver?.disconnect(),this.lazyBodies=new WeakMap,this.bodyObserver=new IntersectionObserver(a=>{for(let e of a){if(!e.isIntersecting)continue;let t=e.target,i=this.lazyBodies.get(t);this.bodyObserver?.unobserve(t),this.lazyBodies.delete(t),i&&i()}},{root:this.host.contentEl,rootMargin:"1400px 0px"})}dispose(){this.bodyObserver?.disconnect(),this.bodyObserver=null}isArmed(){return!!this.bodyObserver}hasFreshRenderCache(a){let e=this.renderCache.get(a.path);return!!e&&e.mtime===a.stat.mtime}evict(a){let e=this.renderCache;e.evict?e.evict(a.path):e.delete&&e.delete(a.path)}defer(a,e){this.lazyBodies.set(a,e),this.bodyObserver?.observe(a)}splitAttachments(a){let e=[];return{text:a.replace(/!\[\[([^\]\|]+)(?:\|[^\]]+)?\]\]/g,(i,s)=>(e.push(s),"")).replace(/\n{3,}/g,` +`)}renderSuggestion(e,t){if(t.addClass("stashpad-suggest-item"),e.kind==="create"){t.createDiv({cls:"stashpad-suggest-create",text:e.label});return}if(e.kind==="folder-open"){t.addClass("is-folder-open"),t.createDiv({cls:"stashpad-suggest-title",text:e.label}),e.folder?t.createDiv({cls:"stashpad-suggest-preview",text:e.folder}):t.createDiv({cls:"stashpad-suggest-preview",text:"Click to choose a folder\u2026"});return}if(e.kind==="search-excluded"){t.addClass("is-search-excluded");let u=t.createDiv({cls:"stashpad-suggest-title stashpad-search-excluded-row"}),f=u.createSpan({cls:"stashpad-search-excluded-icon"});(0,pe.setIcon)(f,"folder-search"),u.createSpan({text:e.label}),t.createDiv({cls:"stashpad-suggest-preview",text:"Include folders you've excluded from search (e.g. to move a note there)."});return}if(e.locked){t.addClass("stashpad-suggest-row","is-locked");let u=t.createDiv({cls:"stashpad-suggest-body"}),f=u.createDiv({cls:"stashpad-suggest-title stashpad-suggest-locked"});(0,pe.setIcon)(f.createSpan({cls:"stashpad-suggest-locked-icon"}),"lock");let g=Lo(this.inputEl?.value??"").text;this.highlightInto(f.createSpan(),e.label,g),u.createDiv({cls:"stashpad-suggest-preview",text:e.locked.count>1?`${e.locked.count} notes \xB7 locked`:"Encrypted \u2014 locked"});return}e.crossFolder&&t.addClass("is-cross-folder"),t.addClass("stashpad-suggest-row");let i=t.createDiv({cls:"stashpad-suggest-body"}),s=this.notes.find(u=>e.crossFolder?u.cross?.folder===e.crossFolder&&u.cross?.id===e.crossId:u.node?.id===e.id),n=Lo(this.inputEl?.value??"").text,o=this.firstLineOfBody(s?.body??"")||e.label.trim(),r=i.createDiv({cls:"stashpad-suggest-title"});this.highlightInto(r,o,n);let l=e.crossFolder??this.opts.localFolder??null;if(e.bodyPreview&&e.matchLine!=null&&e.matchLine>=0){let u=i.createDiv({cls:"stashpad-suggest-preview stashpad-suggest-snippet"});this.highlightInto(u,e.bodyPreview,n)}let c="";if(e.crossFolder?c=s?.cross?.parentBlurb??"":c=this.parentBlurbFor(e.node),c){let u=i.createDiv({cls:"stashpad-suggest-preview"});u.appendText("Parent: "),this.highlightInto(u,c,n)}let A=e.crossFolder?this.buildCrossBreadcrumb(e):this.buildLocalBreadcrumb(e.node),h=e.crossFolder??this.opts.localFolder??null;if(h||A){let u=i.createDiv({cls:"stashpad-suggest-breadcrumb"}),g=[h?h.split("/").pop()||h:"",A].filter(I=>I&&I.length>0).join(" \u203A ");g&&u.setText(g)}let p=s?this.createdMsFor(s):null;if(p!=null||l){let u=t.createDiv({cls:"stashpad-suggest-rail"});if(p!=null){let f=u.createDiv({cls:"stashpad-suggest-time"});f.setText(this.formatRelativeTime(p)),f.title=Ie(p).format("YYYY-MM-DD HH:mm")}l&&u.createDiv({cls:"stashpad-suggest-folder-badge",text:l.split("/").pop()||l})}}formatRelativeTime(e){let t=Ie(e),i=Ie().startOf("day").diff(Ie(e).startOf("day"),"days");return i===0?t.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?t.format("MMM D"):t.format("MMM D, YYYY")}highlightInto(e,t,i){if(!t)return;let s=i.filter(c=>c&&c.length>0);if(!s.length){e.appendText(t);return}let n=t.toLowerCase(),o=[];for(let c of s){let A=0;for(;(A=n.indexOf(c,A))!==-1;)o.push([A,A+c.length]),A+=1}if(!o.length){e.appendText(t);return}o.sort((c,A)=>c[0]-A[0]);let r=[];for(let c of o){let A=r[r.length-1];A&&c[0]<=A[1]?A[1]=Math.max(A[1],c[1]):r.push([c[0],c[1]])}let l=0;for(let[c,A]of r)c>l&&e.appendText(t.slice(l,c)),e.createSpan({cls:"stashpad-suggest-match",text:t.slice(c,A)}),l=A;l<t.length&&e.appendText(t.slice(l))}buildLocalBreadcrumb(e){if(!e||!e.parent||e.parent===k)return"";let t=[],i=new Set([e.id]),s=this.tree.get(e.parent);for(;s&&s.id!==k&&!i.has(s.id);)i.add(s.id),t.unshift(this.titleFn(s)),s=s.parent&&s.parent!==k?this.tree.get(s.parent):void 0;return t.join(" \u203A ")}buildCrossBreadcrumb(e){if(!e.crossFolder)return"";if(!this.crossFolderIndex){this.crossFolderIndex=new Map;for(let l of this.notes){if(!l.cross)continue;let c=this.crossFolderIndex.get(l.cross.folder);c||(c=new Map,this.crossFolderIndex.set(l.cross.folder,c)),c.set(l.cross.id,l.cross)}}let t=this.crossFolderIndex.get(e.crossFolder);if(!t)return"";let i=e.crossId??e.id.replace(/^cross:/,""),s=t.get(i);if(!s)return"";let n=[],o=new Set([s.id]),r=s.parentId?t.get(s.parentId):null;for(;r&&!o.has(r.id);)o.add(r.id),n.unshift(r.title),r=r.parentId?t.get(r.parentId):null;return n.join(" \u203A ")}firstLineOfBody(e){if(!e)return"";let t=e.split(/\r?\n/);for(let i of t){let s=i.trim();if(s)return s}return""}parentBlurbFor(e){if(!e||!e.parent||e.parent===k)return"";let t=this.tree.get(e.parent);if(!t||!t.file)return"";let i=this.notes.find(s=>s.node?.id===t.id);return i?this.firstLineOfBody(i.body):""}onOpen(){if(super.onOpen(),this.opts.showFilterChips&&!pe.Platform.isMobile){let e=this.inputEl,t=this.resultContainerEl;if(!e||!t)return;this.mountFilterChipRow(e,t);return}if(pe.Platform.isMobile){let e=this.inputEl;e&&e.focus()}}mountFilterChipRow(e,t){e.addEventListener("keydown",c=>{if(c.key==="["){c.preventDefault();let A=e.selectionStart??e.value.length,h=e.selectionEnd??A,p=e.value.slice(0,A),u=e.value.slice(A,h),f=e.value.slice(h);e.value=`${p}[${u}]${f}`;let g=A+1+u.length;e.setSelectionRange(g,g),e.dispatchEvent(new Event("input",{bubbles:!0}));return}if(c.key==="]"){let A=e.selectionStart??-1;A>=0&&e.value[A]==="]"&&(c.preventDefault(),e.setSelectionRange(A+1,A+1));return}if(c.key==="Backspace"&&!c.metaKey&&!c.ctrlKey&&!c.altKey&&e.selectionStart===e.selectionEnd){let A=e.selectionStart??-1;if(A>0&&e.value[A-1]==="["&&e.value[A]==="]"){c.preventDefault();let h=e.value.slice(0,A-1),p=e.value.slice(A+1);e.value=`${h}${p}`,e.setSelectionRange(A-1,A-1),e.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",c=>{c.preventDefault()}),n.addEventListener("click",c=>{c.preventDefault(),this.appendFilterToInput(e,"in","")}),n.addEventListener("keydown",c=>{(c.key==="Enter"||c.key===" ")&&(c.preventDefault(),c.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",c=>{c.preventDefault()}),o.addEventListener("click",c=>{c.preventDefault(),this.toggleWhenBuilder(e,i)}),o.addEventListener("keydown",c=>{(c.key==="Enter"||c.key===" ")&&(c.preventDefault(),c.stopPropagation(),o.click())}),i.appendChild(o),t.parentElement?.insertBefore(i,t);let r=new pe.Scope(this.scope),l=c=>{let A=document.activeElement;return A?.classList?.contains("stashpad-search-filter-chip")?(c.preventDefault(),A.click(),!1):c.key==="Enter"&&!c.isComposing?(c.preventDefault(),this.selectActiveSuggestion?.(c),!1):!0};r.register([],"Enter",l),r.register([]," ",l),r.register(["Mod"],"f",c=>{c.preventDefault();let A=this.inputEl;return A&&(A.focus(),A.select()),!1}),r.register([],"Tab",c=>{let A=this.modalEl,h=this.inputEl;if(!A)return!0;let p=Array.from(A.querySelectorAll('input, button, select, textarea, a[href], [tabindex]:not([tabindex="-1"])')).filter(g=>!g.hasAttribute("disabled")&&g.tabIndex!==-1&&g.offsetParent!==null);if(p.length===0)return!0;let u=document.activeElement,f=u?p.indexOf(u):-1;if(c.shiftKey){if(f<=0)return c.preventDefault(),p[p.length-1].focus(),!1}else if(f===p.length-1)return c.preventDefault(),(h??p[0]).focus(),!1;return!0}),this.app.keymap?.pushScope(r),this.pendingCleanups.push(()=>{try{this.app.keymap?.popScope(r)}catch{}})}appendFilterToInput(e,t,i){let s=e.value,o=`${s.length>0&&!/\s$/.test(s)?" ":""}${t}: [`,r="]",l=i;e.value=`${s}${o}${l}${r}`;let c=s.length+o.length+l.length;if(e.setSelectionRange(c,c+0),!l){let A=s.length+o.length;e.setSelectionRange(A,A)}e.focus(),e.dispatchEvent(new Event("input",{bubbles:!0}))}toggleWhenBuilder(e,t){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 g of o){let I=document.createElement("button");I.type="button",I.className="stashpad-when-tab",I.textContent=g.label,this.whenMode===g.id&&I.addClass("is-active"),I.addEventListener("mousedown",m=>m.preventDefault()),I.addEventListener("click",m=>{if(m.preventDefault(),this.whenMode===g.id)return;let B=this.whenMode;B!=="between"&&g.id==="between"?this.whenBetweenEndText="":B==="between"&&g.id!=="between"&&(!this.whenSingleText&&this.whenBetweenEndText&&(this.whenSingleText=this.whenBetweenEndText),this.whenBetweenEndText=""),this.whenMode=g.id;for(let C in r)r[C].toggleClass("is-active",C===g.id);f()}),r[g.id]=I,n.appendChild(I)}s.appendChild(n);let l=document.createElement("div");l.className="stashpad-when-body",s.appendChild(l);let c=(g,I,m="single")=>{let B=Ie().format("YYYY-MM-DD"),C=!I||I===B;if(m==="betweenStart")return"00:00";if(m==="betweenEnd")return"23:59";switch(g){case"after":return"00:00";case"on":return C?Ie().format("HH:mm"):"23:59";case"before":return C?Ie().format("HH:mm"):"23:59";default:return"23:59"}},A=(g,I)=>{g.addEventListener("keydown",m=>{m.key==="Enter"?(m.preventDefault(),m.stopPropagation(),I()):m.key==="Escape"&&(m.preventDefault(),m.stopPropagation(),this.closeWhenBuilder())})},h=(g,I)=>{let m=g.selectionStart??g.value.length,B=g.selectionEnd??g.value.length,Q=`${m>0&&!/\s$/.test(g.value.slice(0,m))?" ":""}${I}`,y=g.value.slice(0,m)+Q+g.value.slice(B);g.value=y;let E=m+Q.length;g.setSelectionRange(E,E),g.focus(),g.dispatchEvent(new Event("input",{bubbles:!0}))},p=(g,I)=>{let B=g.slice(0,I).match(/(\d{4}-\d{2}-\d{2})(?!.*\d{4}-\d{2}-\d{2})/);return B?B[1]:null},u=(g,I,m,B)=>{let C=l.createDiv({cls:"stashpad-when-input-wrap has-icons"}),Q=C.createDiv({cls:"stashpad-when-icon-slot"}),y=Q.createEl("button",{cls:"stashpad-when-icon stashpad-when-icon-cal"});y.type="button",y.title="Pick date",(0,pe.setIcon)(y,"calendar-days");let E=Q.createEl("input",{cls:"stashpad-when-native",attr:{type:"date"}});E.tabIndex=-1;let w=C.createDiv({cls:"stashpad-when-icon-slot"}),v=w.createEl("button",{cls:"stashpad-when-icon stashpad-when-icon-clock"});v.type="button",v.title="Pick time",(0,pe.setIcon)(v,"clock");let F=C.createDiv({cls:"stashpad-when-icon-slot"}),D=F.createEl("button",{cls:"stashpad-when-icon stashpad-when-icon-day"});D.type="button",D.title="Pick day",(0,pe.setIcon)(D,"calendar");let R=C.createDiv({cls:"stashpad-when-icon-slot"}),G=R.createEl("button",{cls:"stashpad-when-icon stashpad-when-icon-tf"});G.type="button",G.title="Pick timeframe",(0,pe.setIcon)(G,"history");let x=C.createEl("input",{cls:"stashpad-when-input",attr:{type:"text",placeholder:g}});x.value=I(),x.addEventListener("input",()=>m(x.value));let H=C.createEl("button",{cls:"stashpad-when-clear"});H.type="button",H.textContent="\xD7",H.title="Clear";for(let O of[y,v,D,G,H])O.addEventListener("mousedown",L=>L.preventDefault());let U=null,N=(O,L)=>{U&&U();let K=O.createDiv({cls:"stashpad-when-popover"}),V=O.ownerDocument??document,Y=new pe.Scope(this.scope),$=null,j=te=>{$=te},ce=!1,re=te=>{!K.contains(te.target)&&te.target!==O&&!O.contains(te.target)&&se()},se=()=>{if(!ce){ce=!0,K.remove(),V.removeEventListener("mousedown",re,!0);try{this.app.keymap?.popScope(Y)}catch{}U===se&&(U=null)}};U=se,Y.register([],"Escape",te=>(te.preventDefault(),se(),!1)),Y.register([],"Enter",te=>(te.preventDefault(),$&&$(),!1));try{L(K,se,j)}catch(te){console.error("[stashpad] popover fill threw:",te),K.remove(),U=null;return}this.app.keymap?.pushScope(Y),this.pendingCleanups.push(se),setTimeout(()=>V.addEventListener("mousedown",re,!0),0)};G.addEventListener("click",O=>{O.preventDefault(),N(R,(L,K,V)=>{let Y=this.whenMode==="on",$=(ne,ve)=>{if(!Y)return`${ne}${ve}`;let xt={d:"days",w:"weeks",m:"months",y:"years"}[ve];return Ie().subtract(ne,xt).format("YYYY-MM-DD")},j=L.createDiv({cls:"stashpad-when-pop-row"}),ce=[{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 ne of ce){let ve=j.createEl("button",{cls:"stashpad-when-pop-chip",text:ne.label});ve.type="button",ve.addEventListener("mousedown",xt=>xt.preventDefault()),ve.addEventListener("click",xt=>{xt.preventDefault(),h(x,$(ne.n,ne.unit)),K()})}let re=L.createDiv({cls:"stashpad-when-pop-row stashpad-when-pop-builder"});re.createSpan({text:"Last",cls:"stashpad-when-pop-label"});let se=re.createEl("input",{cls:"stashpad-when-pop-number",attr:{type:"number",min:"1",max:"999",value:"7"}}),te=re.createEl("select",{cls:"stashpad-when-pop-unit"});for(let ne of[{v:"d",label:"days"},{v:"w",label:"weeks"},{v:"m",label:"months"},{v:"y",label:"years"}]){let ve=te.createEl("option",{text:ne.label});ve.value=ne.v}let ge=re.createEl("button",{cls:"stashpad-when-pop-chip stashpad-when-pop-go",text:"Insert"});ge.type="button";let xe=()=>{let ne=parseInt(se.value,10);!Number.isFinite(ne)||ne<1||(h(x,$(ne,te.value)),K())};ge.addEventListener("mousedown",ne=>ne.preventDefault()),ge.addEventListener("click",ne=>{ne.preventDefault(),xe()}),V(xe),se.focus(),se.select()})});let S=(O,L,K,V,Y)=>{N(L,($,j,ce)=>{Fs($,{seedH:K,seedM:V,seedPeriod:Y,close:j,setOnEnter:ce,onFinalize:re=>h(O,Hr(re))})})};D.addEventListener("click",O=>{O.preventDefault(),N(F,(L,K,V)=>{let Y=L.createDiv({cls:"stashpad-when-pop-row"});for(let se of["Today","Yesterday"]){let te=Y.createEl("button",{cls:"stashpad-when-pop-chip",text:se});te.type="button",te.addEventListener("mousedown",ge=>ge.preventDefault()),te.addEventListener("click",ge=>{ge.preventDefault(),h(x,se),K()})}let $=L.createDiv({cls:"stashpad-when-pop-row stashpad-when-pop-days"}),j=["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],re=(Ie().day()+6)%7;for(let se=0;se<j.length;se++){let te=j[se],ge=$.createEl("button",{cls:"stashpad-when-pop-chip",text:te.slice(0,3)});ge.type="button",ge.title=te,se===re&&ge.addClass("is-today"),ge.addEventListener("mousedown",xe=>xe.preventDefault()),ge.addEventListener("click",xe=>{if(xe.preventDefault(),B==="betweenEnd"){let ne=se,ve=Ie().startOf("day"),xt=(ve.day()+6)%7,Vn=(ne-xt+7)%7;Vn===0&&(Vn=7);let xl=ve.clone().add(Vn,"days").format("YYYY-MM-DD");h(x,xl)}else h(x,te);K()})}})});let P=(O,L)=>{O.value||(O.value=L);let K=O;if(typeof K.showPicker=="function")try{K.showPicker();return}catch{}O.focus(),O.click()};return y.addEventListener("click",O=>{O.preventDefault(),P(E,Ie().format("YYYY-MM-DD"))}),E.addEventListener("change",()=>{E.value&&h(x,E.value)}),v.addEventListener("click",O=>{O.preventDefault();let L=x.selectionStart??x.value.length,K=p(x.value,L),V=c(this.whenMode,K,B),[Y,$]=V.split(":"),j=parseInt(Y,10),ce=parseInt($,10),re=j%12;re===0&&(re=12);let se=j>=12?"pm":"am";S(x,w,re,ce,se)}),H.addEventListener("click",O=>{O.preventDefault(),x.value="",m(""),x.focus()}),x},f=()=>{if(l.empty(),this.whenMode==="between"){let g=u("start (date / day / timeframe)",()=>this.whenSingleText,y=>{this.whenSingleText=y},"betweenStart"),I=u("end (date / day / timeframe)",()=>this.whenBetweenEndText,y=>{this.whenBetweenEndText=y},"betweenEnd"),m=l.createDiv({cls:"stashpad-when-actions"}),B=m.createEl("button",{cls:"stashpad-when-insert",text:"Insert"});B.type="button",B.addEventListener("mousedown",y=>y.preventDefault());let C=()=>{let y=g.value.trim(),E=I.value.trim();y&&this.appendFilterToInput(e,"after",y),E&&this.appendFilterToInput(e,"before",E),this.closeWhenBuilder()};B.addEventListener("click",y=>{y.preventDefault(),C()});let Q=m.createEl("button",{cls:"stashpad-when-cancel",text:"Cancel"});Q.type="button",Q.addEventListener("mousedown",y=>y.preventDefault()),Q.addEventListener("click",y=>{y.preventDefault(),this.closeWhenBuilder()}),A(g,C),A(I,C),g.focus(),g.setSelectionRange(g.value.length,g.value.length)}else{let g=u("date / day / timeframe",()=>this.whenSingleText,Q=>{this.whenSingleText=Q},"single"),I=l.createDiv({cls:"stashpad-when-actions"}),m=I.createEl("button",{cls:"stashpad-when-insert",text:"Insert"});m.type="button",m.addEventListener("mousedown",Q=>Q.preventDefault());let B=()=>{let Q=g.value.trim();Q&&this.appendFilterToInput(e,this.whenMode,Q),this.closeWhenBuilder()};m.addEventListener("click",Q=>{Q.preventDefault(),B()});let C=I.createEl("button",{cls:"stashpad-when-cancel",text:"Cancel"});C.type="button",C.addEventListener("mousedown",Q=>Q.preventDefault()),C.addEventListener("click",Q=>{Q.preventDefault(),this.closeWhenBuilder()}),A(g,B),g.focus(),g.setSelectionRange(g.value.length,g.value.length)}};f(),t.parentElement?.insertBefore(s,t.nextSibling),this.whenBuilderEl=s}closeWhenBuilder(){if(!this.whenBuilderEl)return;this.whenBuilderEl.remove(),this.whenBuilderEl=null,this.modalEl?.removeClass("is-when-builder-open")}selectSuggestion(e,t){if(e&&e.kind==="search-excluded"){this.loadExcludedNotes();return}super.selectSuggestion(e,t)}onChooseSuggestion(e){if(e.kind==="create"&&this.opts.onCreate){let t=this.inputEl?.value??"",i=t.replace(/(?<![\w-])(in|before|after|on):\s*(?:\[[^\]]*\]|[^]*?(?=\s+(?:in|before|after|on):|$))/gi," ").replace(/\s+/g," ").trim();this.opts.onCreate(i||t);return}if(e.kind==="folder-open"&&e.id==="__folder_picker__"){let t=this.opts.folderResults?.()??[];if(!t.length)return;let i=this.inputEl?.value??"",s=!1,n=p=>{s=!0;let u=p.split("/").pop()??p;this.opts.onPick({id:`folder:${p}`,label:`Open folder \u201C${u}\u201D in a new tab`,node:null,kind:"folder-open",folder:p})},o=new Oo(this.app,t,n),r=o.onClose.bind(o),l=this.tree,c=this.titleFn,A=this.opts,h=this.app;o.onClose=()=>{r(),setTimeout(()=>{if(s)return;let p=new d(h,l,c,A);p.open(),setTimeout(()=>{let u=p.inputEl;u&&(i&&(u.value=i,u.dispatchEvent(new Event("input",{bubbles:!0}))),u.focus(),u.setSelectionRange(u.value.length,u.value.length))},0)},0)},o.open();return}if(e.node?.file&&!this.app.vault.getAbstractFileByPath(e.node.file.path)){new pe.Notice("That note no longer exists.");return}this.opts.onPick(e)}},Oo=class extends pe.FuzzySuggestModal{constructor(e,t,i){super(e);this.folders=t;this.onChosen=i;this.setPlaceholder("Open which folder?")}getItems(){return this.folders}getItemText(e){let t=e.split("/").pop()??e;return t===e?e:`${t} \u2014 ${e}`}onChooseItem(e){this.onChosen(e)}};var ns="stashpad";function An(d){let a=[];d.vault&&a.push(`vault=${encodeURIComponent(d.vault)}`),a.push(`folder=${encodeURIComponent(d.folder)}`),d.note&&a.push(`note=${encodeURIComponent(d.note)}`);let e=d.run&&d.run.length?d.run:["reveal"];return a.push(`run=${encodeURIComponent(e.join(","))}`),`obsidian://${ns}?${a.join("&")}`}function wa(d){let a=(d||"").trim();if(!a)return null;let e;if(/^obsidian:\/\//i.test(a)){let c=a.match(/^obsidian:\/\/([^?]*)(?:\?(.*))?$/i);if(!c||decodeURIComponent(c[1].replace(/\/+$/,"")).toLowerCase()!==ns)return null;e=c[2]??""}else e=a.replace(/^\?/,"");let t=new URLSearchParams(e),i=t.get("folder");if(!i)return null;let s={folder:i},n=t.get("vault");n&&(s.vault=n);let o=t.get("note");o&&(s.note=o);let r=t.get("run");r&&(s.run=r);let l=t.get("action");return l&&(s.action=l),s}function Ea(d){let a=d.run;!a&&d.action&&d.action!==ns&&(a=d.action);let e=(a||"reveal").split(",").map(t=>t.trim().toLowerCase()).filter(Boolean);return e.length?e:["reveal"]}var Te=require("obsidian");me();async function Qa(d,a,e,t){let i=e.blob,s=i.replace(/\.stashenc$/,".stashmeta"),n=d.vault.adapter,o=null,r=null;try{o=await n.readBinary(i)}catch{o=null}if(!o){new Te.Notice("Couldn't read the encrypted file to delete it.");return}try{await n.exists(s)&&(r=await n.read(s))}catch{r=null}let l=(a.settings.lockedSubtrees??[]).find(p=>p.blob===i)??null,c=async p=>{let u=d.vault.getAbstractFileByPath(p);if(u)try{await d.fileManager.trashFile(u);return}catch{}try{await n.exists(p)&&await n.remove(p)}catch{}},A=async()=>{await c(i),await c(s),a.settings.lockedSubtrees=(a.settings.lockedSubtrees??[]).filter(p=>p.blob!==i),await a.saveSettings(),t()},h=async()=>{if(await n.writeBinary(i,o),r!=null)try{await n.write(s,r)}catch{}l&&!(a.settings.lockedSubtrees??[]).some(p=>p.blob===i)&&(a.settings.lockedSubtrees=[...a.settings.lockedSubtrees??[],l],await a.saveSettings()),t()};await A(),a.getUndoStack(e.folder).push({label:e.count>1?"Delete encrypted notes":"Delete encrypted note",undo:h,redo:A}),new Te.Notice(e.count>1?"Encrypted notes deleted \u2014 undo to restore.":"Encrypted note deleted \u2014 undo to restore.")}function hn(d,a){let{app:e,plugin:t,descriptor:i}=a,s=p=>new Te.Notice(`Unlock this note first to ${p}.`),n=p=>{if(Te.Platform.isMobile)return p;try{return e.vault.adapter?.getFullPath?.(p)||p}catch{return p}},o=()=>{let p=An({vault:e.vault.getName(),folder:i.folder,note:i.rootId,run:["reveal"]});navigator.clipboard.writeText(p).then(()=>new Te.Notice("Stashpad link copied."),()=>new Te.Notice("Couldn't copy the link."))},r=()=>{d.addItem(p=>{p.setTitle("Share & export").setIcon("share-2");let u=typeof p.setSubmenu=="function"?p.setSubmenu():null;u&&typeof u.addItem=="function"?(u.addItem(f=>{f.setTitle("Copy Stashpad link").setIcon("link"),i.rootId?f.onClick(()=>o()):f.setDisabled(!0)}),u.addItem(f=>f.setTitle("Export to .stash\u2026").setIcon("package").onClick(()=>{t.exportLockedSubtree(i.blob)})),t.settings.okfEnabled&&u.addItem(f=>f.setTitle("Export as OKF\u2026").setIcon("book-marked").onClick(()=>s("export it as OKF")))):i.rootId?p.onClick(()=>o()):p.setDisabled(!0)})},l=()=>{d.addItem(p=>p.setTitle(a.unlockLabel).setIcon("unlock").onClick(()=>a.onUnlock()))},c=()=>{if(Te.Platform.isMobile)return;let p=Te.Platform.isMacOS?"Finder":Te.Platform.isWin?"File Explorer":"file manager";d.addItem(u=>u.setTitle(`Show in ${p}`).setIcon("folder-search").onClick(()=>{try{let f=window.require?.("electron")?.shell,g=e.vault.adapter?.getFullPath?.(i.blob);g&&f?.showItemInFolder&&f.showItemInFolder(g)}catch(f){console.warn("[Stashpad] showItemInFolder failed",f)}}))},A=()=>{d.addItem(p=>p.setTitle("Copy encrypted file path").setIcon("copy").onClick(()=>{navigator.clipboard.writeText(n(i.blob)),new Te.Notice("Path copied.")}))},h=()=>{d.addItem(p=>{p.setTitle(i.count>1?"Delete encrypted notes\u2026":"Delete encrypted note\u2026").setIcon("trash-2"),p.setWarning?.(!0),p.onClick(()=>{a.confirmDelete?new _(e,i.count>1?`Delete ${i.count} encrypted notes?`:"Delete encrypted note?","The encrypted file moves to Obsidian's trash (recoverable there). You'll still need your password to read it if you restore it.","Delete",async u=>{u&&await Qa(e,t,i,a.onChange)}).open():Qa(e,t,i,a.onChange)})})};a.fullParity?(d.addItem(p=>p.setTitle("Open in new Stashpad tab").setIcon("layout-grid").onClick(()=>s("open it in a tab"))),d.addItem(p=>p.setTitle("Open in editor").setIcon("file-text").onClick(()=>s("open it in the editor"))),d.addItem(p=>p.setTitle("Focus in Stashpad").setIcon("arrow-right").onClick(()=>s("focus it"))),d.addSeparator(),d.addItem(p=>p.setTitle("Split note\u2026").setIcon("split").onClick(()=>s("split it"))),d.addItem(p=>p.setTitle("Copy text").setIcon("copy").onClick(()=>s("copy its text"))),d.addItem(p=>p.setTitle("Clone (duplicate / copy)").setIcon("files").onClick(()=>s("clone it"))),d.addItem(p=>p.setTitle("Fork into a separate note\u2026").setIcon("git-branch").onClick(()=>s("fork it"))),r(),l(),c(),A(),d.addSeparator(),d.addItem(p=>p.setTitle("Move to\u2026").setIcon("move").onClick(()=>s("move it"))),d.addItem(p=>p.setTitle("Move to Home").setIcon("home").onClick(()=>s("move it"))),d.addItem(p=>p.setTitle("Pin to sidebar").setIcon("pin").onClick(()=>s("pin it"))),d.addItem(p=>p.setTitle("Pin to top of list").setIcon("arrow-up-to-line").onClick(()=>s("pin it"))),d.addItem(p=>p.setTitle("Set color\u2026").setIcon("palette").onClick(()=>s("set its color"))),d.addItem(p=>p.setTitle("Task").setIcon("check-circle-2").onClick(()=>s("change its task state"))),d.addSeparator(),h()):(l(),r(),d.addSeparator(),c(),A(),d.addSeparator(),h())}var va=require("obsidian");le();var pn=class extends va.SuggestModal{constructor(a){super(a),this.setPlaceholder("Run a Stashpad command\u2026");let e=this.app.commands?.commands??{};this.commands=Object.keys(e).filter(t=>t.startsWith("stashpad:")).filter(t=>t!=="stashpad:stashpad-command-palette").map(t=>({id:t,name:Pc(e[t]?.name??t)})).sort((t,i)=>t.name.localeCompare(i.name))}getSuggestions(a){return this.commands.filter(e=>Qs(a,e.name))}renderSuggestion(a,e){e.createDiv({text:a.name,cls:"stashpad-cmd-palette-name"})}onChooseSuggestion(a){this.app.commands?.executeCommandById?.(a.id)}};function Pc(d){return d.replace(/^(?:\s*Stashpad:\s*)+/i,"").trim()||d}me();var Ko=require("obsidian");function Fa(d){let a=d.code||"",e=/^Key([A-Z])$/.exec(a);if(e)return e[1].toLowerCase();let t=/^Digit(\d)$/.exec(a);return t?t[1]:(d.key||"").toLowerCase()}function Hc(d,a){return!a||d.metaKey||d.ctrlKey||d.altKey?!1:a.length===1&&!/[a-z0-9]/i.test(a)?d.key===a:Fa(d)===a.toLowerCase()}function yi(d,a){return a?a.includes("+")?Rc(d,a):Hc(d,a):!1}function q(d,a){if(!a)return!1;let{primary:e,secondary:t,preferRight:i,useBoth:s}=a;return e&&t?s?yi(d,e)||yi(d,t):i?yi(d,t):yi(d,e):yi(d,e)||yi(d,t)}function os(d){if(!d)return"";let a=Ko.Platform.isMacOS;return d.split("+").map(e=>{let t=e.trim();return t?t.toLowerCase()==="mod"?a?"Cmd":"Ctrl":t.toLowerCase()==="alt"?a?"Opt":"Alt":t.length===1?t.toUpperCase():t:""}).filter(Boolean).join("+")}function Rc(d,a){if(!a)return!1;let e=a.split("+").map(h=>h.trim()).filter(Boolean);if(e.length<2)return!1;let t=e[e.length-1].toLowerCase(),i=new Set(e.slice(0,-1).map(h=>h.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"),l=i.has("shift"),A=Ko.Platform.isMacOS?d.metaKey:d.ctrlKey;return s&&!A||n&&!d.ctrlKey||o&&!d.metaKey||r!==d.altKey||l!==d.shiftKey||!s&&(!n&&d.ctrlKey||!o&&d.metaKey)?!1:Fa(d)===t}var ie=require("obsidian");le();var ka=require("obsidian"),Uc="byfolder";function gn(d,a,e,t){let i=d.createDiv({cls:"stashpad-trash-modes"}),s=i.createEl("button",{cls:"stashpad-agg-reset",attr:{"aria-label":"Reset to default view"}});(0,ka.setIcon)(s,"rotate-ccw"),s.onclick=()=>t(Uc);let n=[{key:"byfolder",label:"By folder",count:e.total},{key:"separated",label:"Separated",count:e.total},{key:"mixed",label:"Mixed (by date)",count:e.total},{key:"encrypted",label:"Encrypted",count:e.enc},{key:"unencrypted",label:"Unencrypted",count:e.dec}];for(let o of n){let r=i.createEl("button",{cls:"stashpad-triage-chip"});a===o.key&&r.addClass("is-active"),r.createSpan({text:o.label}),r.createSpan({cls:"stashpad-triage-chip-count",text:String(o.count)}),r.onclick=()=>t(o.key)}}function gt(d,a,e,t){if(!e||e===a)return;let i=o=>{let r=!1;return d.iterateAllLeaves(l=>{l===o&&(r=!0)}),r},s=a,n=d.on("active-leaf-change",()=>{if(i(a)){s=d.activeLeaf??s;return}d.offref(n),s===a&&i(e)&&(d.setActiveLeaf(e,{focus:!0}),d.revealLeaf(e))});t?.(n)}var un=ie.moment,fn=class extends ie.ItemView{constructor(e,t){super(e);this.plugin=t;this.mode="encrypted";this.taskState=Ds();this.archiveSubMode="byfolder";this.renderPending=!1;this.watchFolderFilter="";this.watchViaFilter="";this.watchQuery=""}getViewType(){return Zt}getDisplayText(){return this.mode==="archived"?"All archived":this.mode==="tasks"?"All tasks":this.mode==="watch"?"Previously encrypted":"All encrypted"}getIcon(){return this.mode==="archived"?"archive":this.mode==="tasks"?"check-square":this.mode==="watch"?"history":"lock"}getState(){return{...super.getState(),mode:this.mode}}async setState(e,t){(e?.mode==="archived"||e?.mode==="encrypted"||e?.mode==="tasks"||e?.mode==="watch")&&(this.mode=e.mode),await super.setState(e,t),await this.render()}async onOpen(){this.containerEl.addClass("stashpad-aggregate-view");let e=s=>s.endsWith(".stashenc")&&!s.startsWith("_deleted/"),t=s=>s.endsWith(".md")&&/(^|\/)archive\//.test(s),i=s=>e(s)||t(s);this.registerEvent(this.app.vault.on("create",s=>{i(s.path)&&this.scheduleRender()})),this.registerEvent(this.app.vault.on("delete",s=>{i(s.path)&&this.scheduleRender()})),this.registerEvent(this.app.vault.on("rename",(s,n)=>{(i(s.path)||i(n))&&this.scheduleRender()})),await this.render()}scheduleRender(){this.renderPending||(this.renderPending=!0,window.setTimeout(()=>{this.renderPending=!1,this.render()},150))}cleanFolder(e){return(e||"").replace(/\/+$/,"")}archiveFolders(){let e=new Set;for(let i of this.plugin.discoverStashpadFolders()){let s=wt(i);this.plugin.app.vault.getAbstractFileByPath(s)&&e.add(s)}for(let i of this.plugin.settings.archiveFolders??[])e.add(this.cleanFolder(i));let t=this.plugin.settings.folderEncPrefs??{};for(let[i,s]of Object.entries(t))s?.archive&&e.add(this.cleanFolder(i));return[...e].sort((i,s)=>i.localeCompare(s))}async render(){let e=this.contentEl;e.empty(),e.addClass("stashpad-aggregate-body");let t=e.createDiv({cls:"stashpad-aggregate-header"});t.createEl("h3",{text:this.getDisplayText()});let i=t.createEl("button",{cls:"stashpad-trash-iconbtn"});if((0,ie.setIcon)(i,"refresh-cw"),i.setAttr("aria-label","Refresh"),i.onclick=()=>void this.render(),this.mode==="tasks"){zi(e.createDiv(),this.app,this.plugin,this.taskState,{onOpen:(s,n)=>void this.plugin.revealNoteByRef(s,n)});return}if(this.mode==="archived"){this.renderArchived(e);return}if(this.mode==="watch"){this.renderWatch(e);return}this.renderEncrypted(e)}renderEncrypted(e){let t=this.plugin.settings.lockedSubtrees??[];if(t.length===0){e.createDiv({cls:"stashpad-trash-empty",text:"Nothing is encrypted yet. Lock a note or folder and it shows up here."});return}let i=new Map;for(let n of t){let o=this.cleanFolder(n.folder)||"(vault root)";(i.get(o)??i.set(o,[]).get(o)).push(n)}let s=[...i.keys()].sort((n,o)=>n.localeCompare(o));e.createDiv({cls:"stashpad-aggregate-sub",text:`${t.length} locked ${t.length===1?"item":"items"} in ${s.length} ${s.length===1?"folder":"folders"}.`});for(let n of s){let o=e.createDiv({cls:"stashpad-trash-group"}),r=o.createDiv({cls:"stashpad-trash-group-head"});(0,ie.setIcon)(r.createSpan({cls:"stashpad-trash-group-icon"}),"folder"),r.createSpan({text:n.split("/").pop()||n}),r.createSpan({cls:"stashpad-trash-group-count",text:String(i.get(n).length)});let l=r.createEl("button",{cls:"stashpad-trash-iconbtn",text:"Open"});l.onclick=()=>void this.plugin.activateViewForFolder(n);for(let c of i.get(n)){let A=o.createDiv({cls:"stashpad-trash-row"}),h=A.createDiv({cls:"stashpad-trash-row-main"});h.createSpan({cls:"stashpad-trash-title",text:c.title||"Locked note"});let p=c.created?`locked ${un(c.created).fromNow()}`:"locked",u=c.count>1?` \xB7 ${c.count} notes`:"";h.createSpan({cls:"stashpad-trash-sub",text:p+u});let f=A.createEl("button",{cls:"stashpad-trash-iconbtn",text:"Export"});f.setAttr("aria-label","Export to .stash (encrypted with a password you choose)"),f.onclick=()=>void this.plugin.exportLockedSubtree(c.blob);let g=A.createSpan({cls:"stashpad-aggregate-lockbadge"});(0,ie.setIcon)(g,"lock"),this.attachLockedRowMenu(A,c,{archived:!1})}}}renderArchived(e){let t=this.archiveFolders();if(t.length===0){e.createDiv({cls:"stashpad-trash-empty",text:"No archive folders yet. Toggle Archive on a folder to collect it here."});return}let i=new Set(t),s=this.plugin.settings.lockedSubtrees??[],n=new Map;for(let g of s){let I=this.cleanFolder(g.folder);i.has(I)&&(n.get(I)??n.set(I,[]).get(I)).push(g)}let o=new Map,r=0;for(let g of t){let I=this.plugin.archivedPlainNotesIn(g);o.set(g,I),r+=I.length}let l=[...n.values()].reduce((g,I)=>g+I.length,0),c=r+l,A=t.flatMap(g=>o.get(g)??[]),h=t.flatMap(g=>n.get(g)??[]);e.createDiv({cls:"stashpad-aggregate-sub",text:`${t.length} archive ${t.length===1?"folder":"folders"}, ${c} archived ${c===1?"item":"items"} (${r} plain \xB7 ${l} locked).`}),gn(e,this.archiveSubMode,{total:c,enc:l,dec:r},g=>{this.archiveSubMode=g,this.render()});let p=this.archiveSubMode;if(p==="mixed"){let g=[];for(let m of A)g.push({ts:m.stat.mtime||0,kind:"plain",f:m});for(let m of h)g.push({ts:m.created&&Date.parse(m.created)||0,kind:"locked",e:m});g.sort((m,B)=>B.ts-m.ts);let I=e.createDiv({cls:"stashpad-trash-group"});for(let m of g)m.kind==="plain"&&m.f?this.archivePlainRow(I,m.f):m.e&&this.archiveLockedRow(I,m.e);return}if(p==="byfolder"){for(let g of t){let I=n.get(g)??[],m=o.get(g)??[],B=e.createDiv({cls:"stashpad-trash-group"}),C=B.createDiv({cls:"stashpad-trash-group-head"});(0,ie.setIcon)(C.createSpan({cls:"stashpad-trash-group-icon"}),"archive"),C.createSpan({text:g.split("/").pop()||g}),C.createSpan({cls:"stashpad-trash-group-count",text:String(I.length+m.length)});let Q=C.createEl("button",{cls:"stashpad-trash-iconbtn",text:"Open"});if(Q.onclick=()=>void this.plugin.activateViewForFolder(g),I.length===0&&m.length===0){B.createDiv({cls:"stashpad-trash-sub",text:"No archived items."});continue}for(let y of m)this.archivePlainRow(B,y);for(let y of I)this.archiveLockedRow(B,y)}return}let u=p!=="encrypted"&&A.length>0,f=p!=="unencrypted"&&h.length>0;if(!u&&!f){e.createDiv({cls:"stashpad-trash-empty",text:"Nothing in this view."});return}if(u){let g=e.createDiv({cls:"stashpad-trash-group"}),I=g.createDiv({cls:"stashpad-trash-group-head"});(0,ie.setIcon)(I.createSpan({cls:"stashpad-trash-group-icon"}),"file-text"),I.createSpan({text:"Plain notes"}),I.createSpan({cls:"stashpad-trash-group-count",text:String(A.length)});for(let m of A)this.archivePlainRow(g,m)}if(f){let g=e.createDiv({cls:"stashpad-trash-group"}),I=g.createDiv({cls:"stashpad-trash-group-head"});(0,ie.setIcon)(I.createSpan({cls:"stashpad-trash-group-icon"}),"lock"),I.createSpan({text:"Locked (encrypted)"}),I.createSpan({cls:"stashpad-trash-group-count",text:String(h.length)});for(let m of h)this.archiveLockedRow(g,m)}}archivePlainRow(e,t){let i=e.createDiv({cls:"stashpad-trash-row"}),s=i.createDiv({cls:"stashpad-trash-row-main"});s.createSpan({cls:"stashpad-trash-title",text:t.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||t.basename}),s.createSpan({cls:"stashpad-trash-sub",text:`archived ${un(t.stat.mtime).fromNow()}`});let n=i.createEl("button",{cls:"stashpad-trash-restore",text:"Restore"});(0,ie.setIcon)(n.createSpan({cls:"stashpad-btn-icon"}),"rotate-ccw"),n.onclick=async()=>{n.disabled=!0,await this.plugin.unarchiveNote(t)?this.render():n.disabled=!1},this.attachPlainRowMenu(i,t,n)}attachPlainRowMenu(e,t,i){let s=()=>{let o=new ie.Menu;return o.addItem(r=>r.setTitle("Open note").setIcon("file-text").onClick(()=>void this.app.workspace.getLeaf(!1).openFile(t))),o.addItem(r=>r.setTitle("Restore (un-archive)").setIcon("rotate-ccw").onClick(()=>i.click())),o.addSeparator(),ie.Platform.isMobile||o.addItem(r=>r.setTitle("Show in Finder").setIcon("folder-open").onClick(()=>{try{let l=window.require?.("electron")?.shell,c=this.app.vault.adapter?.getFullPath?.(t.path);c&&l?.showItemInFolder&&l.showItemInFolder(c)}catch(l){console.warn("[Stashpad] showItemInFolder failed",l)}})),o.addItem(r=>r.setTitle("Copy file path").setIcon("copy").onClick(()=>{let l=t.path;if(!ie.Platform.isMobile)try{l=this.app.vault.adapter?.getFullPath?.(t.path)||t.path}catch{}navigator.clipboard.writeText(l),new ie.Notice("Path copied.")})),o};e.oncontextmenu=o=>{o.preventDefault(),s().showAtMouseEvent(o)};let n=e.createEl("button",{cls:"stashpad-trash-iconbtn stashpad-agg-more"});(0,ie.setIcon)(n,"ellipsis-vertical"),n.setAttr("aria-label","More actions"),n.onclick=o=>{o.stopPropagation(),s().showAtMouseEvent(o)}}archiveLockedRow(e,t){let i=e.createDiv({cls:"stashpad-trash-row"}),s=i.createDiv({cls:"stashpad-trash-row-main"});s.createSpan({cls:"stashpad-trash-title",text:t.title||"Locked note"});let n=t.created?`archived ${un(t.created).fromNow()}`:"archived",o=(t.count??0)>1?` \xB7 ${t.count} notes`:"";s.createSpan({cls:"stashpad-trash-sub",text:n+o});let r=i.createEl("button",{cls:"stashpad-trash-restore",text:"Restore"});(0,ie.setIcon)(r.createSpan({cls:"stashpad-btn-icon"}),"rotate-ccw"),r.setAttr("aria-label","Unlock and restore (needs the password)"),r.onclick=async()=>{r.disabled=!0;let A=t.blob.split("/"),h=A.lastIndexOf("archive"),p=h>0?A.slice(0,h).join("/"):void 0;await this.plugin.unlockBundleAt(t.blob,p?{destFolder:p}:{})?this.render():r.disabled=!1};let l=i.createEl("button",{cls:"stashpad-trash-iconbtn",text:"Export"});l.setAttr("aria-label","Export to .stash (encrypted with a password you choose)"),l.onclick=()=>void this.plugin.exportLockedSubtree(t.blob);let c=i.createSpan({cls:"stashpad-aggregate-lockbadge"});(0,ie.setIcon)(c,"lock"),this.attachLockedRowMenu(i,t,{archived:!0})}attachLockedRowMenu(e,t,i){let s=()=>{let o=new ie.Menu;return hn(o,{app:this.app,plugin:this.plugin,descriptor:{blob:t.blob,rootId:t.rootId,count:t.count??1,folder:this.cleanFolder(t.folder)},unlockLabel:i.archived?"Unlock & restore":"Decrypt (unlock)",onUnlock:async()=>{let r;if(i.archived){let c=t.blob.split("/"),A=c.lastIndexOf("archive");r=A>0?c.slice(0,A).join("/"):void 0}await this.plugin.unlockBundleAt(t.blob,r?{destFolder:r}:{})&&this.render()},onChange:()=>void this.render(),fullParity:!1,confirmDelete:!1}),o};e.oncontextmenu=o=>{o.preventDefault(),s().showAtMouseEvent(o)};let n=e.createEl("button",{cls:"stashpad-trash-iconbtn stashpad-agg-more"});(0,ie.setIcon)(n,"ellipsis-vertical"),n.setAttr("aria-label","More actions"),n.onclick=o=>{o.stopPropagation(),s().showAtMouseEvent(o)}}renderWatch(e){this.plugin.pruneReEncryptWatch()&&this.plugin.saveSettings();let t=this.plugin.settings.reEncryptWatch??[],i=t.filter(g=>!g.removed),s=t.filter(g=>g.removed);if(t.length===0){e.createDiv({cls:"stashpad-trash-empty",text:"Nothing here yet. When you unlock an encrypted note (or restore one from the trash), it shows up here so you can re-encrypt it later."});return}let n=e.createDiv({cls:"stashpad-trash-modes"}),o=n.createEl("select",{cls:"dropdown"});o.createEl("option",{value:"",text:"All folders"});for(let g of[...new Set(i.map(I=>I.folder))].sort())o.createEl("option",{value:g,text:g});o.value=this.watchFolderFilter,o.onchange=()=>{this.watchFolderFilter=o.value,this.render()};let r=n.createEl("select",{cls:"dropdown"});r.createEl("option",{value:"",text:"Unlocked + restored"}),r.createEl("option",{value:"unlock",text:"Unlocked"}),r.createEl("option",{value:"restore",text:"Restored from trash"}),r.value=this.watchViaFilter,r.onchange=()=>{this.watchViaFilter=r.value,this.render()};let l=n.createEl("input",{type:"text",attr:{placeholder:"Search\u2026"}});l.value=this.watchQuery,l.oninput=()=>{this.watchQuery=l.value,f()};let c=(g,I)=>g.toLowerCase().split(/\s+/).filter(Boolean).every(m=>I.toLowerCase().includes(m)),A=g=>(!this.watchFolderFilter||g.folder===this.watchFolderFilter)&&(!this.watchViaFilter||g.via===this.watchViaFilter)&&(!this.watchQuery.trim()||c(this.watchQuery,`${g.title} ${g.folder}`)),h=async()=>{await this.plugin.saveSettings(),this.render()},p=(g,I,m)=>{let B=g.createDiv({cls:"stashpad-trash-row"}),C=B.createDiv({cls:"stashpad-trash-row-main"});C.createSpan({cls:"stashpad-trash-title",text:this.plugin.reEncryptDisplayTitle(I)});let Q=un(I.unlockedAt).fromNow(),y=I.count>1?` \xB7 ${I.count} notes`:"";if(C.createSpan({cls:"stashpad-trash-sub",text:`${I.via==="restore"?"restored":"unlocked"} ${Q} \xB7 ${I.folder.split("/").pop()||I.folder}${y}`}),m){let E=B.createEl("button",{cls:"stashpad-trash-iconbtn",text:"Un-remove"});E.onclick=()=>{delete I.removed,delete I.removedAt,h()}}else{let E=B.createEl("button",{cls:"stashpad-trash-restore",text:"Re-encrypt"});(0,ie.setIcon)(E.createSpan({cls:"stashpad-btn-icon"}),"lock"),E.onclick=async()=>{E.disabled=!0,await this.plugin.lockNoteSubtree(I.folder,I.rootId,null,{})||(E.disabled=!1),this.render()};let w=B.createEl("input",{type:"number",cls:"stashpad-watch-peek",attr:{placeholder:"auto",title:"Auto re-encrypt after N idle minutes (blank = folder/global default, 0 = off)",min:"0"}});w.value=I.peekMin==null?"":String(I.peekMin),w.onchange=()=>{let F=w.value.trim(),D=Number(F);if(F==="")delete I.peekMin;else if(Number.isFinite(D)&&D>=0)I.peekMin=Math.floor(D);else{w.value=I.peekMin==null?"":String(I.peekMin);return}this.plugin.saveSettings()};let v=B.createEl("button",{cls:"stashpad-trash-iconbtn"});(0,ie.setIcon)(v,"x"),v.setAttr("aria-label","Remove from watchlist (recoverable below)"),v.onclick=()=>{I.removed=!0,I.removedAt=new Date().toISOString(),h()}}},u=e.createDiv(),f=()=>{u.empty();let g=i.filter(A).sort((B,C)=>(C.unlockedAt||"").localeCompare(B.unlockedAt||"")),I=u.createDiv({cls:"stashpad-trash-group-head"});if((0,ie.setIcon)(I.createSpan({cls:"stashpad-trash-group-icon"}),"history"),I.createSpan({text:"Watching"}),I.createSpan({cls:"stashpad-trash-group-count",text:String(g.length)}),i.length>0){let B=I.createEl("button",{cls:"stashpad-trash-iconbtn",text:"Re-encrypt all applicable"});B.onclick=()=>void this.plugin.encryptEverythingApplicable()}g.length===0&&u.createDiv({cls:"stashpad-trash-sub",text:i.length?"No matches for the current filters.":"Nothing being watched."});let m=u.createDiv({cls:"stashpad-trash-group"});for(let B of g)p(m,B,!1);if(s.length>0){let B=u.createEl("details",{cls:"stashpad-watch-removed"});B.createEl("summary",{text:`Removed from watchlist (${s.length})`});let C=B.createDiv({cls:"stashpad-trash-group"});for(let Q of s.filter(A))p(C,Q,!0)}};f()}async onClose(){this.contentEl.empty()}};async function Pe(d,a){let{workspace:e}=d.app,t=e.getLeavesOfType(Zt).find(n=>n.getViewState()?.state?.mode===a);if(t){e.revealLeaf(t);return}let i=e.getMostRecentLeaf(),s=e.getLeaf("tab");await s.setViewState({type:Zt,active:!0,state:{mode:a}}),e.revealLeaf(s),gt(e,s,i,n=>d.registerEvent(n))}var $t=require("obsidian");me();var He=class He{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(),e=(this.host.plugin.settings.authorId??"").trim();if(!a||!e)return null;let t=a.replace(/[^\w\- ]+/g,"").trim().replace(/\s+/g,"-")||"author",i=`${this.host.noteFolder}/_authors/${t}-${e}.md`,s=a.replace(/[\[\]|]/g,"").trim()||t;return{link:`[[${i}|${s}]]`,path:i,name:a,id:e}}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(e=>{let t=e.parent?.path?.replace(/\/+$/,"")??"";if(t!==a&&!t.startsWith(a+"/")||e.path.includes("/_authors/"))return!1;let i=this.host.app.metadataCache.getFileCache(e)?.frontmatter;return typeof i?.id=="string"&&!!i.id})}async pacedFrontmatter(a,e){for(let s=0;s<a.length;s++){let n=this.host.app.vault.getAbstractFileByPath(a[s]);if(n instanceof $t.TFile){this.recentSelfWrites.set(n.path,Date.now());try{await this.host.app.fileManager.processFrontMatter(n,o=>e(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 e=this.currentAuthorLink();if(!e){new $t.Notice("Set your author name in Stashpad settings first.");return}let t=`-${e.id}`,i=a.scope==="selection"?this.host.getActionTargets().map(p=>p.file).filter(p=>!!p):this.fileBackedNotesInFolder();if(i.length===0){new $t.Notice(a.scope==="selection"?"No notes selected.":"No notes in this folder.");return}let s=[],n=[];for(let p of i){let u=this.host.app.metadataCache.getFileCache(p)?.frontmatter,f=typeof u?.author=="string"?u.author:"";if(!f.trim()){s.push(p.path);continue}if(f.includes(t)||!a.contributorMode)continue;(Array.isArray(u?.contributors)?u.contributors.filter(I=>typeof I=="string"):[]).some(I=>I.includes(t))||n.push(p.path)}let o=s.length+n.length;if(o===0){new $t.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(f=>{new _(this.host.app,"Claim authorship",`${p.join(" ")}? +Existing authors are never overwritten. This can be undone.`,"Claim",f).open()}))return}let r=this.host.noteFolder,l=e.link,c=new Set,A=async()=>{await this.pacedFrontmatter(s,(p,u)=>{typeof p.author=="string"&&p.author.trim()||(p.author=l),Array.isArray(p.contributors)&&p.contributors.some(f=>typeof f=="string"&&f.includes(t))&&(p.contributors=p.contributors.filter(f=>!(typeof f=="string"&&f.includes(t))),c.add(u))}),await this.pacedFrontmatter(n,p=>{let u=Array.isArray(p.contributors)?p.contributors.filter(f=>typeof f=="string"):[];u.some(f=>f.includes(t))||u.push(l),p.contributors=u})};this.ensureAuthorFile(e),await A(),this.host.plugin.getUndoStack(r).push({label:`Claim authorship (${o} note${o===1?"":"s"})`,undo:async()=>{await this.pacedFrontmatter(s,(p,u)=>{if(typeof p.author=="string"&&p.author.includes(t)&&delete p.author,c.has(u)){let f=Array.isArray(p.contributors)?p.contributors.filter(g=>typeof g=="string"):[];f.some(g=>g.includes(t))||f.push(l),p.contributors=f}}),await this.pacedFrontmatter(n,p=>{Array.isArray(p.contributors)&&(p.contributors=p.contributors.filter(u=>!(typeof u=="string"&&u.includes(t))))}),this.host.debouncedRender()},redo:async()=>{c.clear(),await A(),this.host.debouncedRender()}});let h=[];s.length&&h.push(`authored ${s.length}`),n.length&&h.push(`contributing to ${n.length}`),new $t.Notice(`Claimed authorship: ${h.join(", ")}. Undo available.`),this.host.debouncedRender()}async ensureAuthorFile(a){try{a.id&&this.host.plugin.authorRegistry.record({id:a.id,name:a.name});let e=`${this.host.noteFolder}/_authors`;if(await this.host.ensureFolder(e),await this.host.app.vault.adapter.exists(a.path))return;let t=a.id===(this.host.plugin.settings.authorId??"").trim(),i=this.host.plugin.buildAuthorStub({id:a.id,name:a.name,role:t?this.host.plugin.settings.authorRole:void 0,department:t?this.host.plugin.settings.authorDepartment:void 0},new Date().toISOString());await this.host.app.vault.create(a.path,i)}catch(e){console.warn("[Stashpad] ensureAuthorFile failed",e)}}collectAuthorIds(a){let e=new Set,t=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=t(s.author);if(n&&e.add(n),Array.isArray(s.contributors))for(let o of s.contributors){let r=t(o);r&&e.add(r)}}return Array.from(e)}pruneContribMaps(){let a=Date.now(),e=He.EXTERNAL_WRITE_GRACE_MS*20,t=He.EXTERNAL_QUIESCENCE_MS*12;for(let[i,s]of this.recentSelfWrites)a-s>e&&this.recentSelfWrites.delete(i);for(let[i,s]of this.lastExternalModify)a-s>t&&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 e=Date.now(),t=this.recentSelfWrites.get(a.path);t!==void 0&&e-t<He.EXTERNAL_WRITE_GRACE_MS||this.lastExternalModify.set(a.path,e),this.scheduleContribution(a)}scheduleContribution(a){let e=this.contribTimers.get(a.path);e&&clearTimeout(e);let t=this.isFileActivelyEdited(a),i=He.CONTRIB_DEBOUNCE_MS+(t?He.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<He.EXTERNAL_QUIESCENCE_MS){this.scheduleContribution(a);return}this.maybeRecordContribution(a)},i);this.contribTimers.set(a.path,s)}isFileActivelyEdited(a){try{let e=this.host.app.workspace.activeLeaf;if(!e)return!1;let t=e.view;if(!t||t.getViewType?.()!=="markdown"||t.file?.path!==a.path)return!1;let i=t.containerEl??null;return!!i&&i.contains(document.activeElement)}catch{return!1}}async maybeRecordContribution(a){let e="";try{e=await this.host.app.vault.cachedRead(a)}catch{return}let t=this.host.stripFrontmatter(e),i=this.knownBodies.get(a.path);if(this.knownBodies.set(a.path,t),i===void 0||i===t||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:"",l=Array.isArray(o.contributors)?o.contributors.filter(p=>typeof p=="string"):[],c=`-${s.id}`,A=r.includes(c),h=l.some(p=>p.includes(c));!A&&!h&&l.push(s.link),o.contributors=l})}catch(o){console.warn("[Stashpad] maybeRecordContribution failed",o)}}};He.CONTRIB_DEBOUNCE_MS=4e3,He.CONTRIB_ACTIVE_EDITOR_BONUS_MS=2e3,He.EXTERNAL_WRITE_GRACE_MS=1500,He.EXTERNAL_QUIESCENCE_MS=5e3;var In=He;var mn=class{constructor(a){this.host=a;this.dragSourceIds=null;this.dragPlaceholder=null;this.dragRowHeight=0}attachRowDnD(a,e,t){a.addEventListener("dragstart",i=>{let s=this.host.selection.has(e.id)&&this.host.selection.size>1?[...this.host.selection]:[e.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,l=this.dragPlaceholder.previousElementSibling;this.removeDragPlaceholder();let c,A="before";r&&r.classList.contains("stashpad-note")?(c=r.dataset.id,A="before"):l&&l.classList.contains("stashpad-note")&&(c=l.dataset.id,A="after"),c&&this.host.reorderToTarget(o,c,A)}),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,e.id,"into"):this.host.reorderToTarget(s,e.id,n==="drop-above"?"before":"after")})}attachListDnD(a){a.addEventListener("dragover",e=>{if(!this.dragSourceIds)return;let t=e.target;if(t&&t.closest&&t.closest(".stashpad-note"))return;e.preventDefault(),e.dataTransfer&&(e.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(e.clientY<n.top+n.height/2){this.placePlaceholder(s,"before");return}}this.placePlaceholder(i[i.length-1],"after")}}),a.addEventListener("drop",e=>{if(!this.dragSourceIds)return;e.preventDefault();let t=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(t,n,"before")}else if(s&&s.classList.contains("stashpad-note")){let n=s.dataset.id;n&&this.host.reorderToTarget(t,n,"after")}})}placePlaceholder(a,e){if(!this.dragPlaceholder||!this.host.listEl)return;let t=e==="before"?a:a.nextSibling;if(e==="before"&&this.dragPlaceholder.nextSibling===a||e==="after"&&this.dragPlaceholder.previousSibling===a)return;let i=!!this.dragPlaceholder.parentElement;this.host.listEl.insertBefore(this.dragPlaceholder,t),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,e){let t=e.getBoundingClientRect(),i=a.clientY-t.top;return i<t.height*.3?"drop-above":i>t.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 Sa=require("obsidian");var Cn=class{constructor(a,e,t){this.host=a;this.component=e;this.bodyObserver=null;this.lazyBodies=new WeakMap;this.renderCache=t??new Map}async getOrComputeRender(a){let e=this.renderCache.get(a.path);if(e&&e.mtime===a.stat.mtime)return ke.record("render.row.cacheHit",0),e;let t=await ke.timeAsync("render.row.read",()=>this.host.app.vault.cachedRead(a)),i=this.host.stripFrontmatter(t),{text:s,attachments:n}=this.splitAttachments(i),o=createDiv({cls:"stashpad-note-text"});await ke.timeAsync("render.row.markdown",()=>Sa.MarkdownRenderer.render(this.host.app,s,o,a.path,this.component));let r=o.innerHTML,l={mtime:a.stat.mtime,text:s,attachments:n,html:r};return this.renderCache.set(a.path,l),l}arm(){this.bodyObserver?.disconnect(),this.lazyBodies=new WeakMap,this.bodyObserver=new IntersectionObserver(a=>{for(let e of a){if(!e.isIntersecting)continue;let t=e.target,i=this.lazyBodies.get(t);this.bodyObserver?.unobserve(t),this.lazyBodies.delete(t),i&&i()}},{root:this.host.contentEl,rootMargin:"1400px 0px"})}dispose(){this.bodyObserver?.disconnect(),this.bodyObserver=null}isArmed(){return!!this.bodyObserver}hasFreshRenderCache(a){let e=this.renderCache.get(a.path);return!!e&&e.mtime===a.stat.mtime}evict(a){let e=this.renderCache;e.evict?e.evict(a.path):e.delete&&e.delete(a.path)}defer(a,e){this.lazyBodies.set(a,e),this.bodyObserver?.observe(a)}splitAttachments(a){let e=[];return{text:a.replace(/!\[\[([^\]\|]+)(?:\|[^\]]+)?\]\]/g,(i,s)=>(e.push(s),"")).replace(/\n{3,}/g,` -`).trim(),attachments:e}}};function Fa(d,a,e){return d.tree.getChildren(a).slice().sort((i,s)=>Pc(d,i,s,e)).map(i=>i.id)}function Pc(d,a,e,t){switch(t){case"created-asc":return(a.created||"").localeCompare(e.created||"");case"created-desc":return(e.created||"").localeCompare(a.created||"");case"modified-asc":case"modified-desc":{let i=va(d,a)||a.created||"",s=va(d,e)||e.created||"";return t==="modified-asc"?i.localeCompare(s):s.localeCompare(i)}case"title-az":case"title-za":{let i=d.titleForNode(a),s=d.titleForNode(e),n={numeric:!0,sensitivity:"base"};return t==="title-az"?i.localeCompare(s,void 0,n):s.localeCompare(i,void 0,n)}default:return 0}}function va(d,a){if(!a.file)return"";let e=d.app.metadataCache.getFileCache(a.file)?.frontmatter;return(typeof e?.modified=="string"?e.modified:"")||""}var yi=require("obsidian");Pi();async function Oo(d){let a=d.getActionTargets();if(!a.length)return;let e=X().prefixTimestampsOnCopy,t=[];for(let i of a){if(!i.file)continue;let s=await d.app.vault.cachedRead(i.file),n=d.stripFrontmatter(s).trim();t.push(e?`${d.formatTimeInline(i.created)} ${n}`:n)}await navigator.clipboard.writeText(t.join(` +`).trim(),attachments:e}}};function Da(d,a,e){return d.tree.getChildren(a).slice().sort((i,s)=>Gc(d,i,s,e)).map(i=>i.id)}function Gc(d,a,e,t){switch(t){case"created-asc":return(a.created||"").localeCompare(e.created||"");case"created-desc":return(e.created||"").localeCompare(a.created||"");case"modified-asc":case"modified-desc":{let i=ba(d,a)||a.created||"",s=ba(d,e)||e.created||"";return t==="modified-asc"?i.localeCompare(s):s.localeCompare(i)}case"title-az":case"title-za":{let i=d.titleForNode(a),s=d.titleForNode(e),n={numeric:!0,sensitivity:"base"};return t==="title-az"?i.localeCompare(s,void 0,n):s.localeCompare(i,void 0,n)}default:return 0}}function ba(d,a){if(!a.file)return"";let e=d.app.metadataCache.getFileCache(a.file)?.frontmatter;return(typeof e?.modified=="string"?e.modified:"")||""}var wi=require("obsidian");Hi();async function Jo(d){let a=d.getActionTargets();if(!a.length)return;let e=X().prefixTimestampsOnCopy,t=[];for(let i of a){if(!i.file)continue;let s=await d.app.vault.cachedRead(i.file),n=d.stripFrontmatter(s).trim();t.push(e?`${d.formatTimeInline(i.created)} ${n}`:n)}await navigator.clipboard.writeText(t.join(` -`)),d.plugin.notifications.show({message:`Copied ${d.titleList(a)} to clipboard`,kind:"success",category:"system",affectedIds:a.map(i=>i.id),folder:d.noteFolder})}async function ka(d){let a=d.getActionTargets();if(!a.length||!a[0].file){new yi.Notice("Nothing to copy from.");return}let e=a[0],t=await d.app.vault.cachedRead(e.file),i=d.stripFrontmatter(t),s=Dr(i);if(s.length===0){d.plugin.notifications.show({message:`No codeblock found in "${d.titleForNode(e)}".`,kind:"info",category:"system",affectedIds:[e.id],folder:d.noteFolder});return}if(s.length===1){await navigator.clipboard.writeText(s[0].code),d.plugin.notifications.show({message:`Copied codeblock${s[0].lang?` (${s[0].lang})`:""} from "${d.titleForNode(e)}".`,kind:"success",category:"system",affectedIds:[e.id],folder:d.noteFolder});return}let n=s.map((r,l)=>({kind:"one",idx:l,label:`${l+1}. ${r.lang||"(no language)"} \u2014 ${r.code.split(` +`)),d.plugin.notifications.show({message:`Copied ${d.titleList(a)} to clipboard`,kind:"success",category:"system",affectedIds:a.map(i=>i.id),folder:d.noteFolder})}async function xa(d){let a=d.getActionTargets();if(!a.length||!a[0].file){new wi.Notice("Nothing to copy from.");return}let e=a[0],t=await d.app.vault.cachedRead(e.file),i=d.stripFrontmatter(t),s=Nr(i);if(s.length===0){d.plugin.notifications.show({message:`No codeblock found in "${d.titleForNode(e)}".`,kind:"info",category:"system",affectedIds:[e.id],folder:d.noteFolder});return}if(s.length===1){await navigator.clipboard.writeText(s[0].code),d.plugin.notifications.show({message:`Copied codeblock${s[0].lang?` (${s[0].lang})`:""} from "${d.titleForNode(e)}".`,kind:"success",category:"system",affectedIds:[e.id],folder:d.noteFolder});return}let n=s.map((r,l)=>({kind:"one",idx:l,label:`${l+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 yi.SuggestModal{getSuggestions(r){let l=r.trim().toLowerCase();if(!l)return n;let c=l.split(/\s+/).filter(Boolean);return n.filter(A=>{let h=A.label.toLowerCase();return c.every(g=>h.includes(g))})}renderSuggestion(r,l){l.createDiv({cls:"stashpad-suggest-title",text:r.label})}async onChooseSuggestion(r){let l=r.kind==="all"?s.map(c=>c.code).join(` +`)?"\u2026":""}`}));n.push({kind:"all",idx:-1,label:`Copy all ${s.length} blocks (joined with blank lines)`});let o=new class extends wi.SuggestModal{getSuggestions(r){let l=r.trim().toLowerCase();if(!l)return n;let c=l.split(/\s+/).filter(Boolean);return n.filter(A=>{let h=A.label.toLowerCase();return c.every(p=>h.includes(p))})}renderSuggestion(r,l){l.createDiv({cls:"stashpad-suggest-title",text:r.label})}async onChooseSuggestion(r){let l=r.kind==="all"?s.map(c=>c.code).join(` -`):s[r.idx].code;await navigator.clipboard.writeText(l),d.plugin.notifications.show({message:r.kind==="all"?`Copied all ${s.length} codeblocks from "${d.titleForNode(e)}".`:`Copied codeblock${s[r.idx].lang?` (${s[r.idx].lang})`:""} from "${d.titleForNode(e)}".`,kind:"success",category:"system",affectedIds:[e.id],folder:d.noteFolder})}}(d.app);o.setPlaceholder(`${s.length} codeblocks in "${d.titleForNode(e)}" \u2014 pick one to copy.`),o.open()}async function Sa(d){let a=d.getActionTargets();if(a.length===0){let n=d.tree.get(d.focusId);n?.file&&(a=[n])}if(a.length===0){new yi.Notice("Nothing to copy.");return}let e=X().prefixTimestampsOnCopy,t=[],i=async(n,o)=>{if(n.file){let r=await d.app.vault.cachedRead(n.file),l=d.stripFrontmatter(r).trim().split(/\r?\n/).join(" "),c=e?`${d.formatTimeInline(n.created)} `:"";t.push(`${" ".repeat(o)}- ${c}${l}`)}for(let r of d.tree.getChildren(n.id))await i(r,o+1)};for(let n of a)await i(n,0);let s=t.join(` -`);await navigator.clipboard.writeText(s),d.plugin.clearNoteClipboard(),d.plugin.noteClipboard={mode:"copy",folder:d.noteFolder,ids:a.map(n=>n.id),text:s},d.render(),d.plugin.notifications.show({message:`Copied tree of ${d.titleList(a)} (${t.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:d.noteFolder})}async function ba(d){let a=d.getActionTargets();if(a.length===0){let i=d.tree.get(d.focusId);i?.file&&(a=[i])}if(a.length===0){new yi.Notice("Nothing to copy.");return}let e=[],t=(i,s)=>{if(!i.file)return;let n=" ".repeat(s);e.push(`${n}- ![[${i.file.basename}]]`);for(let o of d.tree.getChildren(i.id))t(o,s+1)};for(let i of a)t(i,0);await navigator.clipboard.writeText(e.join(` -`)),d.plugin.notifications.show({message:`Copied outline of ${d.titleList(a)} (${e.length} entr${e.length===1?"y":"ies"})`,kind:"success",category:"system",affectedIds:a.map(i=>i.id),folder:d.noteFolder})}var Qe=require("obsidian");ae();var wn=require("obsidian");yn();ot();ae();var tt="stash",Xa=1;function tr(d){let e=(d.split(/[\\/]/).pop()??"").trim();return!e||e==="."||e===".."||e.includes("/")||e.includes("\\")||e.includes("..")?"":e}var ir=/!\[\[([^\]\|]+)(?:\|[^\]]+)?\]\]/g;async function ft(d,a){let e=[],t=od([...a.rootNotes,...a.allDescendants]),i=new Map,s=[];for(let o of t){let r=await d.vault.read(o.file),l=r,c=Za(r);for(let A of c){let h=d.metadataCache.getFirstLinkpathDest(A,o.file.path);if(!h){s.push(`Missing attachment "${A}" in ${o.file.path}`);continue}let g=h.name;i.has(g)||i.set(g,await d.vault.readBinary(h)),l=rd(l,A,g)}l=cd(l,d,o.file.path),e.push({name:`notes/${o.file.name}`,data:l})}for(let[o,r]of i)e.push({name:`attachments/${o}`,data:r});let n={stashSchema:Xa,exportedAt:new Date().toISOString(),sourceFolder:a.sourceFolder,noteCount:t.length,rootIds:a.rootNotes.map(o=>o.id)};return e.push({name:"manifest.json",data:JSON.stringify(n,null,2)}),s.length&&e.push({name:"warnings.txt",data:s.join(` -`)}),cs(e,6)}async function Je(d,a,e,t,i={}){let s=await wi(a),n=s["manifest.json"];if(!n)throw new Error("Not a valid .stash package: missing manifest.json");let o=JSON.parse(Bn(n));if(typeof o.stashSchema!="number"||o.stashSchema>Xa)throw new Error(`Unsupported .stash schema: v${o.stashSchema}`);await Wa(d,e);let r=Object.entries(s).filter(([v])=>v.startsWith("notes/")&&v.endsWith(".md")),l=[];for(let[v,E]of r){let Q=Bn(E),{fm:b,body:D}=de(Q),H=tr(v.slice(6))||tr(`${b.id||"imported-"+Ae(4)}.md`)||`imported-${Ae(4)}.md`;l.push({originalName:H,fm:b,body:D})}let c=new Map,A=0;for(let v of l){let E=v.fm.id;E&&(i.forceNewIds?c.set(E,Ae(6)):t.has(E)||c.has(E)?(c.set(E,`${E}-${Ae(4)}-Imported`),A++):c.set(E,E))}let h=new Date().toISOString(),g=[],u=`${e}/_attachments`,f=0,p=Object.entries(s).filter(([v])=>v.startsWith("attachments/")),I=new Map,m=null;if(i.dedupeExisting){m=new Map;for(let v of d.vault.getFiles())m.has(v.name)||m.set(v.name,v.path)}let B=(v,E)=>{if(v.length!==E.length)return!1;for(let Q=0;Q<v.length;Q++)if(v[Q]!==E[Q])return!1;return!0},C=!1;for(let[v,E]of p){let Q=tr(v.slice(12));if(!Q)continue;let b=E,D=[],H=m?.get(Q);H&&D.push(H);let G=`${u}/${Q}`;await d.vault.adapter.exists(G)&&D.push(G);let x=null;for(let R of D)try{if(B(new Uint8Array(await d.vault.adapter.readBinary(R)),b)){x=R;break}}catch{}if(x){I.set(Q,x);continue}let U=G;for(let R=1;await d.vault.adapter.exists(U);R++)U=`${u}/${ad(Q,R)}`;I.set(Q,U),C||(await Wa(d,u),C=!0),await d.vault.createBinary(U,b.buffer),f++}let w=0;for(let v of l){let E=v.fm.id;if(!E){g.push(`Skipped ${v.originalName} \u2014 no id in frontmatter`);continue}let Q=c.get(E),b=v.fm.parent??null,D=b;!b||b===S?D=i.reparentRootsTo??b??S:c.has(b)?D=c.get(b):D=t.has(b)?b:i.reparentRootsTo??S;let H=ld(v.body,I,u),G=v.fm;if(i.stripReserved){let k={};for(let[P,O]of Object.entries(v.fm))ze.includes(P)||(k[P]=O);v.fm.author!==void 0&&(k.author=v.fm.author),v.fm.contributors!==void 0&&(k.contributors=v.fm.contributors),v.fm.created!==void 0&&(k.created=v.fm.created),v.fm.modified!==void 0&&(k.modified=v.fm.modified),Array.isArray(v.fm.attachments)&&(k.attachments=v.fm.attachments),G=k}let x={...G,id:Q,parent:D,import_date:h};Array.isArray(x.attachments)&&(x.attachments=x.attachments.map(k=>{let P=ja(Mt(k));return Ve(I.get(P)??`${u}/${P}`)}));let U=bt(x,H),R=Q===E?v.originalName:Ad(v.originalName,E,Q),M=`${e}/${R}`;await d.vault.adapter.exists(M)&&(R=`${R.replace(/\.md$/,"")}-${Ae(4)}.md`,M=`${e}/${R}`),await d.vault.create(M,U),w++}let y;if(o.colorAliases&&typeof o.colorAliases=="object"){let v={};for(let[E,Q]of Object.entries(o.colorAliases)){let b=String(E).trim().toLowerCase(),D=String(Q??"").trim();/^#([0-9a-f]{6})$/.test(b)&&D&&(v[b]=D.slice(0,60))}Object.keys(v).length&&(y=v)}return{notesWritten:w,attachmentsWritten:f,collisionsRenamed:A,warnings:g,colorAliases:y,idRemap:Object.fromEntries(c)}}function od(d){let a=new Set,e=[];for(let t of d)a.has(t.id)||(a.add(t.id),e.push(t));return e}function Za(d){let a=new Set,e;for(ir.lastIndex=0;(e=ir.exec(d))!==null;)a.add(e[1]);return[...a]}async function $t(d,a){let e=await d.vault.read(a),t=[],i=new Set;for(let s of Za(e)){let n=d.metadataCache.getFirstLinkpathDest(s,a.path);n&&!i.has(n.path)&&(i.add(n.path),t.push(n))}return t}function rd(d,a,e){return d.replace(new RegExp(`!\\[\\[${dd(a)}(\\|[^\\]]+)?\\]\\]`,"g"),(t,i)=>`![[${e}${i??""}]]`)}function ad(d,a){let e=d.lastIndexOf(".");return e>0?`${d.slice(0,e)}-${a}${d.slice(e)}`:`${d}-${a}`}function ld(d,a,e){return d.replace(ir,(t,i,s)=>{if(i.includes("/"))return t;let n=a.get(i)??`${e}/${i}`;return t.replace(i,n)})}function cd(d,a,e){let t=de(d);if(!t.fm.attachments||!Array.isArray(t.fm.attachments))return d;let i=t.fm.attachments.map(n=>{let o=a.metadataCache.getFirstLinkpathDest(n,e);return o?o.name:ja(n)}),s={...t.fm,attachments:i};return bt(s,t.body)}function dd(d){return d.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function ja(d){let a=d.lastIndexOf("/");return a<0?d:d.slice(a+1)}function Ad(d,a,e){return d.includes(a)?d.replace(a,e):d.replace(/\.md$/,`-${e}.md`)}function de(d){if(!d.startsWith("---"))return{fm:{},body:d};let a=d.indexOf(` ----`,3);if(a<0)return{fm:{},body:d};let e=d.slice(3,a).replace(/^\n/,""),t=d.slice(a+4),i={};try{i=(0,wn.parseYaml)(e)??{}}catch{i={}}let s=t.startsWith(` -`)?t.slice(1):t;return{fm:i,body:s}}function bt(d,a){return`--- -${(0,wn.stringifyYaml)(d).trimEnd()} +`):s[r.idx].code;await navigator.clipboard.writeText(l),d.plugin.notifications.show({message:r.kind==="all"?`Copied all ${s.length} codeblocks from "${d.titleForNode(e)}".`:`Copied codeblock${s[r.idx].lang?` (${s[r.idx].lang})`:""} from "${d.titleForNode(e)}".`,kind:"success",category:"system",affectedIds:[e.id],folder:d.noteFolder})}}(d.app);o.setPlaceholder(`${s.length} codeblocks in "${d.titleForNode(e)}" \u2014 pick one to copy.`),o.open()}async function Na(d){let a=d.getActionTargets();if(a.length===0){let n=d.tree.get(d.focusId);n?.file&&(a=[n])}if(a.length===0){new wi.Notice("Nothing to copy.");return}let e=X().prefixTimestampsOnCopy,t=[],i=async(n,o)=>{if(n.file){let r=await d.app.vault.cachedRead(n.file),l=d.stripFrontmatter(r).trim().split(/\r?\n/).join(" "),c=e?`${d.formatTimeInline(n.created)} `:"";t.push(`${" ".repeat(o)}- ${c}${l}`)}for(let r of d.tree.getChildren(n.id))await i(r,o+1)};for(let n of a)await i(n,0);let s=t.join(` +`);await navigator.clipboard.writeText(s),d.plugin.clearNoteClipboard(),d.plugin.noteClipboard={mode:"copy",folder:d.noteFolder,ids:a.map(n=>n.id),text:s},d.render(),d.plugin.notifications.show({message:`Copied tree of ${d.titleList(a)} (${t.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:d.noteFolder})}async function Ma(d){let a=d.getActionTargets();if(a.length===0){let i=d.tree.get(d.focusId);i?.file&&(a=[i])}if(a.length===0){new wi.Notice("Nothing to copy.");return}let e=[],t=(i,s)=>{if(!i.file)return;let n=" ".repeat(s);e.push(`${n}- ![[${i.file.basename}]]`);for(let o of d.tree.getChildren(i.id))t(o,s+1)};for(let i of a)t(i,0);await navigator.clipboard.writeText(e.join(` +`)),d.plugin.notifications.show({message:`Copied outline of ${d.titleList(a)} (${e.length} entr${e.length===1?"y":"ies"})`,kind:"success",category:"system",affectedIds:a.map(i=>i.id),folder:d.noteFolder})}var Qe=require("obsidian");le();var vn=require("obsidian");Qn();rt();le();var it="stash",el=1;function sr(d){let e=(d.split(/[\\/]/).pop()??"").trim();return!e||e==="."||e===".."||e.includes("/")||e.includes("\\")||e.includes("..")?"":e}var nr=/!\[\[([^\]\|]+)(?:\|[^\]]+)?\]\]/g;async function It(d,a){let e=[],t=cd([...a.rootNotes,...a.allDescendants]),i=new Map,s=[];for(let o of t){let r=await d.vault.read(o.file),l=r,c=tl(r);for(let A of c){let h=d.metadataCache.getFirstLinkpathDest(A,o.file.path);if(!h){s.push(`Missing attachment "${A}" in ${o.file.path}`);continue}let p=h.name;i.has(p)||i.set(p,await d.vault.readBinary(h)),l=dd(l,A,p)}l=pd(l,d,o.file.path),e.push({name:`notes/${o.file.name}`,data:l})}for(let[o,r]of i)e.push({name:`attachments/${o}`,data:r});let n={stashSchema:el,exportedAt:new Date().toISOString(),sourceFolder:a.sourceFolder,noteCount:t.length,rootIds:a.rootNotes.map(o=>o.id)};return e.push({name:"manifest.json",data:JSON.stringify(n,null,2)}),s.length&&e.push({name:"warnings.txt",data:s.join(` +`)}),ds(e,6)}async function qe(d,a,e,t,i={}){let s=await Ei(a),n=s["manifest.json"];if(!n)throw new Error("Not a valid .stash package: missing manifest.json");let o=JSON.parse(En(n));if(typeof o.stashSchema!="number"||o.stashSchema>el)throw new Error(`Unsupported .stash schema: v${o.stashSchema}`);await _a(d,e);let r=Object.entries(s).filter(([E])=>E.startsWith("notes/")&&E.endsWith(".md")),l=[];for(let[E,w]of r){let v=En(w),{fm:F,body:D}=Ae(v),R=sr(E.slice(6))||sr(`${F.id||"imported-"+he(4)}.md`)||`imported-${he(4)}.md`;l.push({originalName:R,fm:F,body:D})}let c=new Map,A=0;for(let E of l){let w=E.fm.id;w&&(i.forceNewIds?c.set(w,he(6)):t.has(w)||c.has(w)?(c.set(w,`${w}-${he(4)}-Imported`),A++):c.set(w,w))}let h=new Date().toISOString(),p=[],u=`${e}/_attachments`,f=0,g=Object.entries(s).filter(([E])=>E.startsWith("attachments/")),I=new Map,m=null;if(i.dedupeExisting){m=new Map;for(let E of d.vault.getFiles())m.has(E.name)||m.set(E.name,E.path)}let B=(E,w)=>{if(E.length!==w.length)return!1;for(let v=0;v<E.length;v++)if(E[v]!==w[v])return!1;return!0},C=!1;for(let[E,w]of g){let v=sr(E.slice(12));if(!v)continue;let F=w,D=[],R=m?.get(v);R&&D.push(R);let G=`${u}/${v}`;await d.vault.adapter.exists(G)&&D.push(G);let x=null;for(let U of D)try{if(B(new Uint8Array(await d.vault.adapter.readBinary(U)),F)){x=U;break}}catch{}if(x){I.set(v,x);continue}let H=G;for(let U=1;await d.vault.adapter.exists(H);U++)H=`${u}/${Ad(v,U)}`;I.set(v,H),C||(await _a(d,u),C=!0),await d.vault.createBinary(H,F.buffer),f++}let Q=0;for(let E of l){let w=E.fm.id;if(!w){p.push(`Skipped ${E.originalName} \u2014 no id in frontmatter`);continue}let v=c.get(w),F=E.fm.parent??null,D=F;!F||F===k?D=i.reparentRootsTo??F??k:c.has(F)?D=c.get(F):D=t.has(F)?F:i.reparentRootsTo??k;let R=hd(E.body,I,u),G=E.fm;if(i.stripReserved){let S={};for(let[P,O]of Object.entries(E.fm))Ve.includes(P)||(S[P]=O);E.fm.author!==void 0&&(S.author=E.fm.author),E.fm.contributors!==void 0&&(S.contributors=E.fm.contributors),E.fm.created!==void 0&&(S.created=E.fm.created),E.fm.modified!==void 0&&(S.modified=E.fm.modified),Array.isArray(E.fm.attachments)&&(S.attachments=E.fm.attachments),G=S}let x={...G,id:v,parent:D,import_date:h};Array.isArray(x.attachments)&&(x.attachments=x.attachments.map(S=>{let P=il(Tt(S));return We(I.get(P)??`${u}/${P}`)}));let H=Dt(x,R),U=v===w?E.originalName:ud(E.originalName,w,v),N=`${e}/${U}`;await d.vault.adapter.exists(N)&&(U=`${U.replace(/\.md$/,"")}-${he(4)}.md`,N=`${e}/${U}`),await d.vault.create(N,H),Q++}let y;if(o.colorAliases&&typeof o.colorAliases=="object"){let E={};for(let[w,v]of Object.entries(o.colorAliases)){let F=String(w).trim().toLowerCase(),D=String(v??"").trim();/^#([0-9a-f]{6})$/.test(F)&&D&&(E[F]=D.slice(0,60))}Object.keys(E).length&&(y=E)}return{notesWritten:Q,attachmentsWritten:f,collisionsRenamed:A,warnings:p,colorAliases:y,idRemap:Object.fromEntries(c)}}function cd(d){let a=new Set,e=[];for(let t of d)a.has(t.id)||(a.add(t.id),e.push(t));return e}function tl(d){let a=new Set,e;for(nr.lastIndex=0;(e=nr.exec(d))!==null;)a.add(e[1]);return[...a]}async function Yt(d,a){let e=await d.vault.read(a),t=[],i=new Set;for(let s of tl(e)){let n=d.metadataCache.getFirstLinkpathDest(s,a.path);n&&!i.has(n.path)&&(i.add(n.path),t.push(n))}return t}function dd(d,a,e){return d.replace(new RegExp(`!\\[\\[${gd(a)}(\\|[^\\]]+)?\\]\\]`,"g"),(t,i)=>`![[${e}${i??""}]]`)}function Ad(d,a){let e=d.lastIndexOf(".");return e>0?`${d.slice(0,e)}-${a}${d.slice(e)}`:`${d}-${a}`}function hd(d,a,e){return d.replace(nr,(t,i,s)=>{if(i.includes("/"))return t;let n=a.get(i)??`${e}/${i}`;return t.replace(i,n)})}function pd(d,a,e){let t=Ae(d);if(!t.fm.attachments||!Array.isArray(t.fm.attachments))return d;let i=t.fm.attachments.map(n=>{let o=a.metadataCache.getFirstLinkpathDest(n,e);return o?o.name:il(n)}),s={...t.fm,attachments:i};return Dt(s,t.body)}function gd(d){return d.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function il(d){let a=d.lastIndexOf("/");return a<0?d:d.slice(a+1)}function ud(d,a,e){return d.includes(a)?d.replace(a,e):d.replace(/\.md$/,`-${e}.md`)}function Ae(d){if(!d.startsWith("---"))return{fm:{},body:d};let a=d.indexOf(` +---`,3);if(a<0)return{fm:{},body:d};let e=d.slice(3,a).replace(/^\n/,""),t=d.slice(a+4),i={};try{i=(0,vn.parseYaml)(e)??{}}catch{i={}}let s=t.startsWith(` +`)?t.slice(1):t;return{fm:i,body:s}}function Dt(d,a){return`--- +${(0,vn.stringifyYaml)(d).trimEnd()} --- -${a}`}async function Wa(d,a){if(!(!a||await d.vault.adapter.exists(a)))try{await d.vault.createFolder(a)}catch(t){let i=t?.message??"";if(!/already exists/i.test(i))throw t}}Fs();we();yn();var it="stashenc",_a="stashmeta",ds="stashpack";function Re(d){return d.replace(/\.(stashenc|stashpack)$/,`.${_a}`)}async function vn(d,a){try{return JSON.parse(await d.vault.adapter.read(Re(a)))}catch{return null}}async function It(d,a,e){let t=a.replace(/\/+$/,""),i=[];for(let c of d.vault.getMarkdownFiles()){if((c.parent?.path?.replace(/\/+$/,"")??"")!==t)continue;let A;try{A=de(await d.vault.read(c)).fm}catch{continue}typeof A.id=="string"&&i.push({id:A.id,file:c,parent:typeof A.parent=="string"?A.parent:null,created:typeof A.created=="string"?A.created:""})}let s=i.find(c=>c.id===e);if(!s)return null;let n=new Map;for(let c of i){if(!c.parent)continue;let A=n.get(c.parent)??[];A.push(c),n.set(c.parent,A)}let o=[],r=new Set([e]),l=[e];for(;l.length;){let c=[];for(let A of l)for(let h of n.get(A)??[])r.has(h.id)||(r.add(h.id),o.push(h),c.push(h.id));l=c}return{rootNote:s,descendants:o,parentId:s.parent}}function En(d){if(!d)return null;let a=d.replace(/\/+$/,"");return!a||a.startsWith("/")||a.includes("\\")||/^[a-zA-Z]:/.test(a)||a.split("/").some(e=>e===".."||e===".")?null:a}async function Fn(d,a,e){await d.vault.adapter.writeBinary(a,e);let t;try{t=new Uint8Array(await d.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=t.length===e.length;if(i){for(let s=0;s<e.length;s++)if(t[s]!==e[s]){i=!1;break}}if(!i){try{await d.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 Ei(d){return d.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||d.basename}function Qi(d){return(d.replace(/[\\/:*?"<>|]+/g," ").replace(/\s+/g," ").trim()||"locked").slice(0,60)}async function sr(d,a,e){let t=new Set(a.map(r=>r.file.path)),i=new Map;for(let r of a)for(let l of await $t(d,r.file))i.set(l.path,l);let s=new Set,n=d.metadataCache.resolvedLinks??{};for(let r of Object.keys(n))if(!t.has(r))for(let l of Object.keys(n[r]??{}))i.has(l)&&s.add(l);let o=[];for(let r of a){let l=e?.get(r.file.path);if(l!=null)try{let c=await d.vault.adapter.stat(r.file.path);if(c&&c.mtime!==l){console.warn("[Stashpad] note changed since it was bundled \u2014 keeping plaintext",r.file.path),o.push(r.file.path);continue}}catch{}try{await d.vault.delete(r.file)}catch(c){console.warn("[Stashpad] couldn't delete plaintext note",r.file.path,c),o.push(r.file.path)}}for(let[r,l]of i){if(s.has(r))continue;let c=e?.get(r);if(c!=null)try{let A=await d.vault.adapter.stat(r);if(A&&A.mtime!==c){console.warn("[Stashpad] attachment changed since it was bundled \u2014 keeping plaintext",r),o.push(r);continue}}catch{}try{await d.vault.delete(l)}catch(A){console.warn("[Stashpad] couldn't delete exclusive attachment",r,A),o.push(r)}}return{unpurged:o}}async function el(d,a,e,t,i=null,s=!1,n){let o=await It(d,a,e);if(!o)throw new Error("Couldn't find that note to lock.");let{rootNote:r,descendants:l,parentId:c}=o,A=[r,...l],h=new Map;for(let y of A){try{let v=await d.vault.adapter.stat(y.file.path);v&&h.set(y.file.path,v.mtime)}catch{}for(let v of await $t(d,y.file))try{let E=await d.vault.adapter.stat(v.path);E&&h.set(v.path,E.mtime)}catch{}}let g=await ft(d,{rootNotes:[{id:r.id,file:r.file}],allDescendants:l.map(y=>({id:y.id,file:y.file})),sourceFolder:a}),u=await es(g,t),f=await Oe(u,t);if(f.length!==g.length)throw new Error("Encryption self-check failed (size mismatch).");for(let y=0;y<g.length;y++)if(f[y]!==g[y])throw new Error("Encryption self-check failed (content mismatch).");let p=(n??a).replace(/\/+$/,"");n&&!await d.vault.adapter.exists(p)&&await d.vault.adapter.mkdir(p);let I=Qi(s?e:Ei(r.file)),m=`${p}/${I}.${it}`;for(let y=1;await d.vault.adapter.exists(m);y++)m=`${p}/${I} (${y}).${it}`;await Fn(d,m,u);let B=A,C={v:1,parentId:c,title:s?"":Ei(r.file),count:B.length,created:r.created,rootId:e,prevSibling:i};try{await d.vault.adapter.write(Re(m),JSON.stringify(C))}catch(y){console.warn("[Stashpad] couldn't write lock sidecar",y)}let{unpurged:w}=await sr(d,B,h);return{blobPath:m,noteCount:B.length,rootId:e,parentId:c,title:C.title,created:r.created,unpurged:w}}async function tl(d,a,e,t,i){let s=new Uint8Array(await d.vault.adapter.readBinary(a));if(!Me(s))throw new Error("Not an encrypted bundle.");let n=await Oe(s,e),o=En(i)??a.replace(/\/[^/]*$/,""),r=await Je(d,n,o,t,{dedupeExisting:!0});await d.vault.adapter.remove(a);try{await d.vault.adapter.remove(Re(a))}catch{}return{notesWritten:r.notesWritten,restoredTo:o}}var Qn="_deleted";function hd(d){let a="";for(let e=0;e<d.length;e++)a+=String.fromCharCode(d[e]);return btoa(a)}function pd(d){let a=atob(d),e=new Uint8Array(a.length);for(let t=0;t<a.length;t++)e[t]=a.charCodeAt(t);return e}async function As(d,a,e,t){let i=En(e?.originalFolder);if(!i&&e?.originalFolderEnc&&t)try{i=En(new TextDecoder().decode(await Oe(pd(e.originalFolderEnc),t)))}catch{i=null}let s=a.replace(/\/[^/]*$/,""),n=/(^|\/)trash$/.test(s)?s.replace(/\/?trash$/,""):"";if(i&&n&&i!==n&&!await d.vault.adapter.exists(i)&&(i=n||null),i)return await d.vault.adapter.exists(i)||await d.vault.adapter.mkdir(i),i;if(s===Qn||s.startsWith(`${Qn}/`))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.");if(/(^|\/)trash$/.test(s)){let o=s.replace(/\/?trash$/,"");if(o)return await d.vault.adapter.exists(o)||await d.vault.adapter.mkdir(o),o;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 il(d,a,e,t,i,s=!1,n,o=Qn){let r=await It(d,a,e);if(!r)throw new Error("Couldn't find that note to delete.");let{rootNote:l,descendants:c,parentId:A}=r,h=[l,...c],g=new Map;for(let E of h){try{let Q=await d.vault.adapter.stat(E.file.path);Q&&g.set(E.file.path,Q.mtime)}catch{}for(let Q of await $t(d,E.file))try{let b=await d.vault.adapter.stat(Q.path);b&&g.set(Q.path,b.mtime)}catch{}}let u=await ft(d,{rootNotes:[{id:l.id,file:l.file}],allDescendants:c.map(E=>({id:E.id,file:E.file})),sourceFolder:a}),f=await es(u,t),p=await Oe(f,t);if(p.length!==u.length)throw new Error("Encryption self-check failed (size).");for(let E=0;E<u.length;E++)if(p[E]!==u[E])throw new Error("Encryption self-check failed (content).");{let E=o.replace(/\/+$/,"").split("/").filter(Boolean),Q="";for(let b of E){Q=Q?`${Q}/${b}`:b;try{await d.vault.adapter.exists(Q)||await d.vault.adapter.mkdir(Q)}catch{}}}let I=a.replace(/\/+$/,""),m=I.split("/").pop()||"vault",B=Qi(s?e:`${m} ${Ei(l.file)}`),C=`${o}/${B}.${it}`;for(let E=1;await d.vault.adapter.exists(C);E++)C=`${o}/${B} (${E}).${it}`;await Fn(d,C,f);let w=h,y={v:1,kind:"deleted",originalFolder:s?"":I,...s?{originalFolderEnc:hd(await es(new TextEncoder().encode(I),t))}:{},parentId:A,title:s?"":Ei(l.file),count:w.length,created:l.created,rootId:e,deletedAt:i,...n?{keyId:n}:{}};try{await d.vault.adapter.write(Re(C),JSON.stringify(y))}catch(E){console.warn("[Stashpad] couldn't write deleted sidecar \u2014 aborting delete, keeping plaintext",E);try{await d.vault.adapter.remove(C)}catch{}throw new Error("Couldn't write trash metadata \u2014 the note was NOT deleted (kept intact).")}let{unpurged:v}=await sr(d,w,g);return{blobPath:C,noteCount:w.length,rootId:e,originalFolder:I,title:y.title,unpurged:v}}async function sl(d,a,e,t){let i=new Uint8Array(await d.vault.adapter.readBinary(a));if(!Me(i))throw new Error("Not an encrypted bundle.");let s=await st(d,a),n=await As(d,a,s,e),o=await Oe(i,e),r=await Je(d,o,n,t,{dedupeExisting:!0});await d.vault.adapter.remove(a);try{await d.vault.adapter.remove(Re(a))}catch{}return{notesWritten:r.notesWritten,restoredTo:n}}async function st(d,a){try{return JSON.parse(await d.vault.adapter.read(Re(a)))}catch{return null}}async function nl(d,a,e,t,i){let s=await It(d,a,e);if(!s)throw new Error("Couldn't find that note to delete.");let{rootNote:n,descendants:o,parentId:r}=s,l=[n,...o],c=new Map;for(let m of l){try{let B=await d.vault.adapter.stat(m.file.path);B&&c.set(m.file.path,B.mtime)}catch{}for(let B of await $t(d,m.file))try{let C=await d.vault.adapter.stat(B.path);C&&c.set(B.path,C.mtime)}catch{}}let A=await ft(d,{rootNotes:[{id:n.id,file:n.file}],allDescendants:o.map(m=>({id:m.id,file:m.file})),sourceFolder:a});{let m=i.replace(/\/+$/,"").split("/").filter(Boolean),B="";for(let C of m){B=B?`${B}/${C}`:C;try{await d.vault.adapter.exists(B)||await d.vault.adapter.mkdir(B)}catch{}}}let h=a.replace(/\/+$/,""),g=h.split("/").pop()||"vault",u=Qi(`${g} ${Ei(n.file)}`),f=`${i}/${u}.${ds}`;for(let m=1;await d.vault.adapter.exists(f);m++)f=`${i}/${u} (${m}).${ds}`;await Fn(d,f,A);let p={v:1,kind:"deleted",originalFolder:h,parentId:r,title:Ei(n.file),count:l.length,created:n.created,rootId:e,deletedAt:t,encrypted:!1};try{await d.vault.adapter.write(Re(f),JSON.stringify(p))}catch(m){console.warn("[Stashpad] couldn't write trash sidecar \u2014 aborting delete, keeping plaintext",m);try{await d.vault.adapter.remove(f)}catch{}throw new Error("Couldn't write trash metadata \u2014 the note was NOT deleted (kept intact).")}let{unpurged:I}=await sr(d,l,c);return{blobPath:f,noteCount:l.length,rootId:e,originalFolder:h,title:p.title,unpurged:I}}async function ol(d,a,e){let t=new Uint8Array(await d.vault.adapter.readBinary(a)),i=await st(d,a),s=await As(d,a,i),n=await Je(d,t,s,e,{dedupeExisting:!0});await d.vault.adapter.remove(a);try{await d.vault.adapter.remove(Re(a))}catch{}return{notesWritten:n.notesWritten,restoredTo:s}}async function rl(d,a){let e=[];for(let t of a)try{if(!await d.vault.adapter.exists(t))continue;let i=await d.vault.adapter.list(t);e.push(...i.files.filter(s=>s.endsWith(`.${ds}`)))}catch{}return e}async function nr(d,a){await d.vault.adapter.remove(a);try{await d.vault.adapter.remove(Re(a))}catch{}}var Yt=".trash";async function gd(d,a){let e=[],t=[a];for(;t.length;){let i=t.shift(),s;try{s=await d.vault.adapter.list(i)}catch{continue}e.push(...s.files),t.push(...s.folders)}return e}function al(d){let a=d.split("/").filter(Boolean);if(a.length===0)return null;for(let e of a)if(e===".."||e==="."||e.includes("\\")||/^[a-zA-Z]:/.test(e))return null;return a.join("/")}async function ll(d,a,e){let t=new Uint8Array(await d.vault.adapter.readBinary(a));if(!Me(t))throw new Error("Not an encrypted bundle.");let i=await Oe(t,e),s=await wi(i),n=0;for(let[o,r]of Object.entries(s)){if(!o.startsWith("files/"))continue;let l=al(o.slice(6));if(!l){console.warn("[Stashpad] skipped unsafe trash entry",o);continue}let c=`${Yt}/${l}`.split("/").slice(0,-1).join("/"),A="";for(let g of c.split("/"))A=A?`${A}/${g}`:g,await d.vault.adapter.exists(A)||await d.vault.adapter.mkdir(A);let h=`${Yt}/${l}`;for(let g=1;await d.vault.adapter.exists(h);g++)h=`${Yt}/${l.replace(/(\.[^./]*)?$/,` (${g})$1`)}`;await d.vault.adapter.writeBinary(h,r.buffer),n++}await d.vault.adapter.remove(a);try{await d.vault.adapter.remove(Re(a))}catch{}return{filesWritten:n}}async function cl(d,a,e,t,i){let s=a.replace(/\/+$/,""),n=(await gd(d,s)).filter(p=>!p.endsWith(`.${it}`)&&!p.endsWith(`.${_a}`));if(n.length===0)throw new Error("This folder has no files to encrypt.");let o=[],r=new Map;for(let p of n){o.push({name:`files/${p.slice(s.length+1)}`,data:await d.vault.adapter.readBinary(p)});try{let I=await d.vault.adapter.stat(p);I&&r.set(p,I.mtime)}catch{}}let l=await cs(o),c=await es(l,e),A=await Oe(c,e);if(A.length!==l.length)throw new Error("Encryption self-check failed (size).");for(let p=0;p<l.length;p++)if(A[p]!==l[p])throw new Error("Encryption self-check failed (content).");let h=Qi(s.split("/").pop()||"folder"),g=`${s}/${h}.${it}`;for(let p=1;await d.vault.adapter.exists(g);p++)g=`${s}/${h} (${p}).${it}`;await Fn(d,g,c);let u={v:1,kind:"rawfolder",originalFolder:s,parentId:null,title:s.split("/").pop()||"",count:n.length,created:i,rootId:"",deletedAt:i,...t?{keyId:t}:{}};try{await d.vault.adapter.write(Re(g),JSON.stringify(u))}catch(p){console.warn("[Stashpad] couldn't write rawfolder sidecar",p)}let f=[];for(let p of n){let I=r.get(p);try{if(I!=null){let m=await d.vault.adapter.stat(p);if(m&&m.mtime!==I){f.push(p);continue}}await d.vault.adapter.remove(p)}catch(m){console.warn("[Stashpad] couldn't delete file",p,m),f.push(p)}}if(f.length===0){let p=[...new Set(n.map(I=>I.slice(0,I.lastIndexOf("/"))))].filter(I=>I.length>s.length).sort((I,m)=>m.length-I.length);for(let I of p)try{let m=await d.vault.adapter.list(I);!m.files.length&&!m.folders.length&&await d.vault.adapter.rmdir(I,!0)}catch{}}return{blobPath:g,fileCount:n.length,unpurged:f}}async function dl(d,a,e){let t=new Uint8Array(await d.vault.adapter.readBinary(a));if(!Me(t))throw new Error("Not an encrypted bundle.");let i=await st(d,a),s=En(i?.originalFolder)??a.replace(/\/[^/]*$/,""),n=await Oe(t,e),o=await wi(n),r=0;for(let[l,c]of Object.entries(o)){if(!l.startsWith("files/"))continue;let A=al(l.slice(6));if(!A){console.warn("[Stashpad] skipped unsafe folder entry",l);continue}let h=`${s}/${A}`.split("/").slice(0,-1).join("/"),g="";for(let f of h.split("/"))g=g?`${g}/${f}`:f,g&&!await d.vault.adapter.exists(g)&&await d.vault.adapter.mkdir(g);let u=`${s}/${A}`;for(let f=1;await d.vault.adapter.exists(u);f++)u=`${s}/${A.replace(/(\.[^./]*)?$/,` (${f})$1`)}`;await d.vault.adapter.writeBinary(u,c.buffer),r++}await d.vault.adapter.remove(a);try{await d.vault.adapter.remove(Re(a))}catch{}return{filesWritten:r,folder:s}}async function or(d,a){let e=a.replace(/\/+$/,"");try{let t=await d.vault.adapter.list(e);for(let i of t.files){if(!i.endsWith(`.${it}`))continue;if((await st(d,i))?.kind==="rawfolder")return i}}catch{}return null}async function Al(d){let a=[];for(let e of d.vault.getFiles())if(e.extension===it)try{(await st(d,e.path))?.kind==="rawfolder"&&a.push({folder:e.parent?.path?.replace(/\/+$/,"")??"",blobPath:e.path})}catch{}return a}function hs(d){return`${(d||"").replace(/\/+$/,"")}/trash`}async function kn(d,a=[]){let e=[];for(let t of[Qn,...a])try{if(!await d.vault.adapter.exists(t))continue;let i=await d.vault.adapter.list(t);e.push(...i.files.filter(s=>s.endsWith(`.${it}`)))}catch{}return e}function hl(d){return d.replace(/[^\w.\-]+/g,"_").replace(/^\.+/,"").slice(0,60)||"stash-export"}async function pl(d,a){let e=fl(d,a);if(e.length===0){new Qe.Notice("Nothing to export.");return}let t=Il(d,e);if(t.length===0){new Qe.Notice("No exportable notes (no files attached).");return}let i=(d.noteFolder.split("/").pop()||d.noteFolder).trim(),s=e.length===1?d.titleForNode(e[0]):`${i}-${e.length}notes`;new si(d.app,s,t.length,(n,o,r)=>{fd(d,e,t,n,o,r)},_i).open()}async function gl(d,a){let e=a.replace(/\/[^/]*$/,"").replace(/\/+$/,""),t=await d.ensureFolderUnlocked(e);if(!t)return;let i;try{let l=new Uint8Array(await d.app.vault.adapter.readBinary(a));i=await Oe(l,t)}catch(l){new Qe.Notice(`Couldn't decrypt this note to export it: ${l.message}`);return}finally{t.fill(0)}let s=await vn(d.app,a),n=(d.settings.lockedSubtrees??[]).find(l=>l.blob===a),o=n?.title||s?.title||"locked-note",r=n?.count??s?.count??1;new si(d.app,o,r,(l,c,A)=>{ud(d,e,l,i,c,A)},_i).open()}async function ud(d,a,e,t,i,s=!1){try{let n=t,o="";if(i){let u=await At(n,i);n=u.data;let f=So[u.kdf];o=f.strong?` (encrypted \xB7 ${f.label})`:` (encrypted \xB7 ${f.label} \u2014 Argon2id unavailable here, weaker)`}let r=(0,Qe.moment)().format("YYYYMMDD-HHmmss"),c=(d.settings.exportFolder||"_exports").trim().replace(/^\/+|\/+$/g,"").split("/").filter(u=>u&&u!=="."&&u!==".."&&!/[\\:]/.test(u)).join("/")||"_exports",A=`${a}/${c}`;await d.app.vault.adapter.exists(A)||await d.app.vault.adapter.mkdir(A);let h=`${hl(e)}-${r}`,g=`${A}/${h}.${tt}`;if(await d.app.vault.createBinary(g,n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength)),s&&i)try{d.app.secretStorage?.setSecret(ei(h),i)}catch(u){console.warn("[Stashpad] couldn't save export passphrase",u)}new Qe.Notice(`Exported encrypted note${o} \u2192 ${g}`,0)}catch(n){new Qe.Notice(`Export failed: ${n.message}`),console.error(n)}finally{try{t.fill(0)}catch{}}}async function ul(d,a){let e=fl(d,a);if(e.length===0){new Qe.Notice("Nothing to export.");return}let t=Il(d,e);if(t.length===0){new Qe.Notice("No exportable notes.");return}let i=(d.noteFolder.split("/").pop()||d.noteFolder).trim(),s=e.length===1?d.titleForNode(e[0]):`${i}-okf`;new Ji(d.app,s,t.length,(n,o)=>{(async()=>{try{let r=await d.plugin.exportOkf(d.noteFolder,e.map(l=>l.id),n,o);if(!r.length){new Qe.Notice("Nothing exported.");return}d.plugin.notifications.show({message:`Exported OKF \u2014 ${r.length} file${r.length===1?"":"s"} \u2192 \`${d.noteFolder}/${d.plugin.settings.exportFolder||"_exports"}\``,kind:"success",category:"export",affectedPaths:r,folder:d.noteFolder,duration:0}),await d.log.append({type:"stash_export",id:e[0].id,payload:{okf:!0,paths:r,noteCount:t.length,rootIds:e.map(l=>l.id)}})}catch(r){new Qe.Notice(`OKF export failed: ${r.message}`),console.error(r)}})()}).open()}async function fd(d,a,e,t,i,s=!1){try{let n=await ft(d.app,{rootNotes:a.filter(u=>!!u.file).map(u=>({id:u.id,file:u.file})),allDescendants:e.filter(u=>!a.some(f=>f.id===u.id)).filter(u=>!!u.file).map(u=>({id:u.id,file:u.file})),sourceFolder:d.noteFolder}),o="";if(i){let u=await At(n,i);n=u.data;let f=So[u.kdf];o=f.strong?` (encrypted \xB7 ${f.label})`:` (encrypted \xB7 ${f.label} \u2014 Argon2id unavailable on this device, this export is weaker)`}let r=(0,Qe.moment)().format("YYYYMMDD-HHmmss"),l=hl(t),c=(d.plugin.settings.exportFolder||"_exports").trim().replace(/^\/+|\/+$/g,""),A=`${d.noteFolder}/${c}`;await d.ensureFolder(A);let h=`${l}-${r}`,g=`${A}/${h}.${tt}`;if(await d.app.vault.createBinary(g,n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength)),s&&i){let u=d.app.secretStorage;try{u?.setSecret(ei(h),i)}catch(f){console.warn("[Stashpad] couldn't save export passphrase to secret storage",f)}}await d.log.append({type:"stash_export",id:a[0].id,payload:{path:g,noteCount:e.length,rootIds:a.map(u=>u.id)}}),d.plugin.notifications.show({message:`Exported ${e.length} note${e.length===1?"":"s"}${o} \u2192 \`${g}\``,kind:i&&o.includes("weaker")?"warning":"success",category:"export",affectedPaths:[g],folder:d.noteFolder,actions:d.actionsForFile(g),duration:0})}catch(n){d.plugin.notifications.show({message:`Stashpad: export failed +${a}`}async function _a(d,a){if(!(!a||await d.vault.adapter.exists(a)))try{await d.vault.createFolder(a)}catch(t){let i=t?.message??"";if(!/already exists/i.test(i))throw t}}ks();me();Qn();var st="stashenc",sl="stashmeta",As="stashpack";function Ue(d){return d.replace(/\.(stashenc|stashpack)$/,`.${sl}`)}async function Sn(d,a){try{return JSON.parse(await d.vault.adapter.read(Ue(a)))}catch{return null}}async function mt(d,a,e){let t=a.replace(/\/+$/,""),i=[];for(let c of d.vault.getMarkdownFiles()){if((c.parent?.path?.replace(/\/+$/,"")??"")!==t)continue;let A;try{A=Ae(await d.vault.read(c)).fm}catch{continue}typeof A.id=="string"&&i.push({id:A.id,file:c,parent:typeof A.parent=="string"?A.parent:null,created:typeof A.created=="string"?A.created:""})}let s=i.find(c=>c.id===e);if(!s)return null;let n=new Map;for(let c of i){if(!c.parent)continue;let A=n.get(c.parent)??[];A.push(c),n.set(c.parent,A)}let o=[],r=new Set([e]),l=[e];for(;l.length;){let c=[];for(let A of l)for(let h of n.get(A)??[])r.has(h.id)||(r.add(h.id),o.push(h),c.push(h.id));l=c}return{rootNote:s,descendants:o,parentId:s.parent}}function Fn(d){if(!d)return null;let a=d.replace(/\/+$/,"");return!a||a.startsWith("/")||a.includes("\\")||/^[a-zA-Z]:/.test(a)||a.split("/").some(e=>e===".."||e===".")?null:a}async function bn(d,a,e){await d.vault.adapter.writeBinary(a,e);let t;try{t=new Uint8Array(await d.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=t.length===e.length;if(i){for(let s=0;s<e.length;s++)if(t[s]!==e[s]){i=!1;break}}if(!i){try{await d.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 Qi(d){return d.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||d.basename}function vi(d){return(d.replace(/[\\/:*?"<>|]+/g," ").replace(/\s+/g," ").trim()||"locked").slice(0,60)}async function or(d,a,e){let t=new Set(a.map(r=>r.file.path)),i=new Map;for(let r of a)for(let l of await Yt(d,r.file))i.set(l.path,l);let s=new Set,n=d.metadataCache.resolvedLinks??{};for(let r of Object.keys(n))if(!t.has(r))for(let l of Object.keys(n[r]??{}))i.has(l)&&s.add(l);let o=[];for(let r of a){let l=e?.get(r.file.path);if(l!=null)try{let c=await d.vault.adapter.stat(r.file.path);if(c&&c.mtime!==l){console.warn("[Stashpad] note changed since it was bundled \u2014 keeping plaintext",r.file.path),o.push(r.file.path);continue}}catch{}try{await d.vault.delete(r.file)}catch(c){console.warn("[Stashpad] couldn't delete plaintext note",r.file.path,c),o.push(r.file.path)}}for(let[r,l]of i){if(s.has(r))continue;let c=e?.get(r);if(c!=null)try{let A=await d.vault.adapter.stat(r);if(A&&A.mtime!==c){console.warn("[Stashpad] attachment changed since it was bundled \u2014 keeping plaintext",r),o.push(r);continue}}catch{}try{await d.vault.delete(l)}catch(A){console.warn("[Stashpad] couldn't delete exclusive attachment",r,A),o.push(r)}}return{unpurged:o}}async function nl(d,a,e,t,i=null,s=!1,n){let o=await mt(d,a,e);if(!o)throw new Error("Couldn't find that note to lock.");let{rootNote:r,descendants:l,parentId:c}=o,A=[r,...l],h=new Map;for(let y of A){try{let E=await d.vault.adapter.stat(y.file.path);E&&h.set(y.file.path,E.mtime)}catch{}for(let E of await Yt(d,y.file))try{let w=await d.vault.adapter.stat(E.path);w&&h.set(E.path,w.mtime)}catch{}}let p=await It(d,{rootNotes:[{id:r.id,file:r.file}],allDescendants:l.map(y=>({id:y.id,file:y.file})),sourceFolder:a}),u=await ts(p,t),f=await Ke(u,t);if(f.length!==p.length)throw new Error("Encryption self-check failed (size mismatch).");for(let y=0;y<p.length;y++)if(f[y]!==p[y])throw new Error("Encryption self-check failed (content mismatch).");let g=(n??a).replace(/\/+$/,"");n&&!await d.vault.adapter.exists(g)&&await d.vault.adapter.mkdir(g);let I=vi(s?e:Qi(r.file)),m=`${g}/${I}.${st}`;for(let y=1;await d.vault.adapter.exists(m);y++)m=`${g}/${I} (${y}).${st}`;await bn(d,m,u);let B=A,C={v:1,parentId:c,title:s?"":Qi(r.file),count:B.length,created:r.created,rootId:e,prevSibling:i};try{await d.vault.adapter.write(Ue(m),JSON.stringify(C))}catch(y){console.warn("[Stashpad] couldn't write lock sidecar",y)}let{unpurged:Q}=await or(d,B,h);return{blobPath:m,noteCount:B.length,rootId:e,parentId:c,title:C.title,created:r.created,unpurged:Q}}async function ol(d,a,e,t,i){let s=new Uint8Array(await d.vault.adapter.readBinary(a));if(!Me(s))throw new Error("Not an encrypted bundle.");let n=await Ke(s,e),o=Fn(i)??a.replace(/\/[^/]*$/,""),r=await qe(d,n,o,t,{dedupeExisting:!0});await d.vault.adapter.remove(a);try{await d.vault.adapter.remove(Ue(a))}catch{}return{notesWritten:r.notesWritten,restoredTo:o}}var kn="_deleted";function fd(d){let a="";for(let e=0;e<d.length;e++)a+=String.fromCharCode(d[e]);return btoa(a)}function Id(d){let a=atob(d),e=new Uint8Array(a.length);for(let t=0;t<a.length;t++)e[t]=a.charCodeAt(t);return e}async function hs(d,a,e,t){let i=Fn(e?.originalFolder);if(!i&&e?.originalFolderEnc&&t)try{i=Fn(new TextDecoder().decode(await Ke(Id(e.originalFolderEnc),t)))}catch{i=null}let s=a.replace(/\/[^/]*$/,""),n=/(^|\/)trash$/.test(s)?s.replace(/\/?trash$/,""):"";if(i&&n&&i!==n&&!await d.vault.adapter.exists(i)&&(i=n||null),i)return await d.vault.adapter.exists(i)||await d.vault.adapter.mkdir(i),i;if(s===kn||s.startsWith(`${kn}/`))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.");if(/(^|\/)trash$/.test(s)){let o=s.replace(/\/?trash$/,"");if(o)return await d.vault.adapter.exists(o)||await d.vault.adapter.mkdir(o),o;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 rl(d,a,e,t,i,s=!1,n,o=kn){let r=await mt(d,a,e);if(!r)throw new Error("Couldn't find that note to delete.");let{rootNote:l,descendants:c,parentId:A}=r,h=[l,...c],p=new Map;for(let w of h){try{let v=await d.vault.adapter.stat(w.file.path);v&&p.set(w.file.path,v.mtime)}catch{}for(let v of await Yt(d,w.file))try{let F=await d.vault.adapter.stat(v.path);F&&p.set(v.path,F.mtime)}catch{}}let u=await It(d,{rootNotes:[{id:l.id,file:l.file}],allDescendants:c.map(w=>({id:w.id,file:w.file})),sourceFolder:a}),f=await ts(u,t),g=await Ke(f,t);if(g.length!==u.length)throw new Error("Encryption self-check failed (size).");for(let w=0;w<u.length;w++)if(g[w]!==u[w])throw new Error("Encryption self-check failed (content).");{let w=o.replace(/\/+$/,"").split("/").filter(Boolean),v="";for(let F of w){v=v?`${v}/${F}`:F;try{await d.vault.adapter.exists(v)||await d.vault.adapter.mkdir(v)}catch{}}}let I=a.replace(/\/+$/,""),m=I.split("/").pop()||"vault",B=vi(s?e:`${m} ${Qi(l.file)}`),C=`${o}/${B}.${st}`;for(let w=1;await d.vault.adapter.exists(C);w++)C=`${o}/${B} (${w}).${st}`;await bn(d,C,f);let Q=h,y={v:1,kind:"deleted",originalFolder:s?"":I,...s?{originalFolderEnc:fd(await ts(new TextEncoder().encode(I),t))}:{},parentId:A,title:s?"":Qi(l.file),count:Q.length,created:l.created,rootId:e,deletedAt:i,...n?{keyId:n}:{}};try{await d.vault.adapter.write(Ue(C),JSON.stringify(y))}catch(w){console.warn("[Stashpad] couldn't write deleted sidecar \u2014 aborting delete, keeping plaintext",w);try{await d.vault.adapter.remove(C)}catch{}throw new Error("Couldn't write trash metadata \u2014 the note was NOT deleted (kept intact).")}let{unpurged:E}=await or(d,Q,p);return{blobPath:C,noteCount:Q.length,rootId:e,originalFolder:I,title:y.title,unpurged:E}}async function al(d,a,e,t){let i=new Uint8Array(await d.vault.adapter.readBinary(a));if(!Me(i))throw new Error("Not an encrypted bundle.");let s=await nt(d,a),n=await hs(d,a,s,e),o=await Ke(i,e),r=await qe(d,o,n,t,{dedupeExisting:!0});await d.vault.adapter.remove(a);try{await d.vault.adapter.remove(Ue(a))}catch{}return{notesWritten:r.notesWritten,restoredTo:n}}async function nt(d,a){try{return JSON.parse(await d.vault.adapter.read(Ue(a)))}catch{return null}}async function ll(d,a,e,t,i){let s=await mt(d,a,e);if(!s)throw new Error("Couldn't find that note to delete.");let{rootNote:n,descendants:o,parentId:r}=s,l=[n,...o],c=new Map;for(let m of l){try{let B=await d.vault.adapter.stat(m.file.path);B&&c.set(m.file.path,B.mtime)}catch{}for(let B of await Yt(d,m.file))try{let C=await d.vault.adapter.stat(B.path);C&&c.set(B.path,C.mtime)}catch{}}let A=await It(d,{rootNotes:[{id:n.id,file:n.file}],allDescendants:o.map(m=>({id:m.id,file:m.file})),sourceFolder:a});{let m=i.replace(/\/+$/,"").split("/").filter(Boolean),B="";for(let C of m){B=B?`${B}/${C}`:C;try{await d.vault.adapter.exists(B)||await d.vault.adapter.mkdir(B)}catch{}}}let h=a.replace(/\/+$/,""),p=h.split("/").pop()||"vault",u=vi(`${p} ${Qi(n.file)}`),f=`${i}/${u}.${As}`;for(let m=1;await d.vault.adapter.exists(f);m++)f=`${i}/${u} (${m}).${As}`;await bn(d,f,A);let g={v:1,kind:"deleted",originalFolder:h,parentId:r,title:Qi(n.file),count:l.length,created:n.created,rootId:e,deletedAt:t,encrypted:!1};try{await d.vault.adapter.write(Ue(f),JSON.stringify(g))}catch(m){console.warn("[Stashpad] couldn't write trash sidecar \u2014 aborting delete, keeping plaintext",m);try{await d.vault.adapter.remove(f)}catch{}throw new Error("Couldn't write trash metadata \u2014 the note was NOT deleted (kept intact).")}let{unpurged:I}=await or(d,l,c);return{blobPath:f,noteCount:l.length,rootId:e,originalFolder:h,title:g.title,unpurged:I}}async function cl(d,a,e){let t=new Uint8Array(await d.vault.adapter.readBinary(a)),i=await nt(d,a),s=await hs(d,a,i),n=await qe(d,t,s,e,{dedupeExisting:!0});await d.vault.adapter.remove(a);try{await d.vault.adapter.remove(Ue(a))}catch{}return{notesWritten:n.notesWritten,restoredTo:s}}async function dl(d,a){let e=[];for(let t of a)try{if(!await d.vault.adapter.exists(t))continue;let i=await d.vault.adapter.list(t);e.push(...i.files.filter(s=>s.endsWith(`.${As}`)))}catch{}return e}async function rr(d,a){await d.vault.adapter.remove(a);try{await d.vault.adapter.remove(Ue(a))}catch{}}var zt=".trash";async function md(d,a){let e=[],t=[a];for(;t.length;){let i=t.shift(),s;try{s=await d.vault.adapter.list(i)}catch{continue}e.push(...s.files),t.push(...s.folders)}return e}function Al(d){let a=d.split("/").filter(Boolean);if(a.length===0)return null;for(let e of a)if(e===".."||e==="."||e.includes("\\")||/^[a-zA-Z]:/.test(e))return null;return a.join("/")}async function hl(d,a,e){let t=new Uint8Array(await d.vault.adapter.readBinary(a));if(!Me(t))throw new Error("Not an encrypted bundle.");let i=await Ke(t,e),s=await Ei(i),n=0;for(let[o,r]of Object.entries(s)){if(!o.startsWith("files/"))continue;let l=Al(o.slice(6));if(!l){console.warn("[Stashpad] skipped unsafe trash entry",o);continue}let c=`${zt}/${l}`.split("/").slice(0,-1).join("/"),A="";for(let p of c.split("/"))A=A?`${A}/${p}`:p,await d.vault.adapter.exists(A)||await d.vault.adapter.mkdir(A);let h=`${zt}/${l}`;for(let p=1;await d.vault.adapter.exists(h);p++)h=`${zt}/${l.replace(/(\.[^./]*)?$/,` (${p})$1`)}`;await d.vault.adapter.writeBinary(h,r.buffer),n++}await d.vault.adapter.remove(a);try{await d.vault.adapter.remove(Ue(a))}catch{}return{filesWritten:n}}async function pl(d,a,e,t,i){let s=a.replace(/\/+$/,""),n=(await md(d,s)).filter(g=>!g.endsWith(`.${st}`)&&!g.endsWith(`.${sl}`));if(n.length===0)throw new Error("This folder has no files to encrypt.");let o=[],r=new Map;for(let g of n){o.push({name:`files/${g.slice(s.length+1)}`,data:await d.vault.adapter.readBinary(g)});try{let I=await d.vault.adapter.stat(g);I&&r.set(g,I.mtime)}catch{}}let l=await ds(o),c=await ts(l,e),A=await Ke(c,e);if(A.length!==l.length)throw new Error("Encryption self-check failed (size).");for(let g=0;g<l.length;g++)if(A[g]!==l[g])throw new Error("Encryption self-check failed (content).");let h=vi(s.split("/").pop()||"folder"),p=`${s}/${h}.${st}`;for(let g=1;await d.vault.adapter.exists(p);g++)p=`${s}/${h} (${g}).${st}`;await bn(d,p,c);let u={v:1,kind:"rawfolder",originalFolder:s,parentId:null,title:s.split("/").pop()||"",count:n.length,created:i,rootId:"",deletedAt:i,...t?{keyId:t}:{}};try{await d.vault.adapter.write(Ue(p),JSON.stringify(u))}catch(g){console.warn("[Stashpad] couldn't write rawfolder sidecar",g)}let f=[];for(let g of n){let I=r.get(g);try{if(I!=null){let m=await d.vault.adapter.stat(g);if(m&&m.mtime!==I){f.push(g);continue}}await d.vault.adapter.remove(g)}catch(m){console.warn("[Stashpad] couldn't delete file",g,m),f.push(g)}}if(f.length===0){let g=[...new Set(n.map(I=>I.slice(0,I.lastIndexOf("/"))))].filter(I=>I.length>s.length).sort((I,m)=>m.length-I.length);for(let I of g)try{let m=await d.vault.adapter.list(I);!m.files.length&&!m.folders.length&&await d.vault.adapter.rmdir(I,!0)}catch{}}return{blobPath:p,fileCount:n.length,unpurged:f}}async function gl(d,a,e){let t=new Uint8Array(await d.vault.adapter.readBinary(a));if(!Me(t))throw new Error("Not an encrypted bundle.");let i=await nt(d,a),s=Fn(i?.originalFolder)??a.replace(/\/[^/]*$/,""),n=await Ke(t,e),o=await Ei(n),r=0;for(let[l,c]of Object.entries(o)){if(!l.startsWith("files/"))continue;let A=Al(l.slice(6));if(!A){console.warn("[Stashpad] skipped unsafe folder entry",l);continue}let h=`${s}/${A}`.split("/").slice(0,-1).join("/"),p="";for(let f of h.split("/"))p=p?`${p}/${f}`:f,p&&!await d.vault.adapter.exists(p)&&await d.vault.adapter.mkdir(p);let u=`${s}/${A}`;for(let f=1;await d.vault.adapter.exists(u);f++)u=`${s}/${A.replace(/(\.[^./]*)?$/,` (${f})$1`)}`;await d.vault.adapter.writeBinary(u,c.buffer),r++}await d.vault.adapter.remove(a);try{await d.vault.adapter.remove(Ue(a))}catch{}return{filesWritten:r,folder:s}}async function ar(d,a){let e=a.replace(/\/+$/,"");try{let t=await d.vault.adapter.list(e);for(let i of t.files){if(!i.endsWith(`.${st}`))continue;if((await nt(d,i))?.kind==="rawfolder")return i}}catch{}return null}async function ul(d){let a=[];for(let e of d.vault.getFiles())if(e.extension===st)try{(await nt(d,e.path))?.kind==="rawfolder"&&a.push({folder:e.parent?.path?.replace(/\/+$/,"")??"",blobPath:e.path})}catch{}return a}function ps(d){return`${(d||"").replace(/\/+$/,"")}/trash`}async function Dn(d,a=[]){let e=[];for(let t of[kn,...a])try{if(!await d.vault.adapter.exists(t))continue;let i=await d.vault.adapter.list(t);e.push(...i.files.filter(s=>s.endsWith(`.${st}`)))}catch{}return e}function fl(d){return d.replace(/[^\w.\-]+/g,"_").replace(/^\.+/,"").slice(0,60)||"stash-export"}async function Il(d,a){let e=Bl(d,a);if(e.length===0){new Qe.Notice("Nothing to export.");return}let t=yl(d,e);if(t.length===0){new Qe.Notice("No exportable notes (no files attached).");return}let i=(d.noteFolder.split("/").pop()||d.noteFolder).trim(),s=e.length===1?d.titleForNode(e[0]):`${i}-${e.length}notes`;new ni(d.app,s,t.length,(n,o,r)=>{Bd(d,e,t,n,o,r)},es).open()}async function ml(d,a){let e=a.replace(/\/[^/]*$/,"").replace(/\/+$/,""),t=await d.ensureFolderUnlocked(e);if(!t)return;let i;try{let l=new Uint8Array(await d.app.vault.adapter.readBinary(a));i=await Ke(l,t)}catch(l){new Qe.Notice(`Couldn't decrypt this note to export it: ${l.message}`);return}finally{t.fill(0)}let s=await Sn(d.app,a),n=(d.settings.lockedSubtrees??[]).find(l=>l.blob===a),o=n?.title||s?.title||"locked-note",r=n?.count??s?.count??1;new ni(d.app,o,r,(l,c,A)=>{Cd(d,e,l,i,c,A)},es).open()}async function Cd(d,a,e,t,i,s=!1){try{let n=t,o="";if(i){let u=await ht(n,i);n=u.data;let f=xo[u.kdf];o=f.strong?` (encrypted \xB7 ${f.label})`:` (encrypted \xB7 ${f.label} \u2014 Argon2id unavailable here, weaker)`}let r=(0,Qe.moment)().format("YYYYMMDD-HHmmss"),c=(d.settings.exportFolder||"_exports").trim().replace(/^\/+|\/+$/g,"").split("/").filter(u=>u&&u!=="."&&u!==".."&&!/[\\:]/.test(u)).join("/")||"_exports",A=`${a}/${c}`;await d.app.vault.adapter.exists(A)||await d.app.vault.adapter.mkdir(A);let h=`${fl(e)}-${r}`,p=`${A}/${h}.${it}`;if(await d.app.vault.createBinary(p,n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength)),s&&i)try{d.app.secretStorage?.setSecret(ti(h),i)}catch(u){console.warn("[Stashpad] couldn't save export passphrase",u)}new Qe.Notice(`Exported encrypted note${o} \u2192 ${p}`,0)}catch(n){new Qe.Notice(`Export failed: ${n.message}`),console.error(n)}finally{try{t.fill(0)}catch{}}}async function Cl(d,a){let e=Bl(d,a);if(e.length===0){new Qe.Notice("Nothing to export.");return}let t=yl(d,e);if(t.length===0){new Qe.Notice("No exportable notes.");return}let i=(d.noteFolder.split("/").pop()||d.noteFolder).trim(),s=e.length===1?d.titleForNode(e[0]):`${i}-okf`;new qi(d.app,s,t.length,(n,o)=>{(async()=>{try{let r=await d.plugin.exportOkf(d.noteFolder,e.map(l=>l.id),n,o);if(!r.length){new Qe.Notice("Nothing exported.");return}d.plugin.notifications.show({message:`Exported OKF \u2014 ${r.length} file${r.length===1?"":"s"} \u2192 \`${d.noteFolder}/${d.plugin.settings.exportFolder||"_exports"}\``,kind:"success",category:"export",affectedPaths:r,folder:d.noteFolder,duration:0}),await d.log.append({type:"stash_export",id:e[0].id,payload:{okf:!0,paths:r,noteCount:t.length,rootIds:e.map(l=>l.id)}})}catch(r){new Qe.Notice(`OKF export failed: ${r.message}`),console.error(r)}})()}).open()}async function Bd(d,a,e,t,i,s=!1){try{let n=await It(d.app,{rootNotes:a.filter(u=>!!u.file).map(u=>({id:u.id,file:u.file})),allDescendants:e.filter(u=>!a.some(f=>f.id===u.id)).filter(u=>!!u.file).map(u=>({id:u.id,file:u.file})),sourceFolder:d.noteFolder}),o="";if(i){let u=await ht(n,i);n=u.data;let f=xo[u.kdf];o=f.strong?` (encrypted \xB7 ${f.label})`:` (encrypted \xB7 ${f.label} \u2014 Argon2id unavailable on this device, this export is weaker)`}let r=(0,Qe.moment)().format("YYYYMMDD-HHmmss"),l=fl(t),c=(d.plugin.settings.exportFolder||"_exports").trim().replace(/^\/+|\/+$/g,""),A=`${d.noteFolder}/${c}`;await d.ensureFolder(A);let h=`${l}-${r}`,p=`${A}/${h}.${it}`;if(await d.app.vault.createBinary(p,n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength)),s&&i){let u=d.app.secretStorage;try{u?.setSecret(ti(h),i)}catch(f){console.warn("[Stashpad] couldn't save export passphrase to secret storage",f)}}await d.log.append({type:"stash_export",id:a[0].id,payload:{path:p,noteCount:e.length,rootIds:a.map(u=>u.id)}}),d.plugin.notifications.show({message:`Exported ${e.length} note${e.length===1?"":"s"}${o} \u2192 \`${p}\``,kind:i&&o.includes("weaker")?"warning":"success",category:"export",affectedPaths:[p],folder:d.noteFolder,actions:d.actionsForFile(p),duration:0})}catch(n){d.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 fl(d,a){if(a?.file)return[a];if(d.selection.size>0)return[...d.selection].map(t=>d.tree.get(t)).filter(t=>!!t?.file);if(d.cursorIdx>=0&&d.currentChildren[d.cursorIdx])return[d.currentChildren[d.cursorIdx]];let e=d.tree.get(d.focusId);return e?.file?[e]:[]}function Il(d,a){let e=new Set,t=[],i=s=>{if(!e.has(s.id)){e.add(s.id),s.file&&t.push(s);for(let n of d.tree.getChildren(s.id))i(n)}};for(let s of a)i(s);return t}async function ml(d){let a=d.app.vault.getFiles().filter(t=>t.extension===tt);if(a.length===0){new Qe.Notice("No .stash files found in this vault.");return}let e=new class extends Qe.FuzzySuggestModal{getItems(){return a}getItemText(t){return t.path}onChooseItem(t){rr(d,t)}}(d.app);e.setPlaceholder("Pick a .stash file to import\u2026"),e.open()}async function rr(d,a){try{let e=new Uint8Array(await d.app.vault.readBinary(a)),t=await pi(d.app,e,{secretId:ei(a.basename)});if(!t)return;let i=await Je(d.app,t,d.noteFolder,Id(d),{stripReserved:!0});d.tree.rebuild(d.noteFolder),d.render(),await d.log.append({type:"stash_import",id:S,payload:{from:a.path,into:d.noteFolder,noteCount:i.notesWritten,attachmentsWritten:i.attachmentsWritten,collisionsRenamed:i.collisionsRenamed}});try{await d.app.fileManager.trashFile(a)}catch{}d.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)`),d.plugin.notifications.show({message:s.join(" "),kind:"success",category:"import",folder:d.noteFolder})}catch(e){d.plugin.notifications.show({message:`Stashpad: import failed +Check disk space + write permissions on the export folder.`,kind:"error",category:"export"}),console.error(n)}}function Bl(d,a){if(a?.file)return[a];if(d.selection.size>0)return[...d.selection].map(t=>d.tree.get(t)).filter(t=>!!t?.file);if(d.cursorIdx>=0&&d.currentChildren[d.cursorIdx])return[d.currentChildren[d.cursorIdx]];let e=d.tree.get(d.focusId);return e?.file?[e]:[]}function yl(d,a){let e=new Set,t=[],i=s=>{if(!e.has(s.id)){e.add(s.id),s.file&&t.push(s);for(let n of d.tree.getChildren(s.id))i(n)}};for(let s of a)i(s);return t}async function wl(d){let a=d.app.vault.getFiles().filter(t=>t.extension===it);if(a.length===0){new Qe.Notice("No .stash files found in this vault.");return}let e=new class extends Qe.FuzzySuggestModal{getItems(){return a}getItemText(t){return t.path}onChooseItem(t){lr(d,t)}}(d.app);e.setPlaceholder("Pick a .stash file to import\u2026"),e.open()}async function lr(d,a){try{let e=new Uint8Array(await d.app.vault.readBinary(a)),t=await gi(d.app,e,{secretId:ti(a.basename)});if(!t)return;let i=await qe(d.app,t,d.noteFolder,yd(d),{stripReserved:!0});d.tree.rebuild(d.noteFolder),d.render(),await d.log.append({type:"stash_import",id:k,payload:{from:a.path,into:d.noteFolder,noteCount:i.notesWritten,attachmentsWritten:i.attachmentsWritten,collisionsRenamed:i.collisionsRenamed}});try{await d.app.fileManager.trashFile(a)}catch{}d.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)`),d.plugin.notifications.show({message:s.join(" "),kind:"success",category:"import",folder:d.noteFolder})}catch(e){d.plugin.notifications.show({message:`Stashpad: import failed File: \`${a.name}\` Error: ${e.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:d.actionsForFile(a.path)}),console.error(e)}}function Id(d){let a=new Set,e=t=>{if(a.add(t),!!d.tree.get(t))for(let s of d.tree.getChildren(t))e(s.id)};return e(S),a}Pi();Pi();var Cd=new Set(["png","jpg","jpeg","gif","webp","svg","bmp","avif"]),ps={nested:"Nested",flat:"Flat",everything:"Everything"},gs=[{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"}],us=class us extends F.ItemView{constructor(e,t){super(e);this.focusId=S;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.composerSplitBtn=null;this.composerEnterBtn=null;this.composerHelperEl=null;this.composerDestBtn=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.tapSettleUntil=0;this.aimedTapTargetId=null;this.aimedTapAt=0;this.stickyRowObserver=null;this.listResizeObserver=null;this.composerNarrowObserver=null;this.barOverflowRO=null;this.lastCursorByFocus=new Map;this.lastSelectionByFocus=new Map;this.expandedNotes=new Set;this.cursorExpandOverride=new Set;this.cursorHasMoved=!1;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.syncBurstTimes=[];this.autoSyncDeferActive=!1;this.autoSyncSettleTimer=null;this.autoSyncNotice=null;this.stampLastCursorTimer=null;this.stampSelectionTimer=null;this._renderT0=null;this.tinyOpacityPopover=null;this.tinyOpacityClose=null;this.lastListWidth=0;this.keydownWindow=window;this.onDocKeyDown=e=>{if(!this.viewRoot.isConnected||this.app.workspace.activeLeaf!==this.leaf||br(e.target))return;let t=X().bindings;if(q(e,t.toggleSplit)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.toggleSplit();return}if(q(e,t.pickDestination)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.openDestinationPicker();return}if(q(e,t.search)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.openSearchModal();return}if(q(e,t.commandPalette)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.openStashpadCommandPalette();return}if(q(e,t.lockSelection)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdLockSelection();return}if(q(e,t.unlockAll)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdUnlockAll();return}if(q(e,t.moveToArchive)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdMoveToArchive();return}if(q(e,t.encryptDelete)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdEncryptDelete();return}if(q(e,t.searchInParent)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.openSearchInParentModal();return}if(q(e,t.exportStash)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdExportStash();return}if(q(e,t.importStash)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdImportStash();return}if(q(e,t.pickFolder)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdOpenFolderPicker();return}if(q(e,t.cloneStashpadTab)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdCloneStashpadTab();return}let i=e.target,s=!!i&&(i.tagName==="INPUT"||i.tagName==="TEXTAREA");if(e.key===" "&&!e.metaKey&&!e.ctrlKey&&!e.altKey&&!e.shiftKey&&!s){let l=this.composerInputEl;if(l){e.preventDefault(),e.stopPropagation(),l.focus();let c=l.value.length;l.setSelectionRange(c,c);return}}let n=!!i&&(i.tagName==="INPUT"||i.tagName==="TEXTAREA"||i.tagName==="BUTTON"||i.tagName==="SELECT");if(e.key==="Escape"&&i instanceof HTMLElement&&(i.tagName==="BUTTON"||i.tagName==="SELECT")&&this.viewRoot.contains(i)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.viewRoot.focus();return}if(this.inListPicker&&e.key==="Escape"){e.preventDefault(),e.stopPropagation(),this.inListPicker=null,this.pickerEscapeAt=Date.now();let l=this.listEl,c=!!l&&l.scrollTop+l.clientHeight>=l.scrollHeight-2,A=l?.scrollTop??0;if(this.render(),l){let h=c?l.scrollHeight:A;l.scrollTop=h,requestAnimationFrame(()=>{l.scrollTop=c?l.scrollHeight:A}),setTimeout(()=>{l.scrollTop=c?l.scrollHeight:A},60),this.revealCursorRow()}return}if(this.inListPicker&&!n){if(e.key==="ArrowDown"){e.preventDefault(),this.inListPicker.activeIdx=this.nextPickableIdx(this.inListPicker.activeIdx,1),this.repaintSelectionClasses(),this.revealRowAt(this.inListPicker.activeIdx);return}if(e.key==="ArrowUp"){e.preventDefault(),this.inListPicker.activeIdx=this.nextPickableIdx(this.inListPicker.activeIdx,-1),this.repaintSelectionClasses(),this.revealRowAt(this.inListPicker.activeIdx);return}if(e.key==="Enter"){e.preventDefault(),this.commitInListPicker();return}if(q(e,X().bindings.move)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.inListPicker=null,this.repaintSelectionClasses(),this.cmdMovePicker();return}return}if(n)return;if(q(e,t.delete)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdDelete();return}if(q(e,t.toggleComplete)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdToggleComplete();return}if(q(e,t.moveToTop)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdMoveToTop();return}if(q(e,t.moveToBottom)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdMoveToBottom();return}if(q(e,t.moveUp)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdMoveUp();return}if(q(e,t.moveDown)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdMoveDown();return}if(q(e,t.outdent)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdOutdent();return}if(q(e,t.setColor)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdSetColor();return}if(q(e,t.selectAll)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdSelectAll();return}if(q(e,t.swapWithParent)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdSwapWithParent();return}if(q(e,t.undo)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdUndo();return}if(q(e,t.redo)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdRedo();return}if(e.key===" "){e.preventDefault();let l=this.composerInputEl;if(l){l.focus();let c=l.value.length;l.setSelectionRange(c,c)}return}if(e.key==="ArrowDown"){e.preventDefault(),this.cursorIdx>=this.currentChildren.length-1?this.cursorIdx=0:this.cursorIdx++,this.selectCursor(e.shiftKey);return}if(e.key==="ArrowUp"){e.preventDefault(),this.cursorIdx<=0?this.cursorIdx=this.currentChildren.length-1:this.cursorIdx--,this.selectCursor(e.shiftKey);return}if(e.altKey&&e.key==="ArrowLeft"){e.preventDefault(),this.navigateBack();return}if(e.altKey&&e.key==="ArrowRight"){e.preventDefault(),this.navigateForward();return}if(e.key==="ArrowRight"){let l=this.currentChildren[this.cursorIdx];l&&(e.preventDefault(),this.navigateTo(l.id));return}if(e.key==="ArrowLeft"||e.key==="Backspace"){e.preventDefault(),this.navigateUp();return}if(e.key==="Escape"){if(e.preventDefault(),e.stopPropagation(),e.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 l=this.firstSelectedId??(this.selection.size>0?this.selection.values().next().value:null);if(this.selection.clear(),this.firstSelectedId=null,l){let c=this.currentChildren.findIndex(A=>A.id===l);this.selection.add(l),this.lastSelected=l,c>=0&&(this.cursorIdx=c)}this.repaintSelectionClasses(),this.revealCursorRow();return}let o=X().bindings;if(q(e,o.pasteNotes)&&this.plugin.noteClipboard){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdPasteNotes();return}if(this.selection.size>0||this.cursorIdx>=0&&this.currentChildren[this.cursorIdx]){if(q(e,o.move)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdMovePicker();return}if(q(e,o.pickMove)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdInListPicker();return}if(q(e,o.merge)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdMerge();return}if(q(e,o.copy)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdCopy();return}if(q(e,o.copyNotes)&&!window.getSelection()?.toString()){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdCopyNotes();return}if(q(e,o.cutNotes)&&!window.getSelection()?.toString()){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdCutNotes();return}if(q(e,o.copyTree)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdCopyTree();return}if(q(e,o.copyLink)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdCopyStashpadLink();return}if(q(e,o.copyOutline)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdCopyOutline();return}if(q(e,o.copyCodeBlock)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdCopyCodeBlock();return}if(q(e,o.openEditor)){if(e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),e.shiftKey){let l=this.tree.get(this.focusId);l?.file&&this.cmdOpenInEditor(l)}else this.cmdOpenInEditor();return}if(q(e,o.openTab)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdOpenInNewStashpadTab();return}if(q(e,o.split)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdSplit();return}if(q(e,o.clone)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdClone();return}if(q(e,o.forkNote)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdForkNote();return}if(q(e,o.insertTemplate)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdInsertTemplate();return}if(q(e,o.toggleExpand)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdToggleExpand();return}if(q(e,o.expandAll)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdExpandAll();return}if(q(e,o.collapseAll)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdCollapseAll();return}if(q(e,o.togglePin)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdTogglePin();return}if(q(e,o.listPin)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdToggleListPin();return}if(q(e,o.toggleTask)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdToggleTask();return}if(q(e,o.setDue)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdSetDue();return}}if(this.currentChildren.length>0){if(q(e,o.jumpToTop)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.jumpToTop();return}if(q(e,o.jumpToBottom)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.jumpToBottom();return}}let r=this.tree.get(this.focusId);if(r?.file){if(q(e,o.openEditor)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdOpenInEditor(r);return}if(q(e,o.openTab)){e.preventDefault(),e.stopPropagation(),e.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=e=>{!(e instanceof F.TFile)||e.extension!=="md"||e.path.startsWith(this.noteFolder+"/")&&(this.bodyRenderer.evict(e),this.scheduleSlugRename(e),this.scheduleAttachmentSync(e),this.authorship.noteModify(e),!this.deferDuringSyncBurst()&&this.debouncedRender())};this.onFileCreate=e=>{!(e instanceof F.TFile)||e.extension!=="md"||e.path.startsWith(this.noteFolder+"/")&&(this.deferDuringSyncBurst()||this.debouncedRender())};this.plugin=t,this.tree=new tn(this.app),this.log=t.newLog(),this.integrity=new cn(this.tree,this.log),this.order=new fi(this.app),this.sortStore=new on(this.app),this.fmSync=new an(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):Fa(this,i,n);return this.hoistListPinned(i,o)}),this.debouncedRender=(0,F.debounce)(()=>{this.renderSuppressed()||this.render()},80),this.authorship=new gn(this),this.dnd=new un(this),this.bodyRenderer=new fn(this,this,this.plugin.renderCacheStore)}getViewType(){return z}getDisplayText(){let e=(this.noteFolder||"").trim(),t=e.split("/").pop()||e||"Stashpad";if(this.focusId&&this.focusId!==S){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`${t} \u2014 ${n} \xB7 ${this.focusId}`}}return t}refreshHeaderTitle(){let e=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!==e&&i.setText(e)}getIcon(){return this.plugin.getFolderIcon(this.noteFolder)??"list-tree"}async onOpen(){let e=this.contentEl;e.empty(),e.addClass("stashpad-scroll-host"),this.viewRoot=e.createDiv({cls:"stashpad-view"}),this.viewRoot.setAttribute("tabindex","0"),this.viewRoot.addEventListener("focusin",()=>Ws(this)),this.viewRoot.addEventListener("click",()=>Ws(this)),this.viewRoot.addEventListener("mouseup",l=>{l.button===3?(l.preventDefault(),this.navigateBack()):l.button===4&&(l.preventDefault(),this.navigateForward())}),this.viewRoot.addEventListener("auxclick",l=>{l.button===3?(l.preventDefault(),this.navigateBack()):l.button===4&&(l.preventDefault(),this.navigateForward())}),Ws(this),this.registerInterval(window.setInterval(()=>this.authorship.pruneContribMaps(),6e4));let t=null,i=()=>{t||(t=new F.Scope(this.app.scope),t.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 l=this.firstSelectedId??this.selection.values().next().value??null;if(this.selection.clear(),this.firstSelectedId=null,l){let c=this.currentChildren.findIndex(A=>A.id===l);this.selection.add(l),this.lastSelected=l,c>=0&&(this.cursorIdx=c)}this.render(),this.revealCursorRow()}return!1}),this.app.keymap?.pushScope(t))},s=()=>{if(t){try{this.app.keymap?.popScope(t)}catch{}t=null}};this.viewRoot.addEventListener("focusin",i),this.viewRoot.addEventListener("focusout",l=>{let c=l.relatedTarget;c&&this.viewRoot&&this.viewRoot.contains(c)||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",l=>{if(l.extension!=="md")return;let c=this.app.metadataCache.getFileCache(l)?.frontmatter;this.completedState.set(l.path,!!c?.completed),this.taskTaggedState.set(l.path,this.taggedFromFm(c))})),this.registerEvent(this.app.vault.on("rename",(l,c)=>{for(let A of[this.completedState,this.taskTaggedState])A.has(c)&&(A.set(l.path,A.get(c)),A.delete(c))})),this.registerEvent(this.app.vault.on("delete",l=>{this.completedState.delete(l.path),this.taskTaggedState.delete(l.path);let c=l.path.lastIndexOf("/"),A=(c>=0?l.path.slice(0,c):"").replace(/\/+$/,"");l.path.endsWith(".md")&&A===this.noteFolder.replace(/\/+$/,"")&&(this.tree.rebuild(this.noteFolder),this.debouncedRender())})),this.detachSettings=da(()=>{this.loadConfig();let l=this.plugin.settings.drafts?.[this.noteFolder]??"",c=this.composerInputEl?.value??"";l===""&&this.composerDraft!==""&&c===""?(this.composerDraft="",this.composerInputEl&&(this.composerInputEl.value="")):l===""&&c!==""&&(this.composerDraft=c),!!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),this.keydownWindow=this.containerEl?.ownerDocument?.defaultView??window,this.keydownWindow.addEventListener("keydown",this.onDocKeyDown,!0),this.loadConfig();try{await this.bootstrapFolder()}catch(l){let c=l?.message??"";/already exists/i.test(c)||console.warn("[Stashpad] bootstrapFolder failed:",l)}this.tree.rebuild(this.noteFolder),this.installFmSyncActivityNotice(),this.backfillFrontmatterSync(),this.plugin.maybeSweepFolder(this.noteFolder),this.defaultCursorToLast(),this.refreshHeaderTitle(),await this.loadDraftsForFolder();try{let l=this.plugin.loadLastCursor(this.noteFolder);for(let[c,A]of l)this.lastCursorByFocus.set(c,A);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)}),X().focusComposerOnOpen?this.focusComposer():this.focusView(),this.registerEvent(this.app.workspace.on("active-leaf-change",l=>{l===this.leaf?X().focusComposerOnOpen?this.focusComposer():this.focusView():this.stickToListBottom=!1}))}renderSuppressed(){return this.bulkRenderDepth>0||this.bulkSettleTimer!=null||this.autoSyncDeferActive||this.plugin.rebootstrapInProgress||this.plugin.okfRebuildingFolders.has(this.noteFolder)}beginBulkRender(){this.bulkRenderDepth++,this.bulkSettleTimer!=null&&(window.clearTimeout(this.bulkSettleTimer),this.bulkSettleTimer=null)}endBulkRender(e=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())},e))}deferDuringSyncBurst(){if(this.plugin.rebootstrapInProgress)return!1;let e=Date.now();this.syncBurstTimes.push(e);let t=e-2e3;for(;this.syncBurstTimes.length&&this.syncBurstTimes[0]<t;)this.syncBurstTimes.shift();return!this.autoSyncDeferActive&&this.syncBurstTimes.length>=6&&(this.autoSyncDeferActive=!0,this.autoSyncNotice=new F.Notice("Stashpad: syncing \u2014 list updates paused until it settles\u2026",0)),this.autoSyncDeferActive?(this.autoSyncSettleTimer!=null&&window.clearTimeout(this.autoSyncSettleTimer),this.autoSyncSettleTimer=window.setTimeout(()=>this.endAutoSyncDefer(),1500),!0):!1}endAutoSyncDefer(){this.autoSyncSettleTimer=null,this.autoSyncDeferActive=!1,this.syncBurstTimes=[],this.autoSyncNotice?.hide(),this.autoSyncNotice=null,this.forceReconcileRender()}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 e=this.noteFolder,t=e+"/",i=0;for(let s of this.app.vault.getMarkdownFiles()){let n=s.parent?.path?.replace(/\/+$/,"")??"";if(!(n===e||e!==""&&n.startsWith(t)))continue;let o=this.app.metadataCache.getFileCache(s)?.frontmatter?.id;typeof o=="string"&&o&&i++}i!==this.tree.fileBackedCount()&&(this.tree.rebuild(e),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(!X().focusComposerOnOpen)return;let e=()=>{if(!this.viewRoot?.isConnected||Date.now()<this.suppressComposerFocusUntil||Date.now()<this.plugin.suppressComposerAutofocusUntil)return;let t=document.activeElement;t&&(t.tagName==="INPUT"||t.tagName==="TEXTAREA")&&t!==this.composerInputEl||(t&&t.tagName==="BUTTON"&&this.viewRoot.contains(t),this.composerInputEl?.focus({preventScroll:!0}))};requestAnimationFrame(e),setTimeout(e,50),setTimeout(e,200)}async onClose(){aa(this),this.debouncedRender?.cancel?.(),this.tinyOpacityClose?.(),this.detachTreeHook?.(),this.detachSettings?.(),this.app.vault.off("modify",this.onFileModify),this.app.vault.off("create",this.onFileCreate),this.keydownWindow.removeEventListener("keydown",this.onDocKeyDown,!0),this.listResizeObserver?.disconnect(),this.listResizeObserver=null,this.stickyRowObserver?.disconnect(),this.stickyRowObserver=null,this.bodyRenderer.dispose(),this.barOverflowRO?.disconnect(),this.barOverflowRO=null,this.composerNarrowObserver?.disconnect(),this.composerNarrowObserver=null,this.focusedMiniObserver?.disconnect(),this.focusedMiniObserver=null,this.treeReconcileTimer!=null&&(window.clearTimeout(this.treeReconcileTimer),this.treeReconcileTimer=null),this.autoSyncSettleTimer!=null&&(window.clearTimeout(this.autoSyncSettleTimer),this.autoSyncSettleTimer=null),this.autoSyncNotice?.hide(),this.autoSyncNotice=null,this.composerAutocomplete?.detach(),this.composerAutocomplete=null;for(let e of this.slugDebouncers.values())e.cancel();for(let e of this.attachmentDebouncers.values())e.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(e){let t=e;t?.focusId&&(this.focusId=t.focusId),t?.timeFilter&&(this.timeFilter=t.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(e,t){let i=e??null;if(i){"folderOverride"in i&&(this.folderOverride=i.folderOverride??null),i.timeFilter&&(this.timeFilter=i.timeFilter),i.focusId&&(this.focusId=i.focusId),i.cursorId&&(this.pendingCursorId=i.cursorId),"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(e,t),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 c=this.plugin.loadLastCursor(this.noteFolder);for(let[A,h]of c)this.lastCursorByFocus.set(A,h);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 l=this.foldRestoredSelection(o);l&&(this.pendingFocusIds=l),this.render(r),this.scheduleSelectionRestore()}}focus(){this.viewRoot?.focus({preventScroll:!0})}foldRestoredSelection(e){let t=this.lastSelectionByFocus.get(this.focusId)??null;if(!t||!t.length)return null;let i=t.filter(s=>!!this.tree.get(s));return i.length?e&&i.includes(e)?[e,...i.filter(s=>s!==e)]:i:null}stampSelection(e=!1){let t=[...this.selection],i=()=>{try{this.plugin.saveLastSelection(this.noteFolder,this.focusId,t)}catch{}};if(this.stampSelectionTimer!=null&&(window.clearTimeout(this.stampSelectionTimer),this.stampSelectionTimer=null),e){i();return}this.stampSelectionTimer=window.setTimeout(()=>{this.stampSelectionTimer=null,i()},400)}scheduleSelectionRestore(){let e=this.lastSelectionByFocus.get(this.focusId);if(!e||!e.length)return;let t=()=>{let i=e.filter(r=>this.currentChildren.some(l=>l.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(t,i)}loadConfig(){let e=(this.plugin?.settings?.folder??"Stashpad").trim().replace(/^\/+|\/+$/g,""),i=this.folderOverride?.trim().replace(/^\/+|\/+$/g,"")||null||e||"Stashpad";i!==this.noteFolder?(this.noteFolder=i,this.tree.rebuild(this.noteFolder)):this.noteFolder=i}captureNavSnapshot(){return{folder:this.noteFolder,focusId:this.focusId}}recordNavState(e={}){let t=this.captureNavSnapshot(),i=this.navBackStack[this.navBackStack.length-1];i&&i.folder===t.folder&&i.focusId===t.focusId||(this.navBackStack.push(t),e.keepForward||(this.navForwardSnapshots=[]))}async setFolderOverride(e,t={}){let i=e?.trim().replace(/^\/+|\/+$/g,"")||null;if(i&&this.isReservedFolder(i)){new F.Notice(`"${i}" is a reserved Stashpad subfolder (imports/exports/attachments). Pick a different folder.`);return}if((i||null)!==(this.folderOverride||null)){t.skipHistory||this.recordNavState(),this.folderOverride=i,this.focusId=S,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 e=[];for(let t of this.app.vault.getAllLoadedFiles())if(t instanceof F.TFolder){if(t.path==="/"||t.path===""||t.path.startsWith(".")||this.isReservedFolder(t.path))continue;e.push(t.path)}return e.sort((t,i)=>t.localeCompare(i))}isReservedFolder(e){let t=e.split("/").filter(Boolean).pop()??"";return t?new Set([this.plugin.settings.importDropFolder,this.plugin.settings.exportFolder,"_attachments","_processed","_authors"].map(s=>(s??"").trim().replace(/^\/+|\/+$/g,"")).filter(Boolean)).has(t):!1}persistFocus(){try{this.app.workspace.requestSaveLayout()}catch{}}cmdUndo(){let e=this.plugin.getUndoStack(this.noteFolder);if(!e.canUndo()){new F.Notice("Nothing to undo.");return}let t=e.peekUndoLabel(),i=this.plugin.notifications.recent()[0]?.category??"system";e.undo().then(()=>this.plugin.notifications.show({message:`Undid: ${t}`,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 e=this.plugin.getUndoStack(this.noteFolder);if(!e.canRedo()){new F.Notice("Nothing to redo.");return}let t=e.peekRedoLabel(),i=this.plugin.notifications.recent()[0]?.category??"system";e.redo().then(()=>this.plugin.notifications.show({message:`Redid: ${t}`,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(e,t){let i=[],s=new Set;for(let l of e)!l.file||s.has(l.file.path)||(s.add(l.file.path),i.push(l.file));let n=await Promise.all(i.map(l=>this.app.vault.read(l))),o=i.map((l,c)=>({path:l.path,content:n[c]})),r=[];if(t){let l=new Set,c=[];for(let h of n)for(let g of this.extractAttachments(this.stripFrontmatter(h))){let u=this.app.metadataCache.getFirstLinkpathDest(g,"");u&&!l.has(u.path)&&(l.add(u.path),c.push(u))}let A=await Promise.all(c.map(h=>this.app.vault.readBinary(h)));for(let h=0;h<c.length;h++)r.push({path:c[h].path,data:A[h]})}return{notes:o,attachments:r}}fileForNote(e,t){return(e?this.tree.get(e)?.file:null)??this.app.vault.getAbstractFileByPath(t)}async restoreSnapshots(e,t){for(let s of e.attachments)try{await this.app.vault.adapter.exists(s.path)||await this.app.vault.createBinary(s.path,s.data)}catch{}for(let s of e.notes)try{let n=s.content.split(` ----`)[0]??"",r=/^id:\s*["']?([^"'\s]+)/m.exec(n)?.[1];if(r&&this.tree.get(r)?.file)continue;await this.app.vault.adapter.exists(s.path)||await this.app.vault.create(s.path,s.content)}catch{}let i=()=>{t&&t.some(n=>this.tree.get(n))&&(this.pendingFocusIds=t.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 e.notes){let n=this.tree.idForPath(s.path);n&&this.fmSync.schedule(n)}},500)}async trashNotesAndAttachments(e){let t=new Set;for(let i of e.notes){let s=this.tree.idForPath(i.path);if(!s)continue;let n=this.tree.get(s);n?.parent&&t.add(n.parent)}for(let i of e.notes){let s=this.app.vault.getAbstractFileByPath(i.path);if(s)try{await this.app.fileManager.trashFile(s)}catch{}}for(let i of e.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 t)this.fmSync.scheduleParentOfDeleted(i)}async loadDraftsForFolder(){if(this.draftsLoadedFor===this.noteFolder)return;this.draftsLoadedFor=this.noteFolder;let e=this.plugin.settings.drafts??{};this.composerDraft=e[this.noteFolder]??"",console.debug("[Stashpad] loadDrafts",{folder:this.noteFolder,has:!!e[this.noteFolder],available:Object.keys(e)})}async saveDraft(e){try{let t=this.noteFolder;if((this.plugin.settings.drafts?.[t]??"")===e)return;let s={...this.plugin.settings.drafts??{}};e.length===0?delete s[t]:s[t]=e,this.plugin.settings.drafts=s,e.length===0?await this.plugin.saveSettings():await this.plugin.persistSettingsQuiet()}catch(t){console.warn("Stashpad: drafts save failed",t)}}async recordLastSubmitted(e){try{let t={...this.plugin.settings.lastSubmitted??{}};t[this.noteFolder]=e,this.plugin.settings.lastSubmitted=t,await this.plugin.persistSettingsQuiet()}catch{}}hasRestorableDraft(){let e=this.plugin.settings.drafts?.[this.noteFolder];if(!e||!e.trim())return!1;let t=this.plugin.settings.lastSubmitted?.[this.noteFolder];return!(t&&t===e)}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 t=(0,F.moment)();switch(this.timeFilter){case"day":return t.startOf("day").valueOf();case"week":return t.startOf("isoWeek").valueOf();case"month":return t.startOf("month").valueOf();case"year":return t.startOf("year").valueOf()}}let e=Date.now();switch(this.timeFilter){case"day":return e-864e5;case"week":return e-7*864e5;case"month":return e-30*864e5;case"year":return e-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(e){let t={...this.plugin.settings.includeAttachmentsInEverything??{}};e?t[this.noteFolder]=!0:delete t[this.noteFolder],this.plugin.settings.includeAttachmentsInEverything=t,await this.plugin.saveSettings()}currentEncryptionFilter(){return this.plugin.settings.encryptionFilter?.[this.noteFolder]??"all"}async setEncryptionFilter(e){let t={...this.plugin.settings.encryptionFilter??{}};e==="all"?delete t[this.noteFolder]:t[this.noteFolder]=e,this.plugin.settings.encryptionFilter=t,await this.plugin.saveSettings()}currentHideChildless(){return!!this.plugin.settings.hideChildlessNotes?.[this.noteFolder]}async setHideChildless(e){let t={...this.plugin.settings.hideChildlessNotes??{}};e?t[this.noteFolder]=!0:delete t[this.noteFolder],this.plugin.settings.hideChildlessNotes=t,await this.plugin.saveSettings()}currentHideCompleted(){return!!this.plugin.settings.hideCompletedNotes?.[this.noteFolder]}async setHideCompleted(e){let t={...this.plugin.settings.hideCompletedNotes??{}};e?t[this.noteFolder]=!0:delete t[this.noteFolder],this.plugin.settings.hideCompletedNotes=t,await this.plugin.saveSettings()}currentAttachmentsOnly(){return!!this.plugin.settings.attachmentsOnlyNotes?.[this.noteFolder]}async setAttachmentsOnly(e){let t={...this.plugin.settings.attachmentsOnlyNotes??{}};e?t[this.noteFolder]=!0:delete t[this.noteFolder],this.plugin.settings.attachmentsOnlyNotes=t,await this.plugin.saveSettings()}nodeHasAttachment(e){if(!e.file)return!1;let t=this.app.metadataCache.getFileCache(e.file)?.frontmatter?.attachments;return Array.isArray(t)&&t.length>0}hasAttachmentInSubtree(e){if(this.nodeHasAttachment(e))return!0;for(let t of this.tree.getChildren(e.id))if(this.hasAttachmentInSubtree(t))return!0;return!1}hasIncompleteDescendant(e){for(let t of e.children){let i=this.tree.get(t);if(i&&(!this.isCompleted(i)||this.hasIncompleteDescendant(i)))return!0}return!1}collectEmbeddedAttachmentPaths(){let e=new Set,t=this.noteFolder,i=this.app.vault.getAbstractFileByPath(t);if(!(i instanceof F.TFolder))return e;let s=[i];for(;s.length;){let n=s.pop();for(let o of n.children){if(o instanceof F.TFolder){s.push(o);continue}if(!(o instanceof F.TFile)||o.extension!=="md")continue;let r=this.app.metadataCache.getFileCache(o)?.frontmatter;if(!(!r||!Array.isArray(r.attachments)))for(let l of r.attachments){if(typeof l!="string")continue;let c=Mt(l),A=this.app.metadataCache.getFirstLinkpathDest(c,o.path);A?e.add(A.path):e.add(c)}}}return e}collectFileItems(e){let t=this.noteFolder,i=this.app.vault.getAbstractFileByPath(t);if(!(i instanceof F.TFolder))return[];let s=this.currentIncludeAttachments(),n=s?new Set:this.collectEmbeddedAttachmentPaths(),o=new Set(["_authors","_imports","_exports","_processed","_attachments","_archive",".archive"]),r=[],l=[i];for(;l.length;){let c=l.pop();for(let A of c.children){if(A instanceof F.TFolder){let h=A.name;if(c===i&&o.has(h)||c===i&&h==="_attachments"&&!s)continue;l.push(A);continue}A instanceof F.TFile&&A.extension!=="md"&&(A.name===".stashpad-order.json"||A.name===".stashpad-sort.json"||!s&&n.has(A.path)||r.push(A))}}return r}populateListBody(e,t){if(this.lastListWidth=e.clientWidth||this.lastListWidth,this.bodyRenderer.arm(),this.pendingCursorId){let A=this.currentChildren.findIndex(h=>h.id===this.pendingCursorId);A>=0&&(this.cursorIdx=A,this.selection.clear(),this.selection.add(this.pendingCursorId),this.lastSelected=this.pendingCursorId,this.pendingCursorId=null)}t.file&&F.Platform.isMobile&&!this.compactMode&&(this.renderFocusedHeaderMini(e,t),this.renderFocusedHeader(e,t));let i=this.currentViewMode(),s=i==="everything"?this.collectFileItems(t.id):[],n=A=>A.created&&Number.isFinite(Date.parse(A.created))?Date.parse(A.created):Number.POSITIVE_INFINITY,o=this.currentEncryptionFilter(),r;if(o==="unlocked")r=[];else if(i==="nested")r=this.plugin.lockedSubtreesFor(this.noteFolder,t.id);else{let A=new Set([t.id,...this.currentChildren.map(g=>g.id)]),h=new Set;r=[];for(let g of A)for(let u of this.plugin.lockedSubtreesFor(this.noteFolder,g))h.has(u.blob)||(h.add(u.blob),r.push(u))}let l=r.map(A=>({lk:A,ts:n(A)})).sort((A,h)=>A.ts-h.ts),c=i==="nested"&&this.sortStore.getMode(this.noteFolder,t.id)==="manual";if(this.currentChildren.length===0&&s.length===0&&l.length===0)e.createDiv({cls:"stashpad-empty",text:"No notes here yet. Type below to add one."});else if(c&&l.length>0){let A=new Map(this.currentChildren.map((p,I)=>[p.id,I])),h=new Map;for(let{lk:p}of l)p.rootId&&h.set(p.rootId,p);let g=this.currentChildren.map(p=>p.id),u=l.map(({lk:p})=>p).filter(p=>p.rootId).sort((p,I)=>n(I)-n(p)),f=!0;for(;u.length&&f;){f=!1;for(let p=0;p<u.length;p++){let I=u[p],m=I.prevSibling??null,B;if(m==null)B=0;else{let C=g.indexOf(m);if(C<0)continue;B=C+1}g.splice(B,0,I.rootId),u.splice(p,1),p--,f=!0}}for(let p of u)g.push(p.rootId);for(let p of g){let I=A.get(p);if(I!==void 0)this.renderNote(e,this.currentChildren[I],I);else{let m=h.get(p);m&&this.renderLockedPlaceholder(e,m)}}for(let p of s.slice().sort((I,m)=>I.stat.ctime-m.stat.ctime))this.renderFileRow(e,p)}else if(s.length===0){let A=0;for(let h=0;h<this.currentChildren.length;h++){let g=Number.isFinite(Date.parse(this.currentChildren[h].created))?Date.parse(this.currentChildren[h].created):0;for(;A<l.length&&l[A].ts<=g;)this.renderLockedPlaceholder(e,l[A].lk),A++;this.renderNote(e,this.currentChildren[h],h)}for(;A<l.length;)this.renderLockedPlaceholder(e,l[A].lk),A++}else{let A=[...this.currentChildren.map((h,g)=>({kind:"note",ts:Number.isFinite(Date.parse(h.created))?Date.parse(h.created):0,idx:g})),...s.map(h=>({kind:"file",ts:h.stat.ctime,file:h})),...l.map(h=>({kind:"lock",ts:h.ts,lk:h.lk}))];A.sort((h,g)=>h.ts-g.ts);for(let h of A)h.kind==="note"?this.renderNote(e,this.currentChildren[h.idx],h.idx):h.kind==="file"?this.renderFileRow(e,h.file):this.renderLockedPlaceholder(e,h.lk)}t.file&&F.Platform.isMobile&&!this.compactMode&&this.installFocusedMiniObserver(e)}renderLockedPlaceholder(e,t){let i=e.createDiv({cls:"stashpad-locked-row"});t.created&&i.createSpan({cls:"stashpad-note-time stashpad-locked-time",text:this.formatTime(t.created)});let s=i.createSpan({cls:"stashpad-locked-icon"});(0,F.setIcon)(s,"lock");let n=!t.title;i.createSpan({cls:"stashpad-locked-title",text:n?"Locked note":t.title}),i.createSpan({cls:"stashpad-locked-count",text:t.count>1?`${t.count} notes \xB7 locked`:"locked"});let o=i.createEl("button",{cls:"stashpad-locked-unlock",text:"Unlock"});(0,F.setIcon)(o.createSpan({cls:"stashpad-btn-icon"}),"unlock");let r=async A=>{A.preventDefault(),A.stopPropagation();let h=(this.plugin.settings.lockedSubtrees??[]).find(I=>I.blob===t.blob),g=t.rootId??h?.rootId??null,u=t.parentId??h?.parentId??S,f=t.prevSibling??h?.prevSibling??null;if(await this.plugin.unlockBundleAt(t.blob)){if(this.selection.clear(),this.lastSelected=null,g){let I=this.order.getOrder(this.noteFolder,u),m=this.sortStore.getMode(this.noteFolder,u)==="manual";if(I.length===0&&m&&(I=this.tree.getChildren(u).map(B=>B.id)),I.length>0){let B=I.filter(w=>w!==g),C=f&&B.includes(f)?B.indexOf(f)+1:0;B.splice(Math.max(0,C),0,g),this.order.setOrder(this.noteFolder,u,B),this.order.flush(this.noteFolder)}this.pendingCursorId=g}if(this.render(),g){let I=this.noteFolder,m=t.blob;this.plugin.getUndoStack(I).push({label:"Unlock note",undo:async()=>{let B=await this.plugin.lockNoteSubtree(I,g,f,{silent:!0});B&&(m=B.blobPath),this.render()},redo:async()=>{try{await this.plugin.unlockBundleAt(m,{silent:!0})}catch{}this.render()}})}}};o.onclick=r;let l=A=>{A.preventDefault(),A.stopPropagation();let h=new F.Menu,g=u=>new F.Notice(`Unlock this note first to ${u}.`);if(h.addItem(u=>u.setTitle("Open in new Stashpad tab").setIcon("layout-grid").onClick(()=>g("open it in a tab"))),h.addItem(u=>u.setTitle("Open in editor").setIcon("file-text").onClick(()=>g("open it in the editor"))),h.addItem(u=>u.setTitle("Focus in Stashpad").setIcon("arrow-right").onClick(()=>g("focus it"))),h.addItem(u=>{u.setTitle("Copy Stashpad link").setIcon("link"),t.rootId?u.onClick(()=>{let f=Go({vault:this.app.vault.getName(),folder:this.noteFolder,note:t.rootId,run:["reveal"]});navigator.clipboard.writeText(f).then(()=>new F.Notice("Stashpad link copied."),()=>new F.Notice("Couldn't copy the link."))}):u.setDisabled(!0)}),h.addSeparator(),h.addItem(u=>u.setTitle("Split note\u2026").setIcon("split").onClick(()=>g("split it"))),h.addItem(u=>u.setTitle("Copy text").setIcon("copy").onClick(()=>g("copy its text"))),h.addItem(u=>u.setTitle("Clone (duplicate / copy)").setIcon("files").onClick(()=>g("clone it"))),h.addItem(u=>u.setTitle("Fork into a separate note\u2026").setIcon("git-branch").onClick(()=>g("fork it"))),h.addItem(u=>u.setTitle("Export to .stash\u2026").setIcon("package").onClick(()=>{this.plugin.exportLockedSubtree(t.blob)})),this.plugin.settings.okfEnabled&&h.addItem(u=>u.setTitle("Export as OKF\u2026").setIcon("book-marked").onClick(()=>g("export it as OKF"))),h.addItem(u=>u.setTitle("Decrypt (unlock)").setIcon("unlock").onClick(()=>void r(A))),!F.Platform.isMobile){let u=F.Platform.isMacOS?"Finder":F.Platform.isWin?"File Explorer":"file manager";h.addItem(f=>f.setTitle(`Show in ${u}`).setIcon("folder-search").onClick(()=>{try{let p=window.require?.("electron")?.shell,I=this.app.vault.adapter?.getFullPath?.(t.blob);I&&p?.showItemInFolder&&p.showItemInFolder(I)}catch(p){console.warn("[Stashpad] showItemInFolder failed",p)}}))}h.addItem(u=>u.setTitle("Copy encrypted file path").setIcon("copy").onClick(()=>{let f=t.blob;if(!F.Platform.isMobile)try{f=this.app.vault.adapter?.getFullPath?.(t.blob)||t.blob}catch{}navigator.clipboard.writeText(f),new F.Notice("Path copied.")})),h.addSeparator(),h.addItem(u=>u.setTitle("Move to\u2026").setIcon("move").onClick(()=>g("move it"))),h.addItem(u=>u.setTitle("Move to Home").setIcon("home").onClick(()=>g("move it"))),h.addItem(u=>u.setTitle("Pin to sidebar").setIcon("pin").onClick(()=>g("pin it"))),h.addItem(u=>u.setTitle("Pin to top of list").setIcon("arrow-up-to-line").onClick(()=>g("pin it"))),h.addItem(u=>u.setTitle("Set color\u2026").setIcon("palette").onClick(()=>g("set its color"))),h.addItem(u=>u.setTitle("Task").setIcon("check-circle-2").onClick(()=>g("change its task state"))),h.addItem(u=>{u.setTitle(t.count>1?"Delete encrypted notes\u2026":"Delete encrypted note\u2026").setIcon("trash-2"),u.setWarning?.(!0),u.onClick(()=>{new _(this.app,t.count>1?`Delete ${t.count} encrypted notes?`:"Delete encrypted note?","The encrypted file moves to Obsidian's trash (recoverable there). You'll still need your password to read it if you restore it.","Delete",async f=>{if(!f)return;let p=t.blob,I=p.replace(/\.stashenc$/,".stashmeta"),m=this.app.vault.adapter,B=null,C=null;try{B=await m.readBinary(p)}catch{B=null}if(!B){new F.Notice("Couldn't read the encrypted file to delete it.");return}try{await m.exists(I)&&(C=await m.read(I))}catch{C=null}let w=(this.plugin.settings.lockedSubtrees??[]).find(Q=>Q.blob===p)??null,y=async()=>{let Q=async b=>{let D=this.app.vault.getAbstractFileByPath(b);if(D)try{await this.app.fileManager.trashFile(D);return}catch{}try{await m.exists(b)&&await m.remove(b)}catch{}};return await Q(p),await Q(I),!0},v=async()=>{await y(),this.plugin.settings.lockedSubtrees=(this.plugin.settings.lockedSubtrees??[]).filter(Q=>Q.blob!==p),await this.plugin.saveSettings(),this.render()},E=async()=>{if(await m.writeBinary(p,B),C!=null)try{await m.write(I,C)}catch{}w&&!(this.plugin.settings.lockedSubtrees??[]).some(Q=>Q.blob===p)&&(this.plugin.settings.lockedSubtrees=[...this.plugin.settings.lockedSubtrees??[],w],await this.plugin.saveSettings()),this.render()};await v(),this.plugin.getUndoStack(this.noteFolder).push({label:t.count>1?"Delete encrypted notes":"Delete encrypted note",undo:E,redo:v}),new F.Notice(t.count>1?"Encrypted notes deleted \u2014 undo to restore.":"Encrypted note deleted \u2014 undo to restore.")}).open()})}),h.showAtMouseEvent(A)};i.oncontextmenu=l;let c=i.createEl("button",{cls:"stashpad-pencil stashpad-locked-menu"});(0,F.setIcon)(c,"more-vertical"),c.setAttr("aria-label","Locked note menu"),c.onclick=A=>l(A),i.setAttr("aria-label",`${n?"Locked note":`Locked: ${t.title}`}. Use the Unlock button to decrypt.`)}refreshList(){if(!this.listEl){this.render();return}let e=this.tree.get(this.focusId)??this.tree.getRoot();this.currentChildren=this.filterChildren(this.collectViewItems(e.id)),this.cursorIdx>=this.currentChildren.length&&(this.cursorIdx=this.currentChildren.length-1);let t=this.listEl.scrollTop+this.listEl.clientHeight>=this.listEl.scrollHeight-2,i=this.listEl.scrollTop;this.listEl.empty(),this.populateListBody(this.listEl,e),t?this.listEl.scrollTop=this.listEl.scrollHeight:this.listEl.scrollTop=i}renderFileRow(e,t){if(this.currentEncryptionFilter()==="locked")return;let i=e.createDiv({cls:"stashpad-file-row"});i.dataset.path=t.path,i.createDiv({cls:"stashpad-file-meta"}).createSpan({cls:"stashpad-file-time",text:this.formatTime(new Date(t.stat.ctime).toISOString())});let n=i.createDiv({cls:"stashpad-file-body"});n.createSpan({cls:"stashpad-file-name",text:t.name}),n.createSpan({cls:"stashpad-file-ext",text:t.extension.toUpperCase()}),i.title=`${t.path} \u2014 click to open`,i.onclick=o=>{o.preventDefault(),this.app.workspace.openLinkText(t.path,"",!1)}}async setViewMode(e){let t={...this.plugin.settings.viewModes??{}};e==="nested"?delete t[this.noteFolder]:t[this.noteFolder]=e,this.plugin.settings.viewModes=t,await this.plugin.saveSettings()}collectViewItems(e){let t=this.currentViewMode(),i=this.currentHideChildless(),s=this.tree.getChildren(e),n=i?s.filter(l=>l.children.length>0):s;if(t==="nested")return n;let o=[],r=l=>{o.push(l);for(let c of this.tree.getChildren(l.id))r(c)};for(let l of n)r(l);return o}filterChildren(e){e=this.collapseVersions(e);let t=this.timeFilterCutoff(),i=this.tagFilter?.toLowerCase(),s=this.colorFilter?.toLowerCase()??null,n=this.currentHideCompleted(),o=this.currentAttachmentsOnly(),r=this.importedOnly,l=this.authorFilter;return!t&&!i&&!s&&!n&&!o&&!r&&!l?e:e.filter(c=>{if(r&&(!c.file||this.app.metadataCache.getFileCache(c.file)?.frontmatter?.imported!==!0))return!1;if(l){if(!c.file)return!1;let A=rt(this.app.metadataCache.getFileCache(c.file)?.frontmatter?.author);if(!A||A.id!==l)return!1}if(t&&c.created){let A=Date.parse(c.created);if(!Number.isNaN(A)&&A<t)return!1}if(i){if(!c.file)return!1;if(this.tagFilter===Pt){if(!this.nodeHasAnyTag(c))return!1}else if(this.tagFilter===Ht){if(this.nodeHasAnyTag(c))return!1}else if(!this.nodeHasTag(c,i))return!1}return!(s&&(this.colorForNode(c)?.toLowerCase()??null)!==s||n&&this.isCompleted(c)&&!this.hasIncompleteDescendant(c)||o&&!this.hasAttachmentInSubtree(c))})}collapseVersions(e){if(!this.plugin.settings.enableSheetVersions)return e;let t=new Map,i=!1;for(let n of e){let o=ye(this.app,n);if(!xi(o))continue;i=!0;let r=Ye(o),l=t.get(r);l?l.push(n):t.set(r,[n])}if(!i)return e;let s=new Set;for(let[n,o]of t){let r=this.activeVersionNode(n,o);r&&s.add(r.id)}return e.filter(n=>xi(ye(this.app,n))?s.has(n.id):!0)}activeVersionNode(e,t){let i=this.activeVersionByGroup.get(e);if(i){let s=t.find(n=>n.id===i);if(s)return s}return Cr(this.app,t)}setActiveVersion(e,t){this.activeVersionByGroup.set(e,t),this.plugin.saveActiveVersion(this.noteFolder,e,t),this.render()}nodeHasAnyTag(e){if(!e.file)return!1;let t=this.app.metadataCache.getFileCache(e.file);if(!t)return!1;if(t.tags&&t.tags.length>0)return!0;let i=t.frontmatter?.tags;return!!(i&&(Array.isArray(i)?i:[i]).some(n=>typeof n=="string"&&n.trim().length>0))}nodeHasTag(e,t){if(!e.file)return!1;let i=this.app.metadataCache.getFileCache(e.file);if(!i)return!1;if(i.tags){for(let n of i.tags)if((n.tag||"").replace(/^#/,"").toLowerCase()===t)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()===t)return!0}return!1}collectFolderTags(){let e=new Map,t=this.tree.getChildren(this.focusId);for(let s of t){if(!s.file)continue;let n=this.app.metadataCache.getFileCache(s.file);if(n?.tags)for(let r of n.tags){let l=(r.tag||"").replace(/^#/,"");l&&e.set(l,(e.get(l)??0)+1)}let o=n?.frontmatter?.tags;if(o){let r=Array.isArray(o)?o:[o];for(let l of r){if(typeof l!="string")continue;let c=l.replace(/^#/,"");c&&e.set(c,(e.get(c)??0)+1)}}}let i=[...e.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(e){return e&&e.split("/").map(t=>t.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 e=new Map,t=this.tree.getChildren(this.focusId);for(let s of t){let n=this.colorForNode(s);if(!n)continue;let o=n.toLowerCase();e.set(o,(e.get(o)??0)+1)}let i=[...e.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 e=this.tree.get(this.focusId)??this.tree.getRoot(),t=this.filterChildren(this.collectViewItems(e.id));this.cursorIdx=t.length-1,this.selection.clear(),t.length>0&&(this.selection.add(t[t.length-1].id),this.lastSelected=t[t.length-1].id)}stampSelectedCursor(e=!1){this.stampSelection(e);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(e){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 e=this.listEl;if(!e)return null;let t=e.getBoundingClientRect().top,i=Array.from(e.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-t;if(r>=0){s={id:o,offsetFromListTop:r};break}s={id:o,offsetFromListTop:r}}return s}restoreScrollAnchor(e,t){let i=this.listEl;if(i){if(e){let s=i.querySelector(`[data-id="${e.id}"]`);if(s){let n=i.getBoundingClientRect().top,o=s.getBoundingClientRect().top-n;i.scrollTop+=o-e.offsetFromListTop;return}}t>0&&(i.scrollTop=t)}}render(e){if(ke.enabled&&(this._renderT0=performance.now()),!this.viewRoot?.isConnected)return;this.pendingRenderPolicy=e??{kind:"preserve"},this.loadConfig();let t=this.viewRoot,i=this.listEl?.scrollTop??0,n=(e??{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);t.empty(),t.toggleClass("is-mobile",F.Platform.isMobile),t.toggleClass("is-tiny",this.tinyMode),t.toggleClass("is-compact",this.compactMode);let l=this.containerEl.closest(".workspace-leaf");l&&(l.classList.toggle("stashpad-is-tiny",this.tinyMode),l.classList.toggle("stashpad-is-compact",this.compactMode));let c=this.containerEl.closest(".workspace-tabs");if(c&&c.classList.toggle("stashpad-has-tiny",this.tinyMode),this.tinyMode)this.renderTinyHeader(t);else{let f=this.compactMode&&F.Platform.isMobile;(!this.compactMode||F.Platform.isMobile)&&this.renderTimeFilterBar(t),f||this.renderBreadcrumb(t)}let A=this.tree.get(this.focusId)??this.tree.getRoot();A.file&&!F.Platform.isMobile&&!this.tinyMode&&!this.compactMode&&this.renderFocusedHeader(t,A),this.currentChildren=this.filterChildren(this.collectViewItems(A.id));let h=!1;if(this.autoSelectNewest&&this.currentChildren.length>0){let f=this.currentChildren[this.currentChildren.length-1];this.cursorIdx=this.currentChildren.length-1,this.selection.clear(),this.selection.add(f.id),this.lastSelected=f.id,this.autoSelectNewest=!1,h=!0}else if(this.pendingFocusIds){let f=this.pendingFocusIds;this.pendingFocusIds=null,this.selection.clear();let p=-1;for(let I of f){let m=this.currentChildren.findIndex(B=>B.id===I);m>=0&&(this.selection.add(I),p<0&&(p=m))}this.cursorIdx=p,p>=0&&(this.lastSelected=f.find(I=>this.currentChildren.some(m=>m.id===I))??null)}else this.cursorIdx>=this.currentChildren.length&&(this.cursorIdx=this.currentChildren.length-1);let g=t.createDiv({cls:"stashpad-list"});if(this.listEl=g,this.dnd.attachListDnD(g),this.populateListBody(g,A),this.renderComposer(t),F.Platform.isMobile&&this.renderMobileNav(t),this._renderT0!=null&&(ke.record("render.total",performance.now()-this._renderT0),this._renderT0=null),this.plugin.notifyStashpadContentChanged(),h&&this.plugin.notifyStashpadSelectionChanged(),this.focusComposerOnNextRender){this.focusComposerOnNextRender=!1;let f=this.pendingComposerCaret;this.pendingComposerCaret=null;let p=this.composerInputEl;if(p&&p.isConnected){if(p.focus({preventScroll:!0}),f!=null){let I=Math.min(f,p.value.length);try{p.setSelectionRange(I,I)}catch{}}}else requestAnimationFrame(()=>{let I=this.composerInputEl;if(I&&(I.focus({preventScroll:!0}),f!=null)){let m=Math.min(f,I.value.length);try{I.setSelectionRange(m,m)}catch{}}})}let u=this.pendingRenderPolicy;if(this.pendingRenderPolicy=null,u&&this.listEl){let f=this.scrollToBottomOnNextRender;switch(this.scrollToBottomOnNextRender=!1,u.kind){case"preserve":f?this.scrollListToBottom():r?this.scrollListToBottom():this.restoreScrollAnchor(n,i);break;case"pin-bottom":this.scrollListToBottom();break;case"restore":{let p=u.scrollTop,I=this.listEl,m=()=>{this.suppressScrollSave=!0;let B=Math.max(0,I.scrollHeight-I.clientHeight);I.scrollTop=Math.min(p,B),Promise.resolve().then(()=>{this.suppressScrollSave=!1})};m(),requestAnimationFrame(m),setTimeout(m,60),setTimeout(m,200),setTimeout(m,600);break}case"follow-cursor":i>0&&(this.listEl.scrollTop=i),this.revealCursorRow();break;case"scroll-to-id":{let p=u.id,I=u.align,m=this.listEl,B=()=>{this.suppressScrollSave=!0;let C=m.querySelector(`[data-id="${p}"]`);C&&C.scrollIntoView({block:I,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 f=this.listEl,p=f.scrollTop,I=new ResizeObserver(()=>{if(Date.now()<this.keyboardTransitionUntil)return;if(this.stickToListBottom){f.scrollTop=f.scrollHeight,p=f.scrollTop;return}let B=Math.max(0,f.scrollHeight-f.clientHeight);f.scrollTop<p&&p<=B?f.scrollTop=p:p=f.scrollTop});I.observe(f),this.listResizeObserver=I,f.addEventListener("wheel",B=>{B.deltaY<0&&(this.stickToListBottom=!1)},{passive:!0});let m=0;f.addEventListener("touchstart",B=>{m=B.touches[0]?.clientY??0},{passive:!0}),f.addEventListener("touchmove",B=>{let C=B.touches[0]?.clientY??m;C>m&&(this.stickToListBottom=!1),m=C},{passive:!0}),f.addEventListener("mousedown",()=>{this.stickToListBottom=!1}),f.addEventListener("keydown",()=>{this.stickToListBottom=!1})}}refreshFolderSwitcherIcon(){let e=this.containerEl.querySelector(".stashpad-folder-btn .stashpad-btn-icon");e&&(e.empty(),(0,F.setIcon)(e,this.plugin.getFolderIcon(this.noteFolder)??"folder"))}renderTimeFilterBar(e){let t=e.createDiv({cls:"stashpad-time-filter-bar"});if(!F.Platform.isMobile){let c=t.createEl("button",{cls:"stashpad-folder-btn"}),A=!!this.folderOverride,h=this.noteFolder.split("/").pop()||this.noteFolder||"Stashpad";(0,F.setIcon)(c.createSpan({cls:"stashpad-btn-icon"}),this.plugin.getFolderIcon(this.noteFolder)??"folder"),c.createSpan({text:h,cls:"stashpad-btn-text"}),c.title=A?`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:d.actionsForFile(a.path)}),console.error(e)}}function yd(d){let a=new Set,e=t=>{if(a.add(t),!!d.tree.get(t))for(let s of d.tree.getChildren(t))e(s.id)};return e(k),a}Hi();Hi();var Ed=new Set(["png","jpg","jpeg","gif","webp","svg","bmp","avif"]),gs={nested:"Nested",flat:"Flat",everything:"Everything"},us=[{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"}],fs=class fs extends b.ItemView{constructor(e,t){super(e);this.focusId=k;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.composerSplitBtn=null;this.composerEnterBtn=null;this.composerHelperEl=null;this.composerDestBtn=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.tapSettleUntil=0;this.aimedTapTargetId=null;this.aimedTapAt=0;this.stickyRowObserver=null;this.listResizeObserver=null;this.composerNarrowObserver=null;this.barOverflowRO=null;this.lastCursorByFocus=new Map;this.lastSelectionByFocus=new Map;this.expandedNotes=new Set;this.cursorExpandOverride=new Set;this.cursorHasMoved=!1;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.syncBurstTimes=[];this.autoSyncDeferActive=!1;this.autoSyncSettleTimer=null;this.autoSyncNotice=null;this.stampLastCursorTimer=null;this.stampSelectionTimer=null;this._renderT0=null;this.tinyOpacityPopover=null;this.tinyOpacityClose=null;this.lastListWidth=0;this.keydownWindow=window;this.onDocKeyDown=e=>{if(!this.viewRoot.isConnected||this.app.workspace.activeLeaf!==this.leaf||xr(e.target))return;let t=X().bindings;if(q(e,t.toggleSplit)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.toggleSplit();return}if(q(e,t.pickDestination)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.openDestinationPicker();return}if(q(e,t.search)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.openSearchModal();return}if(q(e,t.commandPalette)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.openStashpadCommandPalette();return}if(q(e,t.lockSelection)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdLockSelection();return}if(q(e,t.unlockAll)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdUnlockAll();return}if(q(e,t.moveToArchive)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdMoveToArchive();return}if(q(e,t.encryptDelete)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdEncryptDelete();return}if(q(e,t.searchInParent)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.openSearchInParentModal();return}if(q(e,t.exportStash)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdExportStash();return}if(q(e,t.importStash)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdImportStash();return}if(q(e,t.pickFolder)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdOpenFolderPicker();return}if(q(e,t.cloneStashpadTab)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdCloneStashpadTab();return}let i=e.target,s=!!i&&(i.tagName==="INPUT"||i.tagName==="TEXTAREA");if(e.key===" "&&!e.metaKey&&!e.ctrlKey&&!e.altKey&&!e.shiftKey&&!s){let l=this.composerInputEl;if(l){e.preventDefault(),e.stopPropagation(),l.focus();let c=l.value.length;l.setSelectionRange(c,c);return}}let n=!!i&&(i.tagName==="INPUT"||i.tagName==="TEXTAREA"||i.tagName==="BUTTON"||i.tagName==="SELECT");if(e.key==="Escape"&&i instanceof HTMLElement&&(i.tagName==="BUTTON"||i.tagName==="SELECT")&&this.viewRoot.contains(i)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.viewRoot.focus();return}if(this.inListPicker&&e.key==="Escape"){e.preventDefault(),e.stopPropagation(),this.inListPicker=null,this.pickerEscapeAt=Date.now();let l=this.listEl,c=!!l&&l.scrollTop+l.clientHeight>=l.scrollHeight-2,A=l?.scrollTop??0;if(this.render(),l){let h=c?l.scrollHeight:A;l.scrollTop=h,requestAnimationFrame(()=>{l.scrollTop=c?l.scrollHeight:A}),setTimeout(()=>{l.scrollTop=c?l.scrollHeight:A},60),this.revealCursorRow()}return}if(this.inListPicker&&!n){if(e.key==="ArrowDown"){e.preventDefault(),this.inListPicker.activeIdx=this.nextPickableIdx(this.inListPicker.activeIdx,1),this.repaintSelectionClasses(),this.revealRowAt(this.inListPicker.activeIdx);return}if(e.key==="ArrowUp"){e.preventDefault(),this.inListPicker.activeIdx=this.nextPickableIdx(this.inListPicker.activeIdx,-1),this.repaintSelectionClasses(),this.revealRowAt(this.inListPicker.activeIdx);return}if(e.key==="Enter"){e.preventDefault(),this.commitInListPicker();return}if(q(e,X().bindings.move)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.inListPicker=null,this.repaintSelectionClasses(),this.cmdMovePicker();return}return}if(n)return;if(q(e,t.delete)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdDelete();return}if(q(e,t.toggleComplete)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdToggleComplete();return}if(q(e,t.moveToTop)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdMoveToTop();return}if(q(e,t.moveToBottom)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdMoveToBottom();return}if(q(e,t.moveUp)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdMoveUp();return}if(q(e,t.moveDown)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdMoveDown();return}if(q(e,t.outdent)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdOutdent();return}if(q(e,t.setColor)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdSetColor();return}if(q(e,t.selectAll)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdSelectAll();return}if(q(e,t.swapWithParent)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdSwapWithParent();return}if(q(e,t.undo)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdUndo();return}if(q(e,t.redo)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdRedo();return}if(e.key===" "){e.preventDefault();let l=this.composerInputEl;if(l){l.focus();let c=l.value.length;l.setSelectionRange(c,c)}return}if(e.key==="ArrowDown"){e.preventDefault(),this.cursorIdx>=this.currentChildren.length-1?this.cursorIdx=0:this.cursorIdx++,this.selectCursor(e.shiftKey);return}if(e.key==="ArrowUp"){e.preventDefault(),this.cursorIdx<=0?this.cursorIdx=this.currentChildren.length-1:this.cursorIdx--,this.selectCursor(e.shiftKey);return}if(e.altKey&&e.key==="ArrowLeft"){e.preventDefault(),this.navigateBack();return}if(e.altKey&&e.key==="ArrowRight"){e.preventDefault(),this.navigateForward();return}if(e.key==="ArrowRight"){let l=this.currentChildren[this.cursorIdx];l&&(e.preventDefault(),this.navigateTo(l.id));return}if(e.key==="ArrowLeft"||e.key==="Backspace"){e.preventDefault(),this.navigateUp();return}if(e.key==="Escape"){if(e.preventDefault(),e.stopPropagation(),e.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 l=this.firstSelectedId??(this.selection.size>0?this.selection.values().next().value:null);if(this.selection.clear(),this.firstSelectedId=null,l){let c=this.currentChildren.findIndex(A=>A.id===l);this.selection.add(l),this.lastSelected=l,c>=0&&(this.cursorIdx=c)}this.repaintSelectionClasses(),this.revealCursorRow();return}let o=X().bindings;if(q(e,o.pasteNotes)&&this.plugin.noteClipboard){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdPasteNotes();return}if(this.selection.size>0||this.cursorIdx>=0&&this.currentChildren[this.cursorIdx]){if(q(e,o.move)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdMovePicker();return}if(q(e,o.pickMove)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdInListPicker();return}if(q(e,o.merge)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdMerge();return}if(q(e,o.copy)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdCopy();return}if(q(e,o.copyNotes)&&!window.getSelection()?.toString()){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdCopyNotes();return}if(q(e,o.cutNotes)&&!window.getSelection()?.toString()){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdCutNotes();return}if(q(e,o.copyTree)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdCopyTree();return}if(q(e,o.copyLink)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdCopyStashpadLink();return}if(q(e,o.copyOutline)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdCopyOutline();return}if(q(e,o.copyCodeBlock)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdCopyCodeBlock();return}if(q(e,o.openEditor)){if(e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),e.shiftKey){let l=this.tree.get(this.focusId);l?.file&&this.cmdOpenInEditor(l)}else this.cmdOpenInEditor();return}if(q(e,o.openTab)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdOpenInNewStashpadTab();return}if(q(e,o.split)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdSplit();return}if(q(e,o.clone)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdClone();return}if(q(e,o.forkNote)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdForkNote();return}if(q(e,o.insertTemplate)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdInsertTemplate();return}if(q(e,o.toggleExpand)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdToggleExpand();return}if(q(e,o.expandAll)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdExpandAll();return}if(q(e,o.collapseAll)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdCollapseAll();return}if(q(e,o.togglePin)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdTogglePin();return}if(q(e,o.listPin)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdToggleListPin();return}if(q(e,o.toggleTask)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdToggleTask();return}if(q(e,o.setDue)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdSetDue();return}}if(this.currentChildren.length>0){if(q(e,o.jumpToTop)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.jumpToTop();return}if(q(e,o.jumpToBottom)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.jumpToBottom();return}}let r=this.tree.get(this.focusId);if(r?.file){if(q(e,o.openEditor)){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.cmdOpenInEditor(r);return}if(q(e,o.openTab)){e.preventDefault(),e.stopPropagation(),e.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=e=>{!(e instanceof b.TFile)||e.extension!=="md"||e.path.startsWith(this.noteFolder+"/")&&(this.bodyRenderer.evict(e),this.scheduleSlugRename(e),this.scheduleAttachmentSync(e),this.authorship.noteModify(e),!this.deferDuringSyncBurst()&&this.debouncedRender())};this.onFileCreate=e=>{!(e instanceof b.TFile)||e.extension!=="md"||e.path.startsWith(this.noteFolder+"/")&&(this.deferDuringSyncBurst()||this.debouncedRender())};this.plugin=t,this.tree=new sn(this.app),this.log=t.newLog(),this.integrity=new dn(this.tree,this.log),this.order=new Ii(this.app),this.sortStore=new rn(this.app),this.fmSync=new ln(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):Da(this,i,n);return this.hoistListPinned(i,o)}),this.debouncedRender=(0,b.debounce)(()=>{this.renderSuppressed()||this.render()},80),this.authorship=new In(this),this.dnd=new mn(this),this.bodyRenderer=new Cn(this,this,this.plugin.renderCacheStore)}getViewType(){return z}getDisplayText(){let e=(this.noteFolder||"").trim(),t=e.split("/").pop()||e||"Stashpad";if(this.focusId&&this.focusId!==k){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`${t} \u2014 ${n} \xB7 ${this.focusId}`}}return t}refreshHeaderTitle(){let e=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!==e&&i.setText(e)}getIcon(){return this.plugin.getFolderIcon(this.noteFolder)??"list-tree"}async onOpen(){let e=this.contentEl;e.empty(),e.addClass("stashpad-scroll-host"),this.viewRoot=e.createDiv({cls:"stashpad-view"}),this.viewRoot.setAttribute("tabindex","0"),this.viewRoot.addEventListener("focusin",()=>Xs(this)),this.viewRoot.addEventListener("click",()=>Xs(this)),this.viewRoot.addEventListener("mouseup",l=>{l.button===3?(l.preventDefault(),this.navigateBack()):l.button===4&&(l.preventDefault(),this.navigateForward())}),this.viewRoot.addEventListener("auxclick",l=>{l.button===3?(l.preventDefault(),this.navigateBack()):l.button===4&&(l.preventDefault(),this.navigateForward())}),Xs(this),this.registerInterval(window.setInterval(()=>this.authorship.pruneContribMaps(),6e4));let t=null,i=()=>{t||(t=new b.Scope(this.app.scope),t.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 l=this.firstSelectedId??this.selection.values().next().value??null;if(this.selection.clear(),this.firstSelectedId=null,l){let c=this.currentChildren.findIndex(A=>A.id===l);this.selection.add(l),this.lastSelected=l,c>=0&&(this.cursorIdx=c)}this.render(),this.revealCursorRow()}return!1}),this.app.keymap?.pushScope(t))},s=()=>{if(t){try{this.app.keymap?.popScope(t)}catch{}t=null}};this.viewRoot.addEventListener("focusin",i),this.viewRoot.addEventListener("focusout",l=>{let c=l.relatedTarget;c&&this.viewRoot&&this.viewRoot.contains(c)||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",l=>{if(l.extension!=="md")return;let c=this.app.metadataCache.getFileCache(l)?.frontmatter;this.completedState.set(l.path,!!c?.completed),this.taskTaggedState.set(l.path,this.taggedFromFm(c))})),this.registerEvent(this.app.vault.on("rename",(l,c)=>{for(let A of[this.completedState,this.taskTaggedState])A.has(c)&&(A.set(l.path,A.get(c)),A.delete(c))})),this.registerEvent(this.app.vault.on("delete",l=>{this.completedState.delete(l.path),this.taskTaggedState.delete(l.path);let c=l.path.lastIndexOf("/"),A=(c>=0?l.path.slice(0,c):"").replace(/\/+$/,"");l.path.endsWith(".md")&&A===this.noteFolder.replace(/\/+$/,"")&&(this.tree.rebuild(this.noteFolder),this.debouncedRender())})),this.detachSettings=pa(()=>{this.loadConfig();let l=this.plugin.settings.drafts?.[this.noteFolder]??"",c=this.composerInputEl?.value??"";l===""&&this.composerDraft!==""&&c===""?(this.composerDraft="",this.composerInputEl&&(this.composerInputEl.value="")):l===""&&c!==""&&(this.composerDraft=c),!!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),this.keydownWindow=this.containerEl?.ownerDocument?.defaultView??window,this.keydownWindow.addEventListener("keydown",this.onDocKeyDown,!0),this.loadConfig();try{await this.bootstrapFolder()}catch(l){let c=l?.message??"";/already exists/i.test(c)||console.warn("[Stashpad] bootstrapFolder failed:",l)}this.tree.rebuild(this.noteFolder),this.installFmSyncActivityNotice(),this.backfillFrontmatterSync(),this.plugin.maybeSweepFolder(this.noteFolder),this.defaultCursorToLast(),this.refreshHeaderTitle(),await this.loadDraftsForFolder();try{let l=this.plugin.loadLastCursor(this.noteFolder);for(let[c,A]of l)this.lastCursorByFocus.set(c,A);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)}),X().focusComposerOnOpen?this.focusComposer():this.focusView(),this.registerEvent(this.app.workspace.on("active-leaf-change",l=>{l===this.leaf?X().focusComposerOnOpen?this.focusComposer():this.focusView():this.stickToListBottom=!1}))}renderSuppressed(){return this.bulkRenderDepth>0||this.bulkSettleTimer!=null||this.autoSyncDeferActive||this.plugin.rebootstrapInProgress||this.plugin.okfRebuildingFolders.has(this.noteFolder)}beginBulkRender(){this.bulkRenderDepth++,this.bulkSettleTimer!=null&&(window.clearTimeout(this.bulkSettleTimer),this.bulkSettleTimer=null)}endBulkRender(e=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())},e))}deferDuringSyncBurst(){if(this.plugin.rebootstrapInProgress)return!1;let e=Date.now();this.syncBurstTimes.push(e);let t=e-2e3;for(;this.syncBurstTimes.length&&this.syncBurstTimes[0]<t;)this.syncBurstTimes.shift();return!this.autoSyncDeferActive&&this.syncBurstTimes.length>=6&&(this.autoSyncDeferActive=!0,this.autoSyncNotice=new b.Notice("Stashpad: syncing \u2014 list updates paused until it settles\u2026",0)),this.autoSyncDeferActive?(this.autoSyncSettleTimer!=null&&window.clearTimeout(this.autoSyncSettleTimer),this.autoSyncSettleTimer=window.setTimeout(()=>this.endAutoSyncDefer(),1500),!0):!1}endAutoSyncDefer(){this.autoSyncSettleTimer=null,this.autoSyncDeferActive=!1,this.syncBurstTimes=[],this.autoSyncNotice?.hide(),this.autoSyncNotice=null,this.forceReconcileRender()}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 e=this.noteFolder,t=e+"/",i=0;for(let s of this.app.vault.getMarkdownFiles()){let n=s.parent?.path?.replace(/\/+$/,"")??"";if(!(n===e||e!==""&&n.startsWith(t)))continue;let o=this.app.metadataCache.getFileCache(s)?.frontmatter?.id;typeof o=="string"&&o&&i++}i!==this.tree.fileBackedCount()&&(this.tree.rebuild(e),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(!X().focusComposerOnOpen)return;let e=()=>{if(!this.viewRoot?.isConnected||Date.now()<this.suppressComposerFocusUntil||Date.now()<this.plugin.suppressComposerAutofocusUntil)return;let t=document.activeElement;t&&(t.tagName==="INPUT"||t.tagName==="TEXTAREA")&&t!==this.composerInputEl||(t&&t.tagName==="BUTTON"&&this.viewRoot.contains(t),this.composerInputEl?.focus({preventScroll:!0}))};requestAnimationFrame(e),setTimeout(e,50),setTimeout(e,200)}async onClose(){da(this),this.debouncedRender?.cancel?.(),this.tinyOpacityClose?.(),this.detachTreeHook?.(),this.detachSettings?.(),this.app.vault.off("modify",this.onFileModify),this.app.vault.off("create",this.onFileCreate),this.keydownWindow.removeEventListener("keydown",this.onDocKeyDown,!0),this.listResizeObserver?.disconnect(),this.listResizeObserver=null,this.stickyRowObserver?.disconnect(),this.stickyRowObserver=null,this.bodyRenderer.dispose(),this.barOverflowRO?.disconnect(),this.barOverflowRO=null,this.composerNarrowObserver?.disconnect(),this.composerNarrowObserver=null,this.focusedMiniObserver?.disconnect(),this.focusedMiniObserver=null,this.treeReconcileTimer!=null&&(window.clearTimeout(this.treeReconcileTimer),this.treeReconcileTimer=null),this.autoSyncSettleTimer!=null&&(window.clearTimeout(this.autoSyncSettleTimer),this.autoSyncSettleTimer=null),this.autoSyncNotice?.hide(),this.autoSyncNotice=null,this.composerAutocomplete?.detach(),this.composerAutocomplete=null;for(let e of this.slugDebouncers.values())e.cancel();for(let e of this.attachmentDebouncers.values())e.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(e){let t=e;t?.focusId&&(this.focusId=t.focusId),t?.timeFilter&&(this.timeFilter=t.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(e,t){let i=e??null;if(i){"folderOverride"in i&&(this.folderOverride=i.folderOverride??null),i.timeFilter&&(this.timeFilter=i.timeFilter),i.focusId&&(this.focusId=i.focusId),i.cursorId&&(this.pendingCursorId=i.cursorId),"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(e,t),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 c=this.plugin.loadLastCursor(this.noteFolder);for(let[A,h]of c)this.lastCursorByFocus.set(A,h);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 l=this.foldRestoredSelection(o);l&&(this.pendingFocusIds=l),this.render(r),this.scheduleSelectionRestore()}}focus(){this.viewRoot?.focus({preventScroll:!0})}foldRestoredSelection(e){let t=this.lastSelectionByFocus.get(this.focusId)??null;if(!t||!t.length)return null;let i=t.filter(s=>!!this.tree.get(s));return i.length?e&&i.includes(e)?[e,...i.filter(s=>s!==e)]:i:null}stampSelection(e=!1){let t=[...this.selection],i=()=>{try{this.plugin.saveLastSelection(this.noteFolder,this.focusId,t)}catch{}};if(this.stampSelectionTimer!=null&&(window.clearTimeout(this.stampSelectionTimer),this.stampSelectionTimer=null),e){i();return}this.stampSelectionTimer=window.setTimeout(()=>{this.stampSelectionTimer=null,i()},400)}scheduleSelectionRestore(){let e=this.lastSelectionByFocus.get(this.focusId);if(!e||!e.length)return;let t=()=>{let i=e.filter(r=>this.currentChildren.some(l=>l.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(t,i)}loadConfig(){let e=(this.plugin?.settings?.folder??"Stashpad").trim().replace(/^\/+|\/+$/g,""),i=this.folderOverride?.trim().replace(/^\/+|\/+$/g,"")||null||e||"Stashpad";i!==this.noteFolder?(this.noteFolder=i,this.tree.rebuild(this.noteFolder)):this.noteFolder=i}captureNavSnapshot(){return{folder:this.noteFolder,focusId:this.focusId}}recordNavState(e={}){let t=this.captureNavSnapshot(),i=this.navBackStack[this.navBackStack.length-1];i&&i.folder===t.folder&&i.focusId===t.focusId||(this.navBackStack.push(t),e.keepForward||(this.navForwardSnapshots=[]))}async setFolderOverride(e,t={}){let i=e?.trim().replace(/^\/+|\/+$/g,"")||null;if(i&&this.isReservedFolder(i)){new b.Notice(`"${i}" is a reserved Stashpad subfolder (imports/exports/attachments). Pick a different folder.`);return}if((i||null)!==(this.folderOverride||null)){t.skipHistory||this.recordNavState(),this.folderOverride=i,this.focusId=k,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 e=[];for(let t of this.app.vault.getAllLoadedFiles())if(t instanceof b.TFolder){if(t.path==="/"||t.path===""||t.path.startsWith(".")||this.isReservedFolder(t.path))continue;e.push(t.path)}return e.sort((t,i)=>t.localeCompare(i))}isReservedFolder(e){let t=e.split("/").filter(Boolean).pop()??"";return t?new Set([this.plugin.settings.importDropFolder,this.plugin.settings.exportFolder,"_attachments","_processed","_authors"].map(s=>(s??"").trim().replace(/^\/+|\/+$/g,"")).filter(Boolean)).has(t):!1}persistFocus(){try{this.app.workspace.requestSaveLayout()}catch{}}cmdUndo(){let e=this.plugin.getUndoStack(this.noteFolder);if(!e.canUndo()){new b.Notice("Nothing to undo.");return}let t=e.peekUndoLabel(),i=this.plugin.notifications.recent()[0]?.category??"system";e.undo().then(()=>this.plugin.notifications.show({message:`Undid: ${t}`,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 e=this.plugin.getUndoStack(this.noteFolder);if(!e.canRedo()){new b.Notice("Nothing to redo.");return}let t=e.peekRedoLabel(),i=this.plugin.notifications.recent()[0]?.category??"system";e.redo().then(()=>this.plugin.notifications.show({message:`Redid: ${t}`,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(e,t){let i=[],s=new Set;for(let l of e)!l.file||s.has(l.file.path)||(s.add(l.file.path),i.push(l.file));let n=await Promise.all(i.map(l=>this.app.vault.read(l))),o=i.map((l,c)=>({path:l.path,content:n[c]})),r=[];if(t){let l=new Set,c=[];for(let h of n)for(let p of this.extractAttachments(this.stripFrontmatter(h))){let u=this.app.metadataCache.getFirstLinkpathDest(p,"");u&&!l.has(u.path)&&(l.add(u.path),c.push(u))}let A=await Promise.all(c.map(h=>this.app.vault.readBinary(h)));for(let h=0;h<c.length;h++)r.push({path:c[h].path,data:A[h]})}return{notes:o,attachments:r}}fileForNote(e,t){return(e?this.tree.get(e)?.file:null)??this.app.vault.getAbstractFileByPath(t)}async restoreSnapshots(e,t){for(let s of e.attachments)try{await this.app.vault.adapter.exists(s.path)||await this.app.vault.createBinary(s.path,s.data)}catch{}for(let s of e.notes)try{let n=s.content.split(` +---`)[0]??"",r=/^id:\s*["']?([^"'\s]+)/m.exec(n)?.[1];if(r&&this.tree.get(r)?.file)continue;await this.app.vault.adapter.exists(s.path)||await this.app.vault.create(s.path,s.content)}catch{}let i=()=>{t&&t.some(n=>this.tree.get(n))&&(this.pendingFocusIds=t.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 e.notes){let n=this.tree.idForPath(s.path);n&&this.fmSync.schedule(n)}},500)}async trashNotesAndAttachments(e){let t=new Set;for(let i of e.notes){let s=this.tree.idForPath(i.path);if(!s)continue;let n=this.tree.get(s);n?.parent&&t.add(n.parent)}for(let i of e.notes){let s=this.app.vault.getAbstractFileByPath(i.path);if(s)try{await this.app.fileManager.trashFile(s)}catch{}}for(let i of e.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 t)this.fmSync.scheduleParentOfDeleted(i)}async loadDraftsForFolder(){if(this.draftsLoadedFor===this.noteFolder)return;this.draftsLoadedFor=this.noteFolder;let e=this.plugin.settings.drafts??{};this.composerDraft=e[this.noteFolder]??"",console.debug("[Stashpad] loadDrafts",{folder:this.noteFolder,has:!!e[this.noteFolder],available:Object.keys(e)})}async saveDraft(e){try{let t=this.noteFolder;if((this.plugin.settings.drafts?.[t]??"")===e)return;let s={...this.plugin.settings.drafts??{}};e.length===0?delete s[t]:s[t]=e,this.plugin.settings.drafts=s,e.length===0?await this.plugin.saveSettings():await this.plugin.persistSettingsQuiet()}catch(t){console.warn("Stashpad: drafts save failed",t)}}async recordLastSubmitted(e){try{let t={...this.plugin.settings.lastSubmitted??{}};t[this.noteFolder]=e,this.plugin.settings.lastSubmitted=t,await this.plugin.persistSettingsQuiet()}catch{}}hasRestorableDraft(){let e=this.plugin.settings.drafts?.[this.noteFolder];if(!e||!e.trim())return!1;let t=this.plugin.settings.lastSubmitted?.[this.noteFolder];return!(t&&t===e)}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 t=(0,b.moment)();switch(this.timeFilter){case"day":return t.startOf("day").valueOf();case"week":return t.startOf("isoWeek").valueOf();case"month":return t.startOf("month").valueOf();case"year":return t.startOf("year").valueOf()}}let e=Date.now();switch(this.timeFilter){case"day":return e-864e5;case"week":return e-7*864e5;case"month":return e-30*864e5;case"year":return e-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(e){let t={...this.plugin.settings.includeAttachmentsInEverything??{}};e?t[this.noteFolder]=!0:delete t[this.noteFolder],this.plugin.settings.includeAttachmentsInEverything=t,await this.plugin.saveSettings()}currentEncryptionFilter(){return this.plugin.settings.encryptionFilter?.[this.noteFolder]??"all"}async setEncryptionFilter(e){let t={...this.plugin.settings.encryptionFilter??{}};e==="all"?delete t[this.noteFolder]:t[this.noteFolder]=e,this.plugin.settings.encryptionFilter=t,await this.plugin.saveSettings()}currentHideChildless(){return!!this.plugin.settings.hideChildlessNotes?.[this.noteFolder]}async setHideChildless(e){let t={...this.plugin.settings.hideChildlessNotes??{}};e?t[this.noteFolder]=!0:delete t[this.noteFolder],this.plugin.settings.hideChildlessNotes=t,await this.plugin.saveSettings()}currentHideCompleted(){return!!this.plugin.settings.hideCompletedNotes?.[this.noteFolder]}async setHideCompleted(e){let t={...this.plugin.settings.hideCompletedNotes??{}};e?t[this.noteFolder]=!0:delete t[this.noteFolder],this.plugin.settings.hideCompletedNotes=t,await this.plugin.saveSettings()}currentAttachmentsOnly(){return!!this.plugin.settings.attachmentsOnlyNotes?.[this.noteFolder]}async setAttachmentsOnly(e){let t={...this.plugin.settings.attachmentsOnlyNotes??{}};e?t[this.noteFolder]=!0:delete t[this.noteFolder],this.plugin.settings.attachmentsOnlyNotes=t,await this.plugin.saveSettings()}nodeHasAttachment(e){if(!e.file)return!1;let t=this.app.metadataCache.getFileCache(e.file)?.frontmatter?.attachments;return Array.isArray(t)&&t.length>0}hasAttachmentInSubtree(e){if(this.nodeHasAttachment(e))return!0;for(let t of this.tree.getChildren(e.id))if(this.hasAttachmentInSubtree(t))return!0;return!1}hasIncompleteDescendant(e){for(let t of e.children){let i=this.tree.get(t);if(i&&(!this.isCompleted(i)||this.hasIncompleteDescendant(i)))return!0}return!1}collectEmbeddedAttachmentPaths(){let e=new Set,t=this.noteFolder,i=this.app.vault.getAbstractFileByPath(t);if(!(i instanceof b.TFolder))return e;let s=[i];for(;s.length;){let n=s.pop();for(let o of n.children){if(o instanceof b.TFolder){s.push(o);continue}if(!(o instanceof b.TFile)||o.extension!=="md")continue;let r=this.app.metadataCache.getFileCache(o)?.frontmatter;if(!(!r||!Array.isArray(r.attachments)))for(let l of r.attachments){if(typeof l!="string")continue;let c=Tt(l),A=this.app.metadataCache.getFirstLinkpathDest(c,o.path);A?e.add(A.path):e.add(c)}}}return e}collectFileItems(e){let t=this.noteFolder,i=this.app.vault.getAbstractFileByPath(t);if(!(i instanceof b.TFolder))return[];let s=this.currentIncludeAttachments(),n=s?new Set:this.collectEmbeddedAttachmentPaths(),o=new Set(["_authors","_imports","_exports","_processed","_attachments","_archive",".archive"]),r=[],l=[i];for(;l.length;){let c=l.pop();for(let A of c.children){if(A instanceof b.TFolder){let h=A.name;if(c===i&&o.has(h)||c===i&&h==="_attachments"&&!s)continue;l.push(A);continue}A instanceof b.TFile&&A.extension!=="md"&&(A.name===".stashpad-order.json"||A.name===".stashpad-sort.json"||!s&&n.has(A.path)||r.push(A))}}return r}populateListBody(e,t){if(this.lastListWidth=e.clientWidth||this.lastListWidth,this.bodyRenderer.arm(),this.pendingCursorId){let A=this.currentChildren.findIndex(h=>h.id===this.pendingCursorId);A>=0&&(this.cursorIdx=A,this.selection.clear(),this.selection.add(this.pendingCursorId),this.lastSelected=this.pendingCursorId,this.pendingCursorId=null)}t.file&&b.Platform.isMobile&&!this.compactMode&&(this.renderFocusedHeaderMini(e,t),this.renderFocusedHeader(e,t));let i=this.currentViewMode(),s=i==="everything"?this.collectFileItems(t.id):[],n=A=>A.created&&Number.isFinite(Date.parse(A.created))?Date.parse(A.created):Number.POSITIVE_INFINITY,o=this.currentEncryptionFilter(),r;if(o==="unlocked")r=[];else if(i==="nested")r=this.plugin.lockedSubtreesFor(this.noteFolder,t.id);else{let A=new Set([t.id,...this.currentChildren.map(p=>p.id)]),h=new Set;r=[];for(let p of A)for(let u of this.plugin.lockedSubtreesFor(this.noteFolder,p))h.has(u.blob)||(h.add(u.blob),r.push(u))}let l=r.map(A=>({lk:A,ts:n(A)})).sort((A,h)=>A.ts-h.ts),c=i==="nested"&&this.sortStore.getMode(this.noteFolder,t.id)==="manual";if(this.currentChildren.length===0&&s.length===0&&l.length===0)e.createDiv({cls:"stashpad-empty",text:"No notes here yet. Type below to add one."});else if(c&&l.length>0){let A=new Map(this.currentChildren.map((g,I)=>[g.id,I])),h=new Map;for(let{lk:g}of l)g.rootId&&h.set(g.rootId,g);let p=this.currentChildren.map(g=>g.id),u=l.map(({lk:g})=>g).filter(g=>g.rootId).sort((g,I)=>n(I)-n(g)),f=!0;for(;u.length&&f;){f=!1;for(let g=0;g<u.length;g++){let I=u[g],m=I.prevSibling??null,B;if(m==null)B=0;else{let C=p.indexOf(m);if(C<0)continue;B=C+1}p.splice(B,0,I.rootId),u.splice(g,1),g--,f=!0}}for(let g of u)p.push(g.rootId);for(let g of p){let I=A.get(g);if(I!==void 0)this.renderNote(e,this.currentChildren[I],I);else{let m=h.get(g);m&&this.renderLockedPlaceholder(e,m)}}for(let g of s.slice().sort((I,m)=>I.stat.ctime-m.stat.ctime))this.renderFileRow(e,g)}else if(s.length===0){let A=0;for(let h=0;h<this.currentChildren.length;h++){let p=Number.isFinite(Date.parse(this.currentChildren[h].created))?Date.parse(this.currentChildren[h].created):0;for(;A<l.length&&l[A].ts<=p;)this.renderLockedPlaceholder(e,l[A].lk),A++;this.renderNote(e,this.currentChildren[h],h)}for(;A<l.length;)this.renderLockedPlaceholder(e,l[A].lk),A++}else{let A=[...this.currentChildren.map((h,p)=>({kind:"note",ts:Number.isFinite(Date.parse(h.created))?Date.parse(h.created):0,idx:p})),...s.map(h=>({kind:"file",ts:h.stat.ctime,file:h})),...l.map(h=>({kind:"lock",ts:h.ts,lk:h.lk}))];A.sort((h,p)=>h.ts-p.ts);for(let h of A)h.kind==="note"?this.renderNote(e,this.currentChildren[h.idx],h.idx):h.kind==="file"?this.renderFileRow(e,h.file):this.renderLockedPlaceholder(e,h.lk)}t.file&&b.Platform.isMobile&&!this.compactMode&&this.installFocusedMiniObserver(e)}renderLockedPlaceholder(e,t){let i=e.createDiv({cls:"stashpad-locked-row"});t.created&&i.createSpan({cls:"stashpad-note-time stashpad-locked-time",text:this.formatTime(t.created)});let s=i.createSpan({cls:"stashpad-locked-icon"});(0,b.setIcon)(s,"lock");let n=!t.title;i.createSpan({cls:"stashpad-locked-title",text:n?"Locked note":t.title}),i.createSpan({cls:"stashpad-locked-count",text:t.count>1?`${t.count} notes \xB7 locked`:"locked"});let o=i.createEl("button",{cls:"stashpad-locked-unlock",text:"Unlock"});(0,b.setIcon)(o.createSpan({cls:"stashpad-btn-icon"}),"unlock");let r=async A=>{A.preventDefault(),A.stopPropagation();let h=(this.plugin.settings.lockedSubtrees??[]).find(I=>I.blob===t.blob),p=t.rootId??h?.rootId??null,u=t.parentId??h?.parentId??k,f=t.prevSibling??h?.prevSibling??null;if(await this.plugin.unlockBundleAt(t.blob)){if(this.selection.clear(),this.lastSelected=null,p){let I=this.order.getOrder(this.noteFolder,u),m=this.sortStore.getMode(this.noteFolder,u)==="manual";if(I.length===0&&m&&(I=this.tree.getChildren(u).map(B=>B.id)),I.length>0){let B=I.filter(Q=>Q!==p),C=f&&B.includes(f)?B.indexOf(f)+1:0;B.splice(Math.max(0,C),0,p),this.order.setOrder(this.noteFolder,u,B),this.order.flush(this.noteFolder)}this.pendingCursorId=p}if(this.render(),p){let I=this.noteFolder,m=t.blob;this.plugin.getUndoStack(I).push({label:"Unlock note",undo:async()=>{let B=await this.plugin.lockNoteSubtree(I,p,f,{silent:!0});B&&(m=B.blobPath),this.render()},redo:async()=>{try{await this.plugin.unlockBundleAt(m,{silent:!0})}catch{}this.render()}})}}};o.onclick=r;let l=A=>{A.preventDefault(),A.stopPropagation();let h=new b.Menu;hn(h,{app:this.app,plugin:this.plugin,descriptor:{blob:t.blob,rootId:t.rootId,count:t.count,folder:this.noteFolder},unlockLabel:"Decrypt (unlock)",onUnlock:()=>void r(A),onChange:()=>this.render(),fullParity:!0,confirmDelete:!0}),h.showAtMouseEvent(A)};i.oncontextmenu=l;let c=i.createEl("button",{cls:"stashpad-pencil stashpad-locked-menu"});(0,b.setIcon)(c,"more-vertical"),c.setAttr("aria-label","Locked note menu"),c.onclick=A=>l(A),i.setAttr("aria-label",`${n?"Locked note":`Locked: ${t.title}`}. Use the Unlock button to decrypt.`)}refreshList(){if(!this.listEl){this.render();return}let e=this.tree.get(this.focusId)??this.tree.getRoot();this.currentChildren=this.filterChildren(this.collectViewItems(e.id)),this.cursorIdx>=this.currentChildren.length&&(this.cursorIdx=this.currentChildren.length-1);let t=this.listEl.scrollTop+this.listEl.clientHeight>=this.listEl.scrollHeight-2,i=this.listEl.scrollTop;this.listEl.empty(),this.populateListBody(this.listEl,e),t?this.listEl.scrollTop=this.listEl.scrollHeight:this.listEl.scrollTop=i}renderFileRow(e,t){if(this.currentEncryptionFilter()==="locked")return;let i=e.createDiv({cls:"stashpad-file-row"});i.dataset.path=t.path,i.createDiv({cls:"stashpad-file-meta"}).createSpan({cls:"stashpad-file-time",text:this.formatTime(new Date(t.stat.ctime).toISOString())});let n=i.createDiv({cls:"stashpad-file-body"});n.createSpan({cls:"stashpad-file-name",text:t.name}),n.createSpan({cls:"stashpad-file-ext",text:t.extension.toUpperCase()}),i.title=`${t.path} \u2014 click to open`,i.onclick=o=>{o.preventDefault(),this.app.workspace.openLinkText(t.path,"",!1)}}async setViewMode(e){let t={...this.plugin.settings.viewModes??{}};e==="nested"?delete t[this.noteFolder]:t[this.noteFolder]=e,this.plugin.settings.viewModes=t,await this.plugin.saveSettings()}collectViewItems(e){let t=this.currentViewMode(),i=this.currentHideChildless(),s=this.tree.getChildren(e),n=i?s.filter(l=>l.children.length>0):s;if(t==="nested")return n;let o=[],r=l=>{o.push(l);for(let c of this.tree.getChildren(l.id))r(c)};for(let l of n)r(l);return o}filterChildren(e){e=this.collapseVersions(e);let t=this.timeFilterCutoff(),i=this.tagFilter?.toLowerCase(),s=this.colorFilter?.toLowerCase()??null,n=this.currentHideCompleted(),o=this.currentAttachmentsOnly(),r=this.importedOnly,l=this.authorFilter;return!t&&!i&&!s&&!n&&!o&&!r&&!l?e:e.filter(c=>{if(r&&(!c.file||this.app.metadataCache.getFileCache(c.file)?.frontmatter?.imported!==!0))return!1;if(l){if(!c.file)return!1;let A=at(this.app.metadataCache.getFileCache(c.file)?.frontmatter?.author);if(!A||A.id!==l)return!1}if(t&&c.created){let A=Date.parse(c.created);if(!Number.isNaN(A)&&A<t)return!1}if(i){if(!c.file)return!1;if(this.tagFilter===Ht){if(!this.nodeHasAnyTag(c))return!1}else if(this.tagFilter===Rt){if(this.nodeHasAnyTag(c))return!1}else if(!this.nodeHasTag(c,i))return!1}return!(s&&(this.colorForNode(c)?.toLowerCase()??null)!==s||n&&this.isCompleted(c)&&!this.hasIncompleteDescendant(c)||o&&!this.hasAttachmentInSubtree(c))})}collapseVersions(e){if(!this.plugin.settings.enableSheetVersions)return e;let t=new Map,i=!1;for(let n of e){let o=we(this.app,n);if(!Ni(o))continue;i=!0;let r=ze(o),l=t.get(r);l?l.push(n):t.set(r,[n])}if(!i)return e;let s=new Set;for(let[n,o]of t){let r=this.activeVersionNode(n,o);r&&s.add(r.id)}return e.filter(n=>Ni(we(this.app,n))?s.has(n.id):!0)}activeVersionNode(e,t){let i=this.activeVersionByGroup.get(e);if(i){let s=t.find(n=>n.id===i);if(s)return s}return yr(this.app,t)}setActiveVersion(e,t){this.activeVersionByGroup.set(e,t),this.plugin.saveActiveVersion(this.noteFolder,e,t),this.render()}nodeHasAnyTag(e){if(!e.file)return!1;let t=this.app.metadataCache.getFileCache(e.file);if(!t)return!1;if(t.tags&&t.tags.length>0)return!0;let i=t.frontmatter?.tags;return!!(i&&(Array.isArray(i)?i:[i]).some(n=>typeof n=="string"&&n.trim().length>0))}nodeHasTag(e,t){if(!e.file)return!1;let i=this.app.metadataCache.getFileCache(e.file);if(!i)return!1;if(i.tags){for(let n of i.tags)if((n.tag||"").replace(/^#/,"").toLowerCase()===t)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()===t)return!0}return!1}collectFolderTags(){let e=new Map,t=this.tree.getChildren(this.focusId);for(let s of t){if(!s.file)continue;let n=this.app.metadataCache.getFileCache(s.file);if(n?.tags)for(let r of n.tags){let l=(r.tag||"").replace(/^#/,"");l&&e.set(l,(e.get(l)??0)+1)}let o=n?.frontmatter?.tags;if(o){let r=Array.isArray(o)?o:[o];for(let l of r){if(typeof l!="string")continue;let c=l.replace(/^#/,"");c&&e.set(c,(e.get(c)??0)+1)}}}let i=[...e.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(e){return e&&e.split("/").map(t=>t.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 e=new Map,t=this.tree.getChildren(this.focusId);for(let s of t){let n=this.colorForNode(s);if(!n)continue;let o=n.toLowerCase();e.set(o,(e.get(o)??0)+1)}let i=[...e.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 e=this.tree.get(this.focusId)??this.tree.getRoot(),t=this.filterChildren(this.collectViewItems(e.id));this.cursorIdx=t.length-1,this.selection.clear(),t.length>0&&(this.selection.add(t[t.length-1].id),this.lastSelected=t[t.length-1].id)}stampSelectedCursor(e=!1){this.stampSelection(e);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(e){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 e=this.listEl;if(!e)return null;let t=e.getBoundingClientRect().top,i=Array.from(e.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-t;if(r>=0){s={id:o,offsetFromListTop:r};break}s={id:o,offsetFromListTop:r}}return s}restoreScrollAnchor(e,t){let i=this.listEl;if(i){if(e){let s=i.querySelector(`[data-id="${e.id}"]`);if(s){let n=i.getBoundingClientRect().top,o=s.getBoundingClientRect().top-n;i.scrollTop+=o-e.offsetFromListTop;return}}t>0&&(i.scrollTop=t)}}render(e){if(ke.enabled&&(this._renderT0=performance.now()),!this.viewRoot?.isConnected)return;this.pendingRenderPolicy=e??{kind:"preserve"},this.loadConfig();let t=this.viewRoot,i=this.listEl?.scrollTop??0,n=(e??{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);t.empty(),t.toggleClass("is-mobile",b.Platform.isMobile),t.toggleClass("is-tiny",this.tinyMode),t.toggleClass("is-compact",this.compactMode);let l=this.containerEl.closest(".workspace-leaf");l&&(l.classList.toggle("stashpad-is-tiny",this.tinyMode),l.classList.toggle("stashpad-is-compact",this.compactMode));let c=this.containerEl.closest(".workspace-tabs");if(c&&c.classList.toggle("stashpad-has-tiny",this.tinyMode),this.tinyMode)this.renderTinyHeader(t);else{let f=this.compactMode&&b.Platform.isMobile;(!this.compactMode||b.Platform.isMobile)&&this.renderTimeFilterBar(t),f||this.renderBreadcrumb(t)}let A=this.tree.get(this.focusId)??this.tree.getRoot();A.file&&!b.Platform.isMobile&&!this.tinyMode&&!this.compactMode&&this.renderFocusedHeader(t,A),this.currentChildren=this.filterChildren(this.collectViewItems(A.id));let h=!1;if(this.autoSelectNewest&&this.currentChildren.length>0){let f=this.currentChildren[this.currentChildren.length-1];this.cursorIdx=this.currentChildren.length-1,this.selection.clear(),this.selection.add(f.id),this.lastSelected=f.id,this.autoSelectNewest=!1,h=!0}else if(this.pendingFocusIds){let f=this.pendingFocusIds;this.pendingFocusIds=null,this.selection.clear();let g=-1;for(let I of f){let m=this.currentChildren.findIndex(B=>B.id===I);m>=0&&(this.selection.add(I),g<0&&(g=m))}this.cursorIdx=g,g>=0&&(this.lastSelected=f.find(I=>this.currentChildren.some(m=>m.id===I))??null)}else this.cursorIdx>=this.currentChildren.length&&(this.cursorIdx=this.currentChildren.length-1);let p=t.createDiv({cls:"stashpad-list"});if(this.listEl=p,this.dnd.attachListDnD(p),this.populateListBody(p,A),this.renderComposer(t),b.Platform.isMobile&&this.renderMobileNav(t),this._renderT0!=null&&(ke.record("render.total",performance.now()-this._renderT0),this._renderT0=null),this.plugin.notifyStashpadContentChanged(),h&&this.plugin.notifyStashpadSelectionChanged(),this.focusComposerOnNextRender){this.focusComposerOnNextRender=!1;let f=this.pendingComposerCaret;this.pendingComposerCaret=null;let g=this.composerInputEl;if(g&&g.isConnected){if(g.focus({preventScroll:!0}),f!=null){let I=Math.min(f,g.value.length);try{g.setSelectionRange(I,I)}catch{}}}else requestAnimationFrame(()=>{let I=this.composerInputEl;if(I&&(I.focus({preventScroll:!0}),f!=null)){let m=Math.min(f,I.value.length);try{I.setSelectionRange(m,m)}catch{}}})}let u=this.pendingRenderPolicy;if(this.pendingRenderPolicy=null,u&&this.listEl){let f=this.scrollToBottomOnNextRender;switch(this.scrollToBottomOnNextRender=!1,u.kind){case"preserve":f?this.scrollListToBottom():r?this.scrollListToBottom():this.restoreScrollAnchor(n,i);break;case"pin-bottom":this.scrollListToBottom();break;case"restore":{let g=u.scrollTop,I=this.listEl,m=()=>{this.suppressScrollSave=!0;let B=Math.max(0,I.scrollHeight-I.clientHeight);I.scrollTop=Math.min(g,B),Promise.resolve().then(()=>{this.suppressScrollSave=!1})};m(),requestAnimationFrame(m),setTimeout(m,60),setTimeout(m,200),setTimeout(m,600);break}case"follow-cursor":i>0&&(this.listEl.scrollTop=i),this.revealCursorRow();break;case"scroll-to-id":{let g=u.id,I=u.align,m=this.listEl,B=()=>{this.suppressScrollSave=!0;let C=m.querySelector(`[data-id="${g}"]`);C&&C.scrollIntoView({block:I,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 f=this.listEl,g=f.scrollTop,I=new ResizeObserver(()=>{if(Date.now()<this.keyboardTransitionUntil)return;if(this.stickToListBottom){f.scrollTop=f.scrollHeight,g=f.scrollTop;return}let B=Math.max(0,f.scrollHeight-f.clientHeight);f.scrollTop<g&&g<=B?f.scrollTop=g:g=f.scrollTop});I.observe(f),this.listResizeObserver=I,f.addEventListener("wheel",B=>{B.deltaY<0&&(this.stickToListBottom=!1)},{passive:!0});let m=0;f.addEventListener("touchstart",B=>{m=B.touches[0]?.clientY??0},{passive:!0}),f.addEventListener("touchmove",B=>{let C=B.touches[0]?.clientY??m;C>m&&(this.stickToListBottom=!1),m=C},{passive:!0}),f.addEventListener("mousedown",()=>{this.stickToListBottom=!1}),f.addEventListener("keydown",()=>{this.stickToListBottom=!1})}}refreshFolderSwitcherIcon(){let e=this.containerEl.querySelector(".stashpad-folder-btn .stashpad-btn-icon");e&&(e.empty(),(0,b.setIcon)(e,this.plugin.getFolderIcon(this.noteFolder)??"folder"))}renderTimeFilterBar(e){let t=e.createDiv({cls:"stashpad-time-filter-bar"});if(!b.Platform.isMobile){let c=t.createEl("button",{cls:"stashpad-folder-btn"}),A=!!this.folderOverride,h=this.noteFolder.split("/").pop()||this.noteFolder||"Stashpad";(0,b.setIcon)(c.createSpan({cls:"stashpad-btn-icon"}),this.plugin.getFolderIcon(this.noteFolder)??"folder"),c.createSpan({text:h,cls:"stashpad-btn-text"}),c.title=A?`Folder (override): ${this.noteFolder} Click to change or revert to default.`:`Folder: ${this.noteFolder} -Click to override for this tab.`,A&&c.addClass("is-override"),c.onclick=u=>{u.preventDefault(),this.openFolderPicker()};let g=t.createEl("button",{cls:"stashpad-search-btn"});Fe(g,"search","\u{1F50D}"),g.title="Search notes (Mod+F)",g.onclick=u=>{u.preventDefault(),this.openSearchModal()}}F.Platform.isMobile?(this.renderActionsCluster(t),this.renderMobileFiltersButton(t)):(this.renderTagFilterDropdown(t),this.renderColorFilterDropdown(t),this.renderSortDropdown(t),this.renderViewDropdown(t));let i=t.createDiv({cls:"stashpad-time-filter-btns"}),s=i.createEl("button",{cls:"stashpad-time-filter-btn stashpad-time-filter-cal"});(0,F.setIcon)(s,this.timeFilterCalendar?"calendar":"history"),s.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&&s.addClass("is-active"),s.onclick=c=>{c.preventDefault(),this.timeFilterCalendar=!this.timeFilterCalendar,this.persistFocus(),this.render()};for(let c of gs){let A=this.timeFilterCalendar?c.calShort:c.rollShort,h=this.timeFilterCalendar?c.calLong:c.rollLong,g=i.createEl("button",{cls:"stashpad-time-filter-btn",text:A});g.title=h,this.timeFilter===c.key&&g.addClass("is-active"),g.onclick=u=>{u.preventDefault(),this.setTimeFilter(c.key)}}let n=t.createEl("select",{cls:"stashpad-time-filter-select"});for(let c of gs){let A=this.timeFilterCalendar?c.calLong:c.rollLong,h=n.createEl("option",{text:A});h.value=c.key,this.timeFilter===c.key&&(h.selected=!0)}n.onchange=()=>this.setTimeFilter(n.value);let o=t.createDiv({cls:"stashpad-view-mode-btns"});if(!F.Platform.isMobile){let c=o.createEl("button",{cls:"stashpad-view-mode-btn"});(0,F.setIcon)(c,"minimize-2"),c.title="Tiny mode \u2014 open this tab in a small always-on-top-capable popout window.",c.onclick=A=>{A.preventDefault(),this.plugin.openTinyWindow()}}let r=o.createEl("button",{cls:"stashpad-view-mode-btn"});if((0,F.setIcon)(r,this.compactMode?"panel-top":"rows-2"),r.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&&r.addClass("is-active"),r.onclick=c=>{c.preventDefault(),this.toggleCompactMode()},F.Platform.isMobile)return;let l=o.createEl("button",{cls:"stashpad-view-mode-btn"});(0,F.setIcon)(l,"external-link"),l.title=X().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.)",l.onclick=c=>{c.preventDefault();let A=X().popoutDuplicates;try{let h=this.app.workspace;if(A){let g=this.leaf.getViewState(),u=h.openPopoutLeaf?.();u?u.setViewState({...g,active:!0}):new F.Notice("Stashpad: this Obsidian build doesn't expose openPopoutLeaf.")}else h.moveLeafToPopout?.(this.leaf)}catch(h){new F.Notice(`Stashpad: open-in-new-window failed (${h.message})`)}},this.setupBarOverflow(t)}setupBarOverflow(e){let t=[{key:"nav",icon:"folder-search",title:"Folder & search",memberSel:[".stashpad-folder-btn",".stashpad-search-btn"],memberKeys:["folder","search"],collapsePrio:5,displayIdx:0},{key:"filter",icon:"filter",title:"Tag & color",memberSel:[".stashpad-tag-filter-btn",".stashpad-color-filter-btn"],memberKeys:["tag","color"],collapsePrio:3,displayIdx:1},{key:"arrange",icon:"sliders-horizontal",title:"Sort & view",memberSel:[".stashpad-sort-btn",".stashpad-view-btn"],memberKeys:["sort","view"],collapsePrio:4,displayIdx:2},{key:"time",icon:"clock",title:"Time",memberSel:[".stashpad-time-filter-btns",".stashpad-time-filter-select"],memberKeys:["time"],collapsePrio:2,displayIdx:3},{key:"window",icon:"app-window",title:"Window & layout",memberSel:[".stashpad-view-mode-btns"],memberKeys:["mode"],collapsePrio:1,displayIdx:4}];e.addClass("stashpad-overflow-managed");let i=[];for(let u of[...t].sort((f,p)=>f.displayIdx-p.displayIdx)){let f=u.memberSel.map(C=>e.querySelector(C)).filter(C=>!!C);if(f.length===0)continue;let p=createDiv({cls:"stashpad-bar-group"});e.insertBefore(p,f[0]);let I=p.createDiv({cls:"stashpad-bar-group-expanded"});for(let C of f)I.appendChild(C);let m=p.createDiv({cls:"stashpad-bar-overflow-btn stashpad-bar-group-icon stashpad-overflow-hidden"});m.setAttribute("role","button"),m.setAttribute("tabindex","0"),(0,F.setIcon)(m.createSpan({cls:"stashpad-bar-group-icon-glyph"}),u.icon),m.title=`${u.title} \u2014 combined menu`;let B=C=>{C.preventDefault(),this.openBarOverflowMenu(m,u.memberKeys)};m.onclick=B,m.onkeydown=C=>{(C.key==="Enter"||C.key===" ")&&B(C)},i.push({...u,wrapper:p,expanded:I,iconBtn:m})}let s=e.createDiv({cls:"stashpad-bar-overflow-btn stashpad-bar-kebab stashpad-overflow-hidden"});s.setAttribute("role","button"),s.setAttribute("tabindex","0"),(0,F.setIcon)(s.createSpan({cls:"stashpad-bar-overflow-icon"}),"more-horizontal"),s.title="More filters / view options";let n=[...i].sort((u,f)=>u.collapsePrio-f.collapsePrio),o=[...i].sort((u,f)=>f.displayIdx-u.displayIdx),r=[],l=()=>e.scrollWidth<=e.clientWidth+1,c=()=>{if(!e.isConnected||e.clientWidth===0)return;for(let f of i)f.wrapper.removeClass("stashpad-overflow-hidden"),f.expanded.removeClass("stashpad-overflow-hidden"),f.iconBtn.addClass("stashpad-overflow-hidden"),f.iconBtn.toggleClass("is-active",f.memberKeys.some(p=>this.barUnitActive(p)));if(s.addClass("stashpad-overflow-hidden"),r=[],l())return;for(let f of n){if(l())break;f.expanded.addClass("stashpad-overflow-hidden"),f.iconBtn.removeClass("stashpad-overflow-hidden")}if(l())return;s.removeClass("stashpad-overflow-hidden");let u=[];for(let f of o){if(l())break;f.wrapper.addClass("stashpad-overflow-hidden"),u.push(f)}r=[...u].sort((f,p)=>f.displayIdx-p.displayIdx).flatMap(f=>f.memberKeys),s.toggleClass("is-active",r.some(f=>this.barUnitActive(f)))},A=u=>{u.preventDefault(),this.openBarOverflowMenu(s,r)};s.onclick=A,s.onkeydown=u=>{(u.key==="Enter"||u.key===" ")&&A(u)};try{this.barOverflowRO?.disconnect()}catch{}let h=(e.ownerDocument?.defaultView??window).ResizeObserver,g=-1;this.barOverflowRO=new h(u=>{let f=Math.round(u[u.length-1].contentRect.width);f!==g&&(g=f,c())}),this.barOverflowRO.observe(e),requestAnimationFrame(()=>c())}barUnitActive(e){switch(e){case"folder":return!!this.folderOverride;case"tag":return!!this.tagFilter;case"color":return!!this.colorFilter;case"time":return this.timeFilter!=="all";case"sort":return this.currentViewMode()==="nested"&&this.sortStore.getMode(this.noteFolder,this.focusId)!=="manual";case"view":return this.currentViewMode()!=="nested"||this.currentEncryptionFilter()!=="all"||this.currentHideChildless()||this.currentHideCompleted()||this.currentAttachmentsOnly()||this.currentIncludeAttachments();case"mode":return this.compactMode;default:return!1}}openBarOverflowMenu(e,t){let i=e.ownerDocument??document;i.querySelectorAll(".stashpad-mobile-filters-popover").forEach(f=>f.remove());let s=i.body.createDiv({cls:"stashpad-mobile-filters-popover"}),n=e.getBoundingClientRect(),o=i.defaultView??window;s.setCssStyles({right:`${Math.max(8,o.innerWidth-n.right)}px`,left:"auto",top:`${n.bottom+4}px`,maxWidth:"min(360px, calc(100vw - 16px))",width:"max-content",minWidth:"260px"});let r=new F.Scope(this.app.scope),l=()=>{s.remove(),i.removeEventListener("mousedown",c,!0);try{this.app.keymap?.popScope(r)}catch{}},c=f=>{!s.contains(f.target)&&f.target!==e&&!e.contains(f.target)&&l()},h=[{key:"folder",title:"Folder",summary:()=>this.noteFolder.split("/").pop()||this.noteFolder||"Stashpad",populate:f=>this.populateFolderMenuBody(f,l)},{key:"search",title:"Search",summary:()=>"Search notes (Mod+F)",populate:f=>this.populateSearchMenuBody(f,l)},{key:"tag",title:"Tag filter",summary:()=>this.tagFilter?`#${this.tagFilter}`:"All tags",populate:f=>this.populateTagMenuBody(f,l)},{key:"color",title:"Color filter",summary:()=>this.colorFilter?this.plugin.getColorAlias(this.noteFolder,this.colorFilter)??this.colorFilter:"All colors",populate:f=>this.populateColorMenuBody(f,this.collectFolderColors(),l)},{key:"sort",title:"Sort",summary:()=>this.currentViewMode()!=="nested"?"\u2014 (Nested only)":Ii[this.sortStore.getMode(this.noteFolder,this.focusId)],populate:f=>{if(this.currentViewMode()!=="nested"){f.createDiv({cls:"stashpad-mobile-filters-note",text:"Sort applies only in Nested view."});return}this.populateSortMenuBody(f,l)}},{key:"view",title:"View",summary:()=>ps[this.currentViewMode()],populate:f=>this.populateViewMenuBody(f,l)},{key:"time",title:"Time filter",summary:()=>{let f=gs.find(p=>p.key===this.timeFilter);return f?this.timeFilterCalendar?f.calShort:f.rollShort:"All"},populate:f=>this.populateTimeMenuBody(f,l)},{key:"mode",title:"View mode",summary:()=>this.compactMode?"Compact on":"Tiny \xB7 Compact \xB7 Window",populate:f=>this.populateModeMenuBody(f,l)}].filter(f=>t.includes(f.key)),g="",u=()=>{s.empty();for(let f of h){let p=s.createDiv({cls:"stashpad-mobile-filters-section"}),I=p.createDiv({cls:"stashpad-mobile-filters-header"}),m=I.createSpan({cls:"stashpad-mobile-filters-chev"});(0,F.setIcon)(m,g===f.key?"chevron-down":"chevron-right"),I.createSpan({cls:"stashpad-mobile-filters-title",text:f.title}),I.createSpan({cls:"stashpad-mobile-filters-summary",text:f.summary()}),I.onclick=B=>{B.preventDefault(),B.stopPropagation(),g=g===f.key?"":f.key,u()},g===f.key&&f.populate(p.createDiv({cls:"stashpad-mobile-filters-body"}))}};u(),r.register([],"Escape",f=>(f.preventDefault(),l(),!1)),this.app.keymap?.pushScope(r),setTimeout(()=>{i.addEventListener("mousedown",c,!0)},0)}populateFolderMenuBody(e,t){let i=e.createDiv({cls:"stashpad-sort-popover-row"});i.createSpan({cls:"stashpad-sort-popover-label",text:this.folderOverride?"Change folder (override active)\u2026":"Change folder for this tab\u2026"}),i.onclick=s=>{s.preventDefault(),s.stopPropagation(),t(),this.openFolderPicker()}}populateSearchMenuBody(e,t){let i=e.createDiv({cls:"stashpad-sort-popover-row"});i.createSpan({cls:"stashpad-sort-popover-label",text:"Search notes\u2026"}),i.onclick=s=>{s.preventDefault(),s.stopPropagation(),t(),this.openSearchModal()}}populateModeMenuBody(e,t){let i=(n,o)=>{let r=e.createDiv({cls:"stashpad-sort-popover-row"});r.createSpan({cls:"stashpad-sort-popover-label",text:n}),r.onclick=l=>{l.preventDefault(),l.stopPropagation(),t(),o()}};i("Tiny mode (popout window)",()=>void this.plugin.openTinyWindow());let s=e.createDiv({cls:"stashpad-sort-popover-row"});this.compactMode&&s.addClass("is-active"),s.createSpan({cls:"stashpad-sort-popover-label",text:this.compactMode?"Compact mode (on)":"Compact mode"}),s.onclick=n=>{n.preventDefault(),n.stopPropagation(),t(),this.toggleCompactMode()},i(X().popoutDuplicates?"Duplicate to new window":"Move to new window",()=>{try{let n=this.app.workspace;if(X().popoutDuplicates){let o=n.openPopoutLeaf?.();o?o.setViewState({...this.leaf.getViewState(),active:!0}):new F.Notice("Stashpad: this Obsidian build doesn't expose openPopoutLeaf.")}else n.moveLeafToPopout?.(this.leaf)}catch(n){new F.Notice(`Stashpad: open-in-new-window failed (${n.message})`)}})}toggleCompactMode(){this.compactMode=!this.compactMode,this.render();try{this.app.workspace.requestSaveLayout?.()}catch{}}renderActionsCluster(e){let t=e.createDiv({cls:"stashpad-mobile-actions"}),i=t.createEl("button",{cls:"stashpad-mobile-action-btn"});Fe(i,"arrow-left","\u2039");let s=this.navBackStack.length>0||this.focusId!==S;i.title=this.navBackStack.length>0?"Back":this.focusId!==S?"Back (up to parent)":"No back history",s||i.addClass("is-disabled"),i.onclick=h=>{h.preventDefault(),this.navigateBack()};let n=t.createEl("button",{cls:"stashpad-mobile-action-btn"});Fe(n,"arrow-right","\u203A");let o=this.navForwardSnapshots.length>0;if(n.title=o?"Forward":"No forward history",o||n.addClass("is-disabled"),n.onclick=h=>{h.preventDefault(),this.navigateForward()},F.Platform.isMobile){let h=t.createEl("button",{cls:"stashpad-mobile-action-btn"});Fe(h,"route","\u22D4"),h.title="Jump to a level in the path",h.onclick=g=>{g.preventDefault(),this.openBreadcrumbLevelsModal()}}let r=t.createEl("button",{cls:"stashpad-mobile-action-btn"}),l=this.mobileSelectMode;Fe(r,l?"check-square":"square",l?"\u2611":"\u2610"),r.title=l?`${this.selection.size} selected \u2014 tap to exit (keeps the first selection)`:"Enter select mode (tap notes to add)",l&&r.addClass("is-active"),r.onclick=h=>{if(h.preventDefault(),this.mobileSelectMode){let g=this.firstSelectedId??this.selection.values().next().value;if(this.selection.clear(),g){let u=this.currentChildren.findIndex(f=>f.id===g);this.selection.add(g),this.lastSelected=g,u>=0&&(this.cursorIdx=u)}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 F.Notice("Select mode: tap notes to add, press \u26A1 for actions")}};let c=t.createEl("button",{cls:"stashpad-mobile-action-btn"});Fe(c,"zap","\u26A1"),c.title="Actions (move, delete, undo, \u2026)",c.onclick=h=>{h.preventDefault(),this.openMobileActionsMenu(c)};let A=t.createEl("button",{cls:"stashpad-mobile-action-btn stashpad-open-link-btn"});Fe(A,"link","\u{1F517}"),A.title="Open a Stashpad link (paste a deep link / URL)",A.onclick=h=>{h.preventDefault(),this.plugin.openDeepLinkModal()}}openMobileActionsMenu(e){let t=new F.Menu,i=this.selection.size>0||this.cursorIdx>=0&&!!this.currentChildren[this.cursorIdx],s=this.selection.size<=1;t.addItem(o=>o.setTitle("Undo").setIcon("undo").onClick(()=>this.cmdUndo())),t.addItem(o=>o.setTitle("Redo").setIcon("redo").onClick(()=>this.cmdRedo())),t.addSeparator(),t.addItem(o=>o.setTitle("Notification history\u2026").setIcon("bell").onClick(()=>{this.app.commands?.executeCommandById?.("stashpad:stashpad-open-notification-history")})),t.addItem(o=>o.setTitle("Reload without saving").setIcon("rotate-ccw").onClick(()=>this.plugin.reloadAppForUpdate())),t.addItem(o=>o.setTitle("Open Stashpad link\u2026").setIcon("link").onClick(()=>this.plugin.openDeepLinkModal())),t.addSeparator(),t.addItem(o=>o.setTitle("Expand all").setIcon("unfold-vertical").onClick(()=>this.cmdExpandAll())),t.addItem(o=>o.setTitle("Collapse all").setIcon("fold-vertical").onClick(()=>this.cmdCollapseAll())),t.addSeparator(),t.addItem(o=>o.setTitle("Open in new Stashpad tab").setIcon("list-tree").setDisabled(!i).onClick(()=>this.cmdOpenInNewStashpadTab())),t.addItem(o=>o.setTitle("Open in editor").setIcon("pencil").setDisabled(!i).onClick(()=>this.cmdOpenInEditor())),t.addSeparator(),t.addItem(o=>o.setTitle("Move\u2026").setIcon("arrow-right-circle").setDisabled(!i).onClick(()=>this.cmdMovePicker())),t.addItem(o=>o.setTitle("Nest under\u2026 (in-list)").setIcon("indent").setDisabled(!i).onClick(()=>this.cmdInListPicker())),t.addItem(o=>o.setTitle("Outdent").setIcon("outdent").setDisabled(!i).onClick(()=>void this.cmdOutdent())),t.addItem(o=>o.setTitle("Set color\u2026").setIcon("palette").setDisabled(!i).onClick(()=>this.cmdSetColor())),t.addItem(o=>o.setTitle("Toggle complete").setIcon("check-circle").setDisabled(!i).onClick(()=>void this.cmdToggleComplete())),t.addItem(o=>o.setTitle("Toggle task (todo)").setIcon("check-square").setDisabled(!i).onClick(()=>void this.cmdToggleTask())),t.addItem(o=>o.setTitle("Set due date\u2026").setIcon("calendar-clock").setDisabled(!i).onClick(()=>this.cmdSetDue())),t.addItem(o=>o.setTitle("Assign to\u2026").setIcon("user-plus").setDisabled(!i).onClick(()=>this.cmdAssign())),t.addSeparator(),t.addItem(o=>o.setTitle("Copy").setIcon("copy").setDisabled(!i).onClick(()=>void this.cmdCopy())),t.addItem(o=>o.setTitle("Copy tree").setIcon("copy-plus").setDisabled(!i).onClick(()=>void this.cmdCopyTree())),t.addItem(o=>o.setTitle("Clone (duplicate / copy)").setIcon("files").setDisabled(!i).onClick(()=>void this.cmdClone())),this.plugin.settings.enableSheetVersions&&(t.addItem(o=>o.setTitle("Fork as a version (draft)").setIcon("git-fork").setDisabled(!i||!s).onClick(()=>void this.cmdForkVersion())),t.addItem(o=>o.setTitle("Mark version as final").setIcon("star").setDisabled(!i||!s).onClick(()=>void this.cmdMarkVersionFinal()))),t.addItem(o=>o.setTitle("Insert template\u2026").setIcon("file-plus-2").onClick(()=>this.cmdInsertTemplate())),t.addItem(o=>o.setTitle("Merge").setIcon("merge").setDisabled(this.selection.size<2).onClick(()=>void this.cmdMerge())),t.addItem(o=>o.setTitle("Split note\u2026").setIcon("scissors").setDisabled(!i||!s).onClick(()=>void this.cmdSplit())),t.addSeparator(),t.addItem(o=>o.setTitle("Delete").setIcon("trash-2").setDisabled(!i).onClick(()=>void this.cmdDelete())),t.addSeparator(),t.addItem(o=>o.setTitle("More commands\u2026").setIcon("terminal").onClick(()=>this.openCommandPalette()));let n=e.getBoundingClientRect();t.showAtPosition({x:n.left,y:n.bottom+4})}openCommandPalette(){this.app.commands?.executeCommandById?.("command-palette:open")}openStashpadCommandPalette(){new dn(this.app).open()}tagFilterLabel(){return this.tagFilter===Pt?"Tagged":this.tagFilter===Ht?"Untagged":this.tagFilter?`#${this.formatTagLabel(this.tagFilter)}`:this.collectFolderTags().length===0?"No tags":"All tags"}renderTagFilterDropdown(e){let t=this.collectFolderTags(),i=e.createDiv({cls:"stashpad-tag-filter-btn"});i.setAttribute("role","button"),i.setAttribute("tabindex","0");let s=i.createSpan({cls:"stashpad-tag-filter-btn-icon"});Fe(s,"tag","#"),i.createSpan({cls:"stashpad-tag-filter-label",text:this.tagFilterLabel()}),t.length===0&&!this.tagFilter&&i.addClass("is-disabled");let n=o=>{o.preventDefault(),!(t.length===0&&!this.tagFilter)&&this.openTagFilterMenu(i)};i.onclick=n,i.onkeydown=o=>{(o.key==="Enter"||o.key===" ")&&n(o)}}openTagFilterMenu(e){let t=e.ownerDocument??document;t.querySelectorAll(".stashpad-tag-filter-popover").forEach(w=>w.remove());let i=t.body.createDiv({cls:"stashpad-tag-filter-popover"}),s=e.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 F.Scope(this.app.scope),o=()=>{i.remove(),t.removeEventListener("mousedown",r,!0);try{this.app.keymap?.popScope(n)}catch{}},r=w=>{!i.contains(w.target)&&w.target!==e&&!e.contains(w.target)&&o()},l=i.createDiv({cls:"stashpad-tag-filter-search"}),c=l.createSpan({cls:"stashpad-tag-filter-search-icon"});Fe(c,"search","\u2315");let A=l.createEl("input",{type:"text",cls:"stashpad-tag-filter-input",attr:{placeholder:"Filter tags\u2026"}}),h=l.createSpan({cls:"stashpad-tag-filter-clear",attr:{"aria-label":"Clear"}});Fe(h,"x","\xD7"),h.setCssStyles({display:"none"});let g=i.createDiv({cls:"stashpad-tag-filter-list"}),u=this.collectFolderTags(),f=[],p=0,I=w=>{this.setTagFilter(w),o()},m=w=>{if(f.length===0){p=0;return}p=(w+f.length)%f.length,f.forEach((y,v)=>y.el.toggleClass("is-highlighted",v===p)),f[p].el.scrollIntoView({block:"nearest"})},B=(w,y,v,E)=>{let Q=g.createDiv({cls:"stashpad-tag-filter-row"});E&&Q.addClass("is-active"),Q.createSpan({cls:"stashpad-tag-filter-row-label",text:w}),typeof v=="number"&&Q.createSpan({cls:"stashpad-tag-filter-row-count",text:String(v)});let b=f.length;f.push({value:y,el:Q}),Q.onmousedown=D=>{D.preventDefault(),I(y)},Q.onmouseenter=()=>m(b)},C=()=>{let w=A.value;h.setCssStyles({display:w?"":"none"}),g.empty(),f=[];let y=this.tagFilter?.toLowerCase();if(w.trim()){let v=Nr(w,u);if(v.length===0)g.createDiv({cls:"stashpad-tag-filter-empty",text:"No matching tags"});else for(let E of v)B(`#${E.label}`,E.raw,E.count,y===E.raw.toLowerCase())}else{B("All tags",null,void 0,!this.tagFilter),B("Tagged",Pt,void 0,this.tagFilter===Pt),B("Untagged",Ht,void 0,this.tagFilter===Ht);for(let v of u)B(`#${v.label}`,v.raw,v.count,y===v.raw.toLowerCase())}m(0)};h.onclick=()=>{A.value="",C(),A.focus()},A.addEventListener("input",C),A.addEventListener("keydown",w=>{w.key==="ArrowDown"?(w.preventDefault(),m(p+1)):w.key==="ArrowUp"?(w.preventDefault(),m(p-1)):w.key==="Enter"&&(w.preventDefault(),f[p]&&I(f[p].value))}),n.register([],"Escape",w=>(w.preventDefault(),o(),!1)),this.app.keymap?.pushScope(n),C(),setTimeout(()=>{t.addEventListener("mousedown",r,!0),A.focus()},0)}renderColorFilterDropdown(e){let t=this.collectFolderColors(),i=e.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 l=this.colorFilter.toLowerCase();o.setCssStyles({background:l});let c=this.plugin.getColorAlias(this.noteFolder,l);r.setText(c??l)}else t.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(),!(t.length===0&&!this.colorFilter)&&this.openColorFilterMenu(i,t)};i.onclick=n,i.onkeydown=o=>{(o.key==="Enter"||o.key===" ")&&n(o)}}openColorFilterMenu(e,t){let i=e.ownerDocument??document;i.querySelectorAll(".stashpad-color-filter-popover").forEach(c=>c.remove());let s=i.body.createDiv({cls:"stashpad-color-filter-popover"}),n=e.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 F.Scope(this.app.scope),r=()=>{s.remove(),i.removeEventListener("mousedown",l,!0);try{this.app.keymap?.popScope(o)}catch{}},l=c=>{!s.contains(c.target)&&c.target!==e&&!e.contains(c.target)&&r()};o.register([],"Escape",c=>(c.preventDefault(),r(),!1)),this.app.keymap?.pushScope(o),this.populateColorMenuBody(s,t,r),setTimeout(()=>{i.addEventListener("mousedown",l,!0)},0)}renderSortDropdown(e){let t=this.noteFolder,i=this.focusId,s=this.sortStore.getMode(t,i),n=this.currentViewMode(),o=n!=="nested",r=e.createDiv({cls:"stashpad-sort-btn"});r.setAttribute("role","button"),r.setAttribute("tabindex",o?"-1":"0"),o&&r.addClass("is-disabled");let l=r.createSpan({cls:"stashpad-sort-icon"});(0,F.setIcon)(l,"arrow-up-down");let c=r.createSpan({cls:"stashpad-sort-label"});o?(c.setText("Sort: \u2014"),r.title=`Sort is per-parent and applies only to Nested view. The current view (${ps[n]}) shows a synthesized flat list sorted by created time \u2014 switch back to Nested to change sort.`):(c.setText(Ii[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: ${Ii[s]}. Drag-reorder will revert this parent to Manual.`);let A=h=>{o||(h.preventDefault(),this.openSortMenu(r))};r.onclick=A,r.onkeydown=h=>{o||(h.key==="Enter"||h.key===" ")&&A(h)}}openSortMenu(e){let t=e.ownerDocument??document;t.querySelectorAll(".stashpad-sort-popover").forEach(l=>l.remove());let i=t.body.createDiv({cls:"stashpad-sort-popover"}),s=e.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(),t.removeEventListener("mousedown",o,!0);try{this.app.keymap?.popScope(r)}catch{}},o=l=>{!i.contains(l.target)&&l.target!==e&&!e.contains(l.target)&&n()};this.populateSortMenuBody(i,n);let r=new F.Scope(this.app.scope);r.register([],"Escape",l=>(l.preventDefault(),n(),!1)),this.app.keymap?.pushScope(r),setTimeout(()=>{t.addEventListener("mousedown",o,!0)},0)}renderMobileFiltersButton(e){let t=e.createDiv({cls:"stashpad-mobile-filters-btn"});t.setAttribute("role","button"),t.setAttribute("tabindex","0");let i=t.createSpan({cls:"stashpad-mobile-filters-icon"});(0,F.setIcon)(i,"sliders-horizontal"),t.title="Filters / view options";let s=!!this.tagFilter,n=!!this.colorFilter,o=this.timeFilter!=="all",r=this.sortStore.getMode(this.noteFolder,this.focusId)!=="manual",l=this.currentViewMode()!=="nested"||this.currentHideChildless()||this.currentHideCompleted()||this.currentAttachmentsOnly()||this.currentIncludeAttachments();(s||n||o||r||l)&&t.addClass("is-active");let c=A=>{A.preventDefault(),this.openMobileFiltersMenu(t)};t.onclick=c,t.onkeydown=A=>{(A.key==="Enter"||A.key===" ")&&c(A)}}openMobileFiltersMenu(e){let t=e.ownerDocument??document;t.querySelectorAll(".stashpad-mobile-filters-popover").forEach(u=>u.remove());let i=t.body.createDiv({cls:"stashpad-mobile-filters-popover"}),s=e.getBoundingClientRect(),n=t.defaultView??window,o=s.bottom+280>n.innerHeight;i.setCssStyles({right:`${Math.max(8,n.innerWidth-s.right)}px`,left:"auto",...o?{bottom:`${Math.max(8,n.innerHeight-s.top+4)}px`,top:"auto"}:{top:`${s.bottom+4}px`,bottom:"auto"},maxWidth:"min(360px, calc(100vw - 16px))",maxHeight:"min(60vh, 420px)",overflowY:"auto",width:"max-content",minWidth:"260px"});let r=()=>{i.remove(),t.removeEventListener("mousedown",l,!0);try{this.app.keymap?.popScope(g)}catch{}},l=u=>{!i.contains(u.target)&&u.target!==e&&!e.contains(u.target)&&r()},c=[{key:"tag",title:"Tag filter",summary:()=>this.tagFilter?`#${this.tagFilter}`:"All tags",populate:u=>this.populateTagMenuBody(u,r)},{key:"color",title:"Color filter",summary:()=>this.colorFilter?this.plugin.getColorAlias(this.noteFolder,this.colorFilter)??this.colorFilter:"All colors",populate:u=>this.populateColorMenuBody(u,this.collectFolderColors(),r)},{key:"time",title:"Time filter",summary:()=>{let u=gs.find(f=>f.key===this.timeFilter);return u?this.timeFilterCalendar?u.calShort:u.rollShort:"All"},populate:u=>this.populateTimeMenuBody(u,r)},{key:"sort",title:"Sort",summary:()=>this.currentViewMode()!=="nested"?"\u2014 (Nested only)":Ii[this.sortStore.getMode(this.noteFolder,this.focusId)],populate:u=>{if(this.currentViewMode()!=="nested"){u.createDiv({cls:"stashpad-mobile-filters-note",text:"Sort applies only in Nested view."});return}this.populateSortMenuBody(u,r)}},{key:"view",title:"View",summary:()=>ps[this.currentViewMode()],populate:u=>this.populateViewMenuBody(u,r)}],A="",h=()=>{i.empty();for(let u of c){let f=i.createDiv({cls:"stashpad-mobile-filters-section"}),p=f.createDiv({cls:"stashpad-mobile-filters-header"}),I=p.createSpan({cls:"stashpad-mobile-filters-chev"});if((0,F.setIcon)(I,A===u.key?"chevron-down":"chevron-right"),p.createSpan({cls:"stashpad-mobile-filters-title",text:u.title}),p.createSpan({cls:"stashpad-mobile-filters-summary",text:u.summary()}),p.onclick=m=>{m.preventDefault(),m.stopPropagation(),A=A===u.key?"":u.key,h()},A===u.key){let m=f.createDiv({cls:"stashpad-mobile-filters-body"});u.populate(m)}}};h();let g=new F.Scope(this.app.scope);g.register([],"Escape",u=>(u.preventDefault(),r(),!1)),this.app.keymap?.pushScope(g),setTimeout(()=>{t.addEventListener("mousedown",l,!0)},0)}renderViewDropdown(e){let t=this.currentViewMode(),i=e.createDiv({cls:"stashpad-view-btn"});i.setAttribute("role","button"),i.setAttribute("tabindex","0");let s=i.createSpan({cls:"stashpad-view-icon"});(0,F.setIcon)(s,t==="flat"?"list":t==="everything"?"layout-grid":"list-tree"),i.createSpan({cls:"stashpad-view-label"}).setText(ps[t]),(t!=="nested"||this.currentEncryptionFilter()!=="all")&&i.addClass("is-active"),i.title=t==="nested"?"View: Nested (the default). Click to switch to Flat or Everything.":t==="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(e){let t=e.ownerDocument??document;t.querySelectorAll(".stashpad-view-popover").forEach(l=>l.remove());let i=t.body.createDiv({cls:"stashpad-view-popover"});F.Platform.isMobile&&i.addClass("is-mobile");let s=e.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(),t.removeEventListener("mousedown",o,!0);try{this.app.keymap?.popScope(r)}catch{}},o=l=>{!i.contains(l.target)&&l.target!==e&&!e.contains(l.target)&&n()};this.populateViewMenuBody(i,n);let r=new F.Scope(this.app.scope);r.register([],"Escape",l=>(l.preventDefault(),n(),!1)),this.app.keymap?.pushScope(r),setTimeout(()=>{t.addEventListener("mousedown",o,!0)},0)}populateViewMenuBody(e,t){let i=this.currentViewMode(),s=(y,v,E)=>{let Q=e.createDiv({cls:"stashpad-view-popover-row"});y===i&&Q.addClass("is-active");let b=Q.createDiv({cls:"stashpad-view-popover-main"});(0,F.setIcon)(b.createSpan({cls:"stashpad-view-popover-icon"}),E),b.createSpan({cls:"stashpad-view-popover-label",text:ps[y]}),Q.createDiv({cls:"stashpad-view-popover-desc",text:v}),Q.onclick=async D=>{D.preventDefault(),D.stopPropagation(),t(),y!==i&&(await this.setViewMode(y),this.render())}};if(s("nested","Tree of immediate children (default).","list-tree"),e.createDiv({cls:"stashpad-view-popover-divider"}),s("flat","All descendants of the current focus, flat by sort.","list"),e.createDiv({cls:"stashpad-view-popover-divider"}),s("everything","All descendants PLUS non-Stashpad files in the folder.","layout-grid"),e.createDiv({cls:"stashpad-view-popover-divider"}),this.plugin.encryption?.isConfigured?.()){let y=this.currentEncryptionFilter(),v=(E,Q,b)=>{let D=e.createDiv({cls:"stashpad-view-popover-row"});E===y&&D.addClass("is-active"),D.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:Q}),D.createDiv({cls:"stashpad-view-popover-desc",text:b}),D.onclick=async H=>{H.preventDefault(),H.stopPropagation(),E!==y&&(await this.setEncryptionFilter(E),this.refreshList()),t()}};v("all","Encryption: show all","Both locked \u{1F512} and decrypted notes."),v("locked","Encryption: locked only","Show only locked \u{1F512} stubs."),v("unlocked","Encryption: decrypted only","Hide locked \u{1F512} stubs."),e.createDiv({cls:"stashpad-view-popover-divider"})}let n=e.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 y=>{y.target!==o&&(y.preventDefault(),o.checked=!o.checked),await this.setHideChildless(o.checked),this.refreshList()};let r=e.createDiv({cls:"stashpad-view-popover-row stashpad-view-popover-toggle"}),l=r.createEl("input",{type:"checkbox"});l.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 y=>{y.target!==l&&(y.preventDefault(),l.checked=!l.checked),await this.setHideCompleted(l.checked),this.refreshList()};let c=e.createDiv({cls:"stashpad-view-popover-row stashpad-view-popover-toggle"}),A=c.createEl("input",{type:"checkbox"});A.checked=this.currentAttachmentsOnly(),c.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:"Hide notes without attachments"}),c.createDiv({cls:"stashpad-view-popover-desc",text:"Show only notes that have an attachment. A parent stays visible while any descendant has one."}),c.onclick=async y=>{y.target!==A&&(y.preventDefault(),A.checked=!A.checked),await this.setAttachmentsOnly(A.checked),this.refreshList()},e.createDiv({cls:"stashpad-view-popover-divider"});let h=e.createDiv({cls:"stashpad-view-popover-row stashpad-view-popover-toggle"});i!=="everything"&&h.addClass("is-disabled");let g=h.createEl("input",{type:"checkbox"});g.checked=this.currentIncludeAttachments(),g.disabled=i!=="everything",h.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:"Include attachments"}),h.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."}),h.onclick=async y=>{i==="everything"&&(y.target!==g&&(y.preventDefault(),g.checked=!g.checked),await this.setIncludeAttachments(g.checked),this.refreshList())},e.createDiv({cls:"stashpad-view-popover-divider"});let u=e.createDiv({cls:"stashpad-view-popover-row stashpad-view-popover-toggle"}),f=u.createEl("input",{type:"checkbox"});f.checked=this.importedOnly,u.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:"Imported notes only"}),u.createDiv({cls:"stashpad-view-popover-desc",text:"Show only notes that came in via import."}),u.onclick=y=>{y.target!==f&&(y.preventDefault(),f.checked=!f.checked),this.importedOnly=f.checked,this.reconcileSelectionAfterFilter(),this.refreshList()};let p=new Map,I=this.noteFolder.replace(/\/+$/,"");for(let y of this.app.vault.getMarkdownFiles()){if((y.parent?.path?.replace(/\/+$/,"")??"")!==I)continue;let v=rt(this.app.metadataCache.getFileCache(y)?.frontmatter?.author);v&&p.set(v.id,v.name)}e.createDiv({cls:"stashpad-view-popover-divider"});let m=e.createDiv({cls:"stashpad-view-popover-row"}),B=m.createDiv({cls:"stashpad-view-popover-main"});(0,F.setIcon)(B.createSpan({cls:"stashpad-view-popover-icon"}),"user"),B.createSpan({cls:"stashpad-view-popover-label",text:"By author"});let C=B.createEl("select",{cls:"stashpad-view-author-select"}),w=C.createEl("option",{text:"All authors",value:""});this.authorFilter||(w.selected=!0);for(let[y,v]of[...p.entries()].sort((E,Q)=>E[1].localeCompare(Q[1]))){let E=C.createEl("option",{text:v,value:y});this.authorFilter===y&&(E.selected=!0)}C.onclick=y=>y.stopPropagation(),C.onchange=()=>{this.authorFilter=C.value||null,this.reconcileSelectionAfterFilter(),this.refreshList()},m.createDiv({cls:"stashpad-view-popover-desc",text:p.size?"Show only notes by the chosen author.":"No authored notes in this folder yet."})}setTagFilter(e){(this.tagFilter??null)!==(e??null)&&(this.tagFilter=e,this.reconcileSelectionAfterFilter(),this.persistFocus(),this.render())}populateSortMenuBody(e,t){let i=this.noteFolder,s=this.focusId,n=this.sortStore.getMode(i,s);for(let o of Po){let r=e.createDiv({cls:"stashpad-sort-popover-row"});o===n&&r.addClass("is-active"),r.createSpan({cls:"stashpad-sort-popover-label",text:Ii[o]}),r.onclick=async l=>{l.preventDefault(),l.stopPropagation(),t(),o!==n&&(this.sortStore.setMode(i,s,o),await this.sortStore.save(i),this.tree.rebuild(i),this.render())}}}populateTimeMenuBody(e,t){let i=e.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 gs){let o=e.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=l=>{l.preventDefault(),l.stopPropagation(),t(),this.timeFilter!==n.key&&this.setTimeFilter(n.key)}}}populateColorMenuBody(e,t,i){let s=(n,o,r)=>{let l=e.createDiv({cls:"stashpad-color-filter-popover-row"}),c=l.createSpan({cls:"stashpad-color-filter-swatch"});o?c.setCssStyles({background:o}):c.addClass("is-empty");let A=l.createSpan({cls:"stashpad-color-filter-popover-label"});A.setText(n),o&&(A.style.color=o),l.onclick=h=>{h.preventDefault(),h.stopPropagation(),r(),i()}};s("All colors",null,()=>this.setColorFilter(null));for(let n of t){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(e,t){let i=this.collectFolderTags(),s=(n,o)=>{let r=e.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=A=>{A.preventDefault(),A.stopPropagation(),this.setTagFilter(o),t()}};s(i.length===0?"No tags":"All tags",null),s("Tagged",Pt),s("Untagged",Ht);for(let n of i)s(`${n.label} (${n.count})`,n.raw)}setColorFilter(e){let t=e?e.toLowerCase():null;(this.colorFilter??null)!==t&&(this.colorFilter=t,this.reconcileSelectionAfterFilter(),this.persistFocus(),this.render())}setTimeFilter(e){this.timeFilter!==e&&(this.timeFilter=e,this.reconcileSelectionAfterFilter(),this.persistFocus(),this.render())}reconcileSelectionAfterFilter(){let e=this.filterChildren(this.collectViewItems(this.focusId)),t=new Set(e.map(i=>i.id));for(let i of[...this.selection])t.has(i)||this.selection.delete(i);if(this.firstSelectedId&&!t.has(this.firstSelectedId)&&(this.firstSelectedId=null),this.lastSelected&&!t.has(this.lastSelected)&&(this.lastSelected=null),this.selection.size>0){let i=e.findIndex(s=>this.selection.has(s.id));this.cursorIdx=i>=0?i:Math.min(this.cursorIdx,e.length-1)}else this.cursorIdx>=e.length&&(this.cursorIdx=e.length-1)}renderTinyHeader(e){let t=e.createDiv({cls:"stashpad-tiny-header"}),i=t.createEl("button",{cls:"stashpad-tiny-nav-btn"});Fe(i,"arrow-left","\u2039"),i.title="Back (up to parent)",this.navBackStack.length>0||this.focusId!==S||i.addClass("is-disabled"),i.title=this.navBackStack.length>0?"Back":this.focusId!==S?"Back (up to parent)":"No back history",i.onclick=()=>this.navigateBack();let n=t.createEl("button",{cls:"stashpad-tiny-nav-btn"});Fe(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(),l=this.focusId===S?r:`${r} / ${this.titleForNode(o).trim()}`,c=t.createEl("button",{cls:"stashpad-tiny-title stashpad-folder-btn"}),A=c.createSpan({cls:"stashpad-tiny-title-icon stashpad-btn-icon"});(0,F.setIcon)(A,"folder"),c.createSpan({cls:"stashpad-tiny-title-text stashpad-btn-text",text:l}),c.title=`${this.noteFolder}${this.focusId!==S?` / ${this.titleForNode(o).trim()}`:""} -Click to switch / create folder.`,c.onclick=p=>{p.preventDefault(),this.plugin.openFolderPicker()};let h=t.createDiv({cls:"stashpad-tiny-sticky"}),g=h.createEl("input",{type:"checkbox"});if(g.checked=this.tinyAlwaysOnTop,h.createSpan({text:"Sticky"}),g.onchange=()=>{this.tinyAlwaysOnTop=g.checked,this.applyTinyAlwaysOnTop()},!F.Platform.isMobile){let p=t.createEl("button",{cls:"stashpad-tiny-nav-btn stashpad-tiny-opacity-btn"});(0,F.setIcon)(p,"contrast"),p.title="Window transparency",this.tinyOpacity<1&&p.addClass("is-active"),p.onclick=I=>{I.stopPropagation(),this.toggleTinyOpacityPopover(p)}}let u=t.createEl("button",{cls:"stashpad-tiny-expand stashpad-tiny-exit-compact"});(0,F.setIcon)(u,this.compactMode?"panel-top":"rows-2"),u.title=this.compactMode?"Compact mode is ON \u2014 click to turn off.":"Compact mode \u2014 click to turn on (strips row metadata).",this.compactMode&&u.addClass("is-active"),u.onclick=()=>{this.toggleCompactMode()};let f=t.createEl("button",{cls:"stashpad-tiny-expand"});(0,F.setIcon)(f,"maximize-2"),f.title="Exit tiny mode",f.onclick=()=>{this.exitTinyMode()}}toggleTinyOpacityPopover(e){if(this.tinyOpacityPopover){this.tinyOpacityPopover.remove(),this.tinyOpacityPopover=null;return}let t=document.createElement("div");t.className="stashpad-tiny-opacity-popover",t.createSpan({cls:"stashpad-tiny-opacity-label",text:"Transparency"});let i=t.createEl("input",{type:"range"});i.min="30",i.max="100",i.step="1",i.value=String(Math.round(this.tinyOpacity*100));let s=t.createSpan({cls:"stashpad-tiny-opacity-pct",text:`${i.value}%`});i.addEventListener("input",()=>{let A=Math.min(100,Math.max(30,parseInt(i.value,10)||100));this.tinyOpacity=A/100,s.setText(`${A}%`),this.applyTinyOpacity(),e.toggleClass("is-active",this.tinyOpacity<1)}),i.addEventListener("change",()=>{this.app.workspace.requestSaveLayout()}),this.viewRoot.appendChild(t);let n=e.getBoundingClientRect(),o=this.viewRoot.getBoundingClientRect();t.setCssStyles({top:`${n.bottom-o.top+4}px`,left:`${Math.max(4,Math.min(n.left-o.left,o.width-180))}px`});let r=A=>{t.contains(A.target)||A.target===e||e.contains(A.target)||c()},l=A=>{A.key==="Escape"&&c()},c=()=>{t.remove(),this.tinyOpacityPopover=null,this.tinyOpacityClose=null,document.removeEventListener("mousedown",r,!0),document.removeEventListener("keydown",l,!0)};setTimeout(()=>{document.addEventListener("mousedown",r,!0),document.addEventListener("keydown",l,!0)},0),this.tinyOpacityPopover=t,this.tinyOpacityClose=c,i.focus()}getOwnElectronWindow(){try{let e=this.containerEl?.ownerDocument?.defaultView??window,s=((e?.require?.("electron")??window.require?.("electron"))?.remote??e?.electron?.remote??e?.["@electron/remote"])?.getCurrentWindow?.()??e?.electronWindow??null;if(!s)try{let n=window.require?.("electron"),o=n?.remote??n?.["@electron/remote"],l=(o?.BrowserWindow??n?.BrowserWindow)?.getAllWindows?.()??[];l.length===1?s=l[0]:l.length>1&&(s=o?.getFocusedWindow?.()??null??l[l.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(e){return console.debug("[Stashpad] resolve own electron window failed",e),null}}applyTinyAlwaysOnTop(){let e=this.getOwnElectronWindow();if(e)try{e.setAlwaysOnTop?.(!!this.tinyAlwaysOnTop)}catch(t){console.debug("[Stashpad] setAlwaysOnTop failed",t)}}applyTinyOpacity(){let e=this.getOwnElectronWindow();if(!e)return;let t=Math.min(1,Math.max(.3,this.tinyOpacity));try{e.setOpacity?.(t)}catch(i){console.debug("[Stashpad] setOpacity failed",i)}}applyTinyWindow(){let e=this.getOwnElectronWindow();if(e)try{if(this.tinyMode){e.setMinimumSize?.(220,260);let s=100,n=100;try{let o=e.getBounds?.();o&&typeof o.x=="number"&&(s=o.x,n=o.y)}catch{}try{e.setBounds?.({x:s,y:n,width:280,height:360})}catch{}try{e.setSize?.(280,360)}catch{}e.setAlwaysOnTop?.(!!this.tinyAlwaysOnTop);try{e.setOpacity?.(Math.min(1,Math.max(.3,this.tinyOpacity)))}catch{}}else e.setAlwaysOnTop?.(!1)}catch(t){console.debug("[Stashpad] tiny window apply failed",t)}}async exitTinyMode(){this.tinyMode=!1,this.tinyAlwaysOnTop=!1,this.tinyOpacity=1;try{this.getOwnElectronWindow()?.setOpacity?.(1)}catch{}this.compactMode=!1,this.applyTinyWindow();let e=this.getOwnElectronWindow();try{if(e?.setMinimumSize?.(400,300),F.Platform.isMacOS??!1){let i=this.containerEl?.ownerDocument?.defaultView?.require?.("electron")??window.require?.("electron"),n=(i?.remote?.screen??i?.screen)?.getPrimaryDisplay?.().workArea;n?e?.setBounds?.({x:n.x,y:n.y,width:n.width,height:n.height}):e?.maximize?.()}else e?.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(e){let t=e.createDiv({cls:"stashpad-breadcrumb"});F.Platform.isMobile||this.renderActionsCluster(t);let i=t.createSpan({cls:"stashpad-crumb stashpad-crumb-home"});if(F.Platform.isMobile?((0,F.setIcon)(i,"home"),i.title="Home"):i.setText("Home"),i.onclick=()=>this.navigateTo(S),this.focusId===S){let c=this.tree.getChildren(this.focusId).length;if(c>0&&(t.createSpan({cls:"stashpad-crumb-count",text:`\xB7 ${c}`}).title=`${c} direct child${c===1?"":"ren"}`),this.compactMode){let A=t.createEl("button",{cls:"stashpad-compact-exit-btn"});(0,F.setIcon)(A,"panel-top"),A.title="Exit compact mode",A.onclick=h=>{h.preventDefault(),this.toggleCompactMode()}}return}let s=28,n=this.tree.pathTo(this.focusId);this.warmCrumbTitles(n);let o=n.map(c=>{let A=this.titleForNode(c),h=A.length>s?A.slice(0,s-1)+"\u2026":A;return{id:c.id,label:h}}),r=F.Platform.isMobile?"/":" / ";for(let c of o)if(t.createSpan({cls:"stashpad-crumb-sep",text:r}),c.isEllipsis)t.createSpan({cls:"stashpad-crumb stashpad-crumb-ellipsis",text:c.label}).title=n.map(A=>this.titleForNode(A)).join(" / ");else{let A=c.id,h=t.createSpan({cls:"stashpad-crumb",text:c.label});h.title=c.label,h.onclick=()=>this.navigateTo(A),h.oncontextmenu=g=>{g.preventDefault(),this.openCrumbMenu(g,A)},F.Platform.isMobile&&this.attachLongPress(h,()=>this.openCrumbMenu(null,A))}if(t.querySelector(".stashpad-crumb-home")?.addEventListener("contextmenu",c=>{c.preventDefault(),this.openCrumbMenu(c,S)}),F.Platform.isMobile){let c=t.querySelector(".stashpad-crumb-home");c&&this.attachLongPress(c,()=>this.openCrumbMenu(null,S))}let l=this.tree.getChildren(this.focusId).length;if(l>0&&(t.createSpan({cls:"stashpad-crumb-count",text:`\xB7 ${l}`}).title=`${l} direct child${l===1?"":"ren"}`),this.compactMode){let c=t.createEl("button",{cls:"stashpad-compact-exit-btn"});(0,F.setIcon)(c,"panel-top"),c.title="Exit compact mode",c.onclick=A=>{A.preventDefault(),this.toggleCompactMode()}}F.Platform.isMobile||this.renderBreadcrumbLevelsButton(t)}renderBreadcrumbLevelsButton(e){let t=e.createEl("button",{cls:"stashpad-mobile-action-btn stashpad-crumb-levels-btn"});Fe(t,"route","\u22D4"),t.title="Show all levels \u2014 jump to any level in the path",t.onclick=i=>{i.preventDefault(),this.openBreadcrumbLevelsModal()}}openBreadcrumbLevelsModal(){let e=this.tree.pathTo(this.focusId),t=[{id:S,label:"Home",level:0,isCurrent:this.focusId===S,isHome:!0}];e.forEach((i,s)=>{t.push({id:i.id,label:this.titleForNode(i),level:s+1,isCurrent:i.id===this.focusId})}),new Li(this.app,t,i=>this.navigateTo(i),{onContext:(i,s,n,o)=>this.openCrumbMenu(s,i,n,o),attachLongPress:(i,s)=>this.attachLongPress(i,s)}).open()}attachLongPress(e,t){let i=null,s=0,n=0,o=()=>{i!=null&&(window.clearTimeout(i),i=null)};e.addEventListener("touchstart",r=>{let l=r.touches[0];s=l?.clientX??0,n=l?.clientY??0,o(),i=window.setTimeout(()=>{i=null,t()},500)},{passive:!0}),e.addEventListener("touchmove",r=>{let l=r.touches[0];l&&(Math.abs(l.clientX-s)>10||Math.abs(l.clientY-n)>10)&&o()},{passive:!0}),e.addEventListener("touchend",o),e.addEventListener("touchcancel",o)}openCrumbMenu(e,t,i,s){let n=this.tree.get(t);if(!n)return;let o=new F.Menu;if(o.addItem(r=>r.setTitle("Navigate here").setIcon("arrow-right-circle").onClick(()=>{s?.(),this.navigateTo(t)})),o.addItem(r=>r.setTitle("Open in new Stashpad tab").setIcon("list-tree").onClick(()=>{s?.(),this.cmdOpenInNewStashpadTab(n)})),n.file&&o.addItem(r=>r.setTitle("Open in editor (new tab)").setIcon("pencil").onClick(()=>{s?.(),this.cmdOpenInEditor(n)})),e&&(e.clientX>0||e.clientY>0))o.showAtMouseEvent(e);else{let l=(i??e?.target??null)?.getBoundingClientRect();o.showAtPosition({x:l?.left??8,y:(l?.bottom??60)+4})}}renderFocusedHeaderMini(e,t){if(!t.file)return;let i=e.createDiv({cls:"stashpad-focused-mini"});i.dataset.id=t.id,i.createDiv({cls:"stashpad-focused-mini-text"}).setText(this.titleForNode(t).trim());let n=i.createEl("button",{cls:"stashpad-pencil stashpad-note-more stashpad-focused-mini-more"});(0,F.setIcon)(n,"more-horizontal"),n.title="Actions",n.onclick=o=>{o.stopPropagation(),this.openNoteMenu(o,t)}}installFocusedMiniObserver(e){let t=e.querySelector(".stashpad-focused"),i=e.querySelector(".stashpad-focused-mini");!t||!i||(this.focusedMiniObserver&&this.focusedMiniObserver.disconnect(),this.focusedMiniObserver=new IntersectionObserver(s=>{for(let n of s)i.toggleClass("is-visible",!n.isIntersecting)},{root:e,threshold:.05}),this.focusedMiniObserver.observe(t))}renderFocusedHeader(e,t){if(!t.file)return;let i=t.file,s=e.createDiv({cls:"stashpad-focused"});s.oncontextmenu=A=>{A.preventDefault(),this.openNoteMenu(A,t)};let 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(t.created)}),o.createDiv({cls:"stashpad-focused-grip-spacer"});let r=s.createDiv({cls:"stashpad-focused-body"});r.addEventListener("click",A=>this.handleRenderedClick(A,t));let l=s.createDiv({cls:"stashpad-focused-actions"}),c;if(F.Platform.isMobile){let A=l.createEl("button",{cls:"stashpad-pencil stashpad-note-more stashpad-focused-more"});(0,F.setIcon)(A,"more-horizontal"),A.title="Actions",A.onclick=h=>{h.stopPropagation(),this.openNoteMenu(h,t)},c=A}else{let A=l.createEl("button",{cls:"stashpad-pencil stashpad-focused-pencil"});(0,F.setIcon)(A,"pencil"),A.title="Edit in new tab",A.onclick=()=>void this.openFileAtEnd(i);let h=l.createEl("button",{cls:"stashpad-pencil stashpad-focused-dup"});(0,F.setIcon)(h,"copy"),h.title="Open this Stashpad in a new tab (clone)",h.onclick=()=>this.cmdOpenInNewStashpadTab(t),c=A}this.renderNoteBody(r,t,{clamp:F.Platform.isMobile,immediate:!0,toggleHost:l,toggleAnchor:c})}renderRowBreadcrumb(e,t){let i=this.tree.pathTo(t.id),s=i.findIndex(r=>r.id===this.focusId),n=i.slice(s+1,i.length-1);if(n.length===0)return;let o=e.createDiv({cls:"stashpad-row-breadcrumb"});n.forEach((r,l)=>{let c=o.createSpan({cls:"stashpad-row-breadcrumb-seg",text:this.titleForNode(r)});c.title=`Focus into "${this.titleForNode(r)}"`,c.onclick=A=>{A.stopPropagation(),this.navigateTo(r.id)},l<n.length-1&&o.createSpan({cls:"stashpad-row-breadcrumb-sep",text:" / "})})}actionsForFile(e){return Ls(this.app,e,F.Platform.isMobile)}bulkActionMessage(e){let t=e.nodes.map(r=>`"${this.titleForNode(r).trim()||"(untitled)"}"`),i=e.suffix?` ${e.suffix}`:"",s=e.destination?` ${e.destination}`:"";if(t.length===0)return`${e.verb}${i}${s}`;if(t.length===1)return`${e.verb} ${t[0]}${i}${s}`;let n=e.bulletMax??10,o=t.length<=n?t.map(r=>`\u2022 ${r}`).join(` +Click to override for this tab.`,A&&c.addClass("is-override"),c.onclick=u=>{u.preventDefault(),this.openFolderPicker()};let p=t.createEl("button",{cls:"stashpad-search-btn"});Fe(p,"search","\u{1F50D}"),p.title="Search notes (Mod+F)",p.onclick=u=>{u.preventDefault(),this.openSearchModal()}}b.Platform.isMobile?(this.renderActionsCluster(t),this.renderMobileFiltersButton(t)):(this.renderTagFilterDropdown(t),this.renderColorFilterDropdown(t),this.renderSortDropdown(t),this.renderViewDropdown(t));let i=t.createDiv({cls:"stashpad-time-filter-btns"}),s=i.createEl("button",{cls:"stashpad-time-filter-btn stashpad-time-filter-cal"});(0,b.setIcon)(s,this.timeFilterCalendar?"calendar":"history"),s.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&&s.addClass("is-active"),s.onclick=c=>{c.preventDefault(),this.timeFilterCalendar=!this.timeFilterCalendar,this.persistFocus(),this.render()};for(let c of us){let A=this.timeFilterCalendar?c.calShort:c.rollShort,h=this.timeFilterCalendar?c.calLong:c.rollLong,p=i.createEl("button",{cls:"stashpad-time-filter-btn",text:A});p.title=h,this.timeFilter===c.key&&p.addClass("is-active"),p.onclick=u=>{u.preventDefault(),this.setTimeFilter(c.key)}}let n=t.createEl("select",{cls:"stashpad-time-filter-select"});for(let c of us){let A=this.timeFilterCalendar?c.calLong:c.rollLong,h=n.createEl("option",{text:A});h.value=c.key,this.timeFilter===c.key&&(h.selected=!0)}n.onchange=()=>this.setTimeFilter(n.value);let o=t.createDiv({cls:"stashpad-view-mode-btns"});if(!b.Platform.isMobile){let c=o.createEl("button",{cls:"stashpad-view-mode-btn"});(0,b.setIcon)(c,"minimize-2"),c.title="Tiny mode \u2014 open this tab in a small always-on-top-capable popout window.",c.onclick=A=>{A.preventDefault(),this.plugin.openTinyWindow()}}let r=o.createEl("button",{cls:"stashpad-view-mode-btn"});if((0,b.setIcon)(r,this.compactMode?"panel-top":"rows-2"),r.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&&r.addClass("is-active"),r.onclick=c=>{c.preventDefault(),this.toggleCompactMode()},b.Platform.isMobile)return;let l=o.createEl("button",{cls:"stashpad-view-mode-btn"});(0,b.setIcon)(l,"external-link"),l.title=X().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.)",l.onclick=c=>{c.preventDefault();let A=X().popoutDuplicates;try{let h=this.app.workspace;if(A){let p=this.leaf.getViewState(),u=h.openPopoutLeaf?.();u?u.setViewState({...p,active:!0}):new b.Notice("Stashpad: this Obsidian build doesn't expose openPopoutLeaf.")}else h.moveLeafToPopout?.(this.leaf)}catch(h){new b.Notice(`Stashpad: open-in-new-window failed (${h.message})`)}},this.setupBarOverflow(t)}setupBarOverflow(e){let t=[{key:"nav",icon:"folder-search",title:"Folder & search",memberSel:[".stashpad-folder-btn",".stashpad-search-btn"],memberKeys:["folder","search"],collapsePrio:5,displayIdx:0},{key:"filter",icon:"filter",title:"Tag & color",memberSel:[".stashpad-tag-filter-btn",".stashpad-color-filter-btn"],memberKeys:["tag","color"],collapsePrio:3,displayIdx:1},{key:"arrange",icon:"sliders-horizontal",title:"Sort & view",memberSel:[".stashpad-sort-btn",".stashpad-view-btn"],memberKeys:["sort","view"],collapsePrio:4,displayIdx:2},{key:"time",icon:"clock",title:"Time",memberSel:[".stashpad-time-filter-btns",".stashpad-time-filter-select"],memberKeys:["time"],collapsePrio:2,displayIdx:3},{key:"window",icon:"app-window",title:"Window & layout",memberSel:[".stashpad-view-mode-btns"],memberKeys:["mode"],collapsePrio:1,displayIdx:4}];e.addClass("stashpad-overflow-managed");let i=[];for(let u of[...t].sort((f,g)=>f.displayIdx-g.displayIdx)){let f=u.memberSel.map(C=>e.querySelector(C)).filter(C=>!!C);if(f.length===0)continue;let g=createDiv({cls:"stashpad-bar-group"});e.insertBefore(g,f[0]);let I=g.createDiv({cls:"stashpad-bar-group-expanded"});for(let C of f)I.appendChild(C);let m=g.createDiv({cls:"stashpad-bar-overflow-btn stashpad-bar-group-icon stashpad-overflow-hidden"});m.setAttribute("role","button"),m.setAttribute("tabindex","0"),(0,b.setIcon)(m.createSpan({cls:"stashpad-bar-group-icon-glyph"}),u.icon),m.title=`${u.title} \u2014 combined menu`;let B=C=>{C.preventDefault(),this.openBarOverflowMenu(m,u.memberKeys)};m.onclick=B,m.onkeydown=C=>{(C.key==="Enter"||C.key===" ")&&B(C)},i.push({...u,wrapper:g,expanded:I,iconBtn:m})}let s=e.createDiv({cls:"stashpad-bar-overflow-btn stashpad-bar-kebab stashpad-overflow-hidden"});s.setAttribute("role","button"),s.setAttribute("tabindex","0"),(0,b.setIcon)(s.createSpan({cls:"stashpad-bar-overflow-icon"}),"more-horizontal"),s.title="More filters / view options";let n=[...i].sort((u,f)=>u.collapsePrio-f.collapsePrio),o=[...i].sort((u,f)=>f.displayIdx-u.displayIdx),r=[],l=()=>e.scrollWidth<=e.clientWidth+1,c=()=>{if(!e.isConnected||e.clientWidth===0)return;for(let f of i)f.wrapper.removeClass("stashpad-overflow-hidden"),f.expanded.removeClass("stashpad-overflow-hidden"),f.iconBtn.addClass("stashpad-overflow-hidden"),f.iconBtn.toggleClass("is-active",f.memberKeys.some(g=>this.barUnitActive(g)));if(s.addClass("stashpad-overflow-hidden"),r=[],l())return;for(let f of n){if(l())break;f.expanded.addClass("stashpad-overflow-hidden"),f.iconBtn.removeClass("stashpad-overflow-hidden")}if(l())return;s.removeClass("stashpad-overflow-hidden");let u=[];for(let f of o){if(l())break;f.wrapper.addClass("stashpad-overflow-hidden"),u.push(f)}r=[...u].sort((f,g)=>f.displayIdx-g.displayIdx).flatMap(f=>f.memberKeys),s.toggleClass("is-active",r.some(f=>this.barUnitActive(f)))},A=u=>{u.preventDefault(),this.openBarOverflowMenu(s,r)};s.onclick=A,s.onkeydown=u=>{(u.key==="Enter"||u.key===" ")&&A(u)};try{this.barOverflowRO?.disconnect()}catch{}let h=(e.ownerDocument?.defaultView??window).ResizeObserver,p=-1;this.barOverflowRO=new h(u=>{let f=Math.round(u[u.length-1].contentRect.width);f!==p&&(p=f,c())}),this.barOverflowRO.observe(e),requestAnimationFrame(()=>c())}barUnitActive(e){switch(e){case"folder":return!!this.folderOverride;case"tag":return!!this.tagFilter;case"color":return!!this.colorFilter;case"time":return this.timeFilter!=="all";case"sort":return this.currentViewMode()==="nested"&&this.sortStore.getMode(this.noteFolder,this.focusId)!=="manual";case"view":return this.currentViewMode()!=="nested"||this.currentEncryptionFilter()!=="all"||this.currentHideChildless()||this.currentHideCompleted()||this.currentAttachmentsOnly()||this.currentIncludeAttachments();case"mode":return this.compactMode;default:return!1}}openBarOverflowMenu(e,t){let i=e.ownerDocument??document;i.querySelectorAll(".stashpad-mobile-filters-popover").forEach(f=>f.remove());let s=i.body.createDiv({cls:"stashpad-mobile-filters-popover"}),n=e.getBoundingClientRect(),o=i.defaultView??window;s.setCssStyles({right:`${Math.max(8,o.innerWidth-n.right)}px`,left:"auto",top:`${n.bottom+4}px`,maxWidth:"min(360px, calc(100vw - 16px))",width:"max-content",minWidth:"260px"});let r=new b.Scope(this.app.scope),l=()=>{s.remove(),i.removeEventListener("mousedown",c,!0);try{this.app.keymap?.popScope(r)}catch{}},c=f=>{!s.contains(f.target)&&f.target!==e&&!e.contains(f.target)&&l()},h=[{key:"folder",title:"Folder",summary:()=>this.noteFolder.split("/").pop()||this.noteFolder||"Stashpad",populate:f=>this.populateFolderMenuBody(f,l)},{key:"search",title:"Search",summary:()=>"Search notes (Mod+F)",populate:f=>this.populateSearchMenuBody(f,l)},{key:"tag",title:"Tag filter",summary:()=>this.tagFilter?`#${this.tagFilter}`:"All tags",populate:f=>this.populateTagMenuBody(f,l)},{key:"color",title:"Color filter",summary:()=>this.colorFilter?this.plugin.getColorAlias(this.noteFolder,this.colorFilter)??this.colorFilter:"All colors",populate:f=>this.populateColorMenuBody(f,this.collectFolderColors(),l)},{key:"sort",title:"Sort",summary:()=>this.currentViewMode()!=="nested"?"\u2014 (Nested only)":mi[this.sortStore.getMode(this.noteFolder,this.focusId)],populate:f=>{if(this.currentViewMode()!=="nested"){f.createDiv({cls:"stashpad-mobile-filters-note",text:"Sort applies only in Nested view."});return}this.populateSortMenuBody(f,l)}},{key:"view",title:"View",summary:()=>gs[this.currentViewMode()],populate:f=>this.populateViewMenuBody(f,l)},{key:"time",title:"Time filter",summary:()=>{let f=us.find(g=>g.key===this.timeFilter);return f?this.timeFilterCalendar?f.calShort:f.rollShort:"All"},populate:f=>this.populateTimeMenuBody(f,l)},{key:"mode",title:"View mode",summary:()=>this.compactMode?"Compact on":"Tiny \xB7 Compact \xB7 Window",populate:f=>this.populateModeMenuBody(f,l)}].filter(f=>t.includes(f.key)),p="",u=()=>{s.empty();for(let f of h){let g=s.createDiv({cls:"stashpad-mobile-filters-section"}),I=g.createDiv({cls:"stashpad-mobile-filters-header"}),m=I.createSpan({cls:"stashpad-mobile-filters-chev"});(0,b.setIcon)(m,p===f.key?"chevron-down":"chevron-right"),I.createSpan({cls:"stashpad-mobile-filters-title",text:f.title}),I.createSpan({cls:"stashpad-mobile-filters-summary",text:f.summary()}),I.onclick=B=>{B.preventDefault(),B.stopPropagation(),p=p===f.key?"":f.key,u()},p===f.key&&f.populate(g.createDiv({cls:"stashpad-mobile-filters-body"}))}};u(),r.register([],"Escape",f=>(f.preventDefault(),l(),!1)),this.app.keymap?.pushScope(r),setTimeout(()=>{i.addEventListener("mousedown",c,!0)},0)}populateFolderMenuBody(e,t){let i=e.createDiv({cls:"stashpad-sort-popover-row"});i.createSpan({cls:"stashpad-sort-popover-label",text:this.folderOverride?"Change folder (override active)\u2026":"Change folder for this tab\u2026"}),i.onclick=s=>{s.preventDefault(),s.stopPropagation(),t(),this.openFolderPicker()}}populateSearchMenuBody(e,t){let i=e.createDiv({cls:"stashpad-sort-popover-row"});i.createSpan({cls:"stashpad-sort-popover-label",text:"Search notes\u2026"}),i.onclick=s=>{s.preventDefault(),s.stopPropagation(),t(),this.openSearchModal()}}populateModeMenuBody(e,t){let i=(n,o)=>{let r=e.createDiv({cls:"stashpad-sort-popover-row"});r.createSpan({cls:"stashpad-sort-popover-label",text:n}),r.onclick=l=>{l.preventDefault(),l.stopPropagation(),t(),o()}};i("Tiny mode (popout window)",()=>void this.plugin.openTinyWindow());let s=e.createDiv({cls:"stashpad-sort-popover-row"});this.compactMode&&s.addClass("is-active"),s.createSpan({cls:"stashpad-sort-popover-label",text:this.compactMode?"Compact mode (on)":"Compact mode"}),s.onclick=n=>{n.preventDefault(),n.stopPropagation(),t(),this.toggleCompactMode()},i(X().popoutDuplicates?"Duplicate to new window":"Move to new window",()=>{try{let n=this.app.workspace;if(X().popoutDuplicates){let o=n.openPopoutLeaf?.();o?o.setViewState({...this.leaf.getViewState(),active:!0}):new b.Notice("Stashpad: this Obsidian build doesn't expose openPopoutLeaf.")}else n.moveLeafToPopout?.(this.leaf)}catch(n){new b.Notice(`Stashpad: open-in-new-window failed (${n.message})`)}})}toggleCompactMode(){this.compactMode=!this.compactMode,this.render();try{this.app.workspace.requestSaveLayout?.()}catch{}}renderActionsCluster(e){let t=e.createDiv({cls:"stashpad-mobile-actions"}),i=t.createEl("button",{cls:"stashpad-mobile-action-btn"});Fe(i,"arrow-left","\u2039");let s=this.navBackStack.length>0||this.focusId!==k;i.title=this.navBackStack.length>0?"Back":this.focusId!==k?"Back (up to parent)":"No back history",s||i.addClass("is-disabled"),i.onclick=h=>{h.preventDefault(),this.navigateBack()};let n=t.createEl("button",{cls:"stashpad-mobile-action-btn"});Fe(n,"arrow-right","\u203A");let o=this.navForwardSnapshots.length>0;if(n.title=o?"Forward":"No forward history",o||n.addClass("is-disabled"),n.onclick=h=>{h.preventDefault(),this.navigateForward()},b.Platform.isMobile){let h=t.createEl("button",{cls:"stashpad-mobile-action-btn"});Fe(h,"route","\u22D4"),h.title="Jump to a level in the path",h.onclick=p=>{p.preventDefault(),this.openBreadcrumbLevelsModal()}}let r=t.createEl("button",{cls:"stashpad-mobile-action-btn"}),l=this.mobileSelectMode;Fe(r,l?"check-square":"square",l?"\u2611":"\u2610"),r.title=l?`${this.selection.size} selected \u2014 tap to exit (keeps the first selection)`:"Enter select mode (tap notes to add)",l&&r.addClass("is-active"),r.onclick=h=>{if(h.preventDefault(),this.mobileSelectMode){let p=this.firstSelectedId??this.selection.values().next().value;if(this.selection.clear(),p){let u=this.currentChildren.findIndex(f=>f.id===p);this.selection.add(p),this.lastSelected=p,u>=0&&(this.cursorIdx=u)}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 b.Notice("Select mode: tap notes to add, press \u26A1 for actions")}};let c=t.createEl("button",{cls:"stashpad-mobile-action-btn"});Fe(c,"zap","\u26A1"),c.title="Actions (move, delete, undo, \u2026)",c.onclick=h=>{h.preventDefault(),this.openMobileActionsMenu(c)};let A=t.createEl("button",{cls:"stashpad-mobile-action-btn stashpad-open-link-btn"});Fe(A,"link","\u{1F517}"),A.title="Open a Stashpad link (paste a deep link / URL)",A.onclick=h=>{h.preventDefault(),this.plugin.openDeepLinkModal()}}openMobileActionsMenu(e){let t=new b.Menu,i=this.selection.size>0||this.cursorIdx>=0&&!!this.currentChildren[this.cursorIdx],s=this.selection.size<=1;t.addItem(o=>o.setTitle("Undo").setIcon("undo").onClick(()=>this.cmdUndo())),t.addItem(o=>o.setTitle("Redo").setIcon("redo").onClick(()=>this.cmdRedo())),t.addSeparator(),t.addItem(o=>o.setTitle("Notification history\u2026").setIcon("bell").onClick(()=>{this.app.commands?.executeCommandById?.("stashpad:stashpad-open-notification-history")})),t.addItem(o=>o.setTitle("Reload without saving").setIcon("rotate-ccw").onClick(()=>this.plugin.reloadAppForUpdate())),t.addItem(o=>o.setTitle("Open Stashpad link\u2026").setIcon("link").onClick(()=>this.plugin.openDeepLinkModal())),t.addSeparator(),t.addItem(o=>o.setTitle("Expand all").setIcon("unfold-vertical").onClick(()=>this.cmdExpandAll())),t.addItem(o=>o.setTitle("Collapse all").setIcon("fold-vertical").onClick(()=>this.cmdCollapseAll())),t.addSeparator(),t.addItem(o=>o.setTitle("Open in new Stashpad tab").setIcon("list-tree").setDisabled(!i).onClick(()=>this.cmdOpenInNewStashpadTab())),t.addItem(o=>o.setTitle("Open in editor").setIcon("pencil").setDisabled(!i).onClick(()=>this.cmdOpenInEditor())),t.addSeparator(),t.addItem(o=>o.setTitle("Move\u2026").setIcon("arrow-right-circle").setDisabled(!i).onClick(()=>this.cmdMovePicker())),t.addItem(o=>o.setTitle("Nest under\u2026 (in-list)").setIcon("indent").setDisabled(!i).onClick(()=>this.cmdInListPicker())),t.addItem(o=>o.setTitle("Outdent").setIcon("outdent").setDisabled(!i).onClick(()=>void this.cmdOutdent())),t.addItem(o=>o.setTitle("Set color\u2026").setIcon("palette").setDisabled(!i).onClick(()=>this.cmdSetColor())),t.addItem(o=>o.setTitle("Toggle complete").setIcon("check-circle").setDisabled(!i).onClick(()=>void this.cmdToggleComplete())),t.addItem(o=>o.setTitle("Toggle task (todo)").setIcon("check-square").setDisabled(!i).onClick(()=>void this.cmdToggleTask())),t.addItem(o=>o.setTitle("Set due date\u2026").setIcon("calendar-clock").setDisabled(!i).onClick(()=>this.cmdSetDue())),t.addItem(o=>o.setTitle("Assign to\u2026").setIcon("user-plus").setDisabled(!i).onClick(()=>this.cmdAssign())),t.addSeparator(),t.addItem(o=>o.setTitle("Copy").setIcon("copy").setDisabled(!i).onClick(()=>void this.cmdCopy())),t.addItem(o=>o.setTitle("Copy tree").setIcon("copy-plus").setDisabled(!i).onClick(()=>void this.cmdCopyTree())),t.addItem(o=>o.setTitle("Clone (duplicate / copy)").setIcon("files").setDisabled(!i).onClick(()=>void this.cmdClone())),this.addShareExportSubmenu(t,this.getActionTargets()[0]??null,{normalizeToNode:!1}),this.plugin.settings.enableSheetVersions&&(t.addItem(o=>o.setTitle("Fork as a version (draft)").setIcon("git-fork").setDisabled(!i||!s).onClick(()=>void this.cmdForkVersion())),t.addItem(o=>o.setTitle("Mark version as final").setIcon("star").setDisabled(!i||!s).onClick(()=>void this.cmdMarkVersionFinal()))),t.addItem(o=>o.setTitle("Insert template\u2026").setIcon("file-plus-2").onClick(()=>this.cmdInsertTemplate())),t.addItem(o=>o.setTitle("Merge").setIcon("merge").setDisabled(this.selection.size<2).onClick(()=>void this.cmdMerge())),t.addItem(o=>o.setTitle("Split note\u2026").setIcon("scissors").setDisabled(!i||!s).onClick(()=>void this.cmdSplit())),t.addSeparator(),t.addItem(o=>o.setTitle("Delete").setIcon("trash-2").setDisabled(!i).onClick(()=>void this.cmdDelete())),t.addSeparator(),t.addItem(o=>o.setTitle("More commands\u2026").setIcon("terminal").onClick(()=>this.openCommandPalette()));let n=e.getBoundingClientRect();t.showAtPosition({x:n.left,y:n.bottom+4})}openCommandPalette(){this.app.commands?.executeCommandById?.("command-palette:open")}openStashpadCommandPalette(){new pn(this.app).open()}tagFilterLabel(){return this.tagFilter===Ht?"Tagged":this.tagFilter===Rt?"Untagged":this.tagFilter?`#${this.formatTagLabel(this.tagFilter)}`:this.collectFolderTags().length===0?"No tags":"All tags"}renderTagFilterDropdown(e){let t=this.collectFolderTags(),i=e.createDiv({cls:"stashpad-tag-filter-btn"});i.setAttribute("role","button"),i.setAttribute("tabindex","0");let s=i.createSpan({cls:"stashpad-tag-filter-btn-icon"});Fe(s,"tag","#"),i.createSpan({cls:"stashpad-tag-filter-label",text:this.tagFilterLabel()}),t.length===0&&!this.tagFilter&&i.addClass("is-disabled");let n=o=>{o.preventDefault(),!(t.length===0&&!this.tagFilter)&&this.openTagFilterMenu(i)};i.onclick=n,i.onkeydown=o=>{(o.key==="Enter"||o.key===" ")&&n(o)}}openTagFilterMenu(e){let t=e.ownerDocument??document;t.querySelectorAll(".stashpad-tag-filter-popover").forEach(Q=>Q.remove());let i=t.body.createDiv({cls:"stashpad-tag-filter-popover"}),s=e.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 b.Scope(this.app.scope),o=()=>{i.remove(),t.removeEventListener("mousedown",r,!0);try{this.app.keymap?.popScope(n)}catch{}},r=Q=>{!i.contains(Q.target)&&Q.target!==e&&!e.contains(Q.target)&&o()},l=i.createDiv({cls:"stashpad-tag-filter-search"}),c=l.createSpan({cls:"stashpad-tag-filter-search-icon"});Fe(c,"search","\u2315");let A=l.createEl("input",{type:"text",cls:"stashpad-tag-filter-input",attr:{placeholder:"Filter tags\u2026"}}),h=l.createSpan({cls:"stashpad-tag-filter-clear",attr:{"aria-label":"Clear"}});Fe(h,"x","\xD7"),h.setCssStyles({display:"none"});let p=i.createDiv({cls:"stashpad-tag-filter-list"}),u=this.collectFolderTags(),f=[],g=0,I=Q=>{this.setTagFilter(Q),o()},m=Q=>{if(f.length===0){g=0;return}g=(Q+f.length)%f.length,f.forEach((y,E)=>y.el.toggleClass("is-highlighted",E===g)),f[g].el.scrollIntoView({block:"nearest"})},B=(Q,y,E,w)=>{let v=p.createDiv({cls:"stashpad-tag-filter-row"});w&&v.addClass("is-active"),v.createSpan({cls:"stashpad-tag-filter-row-label",text:Q}),typeof E=="number"&&v.createSpan({cls:"stashpad-tag-filter-row-count",text:String(E)});let F=f.length;f.push({value:y,el:v}),v.onmousedown=D=>{D.preventDefault(),I(y)},v.onmouseenter=()=>m(F)},C=()=>{let Q=A.value;h.setCssStyles({display:Q?"":"none"}),p.empty(),f=[];let y=this.tagFilter?.toLowerCase();if(Q.trim()){let E=Tr(Q,u);if(E.length===0)p.createDiv({cls:"stashpad-tag-filter-empty",text:"No matching tags"});else for(let w of E)B(`#${w.label}`,w.raw,w.count,y===w.raw.toLowerCase())}else{B("All tags",null,void 0,!this.tagFilter),B("Tagged",Ht,void 0,this.tagFilter===Ht),B("Untagged",Rt,void 0,this.tagFilter===Rt);for(let E of u)B(`#${E.label}`,E.raw,E.count,y===E.raw.toLowerCase())}m(0)};h.onclick=()=>{A.value="",C(),A.focus()},A.addEventListener("input",C),A.addEventListener("keydown",Q=>{Q.key==="ArrowDown"?(Q.preventDefault(),m(g+1)):Q.key==="ArrowUp"?(Q.preventDefault(),m(g-1)):Q.key==="Enter"&&(Q.preventDefault(),f[g]&&I(f[g].value))}),n.register([],"Escape",Q=>(Q.preventDefault(),o(),!1)),this.app.keymap?.pushScope(n),C(),setTimeout(()=>{t.addEventListener("mousedown",r,!0),A.focus()},0)}renderColorFilterDropdown(e){let t=this.collectFolderColors(),i=e.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 l=this.colorFilter.toLowerCase();o.setCssStyles({background:l});let c=this.plugin.getColorAlias(this.noteFolder,l);r.setText(c??l)}else t.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(),!(t.length===0&&!this.colorFilter)&&this.openColorFilterMenu(i,t)};i.onclick=n,i.onkeydown=o=>{(o.key==="Enter"||o.key===" ")&&n(o)}}openColorFilterMenu(e,t){let i=e.ownerDocument??document;i.querySelectorAll(".stashpad-color-filter-popover").forEach(c=>c.remove());let s=i.body.createDiv({cls:"stashpad-color-filter-popover"}),n=e.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 b.Scope(this.app.scope),r=()=>{s.remove(),i.removeEventListener("mousedown",l,!0);try{this.app.keymap?.popScope(o)}catch{}},l=c=>{!s.contains(c.target)&&c.target!==e&&!e.contains(c.target)&&r()};o.register([],"Escape",c=>(c.preventDefault(),r(),!1)),this.app.keymap?.pushScope(o),this.populateColorMenuBody(s,t,r),setTimeout(()=>{i.addEventListener("mousedown",l,!0)},0)}renderSortDropdown(e){let t=this.noteFolder,i=this.focusId,s=this.sortStore.getMode(t,i),n=this.currentViewMode(),o=n!=="nested",r=e.createDiv({cls:"stashpad-sort-btn"});r.setAttribute("role","button"),r.setAttribute("tabindex",o?"-1":"0"),o&&r.addClass("is-disabled");let l=r.createSpan({cls:"stashpad-sort-icon"});(0,b.setIcon)(l,"arrow-up-down");let c=r.createSpan({cls:"stashpad-sort-label"});o?(c.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.`):(c.setText(mi[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: ${mi[s]}. Drag-reorder will revert this parent to Manual.`);let A=h=>{o||(h.preventDefault(),this.openSortMenu(r))};r.onclick=A,r.onkeydown=h=>{o||(h.key==="Enter"||h.key===" ")&&A(h)}}openSortMenu(e){let t=e.ownerDocument??document;t.querySelectorAll(".stashpad-sort-popover").forEach(l=>l.remove());let i=t.body.createDiv({cls:"stashpad-sort-popover"}),s=e.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(),t.removeEventListener("mousedown",o,!0);try{this.app.keymap?.popScope(r)}catch{}},o=l=>{!i.contains(l.target)&&l.target!==e&&!e.contains(l.target)&&n()};this.populateSortMenuBody(i,n);let r=new b.Scope(this.app.scope);r.register([],"Escape",l=>(l.preventDefault(),n(),!1)),this.app.keymap?.pushScope(r),setTimeout(()=>{t.addEventListener("mousedown",o,!0)},0)}renderMobileFiltersButton(e){let t=e.createDiv({cls:"stashpad-mobile-filters-btn"});t.setAttribute("role","button"),t.setAttribute("tabindex","0");let i=t.createSpan({cls:"stashpad-mobile-filters-icon"});(0,b.setIcon)(i,"sliders-horizontal"),t.title="Filters / view options";let s=!!this.tagFilter,n=!!this.colorFilter,o=this.timeFilter!=="all",r=this.sortStore.getMode(this.noteFolder,this.focusId)!=="manual",l=this.currentViewMode()!=="nested"||this.currentHideChildless()||this.currentHideCompleted()||this.currentAttachmentsOnly()||this.currentIncludeAttachments();(s||n||o||r||l)&&t.addClass("is-active");let c=A=>{A.preventDefault(),this.openMobileFiltersMenu(t)};t.onclick=c,t.onkeydown=A=>{(A.key==="Enter"||A.key===" ")&&c(A)}}openMobileFiltersMenu(e){let t=e.ownerDocument??document;t.querySelectorAll(".stashpad-mobile-filters-popover").forEach(u=>u.remove());let i=t.body.createDiv({cls:"stashpad-mobile-filters-popover"}),s=e.getBoundingClientRect(),n=t.defaultView??window,o=s.bottom+280>n.innerHeight;i.setCssStyles({right:`${Math.max(8,n.innerWidth-s.right)}px`,left:"auto",...o?{bottom:`${Math.max(8,n.innerHeight-s.top+4)}px`,top:"auto"}:{top:`${s.bottom+4}px`,bottom:"auto"},maxWidth:"min(360px, calc(100vw - 16px))",maxHeight:"min(60vh, 420px)",overflowY:"auto",width:"max-content",minWidth:"260px"});let r=()=>{i.remove(),t.removeEventListener("mousedown",l,!0);try{this.app.keymap?.popScope(p)}catch{}},l=u=>{!i.contains(u.target)&&u.target!==e&&!e.contains(u.target)&&r()},c=[{key:"tag",title:"Tag filter",summary:()=>this.tagFilter?`#${this.tagFilter}`:"All tags",populate:u=>this.populateTagMenuBody(u,r)},{key:"color",title:"Color filter",summary:()=>this.colorFilter?this.plugin.getColorAlias(this.noteFolder,this.colorFilter)??this.colorFilter:"All colors",populate:u=>this.populateColorMenuBody(u,this.collectFolderColors(),r)},{key:"time",title:"Time filter",summary:()=>{let u=us.find(f=>f.key===this.timeFilter);return u?this.timeFilterCalendar?u.calShort:u.rollShort:"All"},populate:u=>this.populateTimeMenuBody(u,r)},{key:"sort",title:"Sort",summary:()=>this.currentViewMode()!=="nested"?"\u2014 (Nested only)":mi[this.sortStore.getMode(this.noteFolder,this.focusId)],populate:u=>{if(this.currentViewMode()!=="nested"){u.createDiv({cls:"stashpad-mobile-filters-note",text:"Sort applies only in Nested view."});return}this.populateSortMenuBody(u,r)}},{key:"view",title:"View",summary:()=>gs[this.currentViewMode()],populate:u=>this.populateViewMenuBody(u,r)}],A="",h=()=>{i.empty();for(let u of c){let f=i.createDiv({cls:"stashpad-mobile-filters-section"}),g=f.createDiv({cls:"stashpad-mobile-filters-header"}),I=g.createSpan({cls:"stashpad-mobile-filters-chev"});if((0,b.setIcon)(I,A===u.key?"chevron-down":"chevron-right"),g.createSpan({cls:"stashpad-mobile-filters-title",text:u.title}),g.createSpan({cls:"stashpad-mobile-filters-summary",text:u.summary()}),g.onclick=m=>{m.preventDefault(),m.stopPropagation(),A=A===u.key?"":u.key,h()},A===u.key){let m=f.createDiv({cls:"stashpad-mobile-filters-body"});u.populate(m)}}};h();let p=new b.Scope(this.app.scope);p.register([],"Escape",u=>(u.preventDefault(),r(),!1)),this.app.keymap?.pushScope(p),setTimeout(()=>{t.addEventListener("mousedown",l,!0)},0)}renderViewDropdown(e){let t=this.currentViewMode(),i=e.createDiv({cls:"stashpad-view-btn"});i.setAttribute("role","button"),i.setAttribute("tabindex","0");let s=i.createSpan({cls:"stashpad-view-icon"});(0,b.setIcon)(s,t==="flat"?"list":t==="everything"?"layout-grid":"list-tree"),i.createSpan({cls:"stashpad-view-label"}).setText(gs[t]),(t!=="nested"||this.currentEncryptionFilter()!=="all")&&i.addClass("is-active"),i.title=t==="nested"?"View: Nested (the default). Click to switch to Flat or Everything.":t==="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(e){let t=e.ownerDocument??document;t.querySelectorAll(".stashpad-view-popover").forEach(l=>l.remove());let i=t.body.createDiv({cls:"stashpad-view-popover"});b.Platform.isMobile&&i.addClass("is-mobile");let s=e.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(),t.removeEventListener("mousedown",o,!0);try{this.app.keymap?.popScope(r)}catch{}},o=l=>{!i.contains(l.target)&&l.target!==e&&!e.contains(l.target)&&n()};this.populateViewMenuBody(i,n);let r=new b.Scope(this.app.scope);r.register([],"Escape",l=>(l.preventDefault(),n(),!1)),this.app.keymap?.pushScope(r),setTimeout(()=>{t.addEventListener("mousedown",o,!0)},0)}populateViewMenuBody(e,t){let i=this.currentViewMode(),s=(y,E,w)=>{let v=e.createDiv({cls:"stashpad-view-popover-row"});y===i&&v.addClass("is-active");let F=v.createDiv({cls:"stashpad-view-popover-main"});(0,b.setIcon)(F.createSpan({cls:"stashpad-view-popover-icon"}),w),F.createSpan({cls:"stashpad-view-popover-label",text:gs[y]}),v.createDiv({cls:"stashpad-view-popover-desc",text:E}),v.onclick=async D=>{D.preventDefault(),D.stopPropagation(),t(),y!==i&&(await this.setViewMode(y),this.render())}};if(s("nested","Tree of immediate children (default).","list-tree"),e.createDiv({cls:"stashpad-view-popover-divider"}),s("flat","All descendants of the current focus, flat by sort.","list"),e.createDiv({cls:"stashpad-view-popover-divider"}),s("everything","All descendants PLUS non-Stashpad files in the folder.","layout-grid"),e.createDiv({cls:"stashpad-view-popover-divider"}),this.plugin.encryption?.isConfigured?.()){let y=this.currentEncryptionFilter(),E=(w,v,F)=>{let D=e.createDiv({cls:"stashpad-view-popover-row"});w===y&&D.addClass("is-active"),D.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:v}),D.createDiv({cls:"stashpad-view-popover-desc",text:F}),D.onclick=async R=>{R.preventDefault(),R.stopPropagation(),w!==y&&(await this.setEncryptionFilter(w),this.refreshList()),t()}};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."),e.createDiv({cls:"stashpad-view-popover-divider"})}let n=e.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 y=>{y.target!==o&&(y.preventDefault(),o.checked=!o.checked),await this.setHideChildless(o.checked),this.refreshList()};let r=e.createDiv({cls:"stashpad-view-popover-row stashpad-view-popover-toggle"}),l=r.createEl("input",{type:"checkbox"});l.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 y=>{y.target!==l&&(y.preventDefault(),l.checked=!l.checked),await this.setHideCompleted(l.checked),this.refreshList()};let c=e.createDiv({cls:"stashpad-view-popover-row stashpad-view-popover-toggle"}),A=c.createEl("input",{type:"checkbox"});A.checked=this.currentAttachmentsOnly(),c.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:"Hide notes without attachments"}),c.createDiv({cls:"stashpad-view-popover-desc",text:"Show only notes that have an attachment. A parent stays visible while any descendant has one."}),c.onclick=async y=>{y.target!==A&&(y.preventDefault(),A.checked=!A.checked),await this.setAttachmentsOnly(A.checked),this.refreshList()},e.createDiv({cls:"stashpad-view-popover-divider"});let h=e.createDiv({cls:"stashpad-view-popover-row stashpad-view-popover-toggle"});i!=="everything"&&h.addClass("is-disabled");let p=h.createEl("input",{type:"checkbox"});p.checked=this.currentIncludeAttachments(),p.disabled=i!=="everything",h.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:"Include attachments"}),h.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."}),h.onclick=async y=>{i==="everything"&&(y.target!==p&&(y.preventDefault(),p.checked=!p.checked),await this.setIncludeAttachments(p.checked),this.refreshList())},e.createDiv({cls:"stashpad-view-popover-divider"});let u=e.createDiv({cls:"stashpad-view-popover-row stashpad-view-popover-toggle"}),f=u.createEl("input",{type:"checkbox"});f.checked=this.importedOnly,u.createDiv({cls:"stashpad-view-popover-main"}).createSpan({cls:"stashpad-view-popover-label",text:"Imported notes only"}),u.createDiv({cls:"stashpad-view-popover-desc",text:"Show only notes that came in via import."}),u.onclick=y=>{y.target!==f&&(y.preventDefault(),f.checked=!f.checked),this.importedOnly=f.checked,this.reconcileSelectionAfterFilter(),this.refreshList()};let g=new Map,I=this.noteFolder.replace(/\/+$/,"");for(let y of this.app.vault.getMarkdownFiles()){if((y.parent?.path?.replace(/\/+$/,"")??"")!==I)continue;let E=at(this.app.metadataCache.getFileCache(y)?.frontmatter?.author);E&&g.set(E.id,E.name)}e.createDiv({cls:"stashpad-view-popover-divider"});let m=e.createDiv({cls:"stashpad-view-popover-row"}),B=m.createDiv({cls:"stashpad-view-popover-main"});(0,b.setIcon)(B.createSpan({cls:"stashpad-view-popover-icon"}),"user"),B.createSpan({cls:"stashpad-view-popover-label",text:"By author"});let C=B.createEl("select",{cls:"stashpad-view-author-select"}),Q=C.createEl("option",{text:"All authors",value:""});this.authorFilter||(Q.selected=!0);for(let[y,E]of[...g.entries()].sort((w,v)=>w[1].localeCompare(v[1]))){let w=C.createEl("option",{text:E,value:y});this.authorFilter===y&&(w.selected=!0)}C.onclick=y=>y.stopPropagation(),C.onchange=()=>{this.authorFilter=C.value||null,this.reconcileSelectionAfterFilter(),this.refreshList()},m.createDiv({cls:"stashpad-view-popover-desc",text:g.size?"Show only notes by the chosen author.":"No authored notes in this folder yet."})}setTagFilter(e){(this.tagFilter??null)!==(e??null)&&(this.tagFilter=e,this.reconcileSelectionAfterFilter(),this.persistFocus(),this.render())}populateSortMenuBody(e,t){let i=this.noteFolder,s=this.focusId,n=this.sortStore.getMode(i,s);for(let o of Uo){let r=e.createDiv({cls:"stashpad-sort-popover-row"});o===n&&r.addClass("is-active"),r.createSpan({cls:"stashpad-sort-popover-label",text:mi[o]}),r.onclick=async l=>{l.preventDefault(),l.stopPropagation(),t(),o!==n&&(this.sortStore.setMode(i,s,o),await this.sortStore.save(i),this.tree.rebuild(i),this.render())}}}populateTimeMenuBody(e,t){let i=e.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 us){let o=e.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=l=>{l.preventDefault(),l.stopPropagation(),t(),this.timeFilter!==n.key&&this.setTimeFilter(n.key)}}}populateColorMenuBody(e,t,i){let s=(n,o,r)=>{let l=e.createDiv({cls:"stashpad-color-filter-popover-row"}),c=l.createSpan({cls:"stashpad-color-filter-swatch"});o?c.setCssStyles({background:o}):c.addClass("is-empty");let A=l.createSpan({cls:"stashpad-color-filter-popover-label"});A.setText(n),o&&(A.style.color=o),l.onclick=h=>{h.preventDefault(),h.stopPropagation(),r(),i()}};s("All colors",null,()=>this.setColorFilter(null));for(let n of t){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(e,t){let i=this.collectFolderTags(),s=(n,o)=>{let r=e.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=A=>{A.preventDefault(),A.stopPropagation(),this.setTagFilter(o),t()}};s(i.length===0?"No tags":"All tags",null),s("Tagged",Ht),s("Untagged",Rt);for(let n of i)s(`${n.label} (${n.count})`,n.raw)}setColorFilter(e){let t=e?e.toLowerCase():null;(this.colorFilter??null)!==t&&(this.colorFilter=t,this.reconcileSelectionAfterFilter(),this.persistFocus(),this.render())}setTimeFilter(e){this.timeFilter!==e&&(this.timeFilter=e,this.reconcileSelectionAfterFilter(),this.persistFocus(),this.render())}reconcileSelectionAfterFilter(){let e=this.filterChildren(this.collectViewItems(this.focusId)),t=new Set(e.map(i=>i.id));for(let i of[...this.selection])t.has(i)||this.selection.delete(i);if(this.firstSelectedId&&!t.has(this.firstSelectedId)&&(this.firstSelectedId=null),this.lastSelected&&!t.has(this.lastSelected)&&(this.lastSelected=null),this.selection.size>0){let i=e.findIndex(s=>this.selection.has(s.id));this.cursorIdx=i>=0?i:Math.min(this.cursorIdx,e.length-1)}else this.cursorIdx>=e.length&&(this.cursorIdx=e.length-1)}renderTinyHeader(e){let t=e.createDiv({cls:"stashpad-tiny-header"}),i=t.createEl("button",{cls:"stashpad-tiny-nav-btn"});Fe(i,"arrow-left","\u2039"),i.title="Back (up to parent)",this.navBackStack.length>0||this.focusId!==k||i.addClass("is-disabled"),i.title=this.navBackStack.length>0?"Back":this.focusId!==k?"Back (up to parent)":"No back history",i.onclick=()=>this.navigateBack();let n=t.createEl("button",{cls:"stashpad-tiny-nav-btn"});Fe(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(),l=this.focusId===k?r:`${r} / ${this.titleForNode(o).trim()}`,c=t.createEl("button",{cls:"stashpad-tiny-title stashpad-folder-btn"}),A=c.createSpan({cls:"stashpad-tiny-title-icon stashpad-btn-icon"});(0,b.setIcon)(A,"folder"),c.createSpan({cls:"stashpad-tiny-title-text stashpad-btn-text",text:l}),c.title=`${this.noteFolder}${this.focusId!==k?` / ${this.titleForNode(o).trim()}`:""} +Click to switch / create folder.`,c.onclick=g=>{g.preventDefault(),this.plugin.openFolderPicker()};let h=t.createDiv({cls:"stashpad-tiny-sticky"}),p=h.createEl("input",{type:"checkbox"});if(p.checked=this.tinyAlwaysOnTop,h.createSpan({text:"Sticky"}),p.onchange=()=>{this.tinyAlwaysOnTop=p.checked,this.applyTinyAlwaysOnTop()},!b.Platform.isMobile){let g=t.createEl("button",{cls:"stashpad-tiny-nav-btn stashpad-tiny-opacity-btn"});(0,b.setIcon)(g,"contrast"),g.title="Window transparency",this.tinyOpacity<1&&g.addClass("is-active"),g.onclick=I=>{I.stopPropagation(),this.toggleTinyOpacityPopover(g)}}let u=t.createEl("button",{cls:"stashpad-tiny-expand stashpad-tiny-exit-compact"});(0,b.setIcon)(u,this.compactMode?"panel-top":"rows-2"),u.title=this.compactMode?"Compact mode is ON \u2014 click to turn off.":"Compact mode \u2014 click to turn on (strips row metadata).",this.compactMode&&u.addClass("is-active"),u.onclick=()=>{this.toggleCompactMode()};let f=t.createEl("button",{cls:"stashpad-tiny-expand"});(0,b.setIcon)(f,"maximize-2"),f.title="Exit tiny mode",f.onclick=()=>{this.exitTinyMode()}}toggleTinyOpacityPopover(e){if(this.tinyOpacityPopover){this.tinyOpacityPopover.remove(),this.tinyOpacityPopover=null;return}let t=document.createElement("div");t.className="stashpad-tiny-opacity-popover",t.createSpan({cls:"stashpad-tiny-opacity-label",text:"Transparency"});let i=t.createEl("input",{type:"range"});i.min="30",i.max="100",i.step="1",i.value=String(Math.round(this.tinyOpacity*100));let s=t.createSpan({cls:"stashpad-tiny-opacity-pct",text:`${i.value}%`});i.addEventListener("input",()=>{let A=Math.min(100,Math.max(30,parseInt(i.value,10)||100));this.tinyOpacity=A/100,s.setText(`${A}%`),this.applyTinyOpacity(),e.toggleClass("is-active",this.tinyOpacity<1)}),i.addEventListener("change",()=>{this.app.workspace.requestSaveLayout()}),this.viewRoot.appendChild(t);let n=e.getBoundingClientRect(),o=this.viewRoot.getBoundingClientRect();t.setCssStyles({top:`${n.bottom-o.top+4}px`,left:`${Math.max(4,Math.min(n.left-o.left,o.width-180))}px`});let r=A=>{t.contains(A.target)||A.target===e||e.contains(A.target)||c()},l=A=>{A.key==="Escape"&&c()},c=()=>{t.remove(),this.tinyOpacityPopover=null,this.tinyOpacityClose=null,document.removeEventListener("mousedown",r,!0),document.removeEventListener("keydown",l,!0)};setTimeout(()=>{document.addEventListener("mousedown",r,!0),document.addEventListener("keydown",l,!0)},0),this.tinyOpacityPopover=t,this.tinyOpacityClose=c,i.focus()}getOwnElectronWindow(){try{let e=this.containerEl?.ownerDocument?.defaultView??window,s=((e?.require?.("electron")??window.require?.("electron"))?.remote??e?.electron?.remote??e?.["@electron/remote"])?.getCurrentWindow?.()??e?.electronWindow??null;if(!s)try{let n=window.require?.("electron"),o=n?.remote??n?.["@electron/remote"],l=(o?.BrowserWindow??n?.BrowserWindow)?.getAllWindows?.()??[];l.length===1?s=l[0]:l.length>1&&(s=o?.getFocusedWindow?.()??null??l[l.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(e){return console.debug("[Stashpad] resolve own electron window failed",e),null}}applyTinyAlwaysOnTop(){let e=this.getOwnElectronWindow();if(e)try{e.setAlwaysOnTop?.(!!this.tinyAlwaysOnTop)}catch(t){console.debug("[Stashpad] setAlwaysOnTop failed",t)}}applyTinyOpacity(){let e=this.getOwnElectronWindow();if(!e)return;let t=Math.min(1,Math.max(.3,this.tinyOpacity));try{e.setOpacity?.(t)}catch(i){console.debug("[Stashpad] setOpacity failed",i)}}applyTinyWindow(){let e=this.getOwnElectronWindow();if(e)try{if(this.tinyMode){e.setMinimumSize?.(220,260);let s=100,n=100;try{let o=e.getBounds?.();o&&typeof o.x=="number"&&(s=o.x,n=o.y)}catch{}try{e.setBounds?.({x:s,y:n,width:280,height:360})}catch{}try{e.setSize?.(280,360)}catch{}e.setAlwaysOnTop?.(!!this.tinyAlwaysOnTop);try{e.setOpacity?.(Math.min(1,Math.max(.3,this.tinyOpacity)))}catch{}}else e.setAlwaysOnTop?.(!1)}catch(t){console.debug("[Stashpad] tiny window apply failed",t)}}async exitTinyMode(){this.tinyMode=!1,this.tinyAlwaysOnTop=!1,this.tinyOpacity=1;try{this.getOwnElectronWindow()?.setOpacity?.(1)}catch{}this.compactMode=!1,this.applyTinyWindow();let e=this.getOwnElectronWindow();try{if(e?.setMinimumSize?.(400,300),b.Platform.isMacOS??!1){let i=this.containerEl?.ownerDocument?.defaultView?.require?.("electron")??window.require?.("electron"),n=(i?.remote?.screen??i?.screen)?.getPrimaryDisplay?.().workArea;n?e?.setBounds?.({x:n.x,y:n.y,width:n.width,height:n.height}):e?.maximize?.()}else e?.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(e){let t=e.createDiv({cls:"stashpad-breadcrumb"});b.Platform.isMobile||this.renderActionsCluster(t);let i=t.createSpan({cls:"stashpad-crumb stashpad-crumb-home"});if(b.Platform.isMobile?((0,b.setIcon)(i,"home"),i.title="Home"):i.setText("Home"),i.onclick=()=>this.navigateTo(k),this.focusId===k){let c=this.tree.getChildren(this.focusId).length;if(c>0&&(t.createSpan({cls:"stashpad-crumb-count",text:`\xB7 ${c}`}).title=`${c} direct child${c===1?"":"ren"}`),this.compactMode){let A=t.createEl("button",{cls:"stashpad-compact-exit-btn"});(0,b.setIcon)(A,"panel-top"),A.title="Exit compact mode",A.onclick=h=>{h.preventDefault(),this.toggleCompactMode()}}return}let s=28,n=this.tree.pathTo(this.focusId);this.warmCrumbTitles(n);let o=n.map(c=>{let A=this.titleForNode(c),h=A.length>s?A.slice(0,s-1)+"\u2026":A;return{id:c.id,label:h}}),r=b.Platform.isMobile?"/":" / ";for(let c of o)if(t.createSpan({cls:"stashpad-crumb-sep",text:r}),c.isEllipsis)t.createSpan({cls:"stashpad-crumb stashpad-crumb-ellipsis",text:c.label}).title=n.map(A=>this.titleForNode(A)).join(" / ");else{let A=c.id,h=t.createSpan({cls:"stashpad-crumb",text:c.label});h.title=c.label,h.onclick=()=>this.navigateTo(A),h.oncontextmenu=p=>{p.preventDefault(),this.openCrumbMenu(p,A)},b.Platform.isMobile&&this.attachLongPress(h,()=>this.openCrumbMenu(null,A))}if(t.querySelector(".stashpad-crumb-home")?.addEventListener("contextmenu",c=>{c.preventDefault(),this.openCrumbMenu(c,k)}),b.Platform.isMobile){let c=t.querySelector(".stashpad-crumb-home");c&&this.attachLongPress(c,()=>this.openCrumbMenu(null,k))}let l=this.tree.getChildren(this.focusId).length;if(l>0&&(t.createSpan({cls:"stashpad-crumb-count",text:`\xB7 ${l}`}).title=`${l} direct child${l===1?"":"ren"}`),this.compactMode){let c=t.createEl("button",{cls:"stashpad-compact-exit-btn"});(0,b.setIcon)(c,"panel-top"),c.title="Exit compact mode",c.onclick=A=>{A.preventDefault(),this.toggleCompactMode()}}b.Platform.isMobile||this.renderBreadcrumbLevelsButton(t)}renderBreadcrumbLevelsButton(e){let t=e.createEl("button",{cls:"stashpad-mobile-action-btn stashpad-crumb-levels-btn"});Fe(t,"route","\u22D4"),t.title="Show all levels \u2014 jump to any level in the path",t.onclick=i=>{i.preventDefault(),this.openBreadcrumbLevelsModal()}}openBreadcrumbLevelsModal(){let e=this.tree.pathTo(this.focusId),t=[{id:k,label:"Home",level:0,isCurrent:this.focusId===k,isHome:!0}];e.forEach((i,s)=>{t.push({id:i.id,label:this.titleForNode(i),level:s+1,isCurrent:i.id===this.focusId})}),new Oi(this.app,t,i=>this.navigateTo(i),{onContext:(i,s,n,o)=>this.openCrumbMenu(s,i,n,o),attachLongPress:(i,s)=>this.attachLongPress(i,s)}).open()}attachLongPress(e,t){let i=null,s=0,n=0,o=()=>{i!=null&&(window.clearTimeout(i),i=null)};e.addEventListener("touchstart",r=>{let l=r.touches[0];s=l?.clientX??0,n=l?.clientY??0,o(),i=window.setTimeout(()=>{i=null,t()},500)},{passive:!0}),e.addEventListener("touchmove",r=>{let l=r.touches[0];l&&(Math.abs(l.clientX-s)>10||Math.abs(l.clientY-n)>10)&&o()},{passive:!0}),e.addEventListener("touchend",o),e.addEventListener("touchcancel",o)}openCrumbMenu(e,t,i,s){let n=this.tree.get(t);if(!n)return;let o=new b.Menu;if(o.addItem(r=>r.setTitle("Navigate here").setIcon("arrow-right-circle").onClick(()=>{s?.(),this.navigateTo(t)})),o.addItem(r=>r.setTitle("Open in new Stashpad tab").setIcon("list-tree").onClick(()=>{s?.(),this.cmdOpenInNewStashpadTab(n)})),n.file&&o.addItem(r=>r.setTitle("Open in editor (new tab)").setIcon("pencil").onClick(()=>{s?.(),this.cmdOpenInEditor(n)})),e&&(e.clientX>0||e.clientY>0))o.showAtMouseEvent(e);else{let l=(i??e?.target??null)?.getBoundingClientRect();o.showAtPosition({x:l?.left??8,y:(l?.bottom??60)+4})}}renderFocusedHeaderMini(e,t){if(!t.file)return;let i=e.createDiv({cls:"stashpad-focused-mini"});i.dataset.id=t.id,i.createDiv({cls:"stashpad-focused-mini-text"}).setText(this.titleForNode(t).trim());let n=i.createEl("button",{cls:"stashpad-pencil stashpad-note-more stashpad-focused-mini-more"});(0,b.setIcon)(n,"more-horizontal"),n.title="Actions",n.onclick=o=>{o.stopPropagation(),this.openNoteMenu(o,t)}}installFocusedMiniObserver(e){let t=e.querySelector(".stashpad-focused"),i=e.querySelector(".stashpad-focused-mini");!t||!i||(this.focusedMiniObserver&&this.focusedMiniObserver.disconnect(),this.focusedMiniObserver=new IntersectionObserver(s=>{for(let n of s)i.toggleClass("is-visible",!n.isIntersecting)},{root:e,threshold:.05}),this.focusedMiniObserver.observe(t))}renderFocusedHeader(e,t){if(!t.file)return;let i=t.file,s=e.createDiv({cls:"stashpad-focused"});s.oncontextmenu=A=>{A.preventDefault(),this.openNoteMenu(A,t)};let 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(t.created)}),o.createDiv({cls:"stashpad-focused-grip-spacer"});let r=s.createDiv({cls:"stashpad-focused-body"});r.addEventListener("click",A=>this.handleRenderedClick(A,t));let l=s.createDiv({cls:"stashpad-focused-actions"}),c;if(b.Platform.isMobile){let A=l.createEl("button",{cls:"stashpad-pencil stashpad-note-more stashpad-focused-more"});(0,b.setIcon)(A,"more-horizontal"),A.title="Actions",A.onclick=h=>{h.stopPropagation(),this.openNoteMenu(h,t)},c=A}else{let A=l.createEl("button",{cls:"stashpad-pencil stashpad-focused-pencil"});(0,b.setIcon)(A,"pencil"),A.title="Edit in new tab",A.onclick=()=>void this.openFileAtEnd(i);let h=l.createEl("button",{cls:"stashpad-pencil stashpad-focused-dup"});(0,b.setIcon)(h,"copy"),h.title="Open this Stashpad in a new tab (clone)",h.onclick=()=>this.cmdOpenInNewStashpadTab(t),c=A}this.renderNoteBody(r,t,{clamp:b.Platform.isMobile,immediate:!0,toggleHost:l,toggleAnchor:c})}renderRowBreadcrumb(e,t){let i=this.tree.pathTo(t.id),s=i.findIndex(r=>r.id===this.focusId),n=i.slice(s+1,i.length-1);if(n.length===0)return;let o=e.createDiv({cls:"stashpad-row-breadcrumb"});n.forEach((r,l)=>{let c=o.createSpan({cls:"stashpad-row-breadcrumb-seg",text:this.titleForNode(r)});c.title=`Focus into "${this.titleForNode(r)}"`,c.onclick=A=>{A.stopPropagation(),this.navigateTo(r.id)},l<n.length-1&&o.createSpan({cls:"stashpad-row-breadcrumb-sep",text:" / "})})}actionsForFile(e){return Os(this.app,e,b.Platform.isMobile)}bulkActionMessage(e){let t=e.nodes.map(r=>`"${this.titleForNode(r).trim()||"(untitled)"}"`),i=e.suffix?` ${e.suffix}`:"",s=e.destination?` ${e.destination}`:"";if(t.length===0)return`${e.verb}${i}${s}`;if(t.length===1)return`${e.verb} ${t[0]}${i}${s}`;let n=e.bulletMax??10,o=t.length<=n?t.map(r=>`\u2022 ${r}`).join(` `):t.slice(0,n).map(r=>`\u2022 ${r}`).join(` `)+` \u2026+ ${t.length-n} more`;return`${e.verb} ${t.length} notes${i}${s}: -${o}`}titleList(e,t=3){if(!e.length)return"";let i=e.map(n=>this.titleForNode(n).trim()||"(untitled)");return i.length<=t?i.map(n=>`"${n}"`).join(", "):`${i.slice(0,t).map(n=>`"${n}"`).join(", ")}, +${i.length-t} more`}titleForNode(e){if(!e.file)return"Untitled";let i=this.app.metadataCache.getFileCache(e.file)?.headings?.[0]?.heading;if(i)return i.trim();let n=this.plugin.renderCacheStore.get(e.file.path)?.text?.slice(0,200).split(/\r?\n/).map(o=>o.trim()).find(Boolean);return n||e.file.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ")||"Untitled"}warmCrumbTitles(e){let t=e.filter(i=>!i.file||this.app.metadataCache.getFileCache(i.file)?.headings?.[0]?.heading?!1:!this.plugin.renderCacheStore.get(i.file.path));t.length&&Promise.all(t.map(i=>this.bodyRenderer.getOrComputeRender(i.file).catch(()=>null))).then(i=>{i.some(s=>s&&s.text&&s.text.trim())&&this.debouncedRender()})}async forceManualMode(e){let t=this.noteFolder;this.sortStore.getMode(t,e)!=="manual"&&(this.sortStore.setMode(t,e,"manual"),await this.sortStore.save(t))}renderNote(e,t,i){if(!t.file||this.currentEncryptionFilter()==="locked")return;let s=t.file,n=this.tree.getChildren(t.id).length,o=this.selection.has(t.id),r=i===this.cursorIdx,l=this.inListPicker?.activeIdx===i,c=e.createDiv({cls:"stashpad-note"});o&&c.addClass("is-selected"),r&&c.addClass("is-cursor"),r&&this.cursorHasMoved&&this.plugin.settings.autoExpandCursorRow&&!this.cursorExpandOverride.has(t.id)&&c.addClass("is-cursor-expanded"),l&&c.addClass("is-pick-target"),this.isCompleted(t)&&c.addClass("is-completed"),this.isListPinned(t.id)&&c.addClass("is-list-pinned"),this.isCutPending(t.id)?c.addClass("is-cut-pending"):this.isCopyPending(t.id)&&c.addClass("is-copy-pending"),c.dataset.idx=String(i),c.dataset.id=t.id;let A=this.currentViewMode()==="nested";c.draggable=A,A&&this.dnd.attachRowDnD(c,t,i),c.addEventListener("click",v=>this.handleRowClick(v,i,t)),c.addEventListener("dblclick",v=>{if(!this.plugin.settings.doubleClickToFocus)return;let E=this.shouldAbsorbDismissTap();if(E&&this.aimedTapTargetId&&Date.now()-this.aimedTapAt<=us.AIMED_TAP_WINDOW_MS){let b=this.aimedTapTargetId;this.aimedTapTargetId=null,this.traceTap("dblclick",v,i,!1),v.preventDefault(),window.getSelection()?.removeAllRanges(),this.navigateTo(b);return}if(this.traceTap("dblclick",v,i,E),E){v.preventDefault();return}v.target?.closest?.(".internal-link, .tag, a, .stashpad-note-task-checkbox")||(v.preventDefault(),window.getSelection()?.removeAllRanges(),this.navigateTo(t.id))});let h=this.isTask(t)||this.compactMode;h&&(c.addClass("is-task"),F.Platform.isMobile||this.addTaskCheckbox(c,t));let g=c.createDiv({cls:"stashpad-note-meta"}),u=g.createDiv({cls:"stashpad-note-meta-top"});u.createSpan({cls:"stashpad-note-time",text:this.formatTime(t.created)});let f=this.colorForNode(t),p=u.createDiv({cls:"stashpad-note-grip"});f&&p.addClass("has-color"),(0,F.setIcon)(p,"grip-vertical"),p.title=f?"Drag to reorder \xB7 right-click to change color":"Drag to reorder",p.draggable=A,A||(p.title=f?"Right-click to change color \xB7 drag disabled in this view mode":"Drag disabled in this view mode"),f&&p.style.setProperty("--stashpad-note-color",f);let I=h&&F.Platform.isMobile,m=this.isListPinned(t.id);if(n>0||I||m){let v=g.createDiv({cls:"stashpad-note-meta-bottom"});if(m){let E=v.createSpan({cls:"stashpad-note-listpin"});(0,F.setIcon)(E,"pin"),E.setAttr("aria-label","Pinned to top of list")}if(I&&this.addTaskCheckbox(v,t),n>0){let E=v.createSpan({cls:"stashpad-note-enter"});f&&(E.style.color=f),(0,F.setIcon)(E.createSpan({cls:"stashpad-btn-icon"}),"corner-down-right"),E.createSpan({text:` ${n}`}),E.onclick=Q=>{Q.stopPropagation(),this.navigateTo(t.id)}}}if(f)c.addClass("has-color"),c.style.setProperty("--stashpad-note-color",f);else{let v=this.inheritedColorForNode(t);v&&v.depth>0&&(c.addClass("has-inherited-color"),c.style.setProperty("--stashpad-inherited-color",v.hex),c.style.setProperty("--stashpad-inherited-depth",String(v.depth)))}let B=c.createDiv({cls:"stashpad-note-body"});this.currentViewMode()!=="nested"&&this.renderRowBreadcrumb(B,t);let C=B.createDiv({cls:"stashpad-note-body-content"}),w=c.createDiv({cls:"stashpad-note-actions"}),y;if(F.Platform.isMobile){let v=w.createEl("button",{cls:"stashpad-pencil stashpad-note-more"});(0,F.setIcon)(v,"ellipsis-vertical"),v.title="Actions",v.onclick=E=>{E.stopPropagation(),this.openNoteMenu(E,t)},y=v}else{let v=w.createEl("button",{cls:"stashpad-pencil"});(0,F.setIcon)(v,"pencil"),v.title="Edit in new tab",v.onclick=b=>{b.stopPropagation(),this.openFileAtEnd(s)};let E=w.createEl("button",{cls:"stashpad-pencil stashpad-enter-btn"});(0,F.setIcon)(E,"arrow-right"),E.title="Open in Stashpad view",E.onclick=b=>{b.stopPropagation(),this.navigateTo(t.id)};let Q=w.createEl("button",{cls:"stashpad-pencil stashpad-note-more"});(0,F.setIcon)(Q,"ellipsis-vertical"),Q.title="More actions",Q.onclick=b=>{b.stopPropagation(),this.openNoteMenu(b,t)},y=v}this.renderNoteBody(C,t,{clamp:!0,toggleHost:w,toggleAnchor:y}),this.renderVersionTabs(B,t),c.oncontextmenu=v=>{v.preventDefault(),this.openNoteMenu(v,t)}}renderVersionTabs(e,t){if(!this.plugin.settings.enableSheetVersions||!xi(ye(this.app,t)))return;let i=Ye(ye(this.app,t)),s=t.parent??this.focusId,n=this.tree.getChildren(s),o=Xn(this.app,n.filter(c=>{let A=ye(this.app,c);return xi(A)&&Ye(A)===i}));if(o.length<2)return;let r=e.createDiv({cls:"stashpad-version-tabs"});for(let c of o){let A=c.id===t.id,h=ye(this.app,c),g=Ni(h),u=fr(h),f=r.createDiv({cls:"stashpad-version-tab"+(A?" is-active":"")+(g?" is-final":"")+(u?" is-original":"")});g&&f.createSpan({cls:"stashpad-version-star",text:"\u2605"}),f.createSpan({cls:"stashpad-version-tab-label",text:Br(this.app,c,this.titleForNode(c).trim()||"Untitled")});let p=this.titleForNode(c).trim();f.title=u?`${p} (original)`:`${p} (forked)`,A||(f.onclick=I=>{I.stopPropagation(),this.setActiveVersion(i,c.id)})}let l=r.createEl("button",{cls:"stashpad-version-add stashpad-version-fork"});(0,F.setIcon)(l,"git-fork"),l.title="Fork this version (copy)",l.onclick=c=>{c.stopPropagation(),this.cmdForkVersion(t)}}addTaskCheckbox(e,t){let i=e.createSpan({cls:"stashpad-note-task-checkbox"}),s=this.isCompleted(t);(0,F.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(t)}}renderNoteBody(e,t,i={clamp:!0}){if(!t.file)return;if(i.immediate||this.bodyRenderer.hasFreshRenderCache(t.file)||!this.bodyRenderer.isArmed()){this.renderNoteBodyNow(e,t,i);return}e.empty();let s=e.createDiv({cls:"stashpad-note-text is-plain is-lazy-placeholder"});s.textContent=this.titleForNode(t),this.bodyRenderer.defer(e,()=>this.renderNoteBodyNow(e,t,i))}renderNoteBodyNow(e,t,i={clamp:!0}){if(!t.file)return;let s=t.file,n=(e.__stashpadRenderToken??0)+1;e.__stashpadRenderToken=n,this.bodyRenderer.getOrComputeRender(s).then(o=>{if(e.__stashpadRenderToken!==n)return;let{text:r,attachments:l,html:c}=o;e.empty();let A=e.createDiv({cls:"stashpad-note-text"}),h=this.isNoteExpanded(t.id);if(i.clamp&&!h&&A.addClass("is-clamped"),this.compactMode||this.tinyMode?(A.addClass("is-plain"),A.textContent=r):A.append((0,F.sanitizeHTMLToDom)(c)),l.length>0&&this.renderAttachmentRail(e,l),this.renderAuthorshipFooter(e,t),!i.clamp)return;let g=this.lastListWidth;if(o.ovW===g&&o.ovV!==void 0&&!h){o.ovV?this.attachExpandToggle(i,e,t,h):A.removeClass("is-clamped");return}requestAnimationFrame(()=>{if(h){this.attachExpandToggle(i,e,t,h);return}let u=e.closest?.(".stashpad-note.is-cursor-expanded");u&&u.removeClass("is-cursor-expanded");let f=A.scrollHeight>A.clientHeight+4;if(u&&u.addClass("is-cursor-expanded"),o.ovW=g,o.ovV=f,!f){A.removeClass("is-clamped");return}this.attachExpandToggle(i,e,t,h)})})}attachExpandToggle(e,t,i,s){let n=!!e.toggleHost,o=e.toggleHost??t;o.querySelector(".stashpad-expand-toggle")?.remove();let r=!!t.closest?.(".stashpad-note.is-cursor-expanded"),l=s||r,c=o.createEl("button",{cls:"stashpad-expand-toggle"});c.title=l?"Show less":"Show more",n||F.Platform.isMobile?((0,F.setIcon)(c,l?"chevron-up":"chevron-down"),c.addClass("is-icon"),n&&c.addClass("is-inline")):c.setText(l?"Show less":"Show more"),e.toggleAnchor&&e.toggleAnchor.parentElement===o&&o.insertBefore(c,e.toggleAnchor),c.addEventListener("dblclick",A=>{A.preventDefault(),A.stopPropagation()}),c.addEventListener("mousedown",A=>{A.stopPropagation()}),c.onclick=A=>{A.stopPropagation();let h=t.closest?.(".stashpad-note"),g=!!h?.classList.contains("is-cursor-expanded"),f=!(this.isNoteExpanded(i.id)||g);g&&!f?(h?.removeClass("is-cursor-expanded"),this.cursorExpandOverride.add(i.id)):f&&this.cursorExpandOverride.delete(i.id),this.setNoteExpanded(i.id,f),t.empty(),this.renderNoteBody(t,i,e)}}renderAttachmentRail(e,t){let i=e.createDiv({cls:"stashpad-rail"});for(let s of t){let n=this.app.metadataCache.getFirstLinkpathDest(s,""),o=(s.split(".").pop()??"").toLowerCase(),r=i.createDiv({cls:"stashpad-att"});if(r.title=s,n&&Cd.has(o)){let l=r.createEl("img",{cls:"stashpad-att-img"});l.src=this.app.vault.getResourcePath(n),l.alt=s}else{r.createDiv({cls:"stashpad-att-ext",text:o.toUpperCase()||"?"});let l=(s.split("/").pop()??s).replace(/\.[^.]+$/,"");r.createDiv({cls:"stashpad-att-name",text:l})}r.onclick=l=>{l.stopPropagation(),n&&this.app.workspace.getLeaf("tab").openFile(n)}}}renderComposerNavCluster(e){let t=e.createDiv({cls:"stashpad-composer-nav"}),i=t.createEl("button",{cls:"stashpad-composer-btn stashpad-composer-nav-folder"});(0,F.setIcon)(i,this.plugin.getFolderIcon(this.noteFolder)??"folder");let s=this.noteFolder.split("/").pop()||this.noteFolder||"Stashpad";i.createSpan({cls:"stashpad-btn-text",text:s}),i.title=`Folder: ${this.noteFolder} -Tap to switch / create.`,this.folderOverride&&i.addClass("is-active"),i.onmousedown=o=>o.preventDefault(),i.onclick=o=>{o.preventDefault(),this.openFolderPicker()};let n=t.createEl("button",{cls:"stashpad-composer-btn"});Fe(n,"search","\u{1F50D}"),n.title="Search notes (Mod+F)",n.onmousedown=o=>o.preventDefault(),n.onclick=o=>{o.preventDefault(),this.openSearchModal()}}renderComposer(e){let t=X(),i=this.modeEnterSubmits,s=this.modeSplit??t.splitOnLines,n=e.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,F.debounce)(x=>{this.saveDraft(x)},250)),r.addEventListener("input",()=>{this.composerDraft=r.value,this.debouncedSaveDraft(r.value)}),r.addEventListener("blur",()=>{this.saveDraft(r.value)});let l=null,c=()=>{l||(l=new F.Scope(this.app.scope),l.register([],"Escape",()=>(this.composerExitAt=Date.now(),r.blur(),this.viewRoot?.focus({preventScroll:!0}),!1)),l.register(["Mod"],"z",()=>!0),l.register(["Mod","Shift"],"z",()=>!0),this.app.keymap?.pushScope(l))},A=()=>{if(l){try{this.app.keymap?.popScope(l)}catch{}l=null}};if(r.addEventListener("focus",c),r.addEventListener("blur",A),document.activeElement===r&&c(),F.Platform.isMobile){let x=()=>{this.keyboardTransitionUntil=Date.now()+600};r.addEventListener("focus",()=>{document.body.classList.add("stashpad-keyboard-open"),x()}),r.addEventListener("blur",()=>{document.body.classList.remove("stashpad-keyboard-open"),x(),this.tapSettleUntil=Date.now()+300,F.Platform.isMobile&&this.cursorIdx>=0&&setTimeout(()=>this.revealCursorRow(),350)})}this.composerInputEl=r,this.composerAutocomplete&&this.composerAutocomplete.detach(),this.composerAutocomplete=new ui(this.app,r),this.composerAutocomplete.attach();let h=async x=>{let U="";for(let R of x){let M=await this.importAttachment(R);if(!M)continue;let k=r.value+U,P=k&&!k.endsWith(` +${o}`}titleList(e,t=3){if(!e.length)return"";let i=e.map(n=>this.titleForNode(n).trim()||"(untitled)");return i.length<=t?i.map(n=>`"${n}"`).join(", "):`${i.slice(0,t).map(n=>`"${n}"`).join(", ")}, +${i.length-t} more`}titleForNode(e){if(!e.file)return"Untitled";let i=this.app.metadataCache.getFileCache(e.file)?.headings?.[0]?.heading;if(i)return i.trim();let n=this.plugin.renderCacheStore.get(e.file.path)?.text?.slice(0,200).split(/\r?\n/).map(o=>o.trim()).find(Boolean);return n||e.file.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ")||"Untitled"}warmCrumbTitles(e){let t=e.filter(i=>!i.file||this.app.metadataCache.getFileCache(i.file)?.headings?.[0]?.heading?!1:!this.plugin.renderCacheStore.get(i.file.path));t.length&&Promise.all(t.map(i=>this.bodyRenderer.getOrComputeRender(i.file).catch(()=>null))).then(i=>{i.some(s=>s&&s.text&&s.text.trim())&&this.debouncedRender()})}async forceManualMode(e){let t=this.noteFolder;this.sortStore.getMode(t,e)!=="manual"&&(this.sortStore.setMode(t,e,"manual"),await this.sortStore.save(t))}renderNote(e,t,i){if(!t.file||this.currentEncryptionFilter()==="locked")return;let s=t.file,n=this.tree.getChildren(t.id).length,o=this.selection.has(t.id),r=i===this.cursorIdx,l=this.inListPicker?.activeIdx===i,c=e.createDiv({cls:"stashpad-note"});o&&c.addClass("is-selected"),r&&c.addClass("is-cursor"),r&&this.cursorHasMoved&&this.plugin.settings.autoExpandCursorRow&&!this.cursorExpandOverride.has(t.id)&&c.addClass("is-cursor-expanded"),l&&c.addClass("is-pick-target"),this.isCompleted(t)&&c.addClass("is-completed"),this.isListPinned(t.id)&&c.addClass("is-list-pinned"),this.isCutPending(t.id)?c.addClass("is-cut-pending"):this.isCopyPending(t.id)&&c.addClass("is-copy-pending"),c.dataset.idx=String(i),c.dataset.id=t.id;let A=this.currentViewMode()==="nested";c.draggable=A,A&&this.dnd.attachRowDnD(c,t,i),c.addEventListener("click",E=>this.handleRowClick(E,i,t)),c.addEventListener("dblclick",E=>{if(!this.plugin.settings.doubleClickToFocus)return;let w=this.shouldAbsorbDismissTap();if(w&&this.aimedTapTargetId&&Date.now()-this.aimedTapAt<=fs.AIMED_TAP_WINDOW_MS){let F=this.aimedTapTargetId;this.aimedTapTargetId=null,this.traceTap("dblclick",E,i,!1),E.preventDefault(),window.getSelection()?.removeAllRanges(),this.navigateTo(F);return}if(this.traceTap("dblclick",E,i,w),w){E.preventDefault();return}E.target?.closest?.(".internal-link, .tag, a, .stashpad-note-task-checkbox")||(E.preventDefault(),window.getSelection()?.removeAllRanges(),this.navigateTo(t.id))});let h=this.isTask(t)||this.compactMode;h&&(c.addClass("is-task"),b.Platform.isMobile||this.addTaskCheckbox(c,t));let p=c.createDiv({cls:"stashpad-note-meta"}),u=p.createDiv({cls:"stashpad-note-meta-top"});u.createSpan({cls:"stashpad-note-time",text:this.formatTime(t.created)});let f=this.colorForNode(t),g=u.createDiv({cls:"stashpad-note-grip"});f&&g.addClass("has-color"),(0,b.setIcon)(g,"grip-vertical"),g.title=f?"Drag to reorder \xB7 right-click to change color":"Drag to reorder",g.draggable=A,A||(g.title=f?"Right-click to change color \xB7 drag disabled in this view mode":"Drag disabled in this view mode"),f&&g.style.setProperty("--stashpad-note-color",f);let I=h&&b.Platform.isMobile,m=this.isListPinned(t.id);if(n>0||I||m){let E=p.createDiv({cls:"stashpad-note-meta-bottom"});if(m){let w=E.createSpan({cls:"stashpad-note-listpin"});(0,b.setIcon)(w,"pin"),w.setAttr("aria-label","Pinned to top of list")}if(I&&this.addTaskCheckbox(E,t),n>0){let w=E.createSpan({cls:"stashpad-note-enter"});f&&(w.style.color=f),(0,b.setIcon)(w.createSpan({cls:"stashpad-btn-icon"}),"corner-down-right"),w.createSpan({text:` ${n}`}),w.onclick=v=>{v.stopPropagation(),this.navigateTo(t.id)}}}if(f)c.addClass("has-color"),c.style.setProperty("--stashpad-note-color",f);else{let E=this.inheritedColorForNode(t);E&&E.depth>0&&(c.addClass("has-inherited-color"),c.style.setProperty("--stashpad-inherited-color",E.hex),c.style.setProperty("--stashpad-inherited-depth",String(E.depth)))}let B=c.createDiv({cls:"stashpad-note-body"});this.currentViewMode()!=="nested"&&this.renderRowBreadcrumb(B,t);let C=B.createDiv({cls:"stashpad-note-body-content"}),Q=c.createDiv({cls:"stashpad-note-actions"}),y;if(b.Platform.isMobile){let E=Q.createEl("button",{cls:"stashpad-pencil stashpad-note-more"});(0,b.setIcon)(E,"ellipsis-vertical"),E.title="Actions",E.onclick=w=>{w.stopPropagation(),this.openNoteMenu(w,t)},y=E}else{let E=Q.createEl("button",{cls:"stashpad-pencil"});(0,b.setIcon)(E,"pencil"),E.title="Edit in new tab",E.onclick=F=>{F.stopPropagation(),this.openFileAtEnd(s)};let w=Q.createEl("button",{cls:"stashpad-pencil stashpad-enter-btn"});(0,b.setIcon)(w,"arrow-right"),w.title="Open in Stashpad view",w.onclick=F=>{F.stopPropagation(),this.navigateTo(t.id)};let v=Q.createEl("button",{cls:"stashpad-pencil stashpad-note-more"});(0,b.setIcon)(v,"ellipsis-vertical"),v.title="More actions",v.onclick=F=>{F.stopPropagation(),this.openNoteMenu(F,t)},y=E}this.renderNoteBody(C,t,{clamp:!0,toggleHost:Q,toggleAnchor:y}),this.renderVersionTabs(B,t),c.oncontextmenu=E=>{E.preventDefault(),this.openNoteMenu(E,t)}}renderVersionTabs(e,t){if(!this.plugin.settings.enableSheetVersions||!Ni(we(this.app,t)))return;let i=ze(we(this.app,t)),s=t.parent??this.focusId,n=this.tree.getChildren(s),o=_n(this.app,n.filter(c=>{let A=we(this.app,c);return Ni(A)&&ze(A)===i}));if(o.length<2)return;let r=e.createDiv({cls:"stashpad-version-tabs"});for(let c of o){let A=c.id===t.id,h=we(this.app,c),p=Mi(h),u=mr(h),f=r.createDiv({cls:"stashpad-version-tab"+(A?" is-active":"")+(p?" is-final":"")+(u?" is-original":"")});p&&f.createSpan({cls:"stashpad-version-star",text:"\u2605"}),f.createSpan({cls:"stashpad-version-tab-label",text:wr(this.app,c,this.titleForNode(c).trim()||"Untitled")});let g=this.titleForNode(c).trim();f.title=u?`${g} (original)`:`${g} (forked)`,A||(f.onclick=I=>{I.stopPropagation(),this.setActiveVersion(i,c.id)})}let l=r.createEl("button",{cls:"stashpad-version-add stashpad-version-fork"});(0,b.setIcon)(l,"git-fork"),l.title="Fork this version (copy)",l.onclick=c=>{c.stopPropagation(),this.cmdForkVersion(t)}}addTaskCheckbox(e,t){let i=e.createSpan({cls:"stashpad-note-task-checkbox"}),s=this.isCompleted(t);(0,b.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(t)}}renderNoteBody(e,t,i={clamp:!0}){if(!t.file)return;if(i.immediate||this.bodyRenderer.hasFreshRenderCache(t.file)||!this.bodyRenderer.isArmed()){this.renderNoteBodyNow(e,t,i);return}e.empty();let s=e.createDiv({cls:"stashpad-note-text is-plain is-lazy-placeholder"});s.textContent=this.titleForNode(t),this.bodyRenderer.defer(e,()=>this.renderNoteBodyNow(e,t,i))}renderNoteBodyNow(e,t,i={clamp:!0}){if(!t.file)return;let s=t.file,n=(e.__stashpadRenderToken??0)+1;e.__stashpadRenderToken=n,this.bodyRenderer.getOrComputeRender(s).then(o=>{if(e.__stashpadRenderToken!==n)return;let{text:r,attachments:l,html:c}=o;e.empty();let A=e.createDiv({cls:"stashpad-note-text"}),h=this.isNoteExpanded(t.id);if(i.clamp&&!h&&A.addClass("is-clamped"),this.compactMode||this.tinyMode?(A.addClass("is-plain"),A.textContent=r):A.append((0,b.sanitizeHTMLToDom)(c)),l.length>0&&this.renderAttachmentRail(e,l),this.renderAuthorshipFooter(e,t),!i.clamp)return;let p=this.lastListWidth;if(o.ovW===p&&o.ovV!==void 0&&!h){o.ovV?this.attachExpandToggle(i,e,t,h):A.removeClass("is-clamped");return}requestAnimationFrame(()=>{if(h){this.attachExpandToggle(i,e,t,h);return}let u=e.closest?.(".stashpad-note.is-cursor-expanded");u&&u.removeClass("is-cursor-expanded");let f=A.scrollHeight>A.clientHeight+4;if(u&&u.addClass("is-cursor-expanded"),o.ovW=p,o.ovV=f,!f){A.removeClass("is-clamped");return}this.attachExpandToggle(i,e,t,h)})})}attachExpandToggle(e,t,i,s){let n=!!e.toggleHost,o=e.toggleHost??t;o.querySelector(".stashpad-expand-toggle")?.remove();let r=!!t.closest?.(".stashpad-note.is-cursor-expanded"),l=s||r,c=o.createEl("button",{cls:"stashpad-expand-toggle"});c.title=l?"Show less":"Show more",n||b.Platform.isMobile?((0,b.setIcon)(c,l?"chevron-up":"chevron-down"),c.addClass("is-icon"),n&&c.addClass("is-inline")):c.setText(l?"Show less":"Show more"),e.toggleAnchor&&e.toggleAnchor.parentElement===o&&o.insertBefore(c,e.toggleAnchor),c.addEventListener("dblclick",A=>{A.preventDefault(),A.stopPropagation()}),c.addEventListener("mousedown",A=>{A.stopPropagation()}),c.onclick=A=>{A.stopPropagation();let h=t.closest?.(".stashpad-note"),p=!!h?.classList.contains("is-cursor-expanded"),f=!(this.isNoteExpanded(i.id)||p);p&&!f?(h?.removeClass("is-cursor-expanded"),this.cursorExpandOverride.add(i.id)):f&&this.cursorExpandOverride.delete(i.id),this.setNoteExpanded(i.id,f),t.empty(),this.renderNoteBody(t,i,e)}}renderAttachmentRail(e,t){let i=e.createDiv({cls:"stashpad-rail"});for(let s of t){let n=this.app.metadataCache.getFirstLinkpathDest(s,""),o=(s.split(".").pop()??"").toLowerCase(),r=i.createDiv({cls:"stashpad-att"});if(r.title=s,n&&Ed.has(o)){let l=r.createEl("img",{cls:"stashpad-att-img"});l.src=this.app.vault.getResourcePath(n),l.alt=s}else{r.createDiv({cls:"stashpad-att-ext",text:o.toUpperCase()||"?"});let l=(s.split("/").pop()??s).replace(/\.[^.]+$/,"");r.createDiv({cls:"stashpad-att-name",text:l})}r.onclick=l=>{l.stopPropagation(),n&&this.app.workspace.getLeaf("tab").openFile(n)}}}renderComposerNavCluster(e){let t=e.createDiv({cls:"stashpad-composer-nav"}),i=t.createEl("button",{cls:"stashpad-composer-btn stashpad-composer-nav-folder"});(0,b.setIcon)(i,this.plugin.getFolderIcon(this.noteFolder)??"folder");let s=this.noteFolder.split("/").pop()||this.noteFolder||"Stashpad";i.createSpan({cls:"stashpad-btn-text",text:s}),i.title=`Folder: ${this.noteFolder} +Tap to switch / create.`,this.folderOverride&&i.addClass("is-active"),i.onmousedown=o=>o.preventDefault(),i.onclick=o=>{o.preventDefault(),this.openFolderPicker()};let n=t.createEl("button",{cls:"stashpad-composer-btn"});Fe(n,"search","\u{1F50D}"),n.title="Search notes (Mod+F)",n.onmousedown=o=>o.preventDefault(),n.onclick=o=>{o.preventDefault(),this.openSearchModal()}}renderComposer(e){let t=X(),i=this.modeEnterSubmits,s=this.modeSplit??t.splitOnLines,n=e.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,b.debounce)(x=>{this.saveDraft(x)},250)),r.addEventListener("input",()=>{this.composerDraft=r.value,this.debouncedSaveDraft(r.value)}),r.addEventListener("blur",()=>{this.saveDraft(r.value)});let l=null,c=()=>{l||(l=new b.Scope(this.app.scope),l.register([],"Escape",()=>(this.composerExitAt=Date.now(),r.blur(),this.viewRoot?.focus({preventScroll:!0}),!1)),l.register(["Mod"],"z",()=>!0),l.register(["Mod","Shift"],"z",()=>!0),this.app.keymap?.pushScope(l))},A=()=>{if(l){try{this.app.keymap?.popScope(l)}catch{}l=null}};if(r.addEventListener("focus",c),r.addEventListener("blur",A),document.activeElement===r&&c(),b.Platform.isMobile){let x=()=>{this.keyboardTransitionUntil=Date.now()+600};r.addEventListener("focus",()=>{document.body.classList.add("stashpad-keyboard-open"),x()}),r.addEventListener("blur",()=>{document.body.classList.remove("stashpad-keyboard-open"),x(),this.tapSettleUntil=Date.now()+300,b.Platform.isMobile&&this.cursorIdx>=0&&setTimeout(()=>this.revealCursorRow(),350)})}this.composerInputEl=r,this.composerAutocomplete&&this.composerAutocomplete.detach(),this.composerAutocomplete=new fi(this.app,r),this.composerAutocomplete.attach();let h=async x=>{let H="";for(let U of x){let N=await this.importAttachment(U);if(!N)continue;let S=r.value+H,P=S&&!S.endsWith(` `)?` -`:"";U+=`${P}${M} -`}U&&(r.value=r.value+U,this.composerDraft=r.value,this.saveDraft(r.value),r.focus(),r.setSelectionRange(r.value.length,r.value.length))};r.addEventListener("dragover",x=>{if(!(!x.dataTransfer||!Array.from(x.dataTransfer.types).includes("Files"))){x.preventDefault(),x.stopPropagation();try{x.dataTransfer.dropEffect="copy"}catch{}}}),r.addEventListener("drop",x=>{let U=Array.from(x.dataTransfer?.files??[]);U.length!==0&&(x.preventDefault(),x.stopPropagation(),h(U))}),r.addEventListener("paste",x=>{let U=this.plugin.noteClipboard;if(U?.mode==="cut"&&U.text&&x.clipboardData?.getData("text/plain")===U.text){if(this.focusedInsideCut(U.ids)){x.preventDefault(),new F.Notice("Can't paste a cut note into the note you're cutting.");return}x.preventDefault(),this.completeCutIntoComposer();return}let R=[],M=x.clipboardData;if(M){for(let k of Array.from(M.files??[]))R.push(k);if(R.length===0){for(let k of Array.from(M.items??[]))if(k.kind==="file"){let P=k.getAsFile();P&&R.push(P)}}R.length!==0&&(x.preventDefault(),x.stopPropagation(),h(R))}});let g=n.createEl("input",{cls:"stashpad-composer-file-input",type:"file",attr:{multiple:"true"}});g.setCssStyles({display:"none"});let u=n.createDiv({cls:"stashpad-composer-btn-rail"});F.Platform.isMobile&&this.renderComposerNavCluster(u);let f=u.createDiv({cls:"stashpad-composer-btn-group"}),p=f.createEl("button",{cls:"stashpad-composer-btn"});(0,F.setIcon)(p,"list-end"),this.composerSplitBtn=p;let I=_t[X().splitMode].toLowerCase();p.title=s?`Split: ON \u2014 ${I} (Mod+/ to toggle, right-click to change)`:`Split into notes (Mod+/) \u2014 right-click to choose: ${I}`,s&&p.addClass("is-active"),p.onmousedown=x=>x.preventDefault(),p.onclick=x=>{x.preventDefault(),this.toggleSplit()},p.oncontextmenu=x=>{x.preventDefault();let U=new F.Menu,R=X().splitMode;["lines","paragraphs","headings"].forEach(M=>{U.addItem(k=>k.setTitle(_t[M]).setChecked(M===R).onClick(async()=>{this.plugin.settings.splitMode=M,await this.plugin.saveSettings(),this.syncComposerModeUI()}))}),U.showAtMouseEvent(x)};let m=f.createEl("button",{cls:"stashpad-composer-btn stashpad-composer-dest"});this.composerDestBtn=m,(0,F.setIcon)(m,"map-pin"),this.nextDestination&&m.createSpan({text:` ${this.destinationLabel()}`,cls:"stashpad-btn-text"}),m.title="Set destination (Mod+D)",this.nextDestination&&m.addClass("is-active"),m.onmousedown=x=>x.preventDefault(),m.onclick=x=>{x.preventDefault();let U=document.activeElement===r;this.openDestinationPicker(U)};let B=f.createEl("button",{cls:"stashpad-composer-btn"});this.composerEnterBtn=B,(0,F.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=x=>x.preventDefault(),B.onclick=x=>{x.preventDefault(),this.modeEnterSubmits=!this.modeEnterSubmits,this.syncComposerModeUI(),r.focus()};let C=x=>{let U=r.value&&!r.value.endsWith(` +`:"";H+=`${P}${N} +`}H&&(r.value=r.value+H,this.composerDraft=r.value,this.saveDraft(r.value),r.focus(),r.setSelectionRange(r.value.length,r.value.length))};r.addEventListener("dragover",x=>{if(!(!x.dataTransfer||!Array.from(x.dataTransfer.types).includes("Files"))){x.preventDefault(),x.stopPropagation();try{x.dataTransfer.dropEffect="copy"}catch{}}}),r.addEventListener("drop",x=>{let H=Array.from(x.dataTransfer?.files??[]);H.length!==0&&(x.preventDefault(),x.stopPropagation(),h(H))}),r.addEventListener("paste",x=>{let H=this.plugin.noteClipboard;if(H?.mode==="cut"&&H.text&&x.clipboardData?.getData("text/plain")===H.text){if(this.focusedInsideCut(H.ids)){x.preventDefault(),new b.Notice("Can't paste a cut note into the note you're cutting.");return}x.preventDefault(),this.completeCutIntoComposer();return}let U=[],N=x.clipboardData;if(N){for(let S of Array.from(N.files??[]))U.push(S);if(U.length===0){for(let S of Array.from(N.items??[]))if(S.kind==="file"){let P=S.getAsFile();P&&U.push(P)}}U.length!==0&&(x.preventDefault(),x.stopPropagation(),h(U))}});let p=n.createEl("input",{cls:"stashpad-composer-file-input",type:"file",attr:{multiple:"true"}});p.setCssStyles({display:"none"});let u=n.createDiv({cls:"stashpad-composer-btn-rail"});b.Platform.isMobile&&this.renderComposerNavCluster(u);let f=u.createDiv({cls:"stashpad-composer-btn-group"}),g=f.createEl("button",{cls:"stashpad-composer-btn"});(0,b.setIcon)(g,"list-end"),this.composerSplitBtn=g;let I=ei[X().splitMode].toLowerCase();g.title=s?`Split: ON \u2014 ${I} (Mod+/ to toggle, right-click to change)`:`Split into notes (Mod+/) \u2014 right-click to choose: ${I}`,s&&g.addClass("is-active"),g.onmousedown=x=>x.preventDefault(),g.onclick=x=>{x.preventDefault(),this.toggleSplit()},g.oncontextmenu=x=>{x.preventDefault();let H=new b.Menu,U=X().splitMode;["lines","paragraphs","headings"].forEach(N=>{H.addItem(S=>S.setTitle(ei[N]).setChecked(N===U).onClick(async()=>{this.plugin.settings.splitMode=N,await this.plugin.saveSettings(),this.syncComposerModeUI()}))}),H.showAtMouseEvent(x)};let m=f.createEl("button",{cls:"stashpad-composer-btn stashpad-composer-dest"});this.composerDestBtn=m,(0,b.setIcon)(m,"map-pin"),this.nextDestination&&m.createSpan({text:` ${this.destinationLabel()}`,cls:"stashpad-btn-text"}),m.title="Set destination (Mod+D)",this.nextDestination&&m.addClass("is-active"),m.onmousedown=x=>x.preventDefault(),m.onclick=x=>{x.preventDefault();let H=document.activeElement===r;this.openDestinationPicker(H)};let B=f.createEl("button",{cls:"stashpad-composer-btn"});this.composerEnterBtn=B,(0,b.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=x=>x.preventDefault(),B.onclick=x=>{x.preventDefault(),this.modeEnterSubmits=!this.modeEnterSubmits,this.syncComposerModeUI(),r.focus()};let C=x=>{let H=r.value&&!r.value.endsWith(` `)?` -`:"";r.value+=`${U}${x} -`,this.composerDraft=r.value},w=f.createEl("button",{cls:"stashpad-composer-btn"});(0,F.setIcon)(w,"paperclip"),w.title="Attach files",w.onmousedown=x=>x.preventDefault(),w.onclick=x=>{x.preventDefault();let U=document.activeElement===r;if(g.click(),U){let R=()=>{r.focus()};setTimeout(R,100),setTimeout(R,500)}},g.addEventListener("change",async()=>{let x=Array.from(g.files??[]);g.value="";for(let U of x){let R=await this.importAttachment(U);R&&C(R)}r.focus()}),f.append(m,w,B,p);let y=u.createEl("button",{cls:"stashpad-composer-btn stashpad-composer-rail-toggle"});(0,F.setIcon)(y,"chevron-left"),y.title="Show more composer options",u.insertBefore(y,f);let v=x=>{u.toggleClass("is-expanded",x),y.title=x?"Hide options":"Show more composer options",(0,F.setIcon)(y,x?"chevron-right":"chevron-left")};y.onmousedown=x=>x.preventDefault(),y.onclick=x=>{x.preventDefault(),v(!u.hasClass("is-expanded"))},v(!1);let E=()=>n.clientWidth<(F.Platform.isMobile?360:700),Q=()=>{let x=E();n.toggleClass("is-narrow",x),v(!x)};Q(),requestAnimationFrame(Q);let b=new ResizeObserver(Q);b.observe(n),this.composerNarrowObserver?.disconnect(),this.composerNarrowObserver=b;let D=u.createEl("button",{cls:"stashpad-composer-btn stashpad-composer-send"});D.title="Send (Enter)",(0,F.setIcon)(D,"arrow-up");let H=async()=>{let x=r.value.trim();if(!x)return;r.value="",this.composerDraft="";try{await this.saveDraft("")}catch{}try{await this.recordLastSubmitted(x)}catch{}let U=this.modeSplit??X().splitOnLines,R=this.nextDestination,M=this.nextDestinationFolder,k=!!M&&M!==this.noteFolder;this.nextDestination=null,this.nextDestinationFolder=null,this.nextDestinationLabel=null,this.autoSelectNewest=!k,this.scrollToBottomOnNextRender=!k;let P=k?{targetFolder:M}:void 0,O=R??this.focusId;if(U){let L=Mi(x,X().splitMode);L.length===1?await this.createNoteUnder(L[0],O,P):L.length>1&&await this.createNotesBatch(L,O,P,x,k?M:this.noteFolder)}else await this.createNoteUnder(x,O,P);X().autofocusComposerAfterSend&&(this.focusComposerOnNextRender=!0,k&&this.composerInputEl?.focus())};D.onclick=()=>void H(),r.addEventListener("keydown",x=>{let U=this.modeEnterSubmits;if(x.key==="Escape"){x.preventDefault(),x.stopPropagation(),r.blur(),this.viewRoot.focus({preventScroll:!0});return}if(x.key==="ArrowUp"&&r.selectionStart===0&&r.selectionEnd===0){if(x.preventDefault(),r.blur(),this.viewRoot.focus({preventScroll:!0}),this.currentChildren.length>0){let R=this.lastCursorByFocus.get(this.focusId)??this.lastSelected,M=R?this.currentChildren.findIndex(k=>k.id===R):-1;this.cursorIdx=M>=0?M:this.currentChildren.length-1,this.selectCursor(!1)}return}x.key==="Enter"&&!x.isComposing&&(U?!x.shiftKey:x.shiftKey)&&(x.preventDefault(),x.stopPropagation(),x.stopImmediatePropagation(),H())});let G=e.createDiv({cls:"stashpad-composer-help"});this.composerHelperEl=G,G.setText(this.composerHelperText(i,s))}composerPlaceholder(e,t){return F.Platform.isMobile?t?"New notes (split on newlines)":"New note":`Type a note. ${e?"Enter":"Shift+Enter"} = send, ${e?"Shift+Enter":"Enter"} = newline${t?" (each line \u2192 a note)":""}\u2026`}composerHelperText(e,t){let i=e?"Enter":"Shift+Enter",s=e?"Shift+Enter":"Enter",n=X().bindings,o=h=>{let g=n[h];return g.primary&&g.secondary?g.preferRight?g.secondary:g.primary:g.primary||g.secondary},r=ns(o("toggleSplit")),l=ns(o("pickDestination")),c=ns(o("search")),A=this.nextDestination?` \u2022 destination: ${this.destinationLabel()}`:"";return`${i} sends \xB7 ${s} newline \xB7 ${r} split: ${t?"ON":"off"} \xB7 ${l} destination \xB7 ${c} search${A}`}destinationLabel(){if(!this.nextDestination)return"current";if(this.nextDestinationFolder)return this.nextDestinationLabel??this.nextDestinationFolder;if(this.nextDestination===S)return"Home";let e=this.tree.get(this.nextDestination);return e?this.titleForNode(e).trim():"?"}renderMobileNav(e){let t=e.createDiv({cls:"stashpad-mobile-nav"});t.createEl("button",{text:"Home"}).onclick=()=>this.navigateTo(S),t.createEl("button",{text:"Back"}).onclick=()=>this.navigateUp(),t.createEl("button",{text:"Bookmarks"}).onclick=()=>this.openBookmarks()}handleRenderedClick(e,t){let i=e.target,s=i?.closest?.(".tag");if(s){e.preventDefault(),e.stopPropagation();let r=(s.getAttribute("href")||s.textContent||"").replace(/^#/,"").trim();if(r){let l=this.app.internalPlugins?.plugins?.["global-search"],c=l?.instance?.openGlobalSearch?.bind(l.instance);c&&c(`tag:#${r}`)}return}let n=i?.closest?.(".internal-link");if(n){e.preventDefault(),e.stopPropagation();let o=n.getAttribute("data-href")||n.getAttribute("href");if(o){let r=t.file?.path||"";this.app.workspace.openLinkText(o,r,!0)}}}handleRowClick(e,t,i){let s=this.shouldAbsorbDismissTap();if(this.traceTap("click",e,t,s),s){(!this.aimedTapTargetId||Date.now()-this.aimedTapAt>us.AIMED_TAP_WINDOW_MS)&&(this.aimedTapTargetId=i.id,this.aimedTapAt=Date.now()),e.stopPropagation();return}this.aimedTapTargetId=null,this.cursorHasMoved=!0;let n=e.target,o=n?.closest?.(".tag");if(o){e.preventDefault(),e.stopPropagation();let A=(o.getAttribute("href")||o.textContent||"").replace(/^#/,"").trim();if(A){let h=this.app.internalPlugins?.plugins?.["global-search"],g=h?.instance?.openGlobalSearch?.bind(h.instance);g&&g(`tag:#${A}`)}return}let r=n?.closest?.(".internal-link");if(r){e.preventDefault(),e.stopPropagation();let c=r.getAttribute("data-href")||r.getAttribute("href");if(c){let A=i.file?.path||"";this.app.workspace.openLinkText(c,A,!0)}return}if(n?.tagName==="A"&&n.href)return;if(e.stopPropagation(),this.inListPicker){this.inListPicker.activeIdx=t,this.commitInListPicker();return}let l=this.selection.size===0;if(e.shiftKey&&this.lastSelected){this.cursorIdx=t;let c=this.currentChildren.findIndex(A=>A.id===this.lastSelected);if(l&&(this.firstSelectedId=this.lastSelected),c!==-1){let[A,h]=c<t?[c,t]:[t,c];for(let g=A;g<=h;g++)this.selection.add(this.currentChildren[g].id)}else this.selection.add(i.id)}else if(e.metaKey||e.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 c=this.lastSelected??[...this.selection][this.selection.size-1],A=c?this.currentChildren.findIndex(h=>h.id===c):-1;A>=0&&(this.cursorIdx=A)}else this.cursorIdx=t,l&&(this.firstSelectedId=i.id),this.selection.add(i.id);else this.mobileSelectMode?(this.cursorIdx=t,this.selection.has(i.id)?(this.selection.delete(i.id),this.firstSelectedId===i.id&&(this.firstSelectedId=null)):this.selection.add(i.id)):(this.cursorIdx=t,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 e=()=>{if(this.cursorIdx<0)return;let t=this.listEl?.querySelector(`[data-idx="${this.cursorIdx}"]`);if(!t||!this.listEl)return;let i=this.listEl,s=i.getBoundingClientRect(),n=t.getBoundingClientRect(),o=4,r=s.top+o,l=s.bottom-o;if(F.Platform.isMobile&&document.body.classList.contains("stashpad-keyboard-open")){let c=this.viewRoot?.querySelector(".stashpad-composer");c&&(l=Math.min(l,c.getBoundingClientRect().top-o))}n.top<r?i.scrollTop+=n.top-r:n.bottom>l&&(i.scrollTop+=n.bottom-l)};e(),requestAnimationFrame(e),setTimeout(e,60),setTimeout(e,200)}shouldAbsorbDismissTap(){return F.Platform.isMobile&&Date.now()<this.tapSettleUntil}traceTap(e,t,i,s){if(!this.plugin.settings.debugTrace||!this.listEl)return;let n=this.listEl,o=window.visualViewport,r=n.querySelector(`.stashpad-note[data-idx="${i}"]`)?.getBoundingClientRect();this.plugin.trace(`tap:${e}`,{absorbed:s,clientY:Math.round(t.clientY),clientX:Math.round(t.clientX),idx:i,rowTop:r?Math.round(r.top):null,listTop:Math.round(n.getBoundingClientRect().top),listScrollTop:Math.round(n.scrollTop),listScrollH:Math.round(n.scrollHeight),listClientH:Math.round(n.clientHeight),innerH:window.innerHeight,vvHeight:o?Math.round(o.height):null,vvOffsetTop:o?Math.round(o.offsetTop):null,tapSettleInMs:Math.max(0,this.tapSettleUntil-Date.now()),kbOpen:document.body.classList.contains("stashpad-keyboard-open")})}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(e){let t=this.currentChildren[this.cursorIdx];if(t){if(this.cursorHasMoved=!0,!e)this.selection.clear(),this.selection.add(t.id),this.firstSelectedId=t.id,this.lastSelected=t.id;else{let i=this.firstSelectedId??t.id,s=this.currentChildren.findIndex(n=>n.id===i);if(s===-1)this.selection.add(t.id),this.firstSelectedId=t.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=t.id}this.repaintSelectionClasses(),this.revealCursorRow(),this.stampSelectedCursor(),this.plugin.notifyStashpadSelectionChanged()}}repaintSelectionClasses(){if(!this.listEl)return;let e=!!this.plugin.settings.autoExpandCursorRow,t=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)),r||this.cursorExpandOverride.delete(o),s.classList.toggle("is-cursor-expanded",e&&r&&this.cursorHasMoved&&!this.cursorExpandOverride.has(o)),s.classList.toggle("is-pick-target",n===t)})}revealRowAt(e){if(!this.listEl)return;let t=this.listEl.querySelector(`.stashpad-note[data-idx="${e}"]`);if(!t)return;let i=t.getBoundingClientRect(),s=this.listEl.getBoundingClientRect();(i.top<s.top||i.bottom>s.bottom)&&t.scrollIntoView({block:"nearest",behavior:"auto"})}getActionTargets(){if(this.selection.size>0)return[...this.selection].map(t=>this.tree.get(t)).filter(t=>!!t&&!!t.file);let e=this.currentChildren[this.cursorIdx];return e?[e]:[]}async cmdLockSelection(){if(!this.plugin.encryption?.isConfigured?.()){new F.Notice("Set up encryption first (Settings \u2192 Stashpad \u2192 Encryption).");return}let e=this.getActionTargets();if(e.length===0)return;let t=new Set(e.map(r=>r.id)),i=new Set((this.plugin.settings.lockedSubtrees??[]).map(r=>r.rootId).filter(r=>!!r)),s=e.filter(r=>{if(i.has(r.id))return!1;let l=r.parent;for(;l;){if(t.has(l))return!1;l=this.tree.get(l)?.parent??null}return!0});if(s.length===0){new F.Notice("Nothing to lock (already locked).");return}let n=0,o=[];for(let r of s){let l=this.order.getOrder(this.noteFolder,r.parent??S),c=l.indexOf(r.id),A=c>0?l[c-1]:null,h=await this.plugin.lockNoteSubtree(this.noteFolder,r.id,A,{silent:!0});h&&(n++,o.push({rootId:r.id,prevSibling:A,blob:h.blobPath}),await this.log.append({type:"lock",id:r.id}))}if(n>0){this.selection.clear(),this.lastSelected=null,this.render();let r=this.noteFolder;this.plugin.getUndoStack(r).push({label:`Lock ${n} stash${n===1?"":"es"}`,undo:async()=>{for(let l of o)try{await this.plugin.unlockBundleAt(l.blob,{silent:!0})}catch{}this.render()},redo:async()=>{for(let l of o){let c=await this.plugin.lockNoteSubtree(r,l.rootId,l.prevSibling,{silent:!0});c&&(l.blob=c.blobPath)}this.render()}}),this.plugin.notifications.show({message:`Locked ${n} stash${n===1?"":"es"} \u2014 undo to unlock.`,kind:"success",category:"system",folder:this.noteFolder,actions:[{label:"All encrypted",onClick:()=>void Te(this.plugin,"encrypted")}]})}}async cmdMoveToArchive(){let e=this.getActionTargets();if(e.length===0)return;let t=(this.noteFolder??"").replace(/\/+$/,"");if(ws(t)){new F.Notice("These notes are already in an archive.",6e3);return}this.archiveSources(e,yt(t))}async archiveSources(e,t){let i=this.noteFolder,s=t.replace(/\/+$/,""),n=s.replace(/\/archive$/,""),o=this.plugin.archiveEncryptFor(n);try{await this.app.vault.adapter.exists(s)||await this.app.vault.createFolder(s)}catch{}if(!o){let g=new Set(e.map(C=>C.id)),u=e.filter(C=>{let w=C.parent;for(;w;){if(g.has(w))return!1;w=this.tree.get(w)?.parent??null}return!0});if(u.length===0)return;let f=[],p=new Set,I=C=>{if(!p.has(C.id)){p.add(C.id),C.file&&f.push(C.file);for(let w of this.tree.getChildren(C.id))I(w)}};for(let C of u)I(C);let m=[];for(let C of f){let w=C.path,y=C.name,v=y.lastIndexOf("."),E=v>0?y.slice(0,v):y,Q=v>0?y.slice(v):"",b=`${s}/${y}`;for(let D=1;await this.app.vault.adapter.exists(b);D++)b=`${s}/${E}-${D}${Q}`;try{await this.app.fileManager.renameFile(C,b),m.push({from:w,to:b})}catch(D){console.warn("[Stashpad] plaintext archive move failed",w,D)}}if(this.selection.clear(),this.lastSelected=null,this.tree.rebuild(i),this.render(),m.length>0)for(let C of u)await this.log.append({type:"archive",id:C.id,payload:{to:s,encrypted:!1}});let B=s.split("/").pop()||s;this.plugin.notifications.show({message:`Moved ${m.length} note${m.length===1?"":"s"} \u2192 plaintext archive \u201C${B}\u201D (de-indexed, not encrypted). Undo to bring ${m.length===1?"it":"them"} back.`,kind:"success",category:"system",folder:i,actions:[{label:"All archived",onClick:()=>void Te(this.plugin,"archived")}]}),this.plugin.getUndoStack(i).push({label:`Archive (plaintext, ${u.length})`,undo:async()=>{for(let C of m){let w=this.app.vault.getAbstractFileByPath(C.to);if(w instanceof F.TFile)try{await this.app.fileManager.renameFile(w,C.from)}catch(y){console.warn("[Stashpad] plaintext archive undo failed",C.to,y)}}this.tree.rebuild(i),this.render()},redo:async()=>{for(let C of m){let w=this.app.vault.getAbstractFileByPath(C.from);if(w instanceof F.TFile)try{await this.app.fileManager.renameFile(w,C.to)}catch(y){console.warn("[Stashpad] plaintext archive redo failed",C.from,y)}}this.tree.rebuild(i),this.render()}});return}if(!this.plugin.encryption?.isConfigured?.()){new F.Notice(`Archiving here encrypts the notes ("Encrypt archived notes" is on for \u201C${n.split("/").pop()}\u201D), but encryption isn't set up yet (Settings \u2192 Stashpad \u2192 Encryption). Set it up \u2014 or turn that toggle off for a plaintext archive.`,9e3);return}let r=new Set(e.map(g=>g.id)),l=e.filter(g=>{let u=g.parent;for(;u;){if(r.has(u))return!1;u=this.tree.get(u)?.parent??null}return!0});if(l.length===0)return;let c=l.map(g=>g.id),A=[];for(let g of l){let u=this.order.getOrder(i,g.parent??S),f=u.indexOf(g.id),p=f>0?u[f-1]:null,I=await this.plugin.lockNoteSubtree(i,g.id,p,{silent:!0,blobFolder:t});I&&(A.push(I.blobPath),await this.log.append({type:"archive",id:g.id,payload:{to:t,encrypted:!0}}))}if(A.length===0)return;this.selection.clear(),this.lastSelected=null,this.tree.rebuild(i),this.render();let h=t.split("/").pop()||t;this.plugin.notifications.show({message:`Archived ${A.length} note${A.length===1?"":"s"} \u2192 \u201C${h}\u201D. Undo to bring ${A.length===1?"it":"them"} back.`,kind:"success",category:"system",folder:i,actions:[{label:"All archived",onClick:()=>void Te(this.plugin,"archived")}]}),this.plugin.getUndoStack(i).push({label:`Archive (${A.length})`,undo:async()=>{let g=[];for(let u of A)try{await this.plugin.unlockBundleAt(u,{silent:!0,destFolder:i})||g.push(u)}catch(f){g.push(u),console.warn("[Stashpad] archive undo failed",u,f)}A=g,g.length&&new F.Notice(`Undo incomplete: ${g.length} archived item${g.length===1?"":"s"} couldn't be restored (they're still in the archive). Try again, or restore from the Archived view.`,8e3),this.tree.rebuild(i),this.render()},redo:async()=>{A=[];for(let g of c){let u=await this.plugin.lockNoteSubtree(i,g,null,{silent:!0,blobFolder:t});u&&A.push(u.blobPath)}this.tree.rebuild(i),this.render()}})}async cmdEncryptDelete(){if(!this.plugin.encryption?.isConfigured?.()){new F.Notice("Set up encryption first (Settings \u2192 Stashpad \u2192 Encryption).");return}let e=this.getActionTargets();if(e.length===0)return;let t=new Set(e.map(n=>n.id)),i=e.filter(n=>{let o=n.parent;for(;o;){if(t.has(o))return!1;o=this.tree.get(o)?.parent??null}return!0});if(i.length===0)return;let s=i.length;new _(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(e){if(!this.plugin.encryption?.isConfigured?.()){new F.Notice("Set up encryption first (Settings \u2192 Stashpad \u2192 Encryption).");return}let t=new Set(e.map(r=>r.id)),i=e.filter(r=>{let l=r.parent;for(;l;){if(t.has(l))return!1;l=this.tree.get(l)?.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 l=await this.plugin.encryptDeleteSubtree(s,r);l&&o.push(l)}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,actions:[{label:"Open Trash",onClick:()=>this.plugin.openEncryptedTrash()}]}),this.plugin.getUndoStack(s).push({label:`Secure delete (${o.length})`,undo:async()=>{let r=[];for(let l of o)try{await this.plugin.restoreDeletedAt(l,{silent:!0})||r.push(l)}catch(c){r.push(l),console.warn("[Stashpad] secure-delete undo failed",l,c)}o=r,r.length&&new F.Notice(`Undo incomplete: ${r.length} deleted item${r.length===1?"":"s"} couldn't be restored (still in Trash). Try again, or restore from the Trash view.`,8e3),this.tree.rebuild(s),this.render()},redo:async()=>{o=[];for(let r of n){let l=await this.plugin.encryptDeleteSubtree(s,r);l&&o.push(l)}this.tree.rebuild(s),this.render()}}))}async plaintextDeleteToStashpadTrash(e){let t=new Set(e.map(r=>r.id)),i=e.filter(r=>{let l=r.parent;for(;l;){if(t.has(l))return!1;l=this.tree.get(l)?.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 l=await this.plugin.plaintextDeleteSubtree(s,r);l&&(o.push(l),await this.log.append({type:"delete",id:r,payload:{to:"trash",bundle:l}}))}o.length!==0&&(this.selection.clear(),this.lastSelected=null,this.tree.rebuild(s),this.render(),this.plugin.notifications.show({message:`Deleted ${o.length} note${o.length===1?"":"s"} \u2192 Trash. Undo to bring ${o.length===1?"it":"them"} back.`,kind:"success",category:"system",folder:s,actions:[{label:"Open Trash",onClick:()=>this.plugin.openEncryptedTrash()}]}),this.plugin.getUndoStack(s).push({label:`Delete (${o.length})`,undo:async()=>{let r=[];for(let l of o)try{await this.plugin.restoreDeletedAt(l,{silent:!0})||r.push(l)}catch(c){r.push(l),console.warn("[Stashpad] plaintext-trash undo failed",l,c)}o=r,r.length&&new F.Notice(`Undo incomplete: ${r.length} deleted item${r.length===1?"":"s"} couldn't be restored (still in Trash). Try again, or restore from the Trash view.`,8e3),this.tree.rebuild(s),this.render()},redo:async()=>{o=[];for(let r of n){let l=await this.plugin.plaintextDeleteSubtree(s,r);l&&o.push(l)}this.tree.rebuild(s),this.render()}}))}async cmdUnlockAll(){if(!this.plugin.encryption?.isConfigured?.()){new F.Notice("Set up encryption first (Settings \u2192 Stashpad \u2192 Encryption).");return}let e=new Set,t=new Set,i=this.getActionTargets().map(n=>n.id);for(;i.length;){let n=i.pop();if(!t.has(n)){t.add(n);for(let o of this.tree.getChildren(n))i.push(o.id)}}for(let n of t)for(let o of this.plugin.lockedSubtreesFor(this.noteFolder,n))e.add(o.blob);if(e.size===0){let n=(this.tree.get(this.focusId)??this.tree.getRoot()).id;for(let o of this.plugin.lockedSubtreesFor(this.noteFolder,n))e.add(o.blob)}if(e.size===0){new F.Notice("No locked notes to unlock here.");return}if(!await this.plugin.ensureFolderUnlocked(this.noteFolder))return;let s=0;for(let n of e)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}))}syncComposerModeUI(){let e=this.modeSplit??X().splitOnLines,t=this.modeEnterSubmits;if(this.composerSplitBtn){this.composerSplitBtn.toggleClass("is-active",e);let i=_t[X().splitMode].toLowerCase();this.composerSplitBtn.title=e?`Split: ON \u2014 ${i} (Mod+/ to toggle, right-click to change)`:`Split into notes (Mod+/) \u2014 right-click to choose: ${i}`}this.composerEnterBtn&&((0,F.setIcon)(this.composerEnterBtn,t?"corner-down-left":"arrow-big-down-dash"),this.composerEnterBtn.title=t?"Enter sends (click to switch to Shift+Enter)":"Shift+Enter sends (click to switch to Enter)"),this.composerInputEl&&(this.composerInputEl.placeholder=this.composerPlaceholder(t,e)),this.composerHelperEl&&this.composerHelperEl.setText(this.composerHelperText(t,e))}refreshDestButton(){let e=this.composerDestBtn;e&&(e.empty(),(0,F.setIcon)(e,"map-pin"),this.nextDestination&&e.createSpan({text:` ${this.destinationLabel()}`,cls:"stashpad-btn-text"}),e.toggleClass("is-active",!!this.nextDestination)),this.syncComposerModeUI()}toggleSplit(){let e=this.modeSplit??X().splitOnLines;this.modeSplit=!e,this.syncComposerModeUI(),this.composerInputEl?.focus()}openDestinationPicker(e=!1){let t=!1;new je(this.app,this.tree,i=>this.titleForNode(i),{mode:"pick",placeholder:"Send next note(s) under which note?",allowCreate:!0,onPick:async i=>{if(t=!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===S?"Home":(i.crossFile?.basename??"note").replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ");this.nextDestinationLabel=`${n} \u25B8 ${o}`,this.refreshDestButton(),this.composerInputEl?.focus();return}this.nextDestination=i.id,this.nextDestinationFolder=null,this.nextDestinationLabel=null,this.refreshDestButton(),this.composerInputEl?.focus()},onCreate:async i=>{t=!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:()=>{e&&!t&&this.composerInputEl?.focus()}}).open()}collectCrossFolderDestinations(){let e=this.collectCrossFolderNotes(),t=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(!t.includes(o))continue;this.app.metadataCache.getFileCache(n)?.frontmatter?.id===S&&i.set(o,n)}return[...t.map(n=>({file:i.get(n),folder:n,id:S,title:`Home \u2014 ${n.split("/").pop()||n}`,body:""})),...e]}openSearchInParentModal(){let e=this.focusId,t=s=>{if(s===e)return!0;let n=new Set,o=this.tree.get(s);for(;o&&o.id!==S&&!n.has(o.id);){if(n.add(o.id),o.parent===e||o.id===e)return!0;if(!o.parent)return!1;o=this.tree.get(o.parent)}return e===S},i=new Proxy(this.tree,{get:(s,n)=>n==="getRoot"?()=>s.get(e)??s.getRoot():n==="getChildren"?o=>s.getChildren(o):s[n]});new je(this.app,i,s=>this.titleForNode(s),{mode:"search",placeholder:`Search in "${this.titleForNode(this.tree.get(e)??this.tree.getRoot()).trim()}"\u2026`,allowCreate:!1,onPick:s=>{s.node&&t(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 e=new je(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 je(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 l=(this.plugin.settings.folder||"Stashpad").trim().replace(/^\/+|\/+$/g,"")||"Stashpad",c=this.app.workspace,A=c.getLeaf("tab");await A.setViewState({type:z,active:!0,state:{focusId:o,folderOverride:r===l?null:r}}),c.revealLeaf(A);let h=A.view;if(h&&typeof h.createNoteUnder=="function"){let g=await h.createNoteUnder(s,o);g&&typeof h.navigateTo=="function"&&h.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.locked){let n=i.locked.parentId??S;s?this.openNoteInNewTab(this.noteFolder,n):this.navigateTo(n);return}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}if(i.node){let n=this.plugin.settings.searchOpensInContext!==!1,o=n?i.node.parent??S:i.node.id,r=n?i.node.id:void 0;s?this.openNoteInNewTab(this.noteFolder,o,r):(r&&(this.pendingCursorId=r),this.navigateTo(o))}},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,lockedNotes:()=>this.plugin.lockedSubtreesInFolder(this.noteFolder),hideLockedTitles:!1});this.openSearchInstance=e;let t=e.onClose.bind(e);e.onClose=()=>{t(),this.openSearchInstance===e&&(this.openSearchInstance=null)},e.open()}excludedSearchFolders(){let e=new Set(this.plugin.searchableFolders(this.noteFolder));return this.plugin.discoverStashpadFolders().filter(t=>t!==this.noteFolder&&!e.has(t))}collectExcludedFolderNotes(){let e=this.excludedSearchFolders();if(!e.length)return[];let t=this.collectCrossFolderNotes(e),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===S&&i.set(o,n)}return[...e.map(n=>({file:i.get(n),folder:n,id:S,title:`Home \u2014 ${n.split("/").pop()||n}`,body:""})),...t]}collectCrossFolderNotes(e){let t=[],i=(e??this.plugin.searchableFolders(this.noteFolder)).filter(o=>o!==this.noteFolder);if(!i.length)return t;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 l=n.get(r);l||(l=[],n.set(r,l)),l.push(o)}for(let o of i){let r=n.get(o)??[],l=new Map;for(let c of r){let A=this.app.metadataCache.getFileCache(c)?.frontmatter;typeof A?.id=="string"&&l.set(A.id,c)}for(let c of r){let A=this.app.metadataCache.getFileCache(c)?.frontmatter,h=typeof A?.id=="string"?A.id:"";if(!h||h===S)continue;let g=c.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," "),u,f=A?.parent??null;if(f&&f!==S){let p=l.get(f);p&&(u=p.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," "))}t.push({file:c,folder:o,id:h,title:g,body:"",parentBlurb:u,parentId:f??null})}}return t}async switchToFolderAndFocus(e,t){await this.setFolderOverride(e),this.tree.get(t)&&this.navigateTo(t)}async cmdOutdent(){let e=this.getActionTargets();if(!e.length)return;let t=[],i=[],s=[];for(let o of e){let r=o.parent?this.tree.get(o.parent):null;if(!r||r.id===S){i.push(o.id);continue}let l=r.parent??S;s.push({id:o.id,path:o.file?.path??"",oldParent:o.parent??null,newParent:l}),await this.changeParent(o,l,{record:!1,silentSuccess:!0}),t.push(o)}if(t.length===0){new F.Notice(i.length?"Already at the top level.":"Nothing to outdent.");return}let n=this.noteFolder;if(this.plugin.getUndoStack(n).push({label:`Outdent (${t.length})`,undo:async()=>{for(let o of s){let r=this.fileForNote(o.id,o.path);r&&await this.app.fileManager.processFrontMatter(r,l=>{l.parent=o.oldParent??S})}this.tree.rebuild(n),this.render()},redo:async()=>{for(let o of s){let r=this.fileForNote(o.id,o.path);r&&await this.app.fileManager.processFrontMatter(r,l=>{l.parent=o.newParent})}this.tree.rebuild(n),this.render()}}),this.render(),this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Outdented",nodes:t,suffix:i.length?`(${i.length} already at root)`:void 0}),kind:"success",category:"move",affectedIds:t.map(o=>o.id),folder:this.noteFolder}),this.plugin.settings.autoNavOnMoveOut&&t.length>0){let o=t[0].parent;o!=null&&t.every(l=>l.parent===o)&&o!==this.focusId&&this.navigateTo(o)}}cmdSetColor(){let e=this.getActionTargets();if(!e.length)return;let t=new Set(e.map(n=>this.colorForNode(n)??"")),i=t.size===1&&Array.from(t)[0]||null,s=this.plugin.settings.customPalette??[];new Gt(this.app,i,s,async(n,o)=>{let r=[];for(let h of e)if(h.file){r.push({id:h.id,path:h.file.path,was:this.colorForNode(h)??null});try{await this.app.fileManager.processFrontMatter(h.file,g=>{n?g.color=n:delete g.color})}catch(g){new F.Notice(`Couldn't set color for ${h.id}: ${g.message}`)}}if(o.addToPalette&&typeof n=="string"){let h=[...this.plugin.settings.customPalette??[]],g=n.toLowerCase();h.some(u=>u.toLowerCase()===g)||(h.push(n),this.plugin.settings.customPalette=h,await this.plugin.persistSettingsQuiet(),await this.log.append({type:"palette_color_add",id:S,payload:{color:n}}))}this.render();let l=this.noteFolder,c=n,A=async h=>{for(let g of h){let u=this.fileForNote(g.id,g.path);if(u)try{await this.app.fileManager.processFrontMatter(u,f=>{g.col?f.color=g.col:delete f.color})}catch{}}this.tree.rebuild(l),this.render()};this.plugin.getUndoStack(l).push({label:r.length===1?"Color change":`Color change (${r.length})`,undo:()=>A(r.map(h=>({id:h.id,path:h.path,col:h.was}))),redo:()=>A(r.map(h=>({id:h.id,path:h.path,col:c})))})},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:S,payload:{color:n}}),o}).open()}cmdMovePicker(){let e=this.getActionTargets();e.length&&new je(this.app,this.tree,t=>this.titleForNode(t),{mode:"pick",placeholder:"Move to which note?",allowCreate:!0,onPick:async t=>{if(t.crossFolder){let o=t.crossId??t.id.replace(/^cross:/,"");await this.moveAcrossFolders(e,t.crossFolder,o),this.selection.clear(),this.render();return}let i=t.id,s=new Map(e.map(o=>[o.id,this.tree.getChildren(o.id).length])),n=[];for(let o of e)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 t=>{let i=await this.createNoteUnder(t,this.focusId);if(!i)return;let s=new Map(e.map(o=>[o.id,this.tree.getChildren(o.id).length])),n=[];for(let o of e)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(e,t,i){if(!e.length)return;let s=(t||"").replace(/\/+$/,"");if(!s){new F.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,u)=>{if(!g.file)return;let f=g.file,p=`${s}/${f.name}`;if(o.has(p)){let I=f.basename.match(/^(.*)(-[a-z0-9]{4,12})$/),m=I?I[1]:f.basename,B=I?I[2]:"";for(let C=1;C<1e3;C++){let w=`${m}-${C}${B}.md`,y=`${s}/${w}`;if(!o.has(y)){p=y;break}}}o.add(p),n.push({id:g.id,file:f,oldPath:f.path,newPath:p,oldParent:g.parent,isRoot:u});for(let I of this.tree.getChildren(g.id))r(I,!1)};for(let g of e)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,u=>{u.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(u){new F.Notice(`Move failed for ${g.id}: ${u.message}`)}if(X().writeRecoveryLinks){let g=this.noteFolder;window.setTimeout(()=>{Ci(this.app,g),Ci(this.app,s)},350)}let l=this.titleList(e);this.tree.rebuild(this.noteFolder);let c=i===S?"Open home":"Open parent",A=Math.max(0,n.length-e.length),h=e.length===1?`Moved ${l}${A>0?` and its ${A} nested note${A===1?"":"s"}`:""} \u2192 \`${s}\``:`Moved ${l}${A>0?` (${A} nested)`:""} \u2192 \`${s}\``;this.plugin.notifications.show({message:h,kind:"success",category:"move",duration:0,affectedIds:e.map(g=>g.id),folder:this.noteFolder,actions:[{label:c,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 u=this.app.vault.getAbstractFileByPath(g.newPath);if(u)try{await this.app.fileManager.renameFile(u,g.oldPath),g.isRoot&&await this.app.fileManager.processFrontMatter(u,f=>{f.parent=g.oldParent})}catch{}}this.tree.rebuild(this.noteFolder),this.render()},redo:async()=>{for(let g of n){let u=this.app.vault.getAbstractFileByPath(g.oldPath);if(u)try{await this.app.fileManager.renameFile(u,g.newPath),g.isRoot&&await this.app.fileManager.processFrontMatter(u,f=>{f.parent=i})}catch{}}this.tree.rebuild(this.noteFolder),this.render()}})}nextPickableIdx(e,t){for(let i=e+t;i>=0&&i<this.currentChildren.length;i+=t){let s=this.currentChildren[i];if(s&&!this.selection.has(s.id))return i}return e}cmdInListPicker(){if(this.currentChildren.length===0)return;let e=this.cursorIdx>0?this.cursorIdx-1:0;if(this.currentChildren[e]&&this.selection.has(this.currentChildren[e].id)){let n=this.nextPickableIdx(e,-1);e=n!==e?n:this.nextPickableIdx(e,1)}this.inListPicker={activeIdx:e};let t=X().bindings.move,i=ns(t.primary||t.secondary||"M");new F.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 e=this.currentChildren[this.inListPicker.activeIdx];if(this.inListPicker=null,!e){this.render();return}let t=this.getActionTargets().filter(r=>r.id!==e.id),i=new Map(t.map(r=>[r.id,this.tree.getChildren(r.id).length])),s=[];for(let r of t)await this.changeParent(r,e.id,{silentSuccess:!0})&&s.push(r);if(this.notifyBatchMove(s,e.id,i),this.plugin.settings.autoNavOnMoveIn){this.navigateTo(e.id);return}this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=[e.id],this.render({kind:"follow-cursor"});let n=this.selectionGuardKey,o=()=>{if(this.selectionGuardKey!==n)return;let r=this.currentChildren.findIndex(l=>l.id===e.id);r<0||this.selection.size===1&&this.selection.has(e.id)&&this.cursorIdx===r||(this.selection.clear(),this.selection.add(e.id),this.cursorIdx=r,this.render({kind:"follow-cursor"}))};setTimeout(o,120),setTimeout(o,400)}async cmdMerge(){let e=this.getActionTargets();if(e.length<2){new F.Notice("Select 2+ notes to merge.");return}e.sort((I,m)=>(I.created||"").localeCompare(m.created||""));let t=e[0];if(!t.file)return;let i=t.file.path,s=await this.app.vault.read(t.file),n=await this.snapshotNotes(e.slice(1),!1),o=[],r=[];for(let I of e){if(!I.file)continue;let m=await this.app.vault.cachedRead(I.file);r.push(this.stripFrontmatter(m).trim())}let l=r.map(I=>I.trim()).filter(Boolean).join(` +`:"";r.value+=`${H}${x} +`,this.composerDraft=r.value},Q=f.createEl("button",{cls:"stashpad-composer-btn"});(0,b.setIcon)(Q,"paperclip"),Q.title="Attach files",Q.onmousedown=x=>x.preventDefault(),Q.onclick=x=>{x.preventDefault();let H=document.activeElement===r;if(p.click(),H){let U=()=>{r.focus()};setTimeout(U,100),setTimeout(U,500)}},p.addEventListener("change",async()=>{let x=Array.from(p.files??[]);p.value="";for(let H of x){let U=await this.importAttachment(H);U&&C(U)}r.focus()}),f.append(m,Q,B,g);let y=u.createEl("button",{cls:"stashpad-composer-btn stashpad-composer-rail-toggle"});(0,b.setIcon)(y,"chevron-left"),y.title="Show more composer options",u.insertBefore(y,f);let E=x=>{u.toggleClass("is-expanded",x),y.title=x?"Hide options":"Show more composer options",(0,b.setIcon)(y,x?"chevron-right":"chevron-left")};y.onmousedown=x=>x.preventDefault(),y.onclick=x=>{x.preventDefault(),E(!u.hasClass("is-expanded"))},E(!1);let w=()=>n.clientWidth<(b.Platform.isMobile?360:700),v=()=>{let x=w();n.toggleClass("is-narrow",x),E(!x)};v(),requestAnimationFrame(v);let F=new ResizeObserver(v);F.observe(n),this.composerNarrowObserver?.disconnect(),this.composerNarrowObserver=F;let D=u.createEl("button",{cls:"stashpad-composer-btn stashpad-composer-send"});D.title="Send (Enter)",(0,b.setIcon)(D,"arrow-up");let R=async()=>{let x=r.value.trim();if(!x)return;r.value="",this.composerDraft="";try{await this.saveDraft("")}catch{}try{await this.recordLastSubmitted(x)}catch{}let H=this.modeSplit??X().splitOnLines,U=this.nextDestination,N=this.nextDestinationFolder,S=!!N&&N!==this.noteFolder;this.nextDestination=null,this.nextDestinationFolder=null,this.nextDestinationLabel=null,this.autoSelectNewest=!S,this.scrollToBottomOnNextRender=!S;let P=S?{targetFolder:N}:void 0,O=U??this.focusId;if(H){let L=Ti(x,X().splitMode);L.length===1?await this.createNoteUnder(L[0],O,P):L.length>1&&await this.createNotesBatch(L,O,P,x,S?N:this.noteFolder)}else await this.createNoteUnder(x,O,P);X().autofocusComposerAfterSend&&(this.focusComposerOnNextRender=!0,S&&this.composerInputEl?.focus())};D.onclick=()=>void R(),r.addEventListener("keydown",x=>{let H=this.modeEnterSubmits;if(x.key==="Escape"){x.preventDefault(),x.stopPropagation(),r.blur(),this.viewRoot.focus({preventScroll:!0});return}if(x.key==="ArrowUp"&&r.selectionStart===0&&r.selectionEnd===0){if(x.preventDefault(),r.blur(),this.viewRoot.focus({preventScroll:!0}),this.currentChildren.length>0){let U=this.lastCursorByFocus.get(this.focusId)??this.lastSelected,N=U?this.currentChildren.findIndex(S=>S.id===U):-1;this.cursorIdx=N>=0?N:this.currentChildren.length-1,this.selectCursor(!1)}return}x.key==="Enter"&&!x.isComposing&&(H?!x.shiftKey:x.shiftKey)&&(x.preventDefault(),x.stopPropagation(),x.stopImmediatePropagation(),R())});let G=e.createDiv({cls:"stashpad-composer-help"});this.composerHelperEl=G,G.setText(this.composerHelperText(i,s))}composerPlaceholder(e,t){return b.Platform.isMobile?t?"New notes (split on newlines)":"New note":`Type a note. ${e?"Enter":"Shift+Enter"} = send, ${e?"Shift+Enter":"Enter"} = newline${t?" (each line \u2192 a note)":""}\u2026`}composerHelperText(e,t){let i=e?"Enter":"Shift+Enter",s=e?"Shift+Enter":"Enter",n=X().bindings,o=h=>{let p=n[h];return p.primary&&p.secondary?p.preferRight?p.secondary:p.primary:p.primary||p.secondary},r=os(o("toggleSplit")),l=os(o("pickDestination")),c=os(o("search")),A=this.nextDestination?` \u2022 destination: ${this.destinationLabel()}`:"";return`${i} sends \xB7 ${s} newline \xB7 ${r} split: ${t?"ON":"off"} \xB7 ${l} destination \xB7 ${c} search${A}`}destinationLabel(){if(!this.nextDestination)return"current";if(this.nextDestinationFolder)return this.nextDestinationLabel??this.nextDestinationFolder;if(this.nextDestination===k)return"Home";let e=this.tree.get(this.nextDestination);return e?this.titleForNode(e).trim():"?"}renderMobileNav(e){let t=e.createDiv({cls:"stashpad-mobile-nav"});t.createEl("button",{text:"Home"}).onclick=()=>this.navigateTo(k),t.createEl("button",{text:"Back"}).onclick=()=>this.navigateUp(),t.createEl("button",{text:"Bookmarks"}).onclick=()=>this.openBookmarks()}handleRenderedClick(e,t){let i=e.target,s=i?.closest?.(".tag");if(s){e.preventDefault(),e.stopPropagation();let r=(s.getAttribute("href")||s.textContent||"").replace(/^#/,"").trim();if(r){let l=this.app.internalPlugins?.plugins?.["global-search"],c=l?.instance?.openGlobalSearch?.bind(l.instance);c&&c(`tag:#${r}`)}return}let n=i?.closest?.(".internal-link");if(n){e.preventDefault(),e.stopPropagation();let o=n.getAttribute("data-href")||n.getAttribute("href");if(o){let r=t.file?.path||"";this.app.workspace.openLinkText(o,r,!0)}}}handleRowClick(e,t,i){let s=this.shouldAbsorbDismissTap();if(this.traceTap("click",e,t,s),s){(!this.aimedTapTargetId||Date.now()-this.aimedTapAt>fs.AIMED_TAP_WINDOW_MS)&&(this.aimedTapTargetId=i.id,this.aimedTapAt=Date.now()),e.stopPropagation();return}this.aimedTapTargetId=null,this.cursorHasMoved=!0;let n=e.target,o=n?.closest?.(".tag");if(o){e.preventDefault(),e.stopPropagation();let A=(o.getAttribute("href")||o.textContent||"").replace(/^#/,"").trim();if(A){let h=this.app.internalPlugins?.plugins?.["global-search"],p=h?.instance?.openGlobalSearch?.bind(h.instance);p&&p(`tag:#${A}`)}return}let r=n?.closest?.(".internal-link");if(r){e.preventDefault(),e.stopPropagation();let c=r.getAttribute("data-href")||r.getAttribute("href");if(c){let A=i.file?.path||"";this.app.workspace.openLinkText(c,A,!0)}return}if(n?.tagName==="A"&&n.href)return;if(e.stopPropagation(),this.inListPicker){this.inListPicker.activeIdx=t,this.commitInListPicker();return}let l=this.selection.size===0;if(e.shiftKey&&this.lastSelected){this.cursorIdx=t;let c=this.currentChildren.findIndex(A=>A.id===this.lastSelected);if(l&&(this.firstSelectedId=this.lastSelected),c!==-1){let[A,h]=c<t?[c,t]:[t,c];for(let p=A;p<=h;p++)this.selection.add(this.currentChildren[p].id)}else this.selection.add(i.id)}else if(e.metaKey||e.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 c=this.lastSelected??[...this.selection][this.selection.size-1],A=c?this.currentChildren.findIndex(h=>h.id===c):-1;A>=0&&(this.cursorIdx=A)}else this.cursorIdx=t,l&&(this.firstSelectedId=i.id),this.selection.add(i.id);else this.mobileSelectMode?(this.cursorIdx=t,this.selection.has(i.id)?(this.selection.delete(i.id),this.firstSelectedId===i.id&&(this.firstSelectedId=null)):this.selection.add(i.id)):(this.cursorIdx=t,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 e=()=>{if(this.cursorIdx<0)return;let t=this.listEl?.querySelector(`[data-idx="${this.cursorIdx}"]`);if(!t||!this.listEl)return;let i=this.listEl,s=i.getBoundingClientRect(),n=t.getBoundingClientRect(),o=4,r=s.top+o,l=s.bottom-o;if(b.Platform.isMobile&&document.body.classList.contains("stashpad-keyboard-open")){let c=this.viewRoot?.querySelector(".stashpad-composer");c&&(l=Math.min(l,c.getBoundingClientRect().top-o))}n.top<r?i.scrollTop+=n.top-r:n.bottom>l&&(i.scrollTop+=n.bottom-l)};e(),requestAnimationFrame(e),setTimeout(e,60),setTimeout(e,200)}shouldAbsorbDismissTap(){return b.Platform.isMobile&&Date.now()<this.tapSettleUntil}traceTap(e,t,i,s){if(!this.plugin.settings.debugTrace||!this.listEl)return;let n=this.listEl,o=window.visualViewport,r=n.querySelector(`.stashpad-note[data-idx="${i}"]`)?.getBoundingClientRect();this.plugin.trace(`tap:${e}`,{absorbed:s,clientY:Math.round(t.clientY),clientX:Math.round(t.clientX),idx:i,rowTop:r?Math.round(r.top):null,listTop:Math.round(n.getBoundingClientRect().top),listScrollTop:Math.round(n.scrollTop),listScrollH:Math.round(n.scrollHeight),listClientH:Math.round(n.clientHeight),innerH:window.innerHeight,vvHeight:o?Math.round(o.height):null,vvOffsetTop:o?Math.round(o.offsetTop):null,tapSettleInMs:Math.max(0,this.tapSettleUntil-Date.now()),kbOpen:document.body.classList.contains("stashpad-keyboard-open")})}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(e){let t=this.currentChildren[this.cursorIdx];if(t){if(this.cursorHasMoved=!0,!e)this.selection.clear(),this.selection.add(t.id),this.firstSelectedId=t.id,this.lastSelected=t.id;else{let i=this.firstSelectedId??t.id,s=this.currentChildren.findIndex(n=>n.id===i);if(s===-1)this.selection.add(t.id),this.firstSelectedId=t.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=t.id}this.repaintSelectionClasses(),this.revealCursorRow(),this.stampSelectedCursor(),this.plugin.notifyStashpadSelectionChanged()}}repaintSelectionClasses(){if(!this.listEl)return;let e=!!this.plugin.settings.autoExpandCursorRow,t=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)),r||this.cursorExpandOverride.delete(o),s.classList.toggle("is-cursor-expanded",e&&r&&this.cursorHasMoved&&!this.cursorExpandOverride.has(o)),s.classList.toggle("is-pick-target",n===t)})}revealRowAt(e){if(!this.listEl)return;let t=this.listEl.querySelector(`.stashpad-note[data-idx="${e}"]`);if(!t)return;let i=t.getBoundingClientRect(),s=this.listEl.getBoundingClientRect();(i.top<s.top||i.bottom>s.bottom)&&t.scrollIntoView({block:"nearest",behavior:"auto"})}getActionTargets(){if(this.selection.size>0)return[...this.selection].map(t=>this.tree.get(t)).filter(t=>!!t&&!!t.file);let e=this.currentChildren[this.cursorIdx];return e?[e]:[]}cmdLockSelectionHideName(){return this.cmdLockSelection({hideName:!0})}async cmdLockSelection(e={}){if(!this.plugin.encryption?.isConfigured?.()){new b.Notice("Set up encryption first (Settings \u2192 Stashpad \u2192 Encryption).");return}let t=this.getActionTargets();if(t.length===0)return;let i=new Set(t.map(l=>l.id)),s=new Set((this.plugin.settings.lockedSubtrees??[]).map(l=>l.rootId).filter(l=>!!l)),n=t.filter(l=>{if(s.has(l.id))return!1;let c=l.parent;for(;c;){if(i.has(c))return!1;c=this.tree.get(c)?.parent??null}return!0});if(n.length===0){new b.Notice("Nothing to lock (already locked).");return}let o=0,r=[];for(let l of n){let c=this.order.getOrder(this.noteFolder,l.parent??k),A=c.indexOf(l.id),h=A>0?c[A-1]:null,p=await this.plugin.lockNoteSubtree(this.noteFolder,l.id,h,{silent:!0,hideTitle:e.hideName});p&&(o++,r.push({rootId:l.id,prevSibling:h,blob:p.blobPath}),await this.log.append({type:"lock",id:l.id}))}if(o>0){this.selection.clear(),this.lastSelected=null,this.render();let l=this.noteFolder;this.plugin.getUndoStack(l).push({label:`Lock ${o} stash${o===1?"":"es"}`,undo:async()=>{for(let c of r)try{await this.plugin.unlockBundleAt(c.blob,{silent:!0})}catch{}this.render()},redo:async()=>{for(let c of r){let A=await this.plugin.lockNoteSubtree(l,c.rootId,c.prevSibling,{silent:!0,hideTitle:e.hideName});A&&(c.blob=A.blobPath)}this.render()}}),this.plugin.notifications.show({message:`Locked ${o} stash${o===1?"":"es"} \u2014 undo to unlock.`,kind:"success",category:"system",folder:this.noteFolder,actions:[{label:"All encrypted",onClick:()=>void Pe(this.plugin,"encrypted")}]})}}async cmdMoveToArchive(){let e=this.getActionTargets();if(e.length===0)return;let t=(this.noteFolder??"").replace(/\/+$/,"");if(Es(t)){new b.Notice("These notes are already in an archive.",6e3);return}this.archiveSources(e,wt(t))}async archiveSources(e,t){let i=this.noteFolder,s=t.replace(/\/+$/,""),n=s.replace(/\/archive$/,""),o=this.plugin.archiveEncryptFor(n);try{await this.app.vault.adapter.exists(s)||await this.app.vault.createFolder(s)}catch{}if(!o){let p=new Set(e.map(C=>C.id)),u=e.filter(C=>{let Q=C.parent;for(;Q;){if(p.has(Q))return!1;Q=this.tree.get(Q)?.parent??null}return!0});if(u.length===0)return;let f=[],g=new Set,I=C=>{if(!g.has(C.id)){g.add(C.id),C.file&&f.push(C.file);for(let Q of this.tree.getChildren(C.id))I(Q)}};for(let C of u)I(C);let m=[];for(let C of f){let Q=C.path,y=C.name,E=y.lastIndexOf("."),w=E>0?y.slice(0,E):y,v=E>0?y.slice(E):"",F=`${s}/${y}`;for(let D=1;await this.app.vault.adapter.exists(F);D++)F=`${s}/${w}-${D}${v}`;try{await this.app.fileManager.renameFile(C,F),m.push({from:Q,to:F})}catch(D){console.warn("[Stashpad] plaintext archive move failed",Q,D)}}if(this.selection.clear(),this.lastSelected=null,this.tree.rebuild(i),this.render(),m.length>0)for(let C of u)await this.log.append({type:"archive",id:C.id,payload:{to:s,encrypted:!1}});let B=s.split("/").pop()||s;this.plugin.notifications.show({message:`Moved ${m.length} note${m.length===1?"":"s"} \u2192 plaintext archive \u201C${B}\u201D (de-indexed, not encrypted). Undo to bring ${m.length===1?"it":"them"} back.`,kind:"success",category:"system",folder:i,actions:[{label:"All archived",onClick:()=>void Pe(this.plugin,"archived")}]}),this.plugin.getUndoStack(i).push({label:`Archive (plaintext, ${u.length})`,undo:async()=>{for(let C of m){let Q=this.app.vault.getAbstractFileByPath(C.to);if(Q instanceof b.TFile)try{await this.app.fileManager.renameFile(Q,C.from)}catch(y){console.warn("[Stashpad] plaintext archive undo failed",C.to,y)}}this.tree.rebuild(i),this.render()},redo:async()=>{for(let C of m){let Q=this.app.vault.getAbstractFileByPath(C.from);if(Q instanceof b.TFile)try{await this.app.fileManager.renameFile(Q,C.to)}catch(y){console.warn("[Stashpad] plaintext archive redo failed",C.from,y)}}this.tree.rebuild(i),this.render()}});return}if(!this.plugin.encryption?.isConfigured?.()){new b.Notice(`Archiving here encrypts the notes ("Encrypt archived notes" is on for \u201C${n.split("/").pop()}\u201D), but encryption isn't set up yet (Settings \u2192 Stashpad \u2192 Encryption). Set it up \u2014 or turn that toggle off for a plaintext archive.`,9e3);return}let r=new Set(e.map(p=>p.id)),l=e.filter(p=>{let u=p.parent;for(;u;){if(r.has(u))return!1;u=this.tree.get(u)?.parent??null}return!0});if(l.length===0)return;let c=l.map(p=>p.id),A=[];for(let p of l){let u=this.order.getOrder(i,p.parent??k),f=u.indexOf(p.id),g=f>0?u[f-1]:null,I=await this.plugin.lockNoteSubtree(i,p.id,g,{silent:!0,blobFolder:t});I&&(A.push(I.blobPath),await this.log.append({type:"archive",id:p.id,payload:{to:t,encrypted:!0}}))}if(A.length===0)return;this.selection.clear(),this.lastSelected=null,this.tree.rebuild(i),this.render();let h=t.split("/").pop()||t;this.plugin.notifications.show({message:`Archived ${A.length} note${A.length===1?"":"s"} \u2192 \u201C${h}\u201D. Undo to bring ${A.length===1?"it":"them"} back.`,kind:"success",category:"system",folder:i,actions:[{label:"All archived",onClick:()=>void Pe(this.plugin,"archived")}]}),this.plugin.getUndoStack(i).push({label:`Archive (${A.length})`,undo:async()=>{let p=[];for(let u of A)try{await this.plugin.unlockBundleAt(u,{silent:!0,destFolder:i})||p.push(u)}catch(f){p.push(u),console.warn("[Stashpad] archive undo failed",u,f)}A=p,p.length&&new b.Notice(`Undo incomplete: ${p.length} archived item${p.length===1?"":"s"} couldn't be restored (they're still in the archive). Try again, or restore from the Archived view.`,8e3),this.tree.rebuild(i),this.render()},redo:async()=>{A=[];for(let p of c){let u=await this.plugin.lockNoteSubtree(i,p,null,{silent:!0,blobFolder:t});u&&A.push(u.blobPath)}this.tree.rebuild(i),this.render()}})}async cmdEncryptDelete(){if(!this.plugin.encryption?.isConfigured?.()){new b.Notice("Set up encryption first (Settings \u2192 Stashpad \u2192 Encryption).");return}let e=this.getActionTargets();if(e.length===0)return;let t=new Set(e.map(n=>n.id)),i=e.filter(n=>{let o=n.parent;for(;o;){if(t.has(o))return!1;o=this.tree.get(o)?.parent??null}return!0});if(i.length===0)return;let s=i.length;new _(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(e){if(!this.plugin.encryption?.isConfigured?.()){new b.Notice("Set up encryption first (Settings \u2192 Stashpad \u2192 Encryption).");return}let t=new Set(e.map(r=>r.id)),i=e.filter(r=>{let l=r.parent;for(;l;){if(t.has(l))return!1;l=this.tree.get(l)?.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 l=await this.plugin.encryptDeleteSubtree(s,r);l&&o.push(l)}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,actions:[{label:"Open Trash",onClick:()=>this.plugin.openEncryptedTrash()}]}),this.plugin.getUndoStack(s).push({label:`Secure delete (${o.length})`,undo:async()=>{let r=[];for(let l of o)try{await this.plugin.restoreDeletedAt(l,{silent:!0})||r.push(l)}catch(c){r.push(l),console.warn("[Stashpad] secure-delete undo failed",l,c)}o=r,r.length&&new b.Notice(`Undo incomplete: ${r.length} deleted item${r.length===1?"":"s"} couldn't be restored (still in Trash). Try again, or restore from the Trash view.`,8e3),this.tree.rebuild(s),this.render()},redo:async()=>{o=[];for(let r of n){let l=await this.plugin.encryptDeleteSubtree(s,r);l&&o.push(l)}this.tree.rebuild(s),this.render()}}))}async plaintextDeleteToStashpadTrash(e){let t=new Set(e.map(r=>r.id)),i=e.filter(r=>{let l=r.parent;for(;l;){if(t.has(l))return!1;l=this.tree.get(l)?.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 l=await this.plugin.plaintextDeleteSubtree(s,r);l&&(o.push(l),await this.log.append({type:"delete",id:r,payload:{to:"trash",bundle:l}}))}o.length!==0&&(this.selection.clear(),this.lastSelected=null,this.tree.rebuild(s),this.render(),this.plugin.notifications.show({message:`Deleted ${o.length} note${o.length===1?"":"s"} \u2192 Trash. Undo to bring ${o.length===1?"it":"them"} back.`,kind:"success",category:"system",folder:s,actions:[{label:"Open Trash",onClick:()=>this.plugin.openEncryptedTrash()}]}),this.plugin.getUndoStack(s).push({label:`Delete (${o.length})`,undo:async()=>{let r=[];for(let l of o)try{await this.plugin.restoreDeletedAt(l,{silent:!0})||r.push(l)}catch(c){r.push(l),console.warn("[Stashpad] plaintext-trash undo failed",l,c)}o=r,r.length&&new b.Notice(`Undo incomplete: ${r.length} deleted item${r.length===1?"":"s"} couldn't be restored (still in Trash). Try again, or restore from the Trash view.`,8e3),this.tree.rebuild(s),this.render()},redo:async()=>{o=[];for(let r of n){let l=await this.plugin.plaintextDeleteSubtree(s,r);l&&o.push(l)}this.tree.rebuild(s),this.render()}}))}async cmdUnlockAll(){if(!this.plugin.encryption?.isConfigured?.()){new b.Notice("Set up encryption first (Settings \u2192 Stashpad \u2192 Encryption).");return}let e=new Set,t=new Set,i=this.getActionTargets().map(n=>n.id);for(;i.length;){let n=i.pop();if(!t.has(n)){t.add(n);for(let o of this.tree.getChildren(n))i.push(o.id)}}for(let n of t)for(let o of this.plugin.lockedSubtreesFor(this.noteFolder,n))e.add(o.blob);if(e.size===0){let n=(this.tree.get(this.focusId)??this.tree.getRoot()).id;for(let o of this.plugin.lockedSubtreesFor(this.noteFolder,n))e.add(o.blob)}if(e.size===0){new b.Notice("No locked notes to unlock here.");return}if(!await this.plugin.ensureFolderUnlocked(this.noteFolder))return;let s=0;for(let n of e)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}))}syncComposerModeUI(){let e=this.modeSplit??X().splitOnLines,t=this.modeEnterSubmits;if(this.composerSplitBtn){this.composerSplitBtn.toggleClass("is-active",e);let i=ei[X().splitMode].toLowerCase();this.composerSplitBtn.title=e?`Split: ON \u2014 ${i} (Mod+/ to toggle, right-click to change)`:`Split into notes (Mod+/) \u2014 right-click to choose: ${i}`}this.composerEnterBtn&&((0,b.setIcon)(this.composerEnterBtn,t?"corner-down-left":"arrow-big-down-dash"),this.composerEnterBtn.title=t?"Enter sends (click to switch to Shift+Enter)":"Shift+Enter sends (click to switch to Enter)"),this.composerInputEl&&(this.composerInputEl.placeholder=this.composerPlaceholder(t,e)),this.composerHelperEl&&this.composerHelperEl.setText(this.composerHelperText(t,e))}refreshDestButton(){let e=this.composerDestBtn;e&&(e.empty(),(0,b.setIcon)(e,"map-pin"),this.nextDestination&&e.createSpan({text:` ${this.destinationLabel()}`,cls:"stashpad-btn-text"}),e.toggleClass("is-active",!!this.nextDestination)),this.syncComposerModeUI()}toggleSplit(){let e=this.modeSplit??X().splitOnLines;this.modeSplit=!e,this.syncComposerModeUI(),this.composerInputEl?.focus()}openDestinationPicker(e=!1){let t=!1;new _e(this.app,this.tree,i=>this.titleForNode(i),{mode:"pick",placeholder:"Send next note(s) under which note?",allowCreate:!0,onPick:async i=>{if(t=!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===k?"Home":(i.crossFile?.basename??"note").replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ");this.nextDestinationLabel=`${n} \u25B8 ${o}`,this.refreshDestButton(),this.composerInputEl?.focus();return}this.nextDestination=i.id,this.nextDestinationFolder=null,this.nextDestinationLabel=null,this.refreshDestButton(),this.composerInputEl?.focus()},onCreate:async i=>{t=!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:()=>{e&&!t&&this.composerInputEl?.focus()}}).open()}collectCrossFolderDestinations(){let e=this.collectCrossFolderNotes(),t=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(!t.includes(o))continue;this.app.metadataCache.getFileCache(n)?.frontmatter?.id===k&&i.set(o,n)}return[...t.map(n=>({file:i.get(n),folder:n,id:k,title:`Home \u2014 ${n.split("/").pop()||n}`,body:""})),...e]}openSearchInParentModal(){let e=this.focusId,t=s=>{if(s===e)return!0;let n=new Set,o=this.tree.get(s);for(;o&&o.id!==k&&!n.has(o.id);){if(n.add(o.id),o.parent===e||o.id===e)return!0;if(!o.parent)return!1;o=this.tree.get(o.parent)}return e===k},i=new Proxy(this.tree,{get:(s,n)=>n==="getRoot"?()=>s.get(e)??s.getRoot():n==="getChildren"?o=>s.getChildren(o):s[n]});new _e(this.app,i,s=>this.titleForNode(s),{mode:"search",placeholder:`Search in "${this.titleForNode(this.tree.get(e)??this.tree.getRoot()).trim()}"\u2026`,allowCreate:!1,onPick:s=>{s.node&&t(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 e=new _e(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 _e(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 l=(this.plugin.settings.folder||"Stashpad").trim().replace(/^\/+|\/+$/g,"")||"Stashpad",c=this.app.workspace,A=c.getLeaf("tab");await A.setViewState({type:z,active:!0,state:{focusId:o,folderOverride:r===l?null:r}}),c.revealLeaf(A);let h=A.view;if(h&&typeof h.createNoteUnder=="function"){let p=await h.createNoteUnder(s,o);p&&typeof h.navigateTo=="function"&&h.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.locked){let n=i.locked.parentId??k;s?this.openNoteInNewTab(this.noteFolder,n):this.navigateTo(n);return}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}if(i.node){let n=this.plugin.settings.searchOpensInContext!==!1,o=n?i.node.parent??k:i.node.id,r=n?i.node.id:void 0;s?this.openNoteInNewTab(this.noteFolder,o,r):(r&&(this.pendingCursorId=r),this.navigateTo(o))}},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,lockedNotes:()=>this.plugin.lockedSubtreesInFolder(this.noteFolder),hideLockedTitles:!1});this.openSearchInstance=e;let t=e.onClose.bind(e);e.onClose=()=>{t(),this.openSearchInstance===e&&(this.openSearchInstance=null)},e.open()}excludedSearchFolders(){let e=new Set(this.plugin.searchableFolders(this.noteFolder));return this.plugin.discoverStashpadFolders().filter(t=>t!==this.noteFolder&&!e.has(t))}collectExcludedFolderNotes(){let e=this.excludedSearchFolders();if(!e.length)return[];let t=this.collectCrossFolderNotes(e),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===k&&i.set(o,n)}return[...e.map(n=>({file:i.get(n),folder:n,id:k,title:`Home \u2014 ${n.split("/").pop()||n}`,body:""})),...t]}collectCrossFolderNotes(e){let t=[],i=(e??this.plugin.searchableFolders(this.noteFolder)).filter(o=>o!==this.noteFolder);if(!i.length)return t;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 l=n.get(r);l||(l=[],n.set(r,l)),l.push(o)}for(let o of i){let r=n.get(o)??[],l=new Map;for(let c of r){let A=this.app.metadataCache.getFileCache(c)?.frontmatter;typeof A?.id=="string"&&l.set(A.id,c)}for(let c of r){let A=this.app.metadataCache.getFileCache(c)?.frontmatter,h=typeof A?.id=="string"?A.id:"";if(!h||h===k)continue;let p=c.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," "),u,f=A?.parent??null;if(f&&f!==k){let g=l.get(f);g&&(u=g.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," "))}t.push({file:c,folder:o,id:h,title:p,body:"",parentBlurb:u,parentId:f??null})}}return t}async switchToFolderAndFocus(e,t){await this.setFolderOverride(e),this.tree.get(t)&&this.navigateTo(t)}async cmdOutdent(){let e=this.getActionTargets();if(!e.length)return;let t=[],i=[],s=[];for(let o of e){let r=o.parent?this.tree.get(o.parent):null;if(!r||r.id===k){i.push(o.id);continue}let l=r.parent??k;s.push({id:o.id,path:o.file?.path??"",oldParent:o.parent??null,newParent:l}),await this.changeParent(o,l,{record:!1,silentSuccess:!0}),t.push(o)}if(t.length===0){new b.Notice(i.length?"Already at the top level.":"Nothing to outdent.");return}let n=this.noteFolder;if(this.plugin.getUndoStack(n).push({label:`Outdent (${t.length})`,undo:async()=>{for(let o of s){let r=this.fileForNote(o.id,o.path);r&&await this.app.fileManager.processFrontMatter(r,l=>{l.parent=o.oldParent??k})}this.tree.rebuild(n),this.render()},redo:async()=>{for(let o of s){let r=this.fileForNote(o.id,o.path);r&&await this.app.fileManager.processFrontMatter(r,l=>{l.parent=o.newParent})}this.tree.rebuild(n),this.render()}}),this.render(),this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Outdented",nodes:t,suffix:i.length?`(${i.length} already at root)`:void 0}),kind:"success",category:"move",affectedIds:t.map(o=>o.id),folder:this.noteFolder}),this.plugin.settings.autoNavOnMoveOut&&t.length>0){let o=t[0].parent;o!=null&&t.every(l=>l.parent===o)&&o!==this.focusId&&this.navigateTo(o)}}cmdSetColor(){let e=this.getActionTargets();if(!e.length)return;let t=new Set(e.map(n=>this.colorForNode(n)??"")),i=t.size===1&&Array.from(t)[0]||null,s=this.plugin.settings.customPalette??[];new Lt(this.app,i,s,async(n,o)=>{let r=[];for(let h of e)if(h.file){r.push({id:h.id,path:h.file.path,was:this.colorForNode(h)??null});try{await this.app.fileManager.processFrontMatter(h.file,p=>{n?p.color=n:delete p.color})}catch(p){new b.Notice(`Couldn't set color for ${h.id}: ${p.message}`)}}if(o.addToPalette&&typeof n=="string"){let h=[...this.plugin.settings.customPalette??[]],p=n.toLowerCase();h.some(u=>u.toLowerCase()===p)||(h.push(n),this.plugin.settings.customPalette=h,await this.plugin.persistSettingsQuiet(),await this.log.append({type:"palette_color_add",id:k,payload:{color:n}}))}this.render();let l=this.noteFolder,c=n,A=async h=>{for(let p of h){let u=this.fileForNote(p.id,p.path);if(u)try{await this.app.fileManager.processFrontMatter(u,f=>{p.col?f.color=p.col:delete f.color})}catch{}}this.tree.rebuild(l),this.render()};this.plugin.getUndoStack(l).push({label:r.length===1?"Color change":`Color change (${r.length})`,undo:()=>A(r.map(h=>({id:h.id,path:h.path,col:h.was}))),redo:()=>A(r.map(h=>({id:h.id,path:h.path,col:c})))})},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:k,payload:{color:n}}),o}).open()}cmdMovePicker(){let e=this.getActionTargets();e.length&&new _e(this.app,this.tree,t=>this.titleForNode(t),{mode:"pick",placeholder:"Move to which note?",allowCreate:!0,onPick:async t=>{if(t.crossFolder){let o=t.crossId??t.id.replace(/^cross:/,"");await this.moveAcrossFolders(e,t.crossFolder,o),this.selection.clear(),this.render();return}let i=t.id,s=new Map(e.map(o=>[o.id,this.tree.getChildren(o.id).length])),n=[];for(let o of e)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 t=>{let i=await this.createNoteUnder(t,this.focusId);if(!i)return;let s=new Map(e.map(o=>[o.id,this.tree.getChildren(o.id).length])),n=[];for(let o of e)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(e,t,i){if(!e.length)return;let s=(t||"").replace(/\/+$/,"");if(!s){new b.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,u)=>{if(!p.file)return;let f=p.file,g=`${s}/${f.name}`;if(o.has(g)){let I=f.basename.match(/^(.*)(-[a-z0-9]{4,12})$/),m=I?I[1]:f.basename,B=I?I[2]:"";for(let C=1;C<1e3;C++){let Q=`${m}-${C}${B}.md`,y=`${s}/${Q}`;if(!o.has(y)){g=y;break}}}o.add(g),n.push({id:p.id,file:f,oldPath:f.path,newPath:g,oldParent:p.parent,isRoot:u});for(let I of this.tree.getChildren(p.id))r(I,!1)};for(let p of e)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,u=>{u.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(u){new b.Notice(`Move failed for ${p.id}: ${u.message}`)}if(X().writeRecoveryLinks){let p=this.noteFolder;window.setTimeout(()=>{Bi(this.app,p),Bi(this.app,s)},350)}let l=this.titleList(e);this.tree.rebuild(this.noteFolder);let c=i===k?"Open home":"Open parent",A=Math.max(0,n.length-e.length),h=e.length===1?`Moved ${l}${A>0?` and its ${A} nested note${A===1?"":"s"}`:""} \u2192 \`${s}\``:`Moved ${l}${A>0?` (${A} nested)`:""} \u2192 \`${s}\``;this.plugin.notifications.show({message:h,kind:"success",category:"move",duration:0,affectedIds:e.map(p=>p.id),folder:this.noteFolder,actions:[{label:c,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 u=this.app.vault.getAbstractFileByPath(p.newPath);if(u)try{await this.app.fileManager.renameFile(u,p.oldPath),p.isRoot&&await this.app.fileManager.processFrontMatter(u,f=>{f.parent=p.oldParent})}catch{}}this.tree.rebuild(this.noteFolder),this.render()},redo:async()=>{for(let p of n){let u=this.app.vault.getAbstractFileByPath(p.oldPath);if(u)try{await this.app.fileManager.renameFile(u,p.newPath),p.isRoot&&await this.app.fileManager.processFrontMatter(u,f=>{f.parent=i})}catch{}}this.tree.rebuild(this.noteFolder),this.render()}})}nextPickableIdx(e,t){for(let i=e+t;i>=0&&i<this.currentChildren.length;i+=t){let s=this.currentChildren[i];if(s&&!this.selection.has(s.id))return i}return e}cmdInListPicker(){if(this.currentChildren.length===0)return;let e=this.cursorIdx>0?this.cursorIdx-1:0;if(this.currentChildren[e]&&this.selection.has(this.currentChildren[e].id)){let n=this.nextPickableIdx(e,-1);e=n!==e?n:this.nextPickableIdx(e,1)}this.inListPicker={activeIdx:e};let t=X().bindings.move,i=os(t.primary||t.secondary||"M");new b.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 e=this.currentChildren[this.inListPicker.activeIdx];if(this.inListPicker=null,!e){this.render();return}let t=this.getActionTargets().filter(r=>r.id!==e.id),i=new Map(t.map(r=>[r.id,this.tree.getChildren(r.id).length])),s=[];for(let r of t)await this.changeParent(r,e.id,{silentSuccess:!0})&&s.push(r);if(this.notifyBatchMove(s,e.id,i),this.plugin.settings.autoNavOnMoveIn){this.navigateTo(e.id);return}this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=[e.id],this.render({kind:"follow-cursor"});let n=this.selectionGuardKey,o=()=>{if(this.selectionGuardKey!==n)return;let r=this.currentChildren.findIndex(l=>l.id===e.id);r<0||this.selection.size===1&&this.selection.has(e.id)&&this.cursorIdx===r||(this.selection.clear(),this.selection.add(e.id),this.cursorIdx=r,this.render({kind:"follow-cursor"}))};setTimeout(o,120),setTimeout(o,400)}async cmdMerge(){let e=this.getActionTargets();if(e.length<2){new b.Notice("Select 2+ notes to merge.");return}e.sort((I,m)=>(I.created||"").localeCompare(m.created||""));let t=e[0];if(!t.file)return;let i=t.file.path,s=await this.app.vault.read(t.file),n=await this.snapshotNotes(e.slice(1),!1),o=[],r=[];for(let I of e){if(!I.file)continue;let m=await this.app.vault.cachedRead(I.file);r.push(this.stripFrontmatter(m).trim())}let l=r.map(I=>I.trim()).filter(Boolean).join(` `),c=await this.app.vault.read(t.file),A=c.startsWith("---")?c.indexOf(` ---`,3):-1;if(c.startsWith("---")&&A<0){this.plugin.notifications.show({message:"Can't merge \u2014 the kept note's frontmatter is malformed (no closing ---).",kind:"warning",category:"merge",folder:this.noteFolder});return}let h=c.startsWith("---")?A+4:0,u=`${c.slice(0,h)} ${l} -`;await this.app.vault.modify(t.file,u);for(let I=1;I<e.length;I++){let m=e[I];if(m.file){for(let B of this.tree.getChildren(m.id)){let C=B.parent,w=B.id===t.id?m.parent??S:t.id;await this.changeParent(B,w,{record:!1})&&B.file&&o.push({childId:B.id,childPath:B.file.path,oldParent:C,newParent:w})}await this.app.fileManager.trashFile(m.file),await this.log.append({type:"delete",id:m.id,payload:{mergedInto:t.id}})}}this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=[t.id];let f=this.titleForNode(t);this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Merged",nodes:e,destination:`\u2192 kept "${f}"`}),kind:"success",category:"merge",affectedIds:e.map(I=>I.id),folder:this.noteFolder}),this.tree.rebuild(this.noteFolder),this.render({kind:"follow-cursor"});{let I=t.id,m=this.selectionGuardKey,B=()=>{if(this.selectionGuardKey!==m||this.selection.has(I))return;let C=this.currentChildren.findIndex(w=>w.id===I);C<0||(this.selection.add(I),this.cursorIdx=C,this.render({kind:"follow-cursor"}))};setTimeout(B,120),setTimeout(B,400)}let p=this.noteFolder;this.plugin.getUndoStack(p).push({label:`Merge ${e.length} notes`,undo:async()=>{await this.restoreSnapshots(n,e.map(m=>m.id));let I=this.fileForNote(t.id,i);I&&await this.app.vault.modify(I,s);for(let m of o){let B=this.fileForNote(m.childId,m.childPath);B&&await this.app.fileManager.processFrontMatter(B,C=>{C.parent=m.oldParent})}this.pendingFocusIds=e.map(m=>m.id),this.tree.rebuild(p),this.render({kind:"follow-cursor"})},redo:async()=>{await this.trashNotesAndAttachments(n);let I=this.fileForNote(t.id,i);I&&await this.app.vault.modify(I,u);for(let m of o){let B=this.fileForNote(m.childId,m.childPath);B&&await this.app.fileManager.processFrontMatter(B,C=>{C.parent=m.newParent})}this.tree.rebuild(p),this.render()}})}cmdCopy(){return Oo(this)}cmdCopyCodeBlock(){return ka(this)}cmdCopyTree(){return Sa(this)}cmdCopyOutline(){return ba(this)}cmdToggleExpand(){let e=this.getActionTargets();if(!e.length)return;let t=e.some(i=>!this.isNoteExpanded(i.id));for(let i of e)this.setNoteExpanded(i.id,t);this.render()}isNoteExpanded(e){let t=this.expandedNotes.has(e);return this.plugin.settings.expandBodiesByDefault?!t:t}setNoteExpanded(e,t){let i=this.plugin.settings.expandBodiesByDefault;t===i?this.expandedNotes.delete(e):this.expandedNotes.add(e)}cmdExpandAll(){for(let e of this.currentChildren)this.setNoteExpanded(e.id,!0);this.render()}cmdCollapseAll(){for(let e of this.currentChildren)this.setNoteExpanded(e.id,!1);this.render()}async cloneSubtree(e,t,i,s={}){if(!e.file)return null;if(e.id===t||this.isDescendant(t,e.id))return new F.Notice(`Can't insert "${this.titleForNode(e)}" into itself or a descendant \u2014 that would loop forever.`),null;let n=this.tree.getChildren(e.id).slice(),o=e.file,r=await this.app.vault.read(o),l=this.stripFrontmatter(r),c=this.app.metadataCache.getFileCache(o)?.frontmatter??{},A=this.plugin.mintNoteId(),h=Se(l,this.activeStopwords()),g=be(h,A),u=`${this.noteFolder}/${g}`,f=new Date().toISOString(),p=s.preserveCreated&&e.created?e.created:f,I=this.extractAttachments(l),m=["---",`id: ${A}`,`parent: ${t}`,`created: ${p}`];if(I.length>0){m.push("attachments:");for(let C of I)m.push(` - "${C.replace(/"/g,'\\"')}"`)}else m.push("attachments: []");m.push("---",l),await this.ensureFolder(this.noteFolder),await this.app.vault.create(u,m.join(` -`)),i.push(u);let B=this.app.vault.getAbstractFileByPath(u);if(B){try{await this.app.fileManager.processFrontMatter(B,C=>{for(let[w,y]of Object.entries(c))ze.includes(w)||Wn.includes(w)||(C[w]=y);s.preserveCreated&&(C.modified=f),s.copyKind==="fork"&&(C[Vn]=f)})}catch(C){console.warn("[Stashpad] cloneSubtree: processFrontMatter failed",C)}try{this.tree.insertSynthetic({id:A,parent:t,children:[],file:B,created:p})}catch{}this.fmSync.scheduleParentChange(A,null,t)}for(let C of n)await this.cloneSubtree(C,A,i,s);return A}async cmdClone(){let e=this.getActionTargets();if(!e.length){new F.Notice("Nothing to clone.");return}let t=new Set(e.map(A=>A.id)),i=e.filter(A=>{let h=A.parent;for(;h;){if(t.has(h))return!1;h=this.tree.get(h)?.parent??null}return!0}),s=this.noteFolder,n=[],o=[];try{for(let A of i){if(!A.file)continue;let h=A.parent??this.focusId,g=await this.cloneSubtree(A,h,n);g&&o.push(g)}}catch(A){console.warn("[Stashpad] clone failed partway",A),new F.Notice(`Clone stopped early: ${A.message}`)}if(!o.length)return;this.tree.rebuild(s),this.pendingFocusIds=o.slice(),this.render();let r=n.map(A=>this.app.vault.getAbstractFileByPath(A)).filter(A=>!!A&&A.extension==="md").map(A=>({id:lt(A.basename)??A.basename,parent:null,children:[],file:A,created:new Date().toISOString()})),l=await this.snapshotNotes(r,!1);this.plugin.getUndoStack(s).push({label:`Clone ${o.length} note${o.length===1?"":"s"}`,undo:async()=>{for(let A of[...n].reverse()){let h=this.app.vault.getAbstractFileByPath(A);if(h)try{await this.app.fileManager.trashFile(h)}catch{}}this.tree.rebuild(s),this.render()},redo:async()=>{await this.restoreSnapshots(l,o)}});let c=o.map(A=>this.tree.get(A)).filter(A=>!!A);this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Cloned",nodes:c,suffix:`(${n.length} file${n.length===1?"":"s"} total)`}),kind:"success",category:"clone",affectedIds:o,folder:this.noteFolder})}cmdForkNote(){let e=this.getActionTargets()[0];if(!e?.file){new F.Notice("Nothing to fork.");return}let t=e.parent??S,i=t===S?null:this.tree.get(t),s=i?this.titleForNode(i):"Home";new je(this.app,this.tree,n=>this.titleForNode(n),{mode:"pick",allowCreate:!0,placeholder:`Fork "${this.titleForNode(e)}" under\u2026 (default: ${s})`,onPick:n=>{if(n.crossFolder){new F.Notice("Fork stays in this folder for now.");return}this.forkNoteUnder(e,n.id)},onCreate:n=>{(async()=>{let o=await this.createNoteUnder(n,this.focusId);o&&await this.forkNoteUnder(e,o)})()}}).open()}async forkNoteUnder(e,t){if(!e.file)return;let i=this.noteFolder,s=[],n=await this.cloneSubtree(e,t,s,{preserveCreated:!0,copyKind:"fork"});if(!n)return;let o=s[0]?this.app.vault.getAbstractFileByPath(s[0]):null;if(o)try{await this.app.fileManager.processFrontMatter(o,A=>{A[Di]=`[[${e.file.basename}]]`})}catch{}this.tree.rebuild(i),this.pendingFocusIds=[n],this.render(),await this.syncForkSiblings(this.forkFamilyFiles({originName:e.file.basename,include:[e.file,o]}));let r=s.map(A=>this.app.vault.getAbstractFileByPath(A)).filter(A=>!!A&&A.extension==="md").map(A=>({id:lt(A.basename)??A.basename,parent:null,children:[],file:A,created:new Date().toISOString()})),l=await this.snapshotNotes(r,!1);this.plugin.getUndoStack(i).push({label:"Fork note",undo:async()=>{for(let A of[...s].reverse()){let h=this.app.vault.getAbstractFileByPath(A);if(h)try{await this.app.fileManager.trashFile(h)}catch{}}this.tree.rebuild(i),this.render()},redo:async()=>{await this.restoreSnapshots(l,[n])}});let c=this.tree.get(n);this.plugin.notifications.show({message:c?`Forked "${this.titleForNode(e)}" \u2192 "${this.titleForNode(c)}" (${s.length} file${s.length===1?"":"s"})`:"Forked note",kind:"success",category:"clone",affectedIds:[n],folder:i})}async ensureSheetGroup(e){let t=Ye(this.app.metadataCache.getFileCache(e)?.frontmatter);if(t)return t;let i=mr();return await this.app.fileManager.processFrontMatter(e,s=>{s[Si]=i,typeof s[nt]!="number"&&(s[nt]=0),s[bi]=!0}),i}forkFamilyFiles(e){let t=new Map,i=s=>{s&&t.set(s.path,s)};for(let s of this.app.vault.getMarkdownFiles()){let n=this.app.metadataCache.getFileCache(s)?.frontmatter;e.gid&&Ye(n)===e.gid&&i(s),e.originName&&(s.basename===e.originName||Ir(n)===e.originName)&&i(s)}for(let s of e.include??[])i(s);return[...t.values()]}async syncForkSiblings(e){for(let t of e){let i=e.filter(s=>s.path!==t.path).map(s=>`[[${s.basename}]]`);await this.app.fileManager.processFrontMatter(t,s=>{i.length?s[$e]=i:delete s[$e]})}}async cmdForkVersion(e){this.plugin.settings.enableSheetVersions||(this.plugin.settings.enableSheetVersions=!0,await this.plugin.saveSettings(),new F.Notice("Sheet versions enabled."));let t=e??this.getActionTargets()[0];if(!t?.file){new F.Notice("Select a note to version.");return}let i=this.noteFolder,s={...this.app.metadataCache.getFileCache(t.file)?.frontmatter??{}},n=await this.ensureSheetGroup(t.file),o=t.parent??this.focusId,r=typeof s[nt]=="number"?s[nt]:0;for(let f of this.tree.getChildren(o)){if(f.id===t.id)continue;let p=ye(this.app,f);if(Ye(p)!==n)continue;let I=p?.[nt];typeof I=="number"&&I>r&&(r=I)}let l=r+1,c=[],A=await this.cloneSubtree(t,o,c,{preserveCreated:!0,copyKind:"fork"});if(!A||!c.length){new F.Notice("Sheets: could not create version.");return}let h=this.app.vault.getAbstractFileByPath(c[0]);h&&await this.app.fileManager.processFrontMatter(h,f=>{f[Si]=n,f[nt]=l,delete f[Vt],delete f[bi],f[Di]=`[[${t.file.basename}]]`}),this.tree.rebuild(i),this.activeVersionByGroup.set(n,A),this.plugin.saveActiveVersion(i,n,A),this.render();let g=this.app.vault.getAbstractFileByPath(c[0]);await this.syncForkSiblings(this.forkFamilyFiles({gid:n,include:[t.file,g]})),this.plugin.getUndoStack(i).push({label:"Fork version",undo:async()=>{for(let f of[...c].reverse()){let p=this.app.vault.getAbstractFileByPath(f);if(p)try{await this.app.fileManager.trashFile(p)}catch{}}this.activeVersionByGroup.delete(n),this.tree.rebuild(i),this.render()},redo:async()=>{}});let u=c.length;new F.Notice(`Forked a new version${u>1?` (${u} notes)`:""}`)}async cmdMarkVersionFinal(e){this.plugin.settings.enableSheetVersions||(this.plugin.settings.enableSheetVersions=!0,await this.plugin.saveSettings());let t=e??this.getActionTargets()[0];if(!t?.file)return;let i=Ye(ye(this.app,t));if(!i){new F.Notice("Not a versioned note.");return}let s=!Ni(ye(this.app,t)),n=t.parent??this.focusId,o=this.tree.getChildren(n).filter(r=>Ye(ye(this.app,r))===i);for(let r of o){if(!r.file)continue;let l=Ni(ye(this.app,r)),c=s&&r.id===t.id;l!==c&&await this.app.fileManager.processFrontMatter(r.file,A=>{c?A[Vt]=!0:delete A[Vt]})}this.render()}async cmdCopyNotes(){let e=this.getActionTargets();if(!e.length){new F.Notice("Nothing to copy.");return}await Oo(this),this.plugin.clearNoteClipboard(),this.plugin.noteClipboard={mode:"copy",folder:this.noteFolder,ids:e.map(t=>t.id)},this.render()}isCutPending(e){let t=this.plugin.noteClipboard;return!!t&&t.mode==="cut"&&t.folder===this.noteFolder&&t.ids.includes(e)}isCopyPending(e){let t=this.plugin.noteClipboard;return!!t&&t.mode==="copy"&&t.folder===this.noteFolder&&t.ids.includes(e)}insertIntoComposer(e){let t=this.composerInputEl;if(!t){this.composerDraft=this.composerDraft?`${this.composerDraft} +`;await this.app.vault.modify(t.file,u);for(let I=1;I<e.length;I++){let m=e[I];if(m.file){for(let B of this.tree.getChildren(m.id)){let C=B.parent,Q=B.id===t.id?m.parent??k:t.id;await this.changeParent(B,Q,{record:!1})&&B.file&&o.push({childId:B.id,childPath:B.file.path,oldParent:C,newParent:Q})}await this.app.fileManager.trashFile(m.file),await this.log.append({type:"delete",id:m.id,payload:{mergedInto:t.id}})}}this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=[t.id];let f=this.titleForNode(t);this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Merged",nodes:e,destination:`\u2192 kept "${f}"`}),kind:"success",category:"merge",affectedIds:e.map(I=>I.id),folder:this.noteFolder}),this.tree.rebuild(this.noteFolder),this.render({kind:"follow-cursor"});{let I=t.id,m=this.selectionGuardKey,B=()=>{if(this.selectionGuardKey!==m||this.selection.has(I))return;let C=this.currentChildren.findIndex(Q=>Q.id===I);C<0||(this.selection.add(I),this.cursorIdx=C,this.render({kind:"follow-cursor"}))};setTimeout(B,120),setTimeout(B,400)}let g=this.noteFolder;this.plugin.getUndoStack(g).push({label:`Merge ${e.length} notes`,undo:async()=>{await this.restoreSnapshots(n,e.map(m=>m.id));let I=this.fileForNote(t.id,i);I&&await this.app.vault.modify(I,s);for(let m of o){let B=this.fileForNote(m.childId,m.childPath);B&&await this.app.fileManager.processFrontMatter(B,C=>{C.parent=m.oldParent})}this.pendingFocusIds=e.map(m=>m.id),this.tree.rebuild(g),this.render({kind:"follow-cursor"})},redo:async()=>{await this.trashNotesAndAttachments(n);let I=this.fileForNote(t.id,i);I&&await this.app.vault.modify(I,u);for(let m of o){let B=this.fileForNote(m.childId,m.childPath);B&&await this.app.fileManager.processFrontMatter(B,C=>{C.parent=m.newParent})}this.tree.rebuild(g),this.render()}})}cmdCopy(){return Jo(this)}cmdCopyCodeBlock(){return xa(this)}cmdCopyTree(){return Na(this)}cmdCopyOutline(){return Ma(this)}cmdToggleExpand(){let e=this.getActionTargets();if(!e.length)return;let t=e.some(i=>!this.isNoteExpanded(i.id));for(let i of e)this.setNoteExpanded(i.id,t);this.render()}isNoteExpanded(e){let t=this.expandedNotes.has(e);return this.plugin.settings.expandBodiesByDefault?!t:t}setNoteExpanded(e,t){let i=this.plugin.settings.expandBodiesByDefault;t===i?this.expandedNotes.delete(e):this.expandedNotes.add(e)}cmdExpandAll(){for(let e of this.currentChildren)this.setNoteExpanded(e.id,!0);this.render()}cmdCollapseAll(){for(let e of this.currentChildren)this.setNoteExpanded(e.id,!1);this.render()}async cloneSubtree(e,t,i,s={}){if(!e.file)return null;if(e.id===t||this.isDescendant(t,e.id))return new b.Notice(`Can't insert "${this.titleForNode(e)}" into itself or a descendant \u2014 that would loop forever.`),null;let n=this.tree.getChildren(e.id).slice(),o=e.file,r=await this.app.vault.read(o),l=this.stripFrontmatter(r),c=this.app.metadataCache.getFileCache(o)?.frontmatter??{},A=this.plugin.mintNoteId(),h=Se(l,this.activeStopwords()),p=be(h,A),u=`${this.noteFolder}/${p}`,f=new Date().toISOString(),g=s.preserveCreated&&e.created?e.created:f,I=this.extractAttachments(l),m=["---",`id: ${A}`,`parent: ${t}`,`created: ${g}`];if(I.length>0){m.push("attachments:");for(let C of I)m.push(` - "${C.replace(/"/g,'\\"')}"`)}else m.push("attachments: []");m.push("---",l),await this.ensureFolder(this.noteFolder),await this.app.vault.create(u,m.join(` +`)),i.push(u);let B=this.app.vault.getAbstractFileByPath(u);if(B){try{await this.app.fileManager.processFrontMatter(B,C=>{for(let[Q,y]of Object.entries(c))Ve.includes(Q)||jn.includes(Q)||(C[Q]=y);s.preserveCreated&&(C.modified=f),s.copyKind==="fork"&&(C[Zn]=f)})}catch(C){console.warn("[Stashpad] cloneSubtree: processFrontMatter failed",C)}try{this.tree.insertSynthetic({id:A,parent:t,children:[],file:B,created:g})}catch{}this.fmSync.scheduleParentChange(A,null,t)}for(let C of n)await this.cloneSubtree(C,A,i,s);return A}async cmdClone(){let e=this.getActionTargets();if(!e.length){new b.Notice("Nothing to clone.");return}let t=new Set(e.map(A=>A.id)),i=e.filter(A=>{let h=A.parent;for(;h;){if(t.has(h))return!1;h=this.tree.get(h)?.parent??null}return!0}),s=this.noteFolder,n=[],o=[];try{for(let A of i){if(!A.file)continue;let h=A.parent??this.focusId,p=await this.cloneSubtree(A,h,n);p&&o.push(p)}}catch(A){console.warn("[Stashpad] clone failed partway",A),new b.Notice(`Clone stopped early: ${A.message}`)}if(!o.length)return;this.tree.rebuild(s),this.pendingFocusIds=o.slice(),this.render();let r=n.map(A=>this.app.vault.getAbstractFileByPath(A)).filter(A=>!!A&&A.extension==="md").map(A=>({id:ct(A.basename)??A.basename,parent:null,children:[],file:A,created:new Date().toISOString()})),l=await this.snapshotNotes(r,!1);this.plugin.getUndoStack(s).push({label:`Clone ${o.length} note${o.length===1?"":"s"}`,undo:async()=>{for(let A of[...n].reverse()){let h=this.app.vault.getAbstractFileByPath(A);if(h)try{await this.app.fileManager.trashFile(h)}catch{}}this.tree.rebuild(s),this.render()},redo:async()=>{await this.restoreSnapshots(l,o)}});let c=o.map(A=>this.tree.get(A)).filter(A=>!!A);this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Cloned",nodes:c,suffix:`(${n.length} file${n.length===1?"":"s"} total)`}),kind:"success",category:"clone",affectedIds:o,folder:this.noteFolder})}cmdForkNote(){let e=this.getActionTargets()[0];if(!e?.file){new b.Notice("Nothing to fork.");return}let t=e.parent??k,i=t===k?null:this.tree.get(t),s=i?this.titleForNode(i):"Home";new _e(this.app,this.tree,n=>this.titleForNode(n),{mode:"pick",allowCreate:!0,placeholder:`Fork "${this.titleForNode(e)}" under\u2026 (default: ${s})`,onPick:n=>{if(n.crossFolder){new b.Notice("Fork stays in this folder for now.");return}this.forkNoteUnder(e,n.id)},onCreate:n=>{(async()=>{let o=await this.createNoteUnder(n,this.focusId);o&&await this.forkNoteUnder(e,o)})()}}).open()}async forkNoteUnder(e,t){if(!e.file)return;let i=this.noteFolder,s=[],n=await this.cloneSubtree(e,t,s,{preserveCreated:!0,copyKind:"fork"});if(!n)return;let o=s[0]?this.app.vault.getAbstractFileByPath(s[0]):null;if(o)try{await this.app.fileManager.processFrontMatter(o,A=>{A[xi]=`[[${e.file.basename}]]`})}catch{}this.tree.rebuild(i),this.pendingFocusIds=[n],this.render(),await this.syncForkSiblings(this.forkFamilyFiles({originName:e.file.basename,include:[e.file,o]}));let r=s.map(A=>this.app.vault.getAbstractFileByPath(A)).filter(A=>!!A&&A.extension==="md").map(A=>({id:ct(A.basename)??A.basename,parent:null,children:[],file:A,created:new Date().toISOString()})),l=await this.snapshotNotes(r,!1);this.plugin.getUndoStack(i).push({label:"Fork note",undo:async()=>{for(let A of[...s].reverse()){let h=this.app.vault.getAbstractFileByPath(A);if(h)try{await this.app.fileManager.trashFile(h)}catch{}}this.tree.rebuild(i),this.render()},redo:async()=>{await this.restoreSnapshots(l,[n])}});let c=this.tree.get(n);this.plugin.notifications.show({message:c?`Forked "${this.titleForNode(e)}" \u2192 "${this.titleForNode(c)}" (${s.length} file${s.length===1?"":"s"})`:"Forked note",kind:"success",category:"clone",affectedIds:[n],folder:i})}async ensureSheetGroup(e){let t=ze(this.app.metadataCache.getFileCache(e)?.frontmatter);if(t)return t;let i=Br();return await this.app.fileManager.processFrontMatter(e,s=>{s[bi]=i,typeof s[ot]!="number"&&(s[ot]=0),s[Di]=!0}),i}forkFamilyFiles(e){let t=new Map,i=s=>{s&&t.set(s.path,s)};for(let s of this.app.vault.getMarkdownFiles()){let n=this.app.metadataCache.getFileCache(s)?.frontmatter;e.gid&&ze(n)===e.gid&&i(s),e.originName&&(s.basename===e.originName||Cr(n)===e.originName)&&i(s)}for(let s of e.include??[])i(s);return[...t.values()]}async syncForkSiblings(e){for(let t of e){let i=e.filter(s=>s.path!==t.path).map(s=>`[[${s.basename}]]`);await this.app.fileManager.processFrontMatter(t,s=>{i.length?s[Ye]=i:delete s[Ye]})}}async cmdForkVersion(e){this.plugin.settings.enableSheetVersions||(this.plugin.settings.enableSheetVersions=!0,await this.plugin.saveSettings(),new b.Notice("Sheet versions enabled."));let t=e??this.getActionTargets()[0];if(!t?.file){new b.Notice("Select a note to version.");return}let i=this.noteFolder,s={...this.app.metadataCache.getFileCache(t.file)?.frontmatter??{}},n=await this.ensureSheetGroup(t.file),o=t.parent??this.focusId,r=typeof s[ot]=="number"?s[ot]:0;for(let f of this.tree.getChildren(o)){if(f.id===t.id)continue;let g=we(this.app,f);if(ze(g)!==n)continue;let I=g?.[ot];typeof I=="number"&&I>r&&(r=I)}let l=r+1,c=[],A=await this.cloneSubtree(t,o,c,{preserveCreated:!0,copyKind:"fork"});if(!A||!c.length){new b.Notice("Sheets: could not create version.");return}let h=this.app.vault.getAbstractFileByPath(c[0]);h&&await this.app.fileManager.processFrontMatter(h,f=>{f[bi]=n,f[ot]=l,delete f[Wt],delete f[Di],f[xi]=`[[${t.file.basename}]]`}),this.tree.rebuild(i),this.activeVersionByGroup.set(n,A),this.plugin.saveActiveVersion(i,n,A),this.render();let p=this.app.vault.getAbstractFileByPath(c[0]);await this.syncForkSiblings(this.forkFamilyFiles({gid:n,include:[t.file,p]})),this.plugin.getUndoStack(i).push({label:"Fork version",undo:async()=>{for(let f of[...c].reverse()){let g=this.app.vault.getAbstractFileByPath(f);if(g)try{await this.app.fileManager.trashFile(g)}catch{}}this.activeVersionByGroup.delete(n),this.tree.rebuild(i),this.render()},redo:async()=>{}});let u=c.length;new b.Notice(`Forked a new version${u>1?` (${u} notes)`:""}`)}async cmdMarkVersionFinal(e){this.plugin.settings.enableSheetVersions||(this.plugin.settings.enableSheetVersions=!0,await this.plugin.saveSettings());let t=e??this.getActionTargets()[0];if(!t?.file)return;let i=ze(we(this.app,t));if(!i){new b.Notice("Not a versioned note.");return}let s=!Mi(we(this.app,t)),n=t.parent??this.focusId,o=this.tree.getChildren(n).filter(r=>ze(we(this.app,r))===i);for(let r of o){if(!r.file)continue;let l=Mi(we(this.app,r)),c=s&&r.id===t.id;l!==c&&await this.app.fileManager.processFrontMatter(r.file,A=>{c?A[Wt]=!0:delete A[Wt]})}this.render()}async cmdCopyNotes(){let e=this.getActionTargets();if(!e.length){new b.Notice("Nothing to copy.");return}await Jo(this),this.plugin.clearNoteClipboard(),this.plugin.noteClipboard={mode:"copy",folder:this.noteFolder,ids:e.map(t=>t.id)},this.render()}isCutPending(e){let t=this.plugin.noteClipboard;return!!t&&t.mode==="cut"&&t.folder===this.noteFolder&&t.ids.includes(e)}isCopyPending(e){let t=this.plugin.noteClipboard;return!!t&&t.mode==="copy"&&t.folder===this.noteFolder&&t.ids.includes(e)}insertIntoComposer(e){let t=this.composerInputEl;if(!t){this.composerDraft=this.composerDraft?`${this.composerDraft} -${e}`:e;return}let i=t.selectionStart??t.value.length,s=t.selectionEnd??t.value.length;t.value=t.value.slice(0,i)+e+t.value.slice(s);let n=i+e.length;try{t.setSelectionRange(n,n)}catch{}this.composerDraft=t.value}focusedInsideCut(e){let t=new Set(e),i=this.focusId,s=0;for(;i&&i!==S&&s++<1e3;){if(t.has(i))return!0;i=this.tree.get(i)?.parent??null}return!1}async cmdCutNotes(){let e=this.getActionTargets();if(!e.length){new F.Notice("Nothing to cut.");return}let t=[];for(let s of e)s.file&&t.push(this.stripFrontmatter(await this.app.vault.cachedRead(s.file)).trim());let i=t.join(` +${e}`:e;return}let i=t.selectionStart??t.value.length,s=t.selectionEnd??t.value.length;t.value=t.value.slice(0,i)+e+t.value.slice(s);let n=i+e.length;try{t.setSelectionRange(n,n)}catch{}this.composerDraft=t.value}focusedInsideCut(e){let t=new Set(e),i=this.focusId,s=0;for(;i&&i!==k&&s++<1e3;){if(t.has(i))return!0;i=this.tree.get(i)?.parent??null}return!1}async cmdCutNotes(){let e=this.getActionTargets();if(!e.length){new b.Notice("Nothing to cut.");return}let t=[];for(let s of e)s.file&&t.push(this.stripFrontmatter(await this.app.vault.cachedRead(s.file)).trim());let i=t.join(` -`);await navigator.clipboard.writeText(i),this.plugin.clearNoteClipboard(),this.plugin.noteClipboard={mode:"cut",folder:this.noteFolder,ids:e.map(s=>s.id),text:i},this.render(),this.plugin.noteClipboardNotice=this.plugin.notifications.show({message:`Cut ${this.titleList(e)} \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:e.map(s=>s.id),folder:this.noteFolder,duration:0})}async cmdPasteNotes(){let e=this.plugin.noteClipboard;if(!e){new F.Notice("The note clipboard is empty \u2014 copy or cut notes first.");return}if(e.folder!==this.noteFolder){let g=(this.currentChildren[this.cursorIdx]??null)?.parent??this.focusId??S,u=e.mode,f=e.folder,p=await this.plugin.crossFolderPaste(f,e.ids,this.noteFolder,g,u);if(!p||!p.rootIds.length)return;u==="cut"&&this.plugin.clearNoteClipboard();let I=this.noteFolder;this.tree.rebuild(I),this.pendingFocusIds=p.rootIds.slice(),this.render(),u==="cut"&&this.plugin.refreshOpenViewsForFolder(f);let m=f.split("/").pop(),B=p.rootIds.length,C=()=>{this.tree.rebuild(I),this.render(),this.plugin.refreshOpenViewsForFolder(f)};this.plugin.getUndoStack(I).push({label:`${u==="cut"?"Move":"Paste"} ${B} note${B===1?"":"s"} from ${m}`,undo:async()=>{await p.undo(),C()},redo:async()=>{await p.redo(),C()}});let w=u==="cut"?"Moved":"Pasted (copied)";this.plugin.notifications.show({message:`${w} ${B} note${B===1?"":"s"} (${p.noteCount} total) from "${m}" into this folder. Undo (in the list) reverses it.`,kind:"success",category:u==="cut"?"move":"clone",affectedIds:p.rootIds,folder:I,duration:0});return}let t=e.ids.map(h=>this.tree.get(h)).filter(h=>!!h&&!!h.file);if(!t.length){this.plugin.clearNoteClipboard(),this.render(),new F.Notice("Those notes no longer exist.");return}let i=this.currentChildren[this.cursorIdx]??null,s=i?.parent??this.focusId??S;if(e.mode==="cut"){let h=new Set(e.ids);for(let u=s;u&&u!==S;u=this.tree.get(u)?.parent??null)if(h.has(u)){new F.Notice("Can't paste cut notes under themselves.");return}let g=i&&!h.has(i.id)?i.id:"";this.plugin.clearNoteClipboard(),await this.moveAcrossThenReorder(t.map(u=>u.id),s,g,"after");return}let n=this.noteFolder,o=[],r=[];for(let h of t){let g=await this.cloneSubtree(h,s,o);g&&r.push(g)}if(!r.length)return;this.tree.rebuild(n),this.pendingFocusIds=r.slice(),this.render();let l=o.map(h=>this.app.vault.getAbstractFileByPath(h)).filter(h=>!!h&&h.extension==="md").map(h=>({id:lt(h.basename)??h.basename,parent:null,children:[],file:h,created:new Date().toISOString()})),c=await this.snapshotNotes(l,!1);this.plugin.getUndoStack(n).push({label:`Paste ${r.length} note${r.length===1?"":"s"}`,undo:async()=>{for(let h of[...o].reverse()){let g=this.app.vault.getAbstractFileByPath(h);if(g)try{await this.app.fileManager.trashFile(g)}catch{}}this.tree.rebuild(n),this.render()},redo:async()=>{await this.restoreSnapshots(c,r)}});let A=r.map(h=>this.tree.get(h)).filter(h=>!!h);this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Pasted (duplicated)",nodes:A,suffix:`(${o.length} file${o.length===1?"":"s"} total)`}),kind:"success",category:"clone",affectedIds:r,folder:n,duration:0})}async completeCutIntoComposer(){let e=this.plugin.noteClipboard;if(!e||e.mode!=="cut")return;if(e.folder!==this.noteFolder){let g=e.folder,u=e.ids.slice();this.plugin.clearNoteClipboard();let f=await this.plugin.orderedSubtreeNodes(g,u),p=X().prefixTimestampsOnCopy,I=[];for(let{file:y,created:v,depth:E}of f)try{let Q=this.stripFrontmatter(await this.app.vault.cachedRead(y)).trim().split(/\r?\n/).join(" "),b=p?`${this.formatTimeInline(v)} `:"";I.push(`${" ".repeat(E)}- ${b}${Q}`)}catch{}this.insertIntoComposer(I.length?I.join(` -`):e.text??"");let m=await this.plugin.subtreeFilePaths(g,u),B=await this.plugin.snapshotPaths(m),C=await this.plugin.trashSubtrees(g,u);this.plugin.refreshOpenViewsForFolder(g);let w=C.filter(y=>y.extension==="md").length;this.plugin.getUndoStack(g).push({label:`Cut ${u.length} note${u.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,u),this.plugin.refreshOpenViewsForFolder(g)}}),this.plugin.notifications.show({message:`Pasted the text of ${u.length} cut note${u.length===1?"":"s"} from "${g.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:u,folder:g,duration:0});return}this.plugin.clearNoteClipboard();let t=e.ids.map(g=>this.tree.get(g)).filter(g=>!!g&&!!g.file);if(!t.length)return;let i=[],s=new Set,n=(g,u)=>{if(!s.has(g.id)){s.add(g.id),i.push({node:g,depth:u});for(let f of this.tree.getChildren(g.id))n(f,u+1)}};for(let g of t)n(g,0);let o=this.noteFolder,r=X().prefixTimestampsOnCopy,l=[];for(let{node:g,depth:u}of i)if(g.file)try{let f=this.stripFrontmatter(await this.app.vault.cachedRead(g.file)).trim().split(/\r?\n/).join(" "),p=r?`${this.formatTimeInline(g.created)} `:"";l.push(`${" ".repeat(u)}- ${p}${f}`)}catch{}this.insertIntoComposer(l.join(` -`));let c=i.map(g=>g.node),A=await this.snapshotNotes(c,!1);for(let g of[...c].reverse())if(g.file)try{await this.app.fileManager.trashFile(g.file)}catch(u){console.warn("[Stashpad] cut-paste delete failed",g.file.path,u)}this.selection.clear(),this.tree.rebuild(o),this.render();let h=t.map(g=>g.id);this.plugin.getUndoStack(o).push({label:`Cut ${t.length} note${t.length===1?"":"s"} into composer`,undo:async()=>{await this.restoreSnapshots(A,h)},redo:async()=>{for(let g of[...A.notes]){let u=this.app.vault.getAbstractFileByPath(g.path);if(u)try{await this.app.fileManager.trashFile(u)}catch{}}this.tree.rebuild(o),this.render()}}),this.plugin.notifications.show({message:`Pasted the text of ${this.titleList(t)} into the composer and deleted the original${t.length===1?"":"s"} (${c.length} note${c.length===1?"":"s"}). Undo (in the list) restores them.`,kind:"warning",category:"delete",affectedIds:h,folder:o,duration:0})}cmdInsertTemplate(){new je(this.app,this.tree,e=>this.titleForNode(e),{mode:"pick",placeholder:"Insert which note as a template?",allowCreate:!1,onPick:async e=>{if(e.crossFolder){new F.Notice("Cross-Stashpad templates aren't supported yet \u2014 pick a note from this Stashpad.");return}let t=this.tree.get(e.id);if(!t?.file)return;let i=this.noteFolder,s=[],n=await this.cloneSubtree(t,this.focusId,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:lt(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:"Insert template",undo:async()=>{for(let l of[...s].reverse()){let c=this.app.vault.getAbstractFileByPath(l);if(c)try{await this.app.fileManager.trashFile(c)}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(e,t={}){if(t.keepForwardStack||this.recordNavState(),this.selectionGuardKey++,this.listEl&&this.stampSelectedCursor(!0),this.focusId=e,this.persistFocus(),this.defaultCursorToLast(),this.syncComposerDraftForFocus(),this.tagFilter&&this.tagFilter!==Pt&&this.tagFilter!==Ht){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(e),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 e=this.navBackStack.pop();if(!e){this.focusId!==S&&this.navigateUp();return}this.navForwardSnapshots.push(this.captureNavSnapshot()),this.applyNavSnapshot(e)}navigateForward(){let e=this.navForwardSnapshots.pop();e&&(this.navBackStack.push(this.captureNavSnapshot()),this.applyNavSnapshot(e))}async applyNavSnapshot(e){if(this.tagFilter=null,this.colorFilter=null,e.folder!==this.noteFolder){await this.setFolderOverride(e.folder,{skipHistory:!0}),e.focusId!==this.focusId&&this.tree.get(e.focusId)&&(this.focusId=e.focusId,this.render({kind:"preserve"}));return}if(!this.tree.get(e.focusId))return;this.selectionGuardKey++,this.listEl&&this.stampSelectedCursor(!0),this.focusId=e.focusId,this.persistFocus(),this.defaultCursorToLast(),this.syncComposerDraftForFocus();let t=this.lastCursorByFocus.get(e.focusId),i;t&&this.tree.get(t)?(this.pendingFocusIds=[t],i={kind:"scroll-to-id",id:t,align:"start"}):i={kind:"preserve"},this.render(i),this.refreshHeaderTitle(),this.viewRoot.focus({preventScroll:!0}),this.plugin.notifyStashpadSelectionChanged()}navigateUp(){this.selectionGuardKey++,this.tagFilter=null,this.colorFilter=null;let e=this.tree.get(this.focusId);if(!e||e.parent==null){if(this.navBackStack.length>0){this.navigateBack();return}return this.navigateTo(S)}let t=this.focusId;if(this.recordNavState(),this.listEl){let o=this.currentChildren[this.cursorIdx]?.id??this.lastSelected;o&&this.plugin.saveLastCursor(this.noteFolder,t,o)}this.focusId=e.parent,this.persistFocus(),this.syncComposerDraftForFocus();let i=this.filterChildren(this.tree.getChildren(this.focusId)),s=i.findIndex(n=>n.id===t);this.selection.clear(),s>=0?(this.cursorIdx=s,this.selection.add(t),this.lastSelected=t):(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:t,align:"start"}):this.render({kind:"follow-cursor"}),this.refreshHeaderTitle(),s<0&&this.revealCursorRow(),this.plugin.notifyStashpadSelectionChanged()}openBookmarks(){let e=this.app.internalPlugins?.plugins?.bookmarks?.instance?.items??[],t=this.allowedByBases(),i=new F.Menu,s=0;for(let n of e){if(n.type!=="file"||t&&!t.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 e=(this.plugin.settings.importDropFolder||"").trim().replace(/^\/+|\/+$/g,""),t=(this.plugin.settings.exportFolder||"").trim().replace(/^\/+|\/+$/g,"");e&&await this.ensureFolder(`${this.noteFolder}/${e}`),t&&await this.ensureFolder(`${this.noteFolder}/${t}`),await this.order.load(this.noteFolder),await this.sortStore.load(this.noteFolder),this.bootstrappedFolders.add(this.noteFolder)}backfillFrontmatterSync(){let e=[S],t=this.tree.getRoot(),i=s=>{for(let n of this.tree.getChildren(s))e.push(n.id),i(n.id)};for(let s of t.children)i(s);for(let s of e)this.fmSync.wouldWrite(s)&&this.fmSync.schedule(s)}installFmSyncActivityNotice(){this.fmSyncUnsubscribe||(this.fmSyncUnsubscribe=this.fmSync.onError((e,t)=>{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:e.map(s=>s.id),text:i},this.render(),this.plugin.noteClipboardNotice=this.plugin.notifications.show({message:`Cut ${this.titleList(e)} \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:e.map(s=>s.id),folder:this.noteFolder,duration:0})}async cmdPasteNotes(){let e=this.plugin.noteClipboard;if(!e){new b.Notice("The note clipboard is empty \u2014 copy or cut notes first.");return}if(e.folder!==this.noteFolder){let p=(this.currentChildren[this.cursorIdx]??null)?.parent??this.focusId??k,u=e.mode,f=e.folder,g=await this.plugin.crossFolderPaste(f,e.ids,this.noteFolder,p,u);if(!g||!g.rootIds.length)return;u==="cut"&&this.plugin.clearNoteClipboard();let I=this.noteFolder;this.tree.rebuild(I),this.pendingFocusIds=g.rootIds.slice(),this.render(),u==="cut"&&this.plugin.refreshOpenViewsForFolder(f);let m=f.split("/").pop(),B=g.rootIds.length,C=()=>{this.tree.rebuild(I),this.render(),this.plugin.refreshOpenViewsForFolder(f)};this.plugin.getUndoStack(I).push({label:`${u==="cut"?"Move":"Paste"} ${B} note${B===1?"":"s"} from ${m}`,undo:async()=>{await g.undo(),C()},redo:async()=>{await g.redo(),C()}});let Q=u==="cut"?"Moved":"Pasted (copied)";this.plugin.notifications.show({message:`${Q} ${B} note${B===1?"":"s"} (${g.noteCount} total) from "${m}" into this folder. Undo (in the list) reverses it.`,kind:"success",category:u==="cut"?"move":"clone",affectedIds:g.rootIds,folder:I,duration:0});return}let t=e.ids.map(h=>this.tree.get(h)).filter(h=>!!h&&!!h.file);if(!t.length){this.plugin.clearNoteClipboard(),this.render(),new b.Notice("Those notes no longer exist.");return}let i=this.currentChildren[this.cursorIdx]??null,s=i?.parent??this.focusId??k;if(e.mode==="cut"){let h=new Set(e.ids);for(let u=s;u&&u!==k;u=this.tree.get(u)?.parent??null)if(h.has(u)){new b.Notice("Can't paste cut notes under themselves.");return}let p=i&&!h.has(i.id)?i.id:"";this.plugin.clearNoteClipboard(),await this.moveAcrossThenReorder(t.map(u=>u.id),s,p,"after");return}let n=this.noteFolder,o=[],r=[];for(let h of t){let p=await this.cloneSubtree(h,s,o);p&&r.push(p)}if(!r.length)return;this.tree.rebuild(n),this.pendingFocusIds=r.slice(),this.render();let l=o.map(h=>this.app.vault.getAbstractFileByPath(h)).filter(h=>!!h&&h.extension==="md").map(h=>({id:ct(h.basename)??h.basename,parent:null,children:[],file:h,created:new Date().toISOString()})),c=await this.snapshotNotes(l,!1);this.plugin.getUndoStack(n).push({label:`Paste ${r.length} note${r.length===1?"":"s"}`,undo:async()=>{for(let h of[...o].reverse()){let p=this.app.vault.getAbstractFileByPath(h);if(p)try{await this.app.fileManager.trashFile(p)}catch{}}this.tree.rebuild(n),this.render()},redo:async()=>{await this.restoreSnapshots(c,r)}});let A=r.map(h=>this.tree.get(h)).filter(h=>!!h);this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Pasted (duplicated)",nodes:A,suffix:`(${o.length} file${o.length===1?"":"s"} total)`}),kind:"success",category:"clone",affectedIds:r,folder:n,duration:0})}async completeCutIntoComposer(){let e=this.plugin.noteClipboard;if(!e||e.mode!=="cut")return;if(e.folder!==this.noteFolder){let p=e.folder,u=e.ids.slice();this.plugin.clearNoteClipboard();let f=await this.plugin.orderedSubtreeNodes(p,u),g=X().prefixTimestampsOnCopy,I=[];for(let{file:y,created:E,depth:w}of f)try{let v=this.stripFrontmatter(await this.app.vault.cachedRead(y)).trim().split(/\r?\n/).join(" "),F=g?`${this.formatTimeInline(E)} `:"";I.push(`${" ".repeat(w)}- ${F}${v}`)}catch{}this.insertIntoComposer(I.length?I.join(` +`):e.text??"");let m=await this.plugin.subtreeFilePaths(p,u),B=await this.plugin.snapshotPaths(m),C=await this.plugin.trashSubtrees(p,u);this.plugin.refreshOpenViewsForFolder(p);let Q=C.filter(y=>y.extension==="md").length;this.plugin.getUndoStack(p).push({label:`Cut ${u.length} note${u.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,u),this.plugin.refreshOpenViewsForFolder(p)}}),this.plugin.notifications.show({message:`Pasted the text of ${u.length} cut note${u.length===1?"":"s"} from "${p.split("/").pop()}" into the composer and removed the original${Q===1?"":"s"} (${Q} note${Q===1?"":"s"}). Undo restores them.`,kind:"warning",category:"delete",affectedIds:u,folder:p,duration:0});return}this.plugin.clearNoteClipboard();let t=e.ids.map(p=>this.tree.get(p)).filter(p=>!!p&&!!p.file);if(!t.length)return;let i=[],s=new Set,n=(p,u)=>{if(!s.has(p.id)){s.add(p.id),i.push({node:p,depth:u});for(let f of this.tree.getChildren(p.id))n(f,u+1)}};for(let p of t)n(p,0);let o=this.noteFolder,r=X().prefixTimestampsOnCopy,l=[];for(let{node:p,depth:u}of i)if(p.file)try{let f=this.stripFrontmatter(await this.app.vault.cachedRead(p.file)).trim().split(/\r?\n/).join(" "),g=r?`${this.formatTimeInline(p.created)} `:"";l.push(`${" ".repeat(u)}- ${g}${f}`)}catch{}this.insertIntoComposer(l.join(` +`));let c=i.map(p=>p.node),A=await this.snapshotNotes(c,!1);for(let p of[...c].reverse())if(p.file)try{await this.app.fileManager.trashFile(p.file)}catch(u){console.warn("[Stashpad] cut-paste delete failed",p.file.path,u)}this.selection.clear(),this.tree.rebuild(o),this.render();let h=t.map(p=>p.id);this.plugin.getUndoStack(o).push({label:`Cut ${t.length} note${t.length===1?"":"s"} into composer`,undo:async()=>{await this.restoreSnapshots(A,h)},redo:async()=>{for(let p of[...A.notes]){let u=this.app.vault.getAbstractFileByPath(p.path);if(u)try{await this.app.fileManager.trashFile(u)}catch{}}this.tree.rebuild(o),this.render()}}),this.plugin.notifications.show({message:`Pasted the text of ${this.titleList(t)} into the composer and deleted the original${t.length===1?"":"s"} (${c.length} note${c.length===1?"":"s"}). Undo (in the list) restores them.`,kind:"warning",category:"delete",affectedIds:h,folder:o,duration:0})}cmdInsertTemplate(){new _e(this.app,this.tree,e=>this.titleForNode(e),{mode:"pick",placeholder:"Insert which note as a template?",allowCreate:!1,onPick:async e=>{if(e.crossFolder){new b.Notice("Cross-Stashpad templates aren't supported yet \u2014 pick a note from this Stashpad.");return}let t=this.tree.get(e.id);if(!t?.file)return;let i=this.noteFolder,s=[],n=await this.cloneSubtree(t,this.focusId,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:ct(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:"Insert template",undo:async()=>{for(let l of[...s].reverse()){let c=this.app.vault.getAbstractFileByPath(l);if(c)try{await this.app.fileManager.trashFile(c)}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(e,t={}){if(t.keepForwardStack||this.recordNavState(),this.selectionGuardKey++,this.listEl&&this.stampSelectedCursor(!0),this.focusId=e,this.persistFocus(),this.defaultCursorToLast(),this.syncComposerDraftForFocus(),this.tagFilter&&this.tagFilter!==Ht&&this.tagFilter!==Rt){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(e),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 e=this.navBackStack.pop();if(!e){this.focusId!==k&&this.navigateUp();return}this.navForwardSnapshots.push(this.captureNavSnapshot()),this.applyNavSnapshot(e)}navigateForward(){let e=this.navForwardSnapshots.pop();e&&(this.navBackStack.push(this.captureNavSnapshot()),this.applyNavSnapshot(e))}async applyNavSnapshot(e){if(this.tagFilter=null,this.colorFilter=null,e.folder!==this.noteFolder){await this.setFolderOverride(e.folder,{skipHistory:!0}),e.focusId!==this.focusId&&this.tree.get(e.focusId)&&(this.focusId=e.focusId,this.render({kind:"preserve"}));return}if(!this.tree.get(e.focusId))return;this.selectionGuardKey++,this.listEl&&this.stampSelectedCursor(!0),this.focusId=e.focusId,this.persistFocus(),this.defaultCursorToLast(),this.syncComposerDraftForFocus();let t=this.lastCursorByFocus.get(e.focusId),i;t&&this.tree.get(t)?(this.pendingFocusIds=[t],i={kind:"scroll-to-id",id:t,align:"start"}):i={kind:"preserve"},this.render(i),this.refreshHeaderTitle(),this.viewRoot.focus({preventScroll:!0}),this.plugin.notifyStashpadSelectionChanged()}navigateUp(){this.selectionGuardKey++,this.tagFilter=null,this.colorFilter=null;let e=this.tree.get(this.focusId);if(!e||e.parent==null){if(this.navBackStack.length>0){this.navigateBack();return}return this.navigateTo(k)}let t=this.focusId;if(this.recordNavState(),this.listEl){let o=this.currentChildren[this.cursorIdx]?.id??this.lastSelected;o&&this.plugin.saveLastCursor(this.noteFolder,t,o)}this.focusId=e.parent,this.persistFocus(),this.syncComposerDraftForFocus();let i=this.filterChildren(this.tree.getChildren(this.focusId)),s=i.findIndex(n=>n.id===t);this.selection.clear(),s>=0?(this.cursorIdx=s,this.selection.add(t),this.lastSelected=t):(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:t,align:"start"}):this.render({kind:"follow-cursor"}),this.refreshHeaderTitle(),s<0&&this.revealCursorRow(),this.plugin.notifyStashpadSelectionChanged()}openBookmarks(){let e=this.app.internalPlugins?.plugins?.bookmarks?.instance?.items??[],t=this.allowedByBases(),i=new b.Menu,s=0;for(let n of e){if(n.type!=="file"||t&&!t.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 e=(this.plugin.settings.importDropFolder||"").trim().replace(/^\/+|\/+$/g,""),t=(this.plugin.settings.exportFolder||"").trim().replace(/^\/+|\/+$/g,"");e&&await this.ensureFolder(`${this.noteFolder}/${e}`),t&&await this.ensureFolder(`${this.noteFolder}/${t}`),await this.order.load(this.noteFolder),await this.sortStore.load(this.noteFolder),this.bootstrappedFolders.add(this.noteFolder)}backfillFrontmatterSync(){let e=[k],t=this.tree.getRoot(),i=s=>{for(let n of this.tree.getChildren(s))e.push(n.id),i(n.id)};for(let s of t.children)i(s);for(let s of e)this.fmSync.wouldWrite(s)&&this.fmSync.schedule(s)}installFmSyncActivityNotice(){this.fmSyncUnsubscribe||(this.fmSyncUnsubscribe=this.fmSync.onError((e,t)=>{this.plugin.notifications.show({message:`Stashpad: couldn't update recovery metadata File: \`${e}\` -Error: ${t.message}`,kind:"error",category:"system",duration:0,affectedPaths:[e],folder:this.noteFolder})}))}async ensureHomeNote(){let e=this.noteFolder,t=`${e}/${this.buildHomeFilename(e)}`,i=this.app.vault.getMarkdownFiles().filter(o=>o.path.startsWith(e+"/"));for(let o of i){if(this.app.metadataCache.getFileCache(o)?.frontmatter?.id!==S)continue;if(o.path===t||this.app.vault.getAbstractFileByPath(t))return o;try{await this.app.fileManager.renameFile(o,t);let c=this.app.vault.getAbstractFileByPath(t);if(c instanceof F.TFile)return c}catch(c){console.warn("[Stashpad] home note rename failed; keeping legacy path",c)}return o}let s=new Date().toISOString(),n=["---",`id: ${S}`,"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(t,n)}buildHomeFilename(e){return`Home-${(e.split("/").filter(Boolean).pop()??"Stashpad").replace(/[^A-Za-z0-9_-]+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")||"Stashpad"}.md`}async migrateNullParents(){let e=this.noteFolder,t=this.app.vault.getMarkdownFiles().filter(i=>i.path.startsWith(e+"/"));for(let i of t){let s=this.app.metadataCache.getFileCache(i)?.frontmatter,n=s?.id;if(!n||n===S)continue;let o=s?.parent;(o==null||o===""||o==="null")&&(await this.app.fileManager.processFrontMatter(i,r=>{r.parent=S}),await this.log.append({type:"parent_change",id:n,payload:{from:null,to:S,reason:"migration"}}))}}async openInNewStashpadTab(e){let t=this.app.workspace,i=this.leaf,s=t.getLeaf("tab");await s.setViewState({type:z,active:!0,state:{focusId:e,timeFilter:this.timeFilter,folderOverride:this.folderOverride}}),t.setActiveLeaf(s,{focus:!0}),t.revealLeaf(s),pt(t,s,i,n=>this.plugin.registerEvent(n))}async openNoteInNewTab(e,t,i){let s=(e||"").trim().replace(/^\/+|\/+$/g,"");if(!s||!t)return;let n=(this.plugin.settings.folder||"Stashpad").trim().replace(/^\/+|\/+$/g,"")||"Stashpad",o=this.app.workspace,r=this.leaf,l=o.getLeaf("tab");await l.setViewState({type:z,active:!0,state:{focusId:t,folderOverride:s===n?null:s,...i?{cursorId:i}:{}}}),o.setActiveLeaf(l,{focus:!0}),o.revealLeaf(l),pt(o,l,r,c=>this.plugin.registerEvent(c))}async openFolderInNewTab(e){let t=(e||"").trim().replace(/^\/+|\/+$/g,"");if(!t)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:z,active:!0,state:{focusId:S,folderOverride:t===i?null:t}}),s.setActiveLeaf(o,{focus:!0}),s.revealLeaf(o),pt(s,o,n,r=>this.plugin.registerEvent(r))}cmdOpenInEditor(e){if(e){this.openFileAtEnd(e.file);return}let t=this.getActionTargets();if(t.length)for(let i of t)i.file&&this.openFileAtEnd(i.file)}async cmdCopyStashpadLink(e){let t=e??this.getActionTargets()[0];if(!t?.id){new F.Notice("No note selected to link to.");return}let i=Go({vault:this.app.vault.getName(),folder:this.noteFolder,note:t.id,run:["reveal"]});try{await navigator.clipboard.writeText(i),new F.Notice("Stashpad link copied.")}catch{new F.Notice("Couldn't copy the link to the clipboard.")}}cmdOpenParentInEditor(){let e=this.tree.get(this.focusId);if(!e?.file){new F.Notice("No focused parent to open.");return}this.openFileAtEnd(e.file)}async openFileAtEnd(e){let t=this.app.workspace,i=this.leaf,s=t.getLeaf("tab");await s.openFile(e,{active:!0}),t.setActiveLeaf(s,{focus:!0}),t.revealLeaf(s),pt(t,s,i,r=>this.plugin.registerEvent(r));let o=s.view?.editor;o&&requestAnimationFrame(()=>{try{let r=o.lastLine(),l=o.getLine(r)?.length??0;o.setCursor({line:r,ch:l}),o.scrollIntoView({from:{line:r,ch:l},to:{line:r,ch:l}},!0),o.focus()}catch{}})}cmdSelectAll(){if(this.currentChildren.length!==0){this.selection.clear();for(let e of this.currentChildren)this.selection.add(e.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 e=this.getActionTargets();if(e.length===0){let n=this.tree.get(this.focusId);n?.file&&(e=[n])}if(e.length===0){new F.Notice("Nothing to pin.");return}let t=e.some(n=>!this.plugin.isPinned({folder:this.noteFolder,id:n.id})),i=0,s=0;for(let n of e){let o={folder:this.noteFolder,id:n.id};t?this.plugin.isPinned(o)||(await this.plugin.pinNote(o),i++):this.plugin.isPinned(o)&&(await this.plugin.unpinNote(o),s++)}i>0?new F.Notice(`Pinned ${i} note${i===1?"":"s"} to sidebar.`):s>0&&new F.Notice(`Unpinned ${s} note${s===1?"":"s"} from sidebar.`)}isListPinned(e){let t=this.tree.get(e);if(!t?.file)return!1;let i=this.listPinnedState.get(t.file.path);return i?i.pinned:this.app.metadataCache.getFileCache(t.file)?.frontmatter?.listPinned===!0}listPinnedAt(e){let t=this.tree.get(e);if(!t?.file)return 0;let i=this.listPinnedState.get(t.file.path);if(i)return i.at;let s=this.app.metadataCache.getFileCache(t.file)?.frontmatter?.listPinnedAt,n=typeof s=="string"?Date.parse(s):NaN;return Number.isNaN(n)?0:n}hoistListPinned(e,t){let i=this.tree.getChildren(e).map(l=>l.id);if(!i.some(l=>this.isListPinned(l)))return t;let s=new Set(t),n=[...t,...i.filter(l=>!s.has(l))],o=n.filter(l=>this.isListPinned(l)).sort((l,c)=>this.listPinnedAt(l)-this.listPinnedAt(c)),r=n.filter(l=>!this.isListPinned(l));return[...o,...r]}async cmdToggleListPin(){let e=this.getActionTargets();if(e.length===0){let r=this.tree.get(this.focusId);r?.file&&(e=[r])}if(e.length===0){new F.Notice("Nothing to pin.");return}let t=e.some(r=>!this.isListPinned(r.id)),i=[],s=new Date().toISOString(),n=[];for(let r of e){if(!r.file)continue;let l=this.app.metadataCache.getFileCache(r.file)?.frontmatter;i.push({path:r.file.path,listPinned:l?.listPinned,listPinnedAt:l?.listPinnedAt});let c=t?typeof l?.listPinnedAt=="string"&&Date.parse(l.listPinnedAt)||Date.parse(s):0;this.listPinnedState.set(r.file.path,{pinned:t,at:c}),await this.app.fileManager.processFrontMatter(r.file,A=>{t?(A.listPinned=!0,A.listPinnedAt||(A.listPinnedAt=s)):(delete A.listPinned,delete A.listPinnedAt)}),n.push(r.id)}let o=this.noteFolder;this.tree.rebuild(o),this.render(),this.plugin.notifications.show({message:t?`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:t?`Pin to top (${n.length})`:`Unpin from top (${n.length})`,undo:async()=>{for(let r of i){let l=this.app.vault.getAbstractFileByPath(r.path);if(!l)continue;await this.app.fileManager.processFrontMatter(l,h=>{r.listPinned===void 0?delete h.listPinned:h.listPinned=r.listPinned,r.listPinnedAt===void 0?delete h.listPinnedAt:h.listPinnedAt=r.listPinnedAt});let c=r.listPinned===!0,A=typeof r.listPinnedAt=="string"&&Date.parse(r.listPinnedAt)||0;this.listPinnedState.set(r.path,{pinned:c,at:A})}this.tree.rebuild(o),this.render()}})}async cmdToggleComplete(){let e=this.getActionTargets();if(e.length===0){let l=this.tree.get(this.focusId);l?.file&&(e=[l])}if(e.length===0){new F.Notice("Nothing to toggle.");return}let i=e.some(l=>!this.isCompleted(l)),s=[],n=[],o=[];for(let l of e){if(!l.file)continue;let c=this.isCompleted(l),A=this.app.metadataCache.getFileCache(l.file)?.frontmatter,h=A?.due!=null?String(A.due):null,g={id:l.id,path:l.file.path,was:c,dueBefore:h,rolledTo:null};if(s.push(g),c===i)continue;let u=!1;await this.app.fileManager.processFrontMatter(l.file,f=>{let p=i?sn(f.repeat):null;if(p){let I=f.due!=null?Date.parse(String(f.due)):NaN,m=nn(p,Number.isFinite(I)?I:null,Date.now());f.due=new Date(m).toISOString(),delete f.completed,g.rolledTo=f.due,o.push({title:l.file.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||"task",when:m}),u=!0}else i?f.completed=!0:delete f.completed}),this.completedState.set(l.file.path,u?!1:i),n.push(l.id)}this.render();for(let l of o)this.plugin.notifications.show({message:`\u{1F501} Rescheduled \u201C${l.title}\u201D \u2192 ${We(l.when,this.plugin.settings)}.`,kind:"success",category:"system",folder:this.noteFolder});if(n.length>0){await this.log.append({type:i?"complete":"uncomplete",id:n[0],payload:{ids:n,count:n.length}});let l=n.map(c=>this.tree.get(c)).filter(c=>!!c);this.plugin.notifications.show({message:this.bulkActionMessage({verb:i?"Marked complete":"Unmarked",nodes:l}),kind:"success",category:i?"complete":"uncomplete",affectedIds:n,folder:this.noteFolder})}let r=this.noteFolder;this.plugin.getUndoStack(r).push({label:`${i?"Mark complete":"Unmark complete"} (${e.length})`,undo:async()=>{let l=[];for(let c of s){let A=this.app.vault.getAbstractFileByPath(c.path);A&&(await this.app.fileManager.processFrontMatter(A,h=>{c.rolledTo!=null?(c.dueBefore!=null?h.due=c.dueBefore:delete h.due,delete h.completed):c.was?h.completed=!0:delete h.completed}),n.includes(c.id)&&l.push(c.id))}l.length>0&&await this.log.append({type:i?"uncomplete":"complete",id:l[0],payload:{ids:l,count:l.length,undo:!0}}),this.tree.rebuild(r),this.render()},redo:async()=>{for(let l of s){let c=this.app.vault.getAbstractFileByPath(l.path);c&&await this.app.fileManager.processFrontMatter(c,A=>{l.rolledTo!=null?(A.due=l.rolledTo,delete A.completed):i?A.completed=!0:delete A.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(r),this.render()}})}isCompleted(e){if(!e.file)return!1;let t=this.completedState.get(e.file.path);return t!==void 0?t:!!this.app.metadataCache.getFileCache(e.file)?.frontmatter?.completed}taggedFromFm(e){return e?Zt(e,"task")||e.task===!0:!1}cmdSetDue(){let e=this.getActionTargets();if(e.length===0){let r=this.tree.get(this.focusId);r?.file&&(e=[r])}if(e.length===0){new F.Notice("Nothing to schedule.");return}let t=e[0],i=t.file?this.app.metadataCache.getFileCache(t.file)?.frontmatter:null,s=i&&(typeof i.due=="string"||typeof i.due=="number")?String(i.due):null,n=this.plugin.collectKnownAuthors(),o=Tt(i??{});new Ue(this.app,s,r=>{this.applyDue(e,r.iso,r.assignees,!1,{repeat:r.repeat,autoDoneAfter:r.autoDoneAfter,remindEvery:r.remindEvery})},{knownAuthors:n,currentAssignees:o,quickAdjusts:this.plugin.settings.dueQuickAdjusts,showRecurrence:e.length===1,currentRepeat:typeof i?.repeat=="string"?i.repeat:"",currentAutoDoneAfter:typeof i?.autoDoneAfter=="string"?i.autoDoneAfter:"",currentRemindEvery:typeof i?.remindEvery=="string"?i.remindEvery:""}).open()}cmdSnooze(e){let t;if(e)t=[e];else if(t=this.getActionTargets(),t.length===0){let o=this.tree.get(this.focusId);o?.file&&(t=[o])}if(t.length===0){new F.Notice("Nothing to snooze.");return}let i=t[0],s=i.file?this.app.metadataCache.getFileCache(i.file)?.frontmatter:null,n=s&&(typeof s.due=="string"||typeof s.due=="number")?String(s.due):null;new Ue(this.app,n,o=>{this.applyDue(t,o.iso,[],!0)},{title:"Snooze \u2014 reschedule",hideAssignees:!0,quickAdjusts:this.plugin.settings.dueQuickAdjusts}).open()}async applyDue(e,t,i=[],s=!1,n){let o=[],r=[],l=this.authorship.currentAuthorLink();for(let h of i)await this.plugin.ensureAuthorStubFor(this.noteFolder,h.id,h.name);let c=i.map(h=>this.plugin.authorRefFor(this.noteFolder,h.id,h.name));for(let h of e){if(!h.file)continue;let g=this.app.metadataCache.getFileCache(h.file)?.frontmatter,u=this.isTaskTagged(h);o.push({id:h.id,path:h.file.path,due:g?.due,task:g?.task,assignedTo:g?.assignedTo,assignedBy:g?.assignedBy,wasTagged:u,repeat:g?.repeat,autoDoneAfter:g?.autoDoneAfter,remindEvery:g?.remindEvery}),await this.app.fileManager.processFrontMatter(h.file,p=>{if(t===null?delete p.due:(p.due=t,p.task=!0),n){let I=(m,B)=>{let C=(B??"").trim();C?(p[m]=C,p.task=!0):delete p[m]};I("repeat",n.repeat),I("autoDoneAfter",n.autoDoneAfter),I("remindEvery",n.remindEvery)}s||(c.length>0?(p.assignedTo=c,l&&(p.assignedBy=l.link),p.task=!0):(delete p.assignedTo,delete p.assignedBy))});let f=t!==null||c.length>0;this.taskTaggedState.set(h.file.path,f||u),r.push(h.id)}if(this.render(),r.length>0){let h=r.map(g=>this.tree.get(g)).filter(g=>!!g);this.plugin.notifications.show({message:this.bulkActionMessage({verb:t===null?"Cleared due date":`Due ${We(Date.parse(t),this.plugin.settings)}`,nodes:h}),kind:"success",category:"edit",affectedIds:r,folder:this.noteFolder})}let A=this.noteFolder;this.plugin.getUndoStack(A).push({label:t===null?`Clear due date (${e.length})`:`Set due date (${e.length})`,undo:async()=>{for(let h of o){let g=this.app.vault.getAbstractFileByPath(h.path);g&&(await this.app.fileManager.processFrontMatter(g,u=>{h.due===void 0?delete u.due:u.due=h.due,h.task===void 0?delete u.task:u.task=h.task,h.assignedTo===void 0?delete u.assignedTo:u.assignedTo=h.assignedTo,h.assignedBy===void 0?delete u.assignedBy:u.assignedBy=h.assignedBy,h.repeat===void 0?delete u.repeat:u.repeat=h.repeat,h.autoDoneAfter===void 0?delete u.autoDoneAfter:u.autoDoneAfter=h.autoDoneAfter,h.remindEvery===void 0?delete u.remindEvery:u.remindEvery=h.remindEvery}),this.taskTaggedState.set(h.path,h.wasTagged))}this.tree.rebuild(A),this.render()}})}cmdAssign(){let e=this.getActionTargets();if(e.length===0){let r=this.tree.get(this.focusId);r?.file&&(e=[r])}if(e.length===0){new F.Notice("Nothing to assign.");return}let t=e[0],i=t.file?this.app.metadataCache.getFileCache(t.file)?.frontmatter:null,s=i&&(typeof i.due=="string"||typeof i.due=="number")?String(i.due):null,n=this.plugin.collectKnownAuthors(),o=Tt(i??{});new Ue(this.app,s,r=>{this.applyDue(e,r.iso,r.assignees)},{knownAuthors:n,currentAssignees:o,title:"Assign / schedule task"}).open()}isTask(e){return e.file?this.isTaskTagged(e)?!0:this.app.metadataCache.getFileCache(e.file)?.frontmatter?.completed!==void 0:!1}async cmdToggleTask(){let e=this.getActionTargets();if(e.length===0){let r=this.tree.get(this.focusId);r?.file&&(e=[r])}if(e.length===0){new F.Notice("Nothing to toggle.");return}let t=e.some(r=>!this.isTaskTagged(r)),i=[],s=[];for(let r of e){if(!r.file)continue;let l=this.isTaskTagged(r),c=this.app.metadataCache.getFileCache(r.file)?.frontmatter;if(i.push({id:r.id,path:r.file.path,tags:c?.tags,completed:c?.completed,task:c?.task,wasTagged:l}),l===t)continue;let A=!1;await this.app.fileManager.processFrontMatter(r.file,h=>{t?(eo(h,"task"),h.completed===void 0&&(h.completed=!1),A=h.completed===!0,delete h.task):(to(h,"task"),delete h.completed,delete h.task,A=!1)}),this.completedState.set(r.file.path,A),this.taskTaggedState.set(r.file.path,t),s.push(r.id)}if(this.render(),s.length>0){let r=t?"marked as task":"unmarked as task",l;if(s.length===1){let c=this.tree.get(s[0]);l=`"${c&&this.titleForNode(c).trim()||"(untitled)"}" ${r}`}else l=`${s.length} notes ${r}`;this.plugin.notifications.show({message:l,kind:"success",category:"edit",affectedIds:s,folder:this.noteFolder})}let n=this.noteFolder,o=async()=>{for(let r of i){let l=this.app.vault.getAbstractFileByPath(r.path);l&&(await this.app.fileManager.processFrontMatter(l,c=>{r.tags===void 0?delete c.tags:c.tags=r.tags,r.completed===void 0?delete c.completed:c.completed=r.completed,r.task===void 0?delete c.task:c.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:`${t?"Mark task":"Unmark task"} (${e.length})`,undo:o,redo:async()=>{for(let r of i){let l=this.app.vault.getAbstractFileByPath(r.path);if(!l)continue;let c=!1;await this.app.fileManager.processFrontMatter(l,A=>{t?(eo(A,"task"),A.completed===void 0&&(A.completed=!1),c=A.completed===!0,delete A.task):(to(A,"task"),delete A.completed,delete A.task,c=!1)}),this.completedState.set(r.path,c),this.taskTaggedState.set(r.path,t)}this.tree.rebuild(n),this.render()}})}async toggleCompletedForNode(e){if(!e.file)return;let t=e.file.path,i=this.isCompleted(e);await this.app.fileManager.processFrontMatter(e.file,n=>{n.completed=!i}),this.completedState.set(t,!i),await this.log.append({type:i?"uncomplete":"complete",id:e.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(t);n&&(await this.app.fileManager.processFrontMatter(n,o=>{o.completed=i}),this.tree.rebuild(s),this.render())}})}isTaskTagged(e){if(!e.file)return!1;let t=this.taskTaggedState.get(e.file.path);if(t!==void 0)return t;let i=this.app.metadataCache.getFileCache(e.file)?.frontmatter;return this.taggedFromFm(i)}colorForNode(e){if(!e.file)return null;let t=this.app.metadataCache.getFileCache(e.file)?.frontmatter?.color;if(typeof t!="string")return null;let i=t.trim();return/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(i)?i:null}inheritedColorForNode(e){let t=e,i=0,s=new Set;for(;t&&t.id!==S&&!s.has(t.id);){s.add(t.id);let n=this.colorForNode(t);if(n)return{hex:n,depth:i};t=t.parent?this.tree.get(t.parent):void 0,i+=1}return null}isDescendant(e,t){let i=this.tree.get(e),s=new Set;for(;i&&i.parent&&!s.has(i.id);){if(i.parent===t)return!0;s.add(i.id),i=this.tree.get(i.parent)}return!1}async moveAcrossThenReorder(e,t,i,s){let n=[],o=new Set;for(let E of e){let Q=this.tree.get(E);Q?.file&&(n.push({id:E,path:Q.file.path,oldParent:Q.parent}),o.add(Q.parent??S))}o.add(t);let r=this.authorship.collectAuthorIds(e.map(E=>this.tree.get(E)).filter(E=>!!E)),l=this.noteFolder,c={};for(let E of o)c[E]=this.order.getOrder(l,E).slice();for(let E of n){let Q=this.app.vault.getAbstractFileByPath(E.path);Q&&(await this.app.fileManager.processFrontMatter(Q,b=>{b.parent=t}),this.fmSync.scheduleParentChange(E.id,E.oldParent,t),await this.log.append({type:"parent_change",id:E.id,payload:{from:E.oldParent,to:t,reason:"drag"}}),this.order.removeChild(l,E.id))}this.tree.rebuild(l);let A=this.tree.getChildren(t).map(E=>E.id),h=new Set(e),g=A.filter(E=>!h.has(E)),u=g.indexOf(i);u<0&&(u=g.length),s==="after"&&(u+=1);let f=[...g.slice(0,u),...e.filter(E=>!!this.tree.get(E)),...g.slice(u)];this.order.setOrder(l,t,f),await this.order.save(l),await this.forceManualMode(t),await this.log.append({type:"reorder",id:t,payload:{dir:"drag-cross",parent:t,ids:e,count:e.length}});let p=this.focusId===t,I=p?e[0]:t,m=p?e.slice():[t];p?this.pendingFocusIds=m:(this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=m),this.tree.rebuild(l),this.render({kind:"follow-cursor"});let B=this.selectionGuardKey,C=()=>{if(this.selectionGuardKey!==B||this.selection.has(I))return;let E=this.currentChildren.findIndex(Q=>Q.id===I);E<0||(this.selection.add(I),this.cursorIdx=E,this.render({kind:"follow-cursor"}))};setTimeout(C,120),setTimeout(C,400);let w=e.map(E=>this.tree.get(E)).filter(E=>!!E),y=this.tree.get(t),v=y?this.titleForNode(y):"(root)";this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Reparented",nodes:w,destination:`\u2192 "${v}"`}),kind:"success",category:"move",affectedIds:e,affectedAuthorIds:r,folder:l,actions:t===S?[]:[{label:"Jump to parent",onClick:()=>this.navigateTo(t)}]}),this.plugin.getUndoStack(l).push({label:`Move + reorder (${e.length})`,undo:async()=>{for(let E of n){let Q=this.fileForNote(E.id,E.path);Q&&(await this.app.fileManager.processFrontMatter(Q,b=>{E.oldParent===null||E.oldParent===void 0?b.parent=S:b.parent=E.oldParent}),await this.log.append({type:"parent_change",id:E.id,payload:{from:t,to:E.oldParent,reason:"drag-undo"}}))}for(let[E,Q]of Object.entries(c))if(Q.length===0){let b=this.order.cache.get(l)??{};delete b[E],this.order.cache.set(l,b)}else this.order.setOrder(l,E,Q);await this.order.save(l),this.pendingFocusIds=e.slice(),this.selection.clear(),this.cursorIdx=-1,this.tree.rebuild(l),this.render()},redo:async()=>{for(let E of n){let Q=this.fileForNote(E.id,E.path);Q&&(await this.app.fileManager.processFrontMatter(Q,b=>{b.parent=t}),this.order.removeChild(l,E.id))}this.order.setOrder(l,t,f),await this.order.save(l),this.pendingFocusIds=e.slice(),this.focusId!==t&&(this.selection.clear(),this.cursorIdx=-1),this.tree.rebuild(l),this.render()}})}async reorderToTarget(e,t,i){let s=this.tree.get(t);if(!s)return;let n=e.map(B=>this.tree.get(B)).filter(B=>!!B&&!!B.file);if(n.length===0)return;if(n.some(B=>B.id===t)){this.plugin.notifications.show({message:"Can't move a note into itself.",kind:"warning",category:"move",folder:this.noteFolder});return}let o=i==="into"?t:s.parent??S;for(let B of n)if(o===B.id||this.isDescendant(o,B.id)){this.plugin.notifications.show({message:`Can't move "${this.titleForNode(B)}" under itself or one of its own descendants \u2014 that would create a cycle.`,kind:"warning",category:"move",folder:this.noteFolder});return}if(n.some(B=>(B.parent??S)!==o)){let B=X(),C=async()=>{i==="into"?await this.moveAcrossThenReorder(n.map(w=>w.id),o,"","after"):await this.moveAcrossThenReorder(n.map(w=>w.id),o,t,i)};if(B.confirmCrossParentDrag){let w=this.titleForNode(s),y=n.length,v=i==="into"?"Nest":"Move",E=i==="into"?"as children of":"under";new _(this.app,i==="into"?"Nest under target?":"Move under different parent?",`${v} ${y} note${y===1?"":"s"} ${E} "${w}"? Their parent will change.`,v,Q=>{Q&&C()}).open()}else await C();return}let l=o,c=n.map(B=>B.id),A=this.tree.getChildren(l).map(B=>B.id),h=new Set(c),g=A.filter(B=>!h.has(B)),u=g.indexOf(t);if(u<0)return;i==="after"&&(u+=1);let f=[...g.slice(0,u),...c,...g.slice(u)];if(io(f,A))return;let p=this.noteFolder,I=this.order.getOrder(p,l).slice();this.order.setOrder(p,l,f),await this.order.save(p),await this.forceManualMode(l),await this.log.append({type:"reorder",id:l,payload:{dir:"drag",parent:l,ids:c,count:c.length}}),this.pendingFocusIds=c.slice(),this.tree.rebuild(p),this.render();let m=c.map(B=>this.tree.get(B)).filter(B=>!!B);this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Reordered",nodes:m}),kind:"success",category:"reorder",affectedIds:c,folder:p}),this.plugin.getUndoStack(p).push({label:`Reorder (drag, ${c.length})`,undo:async()=>{if(I.length===0){let B=this.order.cache.get(p)??{};delete B[l],this.order.cache.set(p,B)}else this.order.setOrder(p,l,I);await this.order.save(p),await this.log.append({type:"reorder",id:l,payload:{dir:"undo",parent:l,ids:c,count:c.length}}),this.pendingFocusIds=c.slice(),this.tree.rebuild(p),this.render()},redo:async()=>{this.order.setOrder(p,l,f),await this.order.save(p),await this.log.append({type:"reorder",id:l,payload:{dir:"redo:drag",parent:l,ids:c,count:c.length}}),this.pendingFocusIds=c.slice(),this.tree.rebuild(p),this.render()}})}cmdMoveUp(){this.reorderSelection("up")}cmdMoveDown(){this.reorderSelection("down")}cmdMoveToTop(){this.reorderSelection("top")}cmdMoveToBottom(){this.reorderSelection("bottom")}async reorderSelection(e){let t=[];if(this.selection.size>0){let h=[...this.selection].map(u=>this.tree.get(u)).filter(u=>!!u&&!!u.file);if(h.length===0)return;if(new Set(h.map(u=>u.parent)).size>1){new F.Notice("Reorder requires a single-parent selection.");return}t=h}else this.cursorIdx>=0&&this.currentChildren[this.cursorIdx]&&(t=[this.currentChildren[this.cursorIdx]]);if(t.length===0){new F.Notice("Nothing to reorder.");return}let i=t[0].parent??S,s=this.tree.getChildren(i).map(h=>h.id);if(s.length===0)return;let n=new Set(t.map(h=>h.id)),o=s.filter(h=>n.has(h));if(o.length===0)return;let r=xr(s,o,e);if(io(r,s))return;let l=this.noteFolder,c=this.order.getOrder(l,i).slice();this.order.setOrder(l,i,r),await this.order.save(l),await this.forceManualMode(i),await this.log.append({type:"reorder",id:i,payload:{dir:e,parent:i,ids:o,count:o.length}}),this.pendingFocusIds=o.slice(),this.tree.rebuild(l),this.render({kind:"follow-cursor"});let A=o.map(h=>this.tree.get(h)).filter(h=>!!h);this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Moved",nodes:A,destination:e}),kind:"success",category:"reorder",affectedIds:o,folder:l}),this.plugin.getUndoStack(l).push({label:`Reorder (${e})`,undo:async()=>{if(c.length===0){let h=this.order.cache.get(l)??{};delete h[i],this.order.cache.set(l,h)}else this.order.setOrder(l,i,c);await this.order.save(l),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(l),this.render()},redo:async()=>{this.order.setOrder(l,i,r),await this.order.save(l),await this.log.append({type:"reorder",id:i,payload:{dir:`redo:${e}`,parent:i,ids:o,count:o.length}}),this.pendingFocusIds=o.slice(),this.tree.rebuild(l),this.render()}})}async cmdDeleteUnencrypted(){await this.cmdDelete({forcePlaintext:!0})}async cmdDelete(e={}){let t=this.getActionTargets();if(t.length===0){let C=this.tree.get(this.focusId);C?.file&&(t=[C])}if(t.length===0){new F.Notice("Nothing selected to delete.");return}let i=(this.noteFolder??"").replace(/\/+$/,""),s=(this.plugin.settings.folderEncPrefs??{})[i]??{},n=s.trashEncryptContent??!1,o=s.trashHandling==="obsidian";if(n&&!o&&!e.forcePlaintext){if(!this.plugin.encryption?.isConfigured?.()){new F.Notice("\u201CEncrypt items sent to trash\u201D is ON but encryption isn't set up (Settings \u2192 Stashpad \u2192 Encryption). Nothing was deleted.");return}await this.secureDeleteSources(t);return}if(!e.forcePlaintext&&!o){await this.plaintextDeleteToStashpadTrash(t);return}if(t.length===1){await this.deleteNote(t[0]);return}let r=[],l=new Set,c=C=>{if(!l.has(C.id)){l.add(C.id);for(let w of this.tree.getChildren(C.id))c(w);r.push(C)}};for(let C of t)c(C);let A=r.filter(C=>!!C.file),h=await Promise.all(A.map(C=>this.app.vault.read(C.file))),g=[];for(let C=0;C<A.length;C++){let w=A[C];g.push(...this.extractAttachments(this.stripFrontmatter(h[C])));let y=this.app.metadataCache.getFileCache(w.file)?.frontmatter;if(Array.isArray(y?.attachments))for(let v of y.attachments)typeof v=="string"&&v.trim()&&g.push(Mt(v))}let u=[...new Set(g)],f=r.length-t.length,p=async C=>{let w=await this.snapshotNotes(r,C),y=0;if(C)for(let k of u){let P=this.app.metadataCache.getFirstLinkpathDest(k,"");if(P)try{await this.app.fileManager.trashFile(P),await this.log.append({type:"attachment_remove",id:S,payload:{path:P.path}}),this.plugin.notifications.show({message:`Deleted attachment "${P.name}"`,kind:"warning",category:"attachment",affectedPaths:[P.path],folder:this.noteFolder}),y+=1}catch{}}let v=new Set;for(let k of r)k.parent&&v.add(k.parent);let E=this.authorship.collectAuthorIds(r),Q=new Set(t.map(k=>k.id)),b=this.currentChildren.map((k,P)=>Q.has(k.id)?P:-1).filter(k=>k>=0),D=b.length>0?b[0]:-1,H=null;if(D>=0){for(let k=D+1;k<this.currentChildren.length;k++)if(!Q.has(this.currentChildren[k].id)){H=this.currentChildren[k].id;break}if(!H){for(let k=D-1;k>=0;k--)if(!Q.has(this.currentChildren[k].id)){H=this.currentChildren[k].id;break}}}for(let k of r)if(k.file){try{await this.app.fileManager.trashFile(k.file)}catch{}await this.log.append({type:"delete",id:k.id,payload:{path:k.file.path,attachmentsRemoved:C?u:[]}})}this.selection.clear(),this.cursorIdx=-1,H&&(this.pendingFocusIds=[H]),this.tree.rebuild(this.noteFolder);for(let k of v)r.some(P=>P.id===k)||this.fmSync.scheduleParentOfDeleted(k);this.render({kind:"follow-cursor"});let G=y>0?` with ${y} attachment${y===1?"":"s"}`:"",x=this.noteFolder,U=t.map(k=>k.id),R=!1,M=async()=>{R||(R=!0,this.selection.clear(),this.cursorIdx=-1,await this.restoreSnapshots(w,U.slice()))};this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Deleted",nodes:t,suffix:G.trim()||void 0}),kind:"warning",category:"delete",duration:0,affectedIds:t.map(k=>k.id),affectedAuthorIds:E,folder:this.noteFolder,actions:[{label:"Undo delete",onClick:()=>void M()}]}),this.plugin.getUndoStack(x).push({label:`Delete ${t.length} note${t.length===1?"":"s"}`,undo:async()=>{await M()},redo:async()=>{this.selection.clear(),this.cursorIdx=-1,R=!1,await this.trashNotesAndAttachments(w)}}),this.focusView()},I=X(),m=I.confirmBulkDelete,B=u.length>0&&I.confirmAttachmentDelete;if(!m&&!B){await p(!1);return}new ii(this.app,`${t.length} selected note${t.length===1?"":"s"}`,f,u.length,B,p).open()}async cmdSplit(e){let t=e??this.resolveActionTarget();if(!t?.file){new F.Notice("Pick a note to split.");return}let i=t.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 F.Notice("Note is too short to split.");return}let r=s,l=i.path,c=async(h,g,u)=>{if(!h.trim()||!g.trim()){new F.Notice("Split would leave one part empty.");return}try{let f=s.startsWith("---")?s.slice(0,s.indexOf(` ----`,3)+4):"",p=f+(f?` +Error: ${t.message}`,kind:"error",category:"system",duration:0,affectedPaths:[e],folder:this.noteFolder})}))}async ensureHomeNote(){let e=this.noteFolder,t=`${e}/${this.buildHomeFilename(e)}`,i=this.app.vault.getMarkdownFiles().filter(o=>o.path.startsWith(e+"/"));for(let o of i){if(this.app.metadataCache.getFileCache(o)?.frontmatter?.id!==k)continue;if(o.path===t||this.app.vault.getAbstractFileByPath(t))return o;try{await this.app.fileManager.renameFile(o,t);let c=this.app.vault.getAbstractFileByPath(t);if(c instanceof b.TFile)return c}catch(c){console.warn("[Stashpad] home note rename failed; keeping legacy path",c)}return o}let s=new Date().toISOString(),n=["---",`id: ${k}`,"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(t,n)}buildHomeFilename(e){return`Home-${(e.split("/").filter(Boolean).pop()??"Stashpad").replace(/[^A-Za-z0-9_-]+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")||"Stashpad"}.md`}async migrateNullParents(){let e=this.noteFolder,t=this.app.vault.getMarkdownFiles().filter(i=>i.path.startsWith(e+"/"));for(let i of t){let s=this.app.metadataCache.getFileCache(i)?.frontmatter,n=s?.id;if(!n||n===k)continue;let o=s?.parent;(o==null||o===""||o==="null")&&(await this.app.fileManager.processFrontMatter(i,r=>{r.parent=k}),await this.log.append({type:"parent_change",id:n,payload:{from:null,to:k,reason:"migration"}}))}}async openInNewStashpadTab(e){let t=this.app.workspace,i=this.leaf,s=t.getLeaf("tab");await s.setViewState({type:z,active:!0,state:{focusId:e,timeFilter:this.timeFilter,folderOverride:this.folderOverride}}),t.setActiveLeaf(s,{focus:!0}),t.revealLeaf(s),gt(t,s,i,n=>this.plugin.registerEvent(n))}async openNoteInNewTab(e,t,i){let s=(e||"").trim().replace(/^\/+|\/+$/g,"");if(!s||!t)return;let n=(this.plugin.settings.folder||"Stashpad").trim().replace(/^\/+|\/+$/g,"")||"Stashpad",o=this.app.workspace,r=this.leaf,l=o.getLeaf("tab");await l.setViewState({type:z,active:!0,state:{focusId:t,folderOverride:s===n?null:s,...i?{cursorId:i}:{}}}),o.setActiveLeaf(l,{focus:!0}),o.revealLeaf(l),gt(o,l,r,c=>this.plugin.registerEvent(c))}async openFolderInNewTab(e){let t=(e||"").trim().replace(/^\/+|\/+$/g,"");if(!t)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:z,active:!0,state:{focusId:k,folderOverride:t===i?null:t}}),s.setActiveLeaf(o,{focus:!0}),s.revealLeaf(o),gt(s,o,n,r=>this.plugin.registerEvent(r))}cmdOpenInEditor(e){if(e){this.openFileAtEnd(e.file);return}let t=this.getActionTargets();if(t.length)for(let i of t)i.file&&this.openFileAtEnd(i.file)}async cmdCopyStashpadLink(e){let i=(e?[e]:this.getActionTargets()).filter(n=>!!n?.id);if(i.length===0){new b.Notice("No note selected to link to.");return}let s=i.map(n=>An({vault:this.app.vault.getName(),folder:this.noteFolder,note:n.id,run:["reveal"]}));try{await navigator.clipboard.writeText(s.join(` +`)),new b.Notice(s.length>1?`${s.length} Stashpad links copied.`:"Stashpad link copied.")}catch{new b.Notice("Couldn't copy the link to the clipboard.")}}cmdOpenParentInEditor(){let e=this.tree.get(this.focusId);if(!e?.file){new b.Notice("No focused parent to open.");return}this.openFileAtEnd(e.file)}async openFileAtEnd(e){let t=this.app.workspace,i=this.leaf,s=t.getLeaf("tab");await s.openFile(e,{active:!0}),t.setActiveLeaf(s,{focus:!0}),t.revealLeaf(s),gt(t,s,i,r=>this.plugin.registerEvent(r));let o=s.view?.editor;o&&requestAnimationFrame(()=>{try{let r=o.lastLine(),l=o.getLine(r)?.length??0;o.setCursor({line:r,ch:l}),o.scrollIntoView({from:{line:r,ch:l},to:{line:r,ch:l}},!0),o.focus()}catch{}})}cmdSelectAll(){if(this.currentChildren.length!==0){this.selection.clear();for(let e of this.currentChildren)this.selection.add(e.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 e=this.getActionTargets();if(e.length===0){let n=this.tree.get(this.focusId);n?.file&&(e=[n])}if(e.length===0){new b.Notice("Nothing to pin.");return}let t=e.some(n=>!this.plugin.isPinned({folder:this.noteFolder,id:n.id})),i=0,s=0;for(let n of e){let o={folder:this.noteFolder,id:n.id};t?this.plugin.isPinned(o)||(await this.plugin.pinNote(o),i++):this.plugin.isPinned(o)&&(await this.plugin.unpinNote(o),s++)}i>0?new b.Notice(`Pinned ${i} note${i===1?"":"s"} to sidebar.`):s>0&&new b.Notice(`Unpinned ${s} note${s===1?"":"s"} from sidebar.`)}isListPinned(e){let t=this.tree.get(e);if(!t?.file)return!1;let i=this.listPinnedState.get(t.file.path);return i?i.pinned:this.app.metadataCache.getFileCache(t.file)?.frontmatter?.listPinned===!0}listPinnedAt(e){let t=this.tree.get(e);if(!t?.file)return 0;let i=this.listPinnedState.get(t.file.path);if(i)return i.at;let s=this.app.metadataCache.getFileCache(t.file)?.frontmatter?.listPinnedAt,n=typeof s=="string"?Date.parse(s):NaN;return Number.isNaN(n)?0:n}hoistListPinned(e,t){let i=this.tree.getChildren(e).map(l=>l.id);if(!i.some(l=>this.isListPinned(l)))return t;let s=new Set(t),n=[...t,...i.filter(l=>!s.has(l))],o=n.filter(l=>this.isListPinned(l)).sort((l,c)=>this.listPinnedAt(l)-this.listPinnedAt(c)),r=n.filter(l=>!this.isListPinned(l));return[...o,...r]}async cmdToggleListPin(){let e=this.getActionTargets();if(e.length===0){let r=this.tree.get(this.focusId);r?.file&&(e=[r])}if(e.length===0){new b.Notice("Nothing to pin.");return}let t=e.some(r=>!this.isListPinned(r.id)),i=[],s=new Date().toISOString(),n=[];for(let r of e){if(!r.file)continue;let l=this.app.metadataCache.getFileCache(r.file)?.frontmatter;i.push({path:r.file.path,listPinned:l?.listPinned,listPinnedAt:l?.listPinnedAt});let c=t?typeof l?.listPinnedAt=="string"&&Date.parse(l.listPinnedAt)||Date.parse(s):0;this.listPinnedState.set(r.file.path,{pinned:t,at:c}),await this.app.fileManager.processFrontMatter(r.file,A=>{t?(A.listPinned=!0,A.listPinnedAt||(A.listPinnedAt=s)):(delete A.listPinned,delete A.listPinnedAt)}),n.push(r.id)}let o=this.noteFolder;this.tree.rebuild(o),this.render(),this.plugin.notifications.show({message:t?`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:t?`Pin to top (${n.length})`:`Unpin from top (${n.length})`,undo:async()=>{for(let r of i){let l=this.app.vault.getAbstractFileByPath(r.path);if(!l)continue;await this.app.fileManager.processFrontMatter(l,h=>{r.listPinned===void 0?delete h.listPinned:h.listPinned=r.listPinned,r.listPinnedAt===void 0?delete h.listPinnedAt:h.listPinnedAt=r.listPinnedAt});let c=r.listPinned===!0,A=typeof r.listPinnedAt=="string"&&Date.parse(r.listPinnedAt)||0;this.listPinnedState.set(r.path,{pinned:c,at:A})}this.tree.rebuild(o),this.render()}})}async cmdToggleComplete(){let e=this.getActionTargets();if(e.length===0){let l=this.tree.get(this.focusId);l?.file&&(e=[l])}if(e.length===0){new b.Notice("Nothing to toggle.");return}let i=e.some(l=>!this.isCompleted(l)),s=[],n=[],o=[];for(let l of e){if(!l.file)continue;let c=this.isCompleted(l),A=this.app.metadataCache.getFileCache(l.file)?.frontmatter,h=A?.due!=null?String(A.due):null,p={id:l.id,path:l.file.path,was:c,dueBefore:h,rolledTo:null};if(s.push(p),c===i)continue;let u=!1;await this.app.fileManager.processFrontMatter(l.file,f=>{let g=i?nn(f.repeat):null;if(g){let I=f.due!=null?Date.parse(String(f.due)):NaN,m=on(g,Number.isFinite(I)?I:null,Date.now());f.due=new Date(m).toISOString(),delete f.completed,p.rolledTo=f.due,o.push({title:l.file.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||"task",when:m}),u=!0}else i?f.completed=!0:delete f.completed}),this.completedState.set(l.file.path,u?!1:i),n.push(l.id)}this.render();for(let l of o)this.plugin.notifications.show({message:`\u{1F501} Rescheduled \u201C${l.title}\u201D \u2192 ${Xe(l.when,this.plugin.settings)}.`,kind:"success",category:"system",folder:this.noteFolder});if(n.length>0){await this.log.append({type:i?"complete":"uncomplete",id:n[0],payload:{ids:n,count:n.length}});let l=n.map(c=>this.tree.get(c)).filter(c=>!!c);this.plugin.notifications.show({message:this.bulkActionMessage({verb:i?"Marked complete":"Unmarked",nodes:l}),kind:"success",category:i?"complete":"uncomplete",affectedIds:n,folder:this.noteFolder})}let r=this.noteFolder;this.plugin.getUndoStack(r).push({label:`${i?"Mark complete":"Unmark complete"} (${e.length})`,undo:async()=>{let l=[];for(let c of s){let A=this.app.vault.getAbstractFileByPath(c.path);A&&(await this.app.fileManager.processFrontMatter(A,h=>{c.rolledTo!=null?(c.dueBefore!=null?h.due=c.dueBefore:delete h.due,delete h.completed):c.was?h.completed=!0:delete h.completed}),n.includes(c.id)&&l.push(c.id))}l.length>0&&await this.log.append({type:i?"uncomplete":"complete",id:l[0],payload:{ids:l,count:l.length,undo:!0}}),this.tree.rebuild(r),this.render()},redo:async()=>{for(let l of s){let c=this.app.vault.getAbstractFileByPath(l.path);c&&await this.app.fileManager.processFrontMatter(c,A=>{l.rolledTo!=null?(A.due=l.rolledTo,delete A.completed):i?A.completed=!0:delete A.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(r),this.render()}})}isCompleted(e){if(!e.file)return!1;let t=this.completedState.get(e.file.path);return t!==void 0?t:!!this.app.metadataCache.getFileCache(e.file)?.frontmatter?.completed}taggedFromFm(e){return e?jt(e,"task")||e.task===!0:!1}cmdSetDue(){let e=this.getActionTargets();if(e.length===0){let r=this.tree.get(this.focusId);r?.file&&(e=[r])}if(e.length===0){new b.Notice("Nothing to schedule.");return}let t=e[0],i=t.file?this.app.metadataCache.getFileCache(t.file)?.frontmatter:null,s=i&&(typeof i.due=="string"||typeof i.due=="number")?String(i.due):null,n=this.plugin.collectKnownAuthors(),o=Pt(i??{});new Ge(this.app,s,r=>{this.applyDue(e,r.iso,r.assignees,!1,{repeat:r.repeat,autoDoneAfter:r.autoDoneAfter,remindEvery:r.remindEvery})},{knownAuthors:n,currentAssignees:o,quickAdjusts:this.plugin.settings.dueQuickAdjusts,showRecurrence:e.length===1,currentRepeat:typeof i?.repeat=="string"?i.repeat:"",currentAutoDoneAfter:typeof i?.autoDoneAfter=="string"?i.autoDoneAfter:"",currentRemindEvery:typeof i?.remindEvery=="string"?i.remindEvery:""}).open()}cmdSnooze(e){let t;if(e)t=[e];else if(t=this.getActionTargets(),t.length===0){let o=this.tree.get(this.focusId);o?.file&&(t=[o])}if(t.length===0){new b.Notice("Nothing to snooze.");return}let i=t[0],s=i.file?this.app.metadataCache.getFileCache(i.file)?.frontmatter:null,n=s&&(typeof s.due=="string"||typeof s.due=="number")?String(s.due):null;new Ge(this.app,n,o=>{this.applyDue(t,o.iso,[],!0)},{title:"Snooze \u2014 reschedule",hideAssignees:!0,quickAdjusts:this.plugin.settings.dueQuickAdjusts}).open()}async applyDue(e,t,i=[],s=!1,n){let o=[],r=[],l=this.authorship.currentAuthorLink();for(let h of i)await this.plugin.ensureAuthorStubFor(this.noteFolder,h.id,h.name);let c=i.map(h=>this.plugin.authorRefFor(this.noteFolder,h.id,h.name));for(let h of e){if(!h.file)continue;let p=this.app.metadataCache.getFileCache(h.file)?.frontmatter,u=this.isTaskTagged(h);o.push({id:h.id,path:h.file.path,due:p?.due,task:p?.task,assignedTo:p?.assignedTo,assignedBy:p?.assignedBy,wasTagged:u,repeat:p?.repeat,autoDoneAfter:p?.autoDoneAfter,remindEvery:p?.remindEvery}),await this.app.fileManager.processFrontMatter(h.file,g=>{if(t===null?delete g.due:(g.due=t,g.task=!0),n){let I=(m,B)=>{let C=(B??"").trim();C?(g[m]=C,g.task=!0):delete g[m]};I("repeat",n.repeat),I("autoDoneAfter",n.autoDoneAfter),I("remindEvery",n.remindEvery)}s||(c.length>0?(g.assignedTo=c,l&&(g.assignedBy=l.link),g.task=!0):(delete g.assignedTo,delete g.assignedBy))});let f=t!==null||c.length>0;this.taskTaggedState.set(h.file.path,f||u),r.push(h.id)}if(this.render(),r.length>0){let h=r.map(p=>this.tree.get(p)).filter(p=>!!p);this.plugin.notifications.show({message:this.bulkActionMessage({verb:t===null?"Cleared due date":`Due ${Xe(Date.parse(t),this.plugin.settings)}`,nodes:h}),kind:"success",category:"edit",affectedIds:r,folder:this.noteFolder})}let A=this.noteFolder;this.plugin.getUndoStack(A).push({label:t===null?`Clear due date (${e.length})`:`Set due date (${e.length})`,undo:async()=>{for(let h of o){let p=this.app.vault.getAbstractFileByPath(h.path);p&&(await this.app.fileManager.processFrontMatter(p,u=>{h.due===void 0?delete u.due:u.due=h.due,h.task===void 0?delete u.task:u.task=h.task,h.assignedTo===void 0?delete u.assignedTo:u.assignedTo=h.assignedTo,h.assignedBy===void 0?delete u.assignedBy:u.assignedBy=h.assignedBy,h.repeat===void 0?delete u.repeat:u.repeat=h.repeat,h.autoDoneAfter===void 0?delete u.autoDoneAfter:u.autoDoneAfter=h.autoDoneAfter,h.remindEvery===void 0?delete u.remindEvery:u.remindEvery=h.remindEvery}),this.taskTaggedState.set(h.path,h.wasTagged))}this.tree.rebuild(A),this.render()}})}cmdAssign(){let e=this.getActionTargets();if(e.length===0){let r=this.tree.get(this.focusId);r?.file&&(e=[r])}if(e.length===0){new b.Notice("Nothing to assign.");return}let t=e[0],i=t.file?this.app.metadataCache.getFileCache(t.file)?.frontmatter:null,s=i&&(typeof i.due=="string"||typeof i.due=="number")?String(i.due):null,n=this.plugin.collectKnownAuthors(),o=Pt(i??{});new Ge(this.app,s,r=>{this.applyDue(e,r.iso,r.assignees,!1,{repeat:r.repeat,autoDoneAfter:r.autoDoneAfter,remindEvery:r.remindEvery})},{knownAuthors:n,currentAssignees:o,title:"Assign / schedule task",quickAdjusts:this.plugin.settings.dueQuickAdjusts,showRecurrence:e.length===1,currentRepeat:typeof i?.repeat=="string"?i.repeat:"",currentAutoDoneAfter:typeof i?.autoDoneAfter=="string"?i.autoDoneAfter:"",currentRemindEvery:typeof i?.remindEvery=="string"?i.remindEvery:""}).open()}isTask(e){return e.file?this.isTaskTagged(e)?!0:this.app.metadataCache.getFileCache(e.file)?.frontmatter?.completed!==void 0:!1}async cmdToggleTask(){let e=this.getActionTargets();if(e.length===0){let r=this.tree.get(this.focusId);r?.file&&(e=[r])}if(e.length===0){new b.Notice("Nothing to toggle.");return}let t=e.some(r=>!this.isTaskTagged(r)),i=[],s=[];for(let r of e){if(!r.file)continue;let l=this.isTaskTagged(r),c=this.app.metadataCache.getFileCache(r.file)?.frontmatter;if(i.push({id:r.id,path:r.file.path,tags:c?.tags,completed:c?.completed,task:c?.task,wasTagged:l}),l===t)continue;let A=!1;await this.app.fileManager.processFrontMatter(r.file,h=>{t?(so(h,"task"),h.completed===void 0&&(h.completed=!1),A=h.completed===!0,delete h.task):(no(h,"task"),delete h.completed,delete h.task,A=!1)}),this.completedState.set(r.file.path,A),this.taskTaggedState.set(r.file.path,t),s.push(r.id)}if(this.render(),s.length>0){let r=t?"marked as task":"unmarked as task",l;if(s.length===1){let c=this.tree.get(s[0]);l=`"${c&&this.titleForNode(c).trim()||"(untitled)"}" ${r}`}else l=`${s.length} notes ${r}`;this.plugin.notifications.show({message:l,kind:"success",category:"edit",affectedIds:s,folder:this.noteFolder})}let n=this.noteFolder,o=async()=>{for(let r of i){let l=this.app.vault.getAbstractFileByPath(r.path);l&&(await this.app.fileManager.processFrontMatter(l,c=>{r.tags===void 0?delete c.tags:c.tags=r.tags,r.completed===void 0?delete c.completed:c.completed=r.completed,r.task===void 0?delete c.task:c.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:`${t?"Mark task":"Unmark task"} (${e.length})`,undo:o,redo:async()=>{for(let r of i){let l=this.app.vault.getAbstractFileByPath(r.path);if(!l)continue;let c=!1;await this.app.fileManager.processFrontMatter(l,A=>{t?(so(A,"task"),A.completed===void 0&&(A.completed=!1),c=A.completed===!0,delete A.task):(no(A,"task"),delete A.completed,delete A.task,c=!1)}),this.completedState.set(r.path,c),this.taskTaggedState.set(r.path,t)}this.tree.rebuild(n),this.render()}})}async toggleCompletedForNode(e){if(!e.file)return;let t=e.file.path,i=this.isCompleted(e);await this.app.fileManager.processFrontMatter(e.file,n=>{n.completed=!i}),this.completedState.set(t,!i),await this.log.append({type:i?"uncomplete":"complete",id:e.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(t);n&&(await this.app.fileManager.processFrontMatter(n,o=>{o.completed=i}),this.tree.rebuild(s),this.render())}})}isTaskTagged(e){if(!e.file)return!1;let t=this.taskTaggedState.get(e.file.path);if(t!==void 0)return t;let i=this.app.metadataCache.getFileCache(e.file)?.frontmatter;return this.taggedFromFm(i)}colorForNode(e){if(!e.file)return null;let t=this.app.metadataCache.getFileCache(e.file)?.frontmatter?.color;if(typeof t!="string")return null;let i=t.trim();return/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(i)?i:null}inheritedColorForNode(e){let t=e,i=0,s=new Set;for(;t&&t.id!==k&&!s.has(t.id);){s.add(t.id);let n=this.colorForNode(t);if(n)return{hex:n,depth:i};t=t.parent?this.tree.get(t.parent):void 0,i+=1}return null}isDescendant(e,t){let i=this.tree.get(e),s=new Set;for(;i&&i.parent&&!s.has(i.id);){if(i.parent===t)return!0;s.add(i.id),i=this.tree.get(i.parent)}return!1}async moveAcrossThenReorder(e,t,i,s){let n=[],o=new Set;for(let w of e){let v=this.tree.get(w);v?.file&&(n.push({id:w,path:v.file.path,oldParent:v.parent}),o.add(v.parent??k))}o.add(t);let r=this.authorship.collectAuthorIds(e.map(w=>this.tree.get(w)).filter(w=>!!w)),l=this.noteFolder,c={};for(let w of o)c[w]=this.order.getOrder(l,w).slice();for(let w of n){let v=this.app.vault.getAbstractFileByPath(w.path);v&&(await this.app.fileManager.processFrontMatter(v,F=>{F.parent=t}),this.fmSync.scheduleParentChange(w.id,w.oldParent,t),await this.log.append({type:"parent_change",id:w.id,payload:{from:w.oldParent,to:t,reason:"drag"}}),this.order.removeChild(l,w.id))}this.tree.rebuild(l);let A=this.tree.getChildren(t).map(w=>w.id),h=new Set(e),p=A.filter(w=>!h.has(w)),u=p.indexOf(i);u<0&&(u=p.length),s==="after"&&(u+=1);let f=[...p.slice(0,u),...e.filter(w=>!!this.tree.get(w)),...p.slice(u)];this.order.setOrder(l,t,f),await this.order.save(l),await this.forceManualMode(t),await this.log.append({type:"reorder",id:t,payload:{dir:"drag-cross",parent:t,ids:e,count:e.length}});let g=this.focusId===t,I=g?e[0]:t,m=g?e.slice():[t];g?this.pendingFocusIds=m:(this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=m),this.tree.rebuild(l),this.render({kind:"follow-cursor"});let B=this.selectionGuardKey,C=()=>{if(this.selectionGuardKey!==B||this.selection.has(I))return;let w=this.currentChildren.findIndex(v=>v.id===I);w<0||(this.selection.add(I),this.cursorIdx=w,this.render({kind:"follow-cursor"}))};setTimeout(C,120),setTimeout(C,400);let Q=e.map(w=>this.tree.get(w)).filter(w=>!!w),y=this.tree.get(t),E=y?this.titleForNode(y):"(root)";this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Reparented",nodes:Q,destination:`\u2192 "${E}"`}),kind:"success",category:"move",affectedIds:e,affectedAuthorIds:r,folder:l,actions:t===k?[]:[{label:"Jump to parent",onClick:()=>this.navigateTo(t)}]}),this.plugin.getUndoStack(l).push({label:`Move + reorder (${e.length})`,undo:async()=>{for(let w of n){let v=this.fileForNote(w.id,w.path);v&&(await this.app.fileManager.processFrontMatter(v,F=>{w.oldParent===null||w.oldParent===void 0?F.parent=k:F.parent=w.oldParent}),await this.log.append({type:"parent_change",id:w.id,payload:{from:t,to:w.oldParent,reason:"drag-undo"}}))}for(let[w,v]of Object.entries(c))if(v.length===0){let F=this.order.cache.get(l)??{};delete F[w],this.order.cache.set(l,F)}else this.order.setOrder(l,w,v);await this.order.save(l),this.pendingFocusIds=e.slice(),this.selection.clear(),this.cursorIdx=-1,this.tree.rebuild(l),this.render()},redo:async()=>{for(let w of n){let v=this.fileForNote(w.id,w.path);v&&(await this.app.fileManager.processFrontMatter(v,F=>{F.parent=t}),this.order.removeChild(l,w.id))}this.order.setOrder(l,t,f),await this.order.save(l),this.pendingFocusIds=e.slice(),this.focusId!==t&&(this.selection.clear(),this.cursorIdx=-1),this.tree.rebuild(l),this.render()}})}async reorderToTarget(e,t,i){let s=this.tree.get(t);if(!s)return;let n=e.map(B=>this.tree.get(B)).filter(B=>!!B&&!!B.file);if(n.length===0)return;if(n.some(B=>B.id===t)){this.plugin.notifications.show({message:"Can't move a note into itself.",kind:"warning",category:"move",folder:this.noteFolder});return}let o=i==="into"?t:s.parent??k;for(let B of n)if(o===B.id||this.isDescendant(o,B.id)){this.plugin.notifications.show({message:`Can't move "${this.titleForNode(B)}" under itself or one of its own descendants \u2014 that would create a cycle.`,kind:"warning",category:"move",folder:this.noteFolder});return}if(n.some(B=>(B.parent??k)!==o)){let B=X(),C=async()=>{i==="into"?await this.moveAcrossThenReorder(n.map(Q=>Q.id),o,"","after"):await this.moveAcrossThenReorder(n.map(Q=>Q.id),o,t,i)};if(B.confirmCrossParentDrag){let Q=this.titleForNode(s),y=n.length,E=i==="into"?"Nest":"Move",w=i==="into"?"as children of":"under";new _(this.app,i==="into"?"Nest under target?":"Move under different parent?",`${E} ${y} note${y===1?"":"s"} ${w} "${Q}"? Their parent will change.`,E,v=>{v&&C()}).open()}else await C();return}let l=o,c=n.map(B=>B.id),A=this.tree.getChildren(l).map(B=>B.id),h=new Set(c),p=A.filter(B=>!h.has(B)),u=p.indexOf(t);if(u<0)return;i==="after"&&(u+=1);let f=[...p.slice(0,u),...c,...p.slice(u)];if(oo(f,A))return;let g=this.noteFolder,I=this.order.getOrder(g,l).slice();this.order.setOrder(g,l,f),await this.order.save(g),await this.forceManualMode(l),await this.log.append({type:"reorder",id:l,payload:{dir:"drag",parent:l,ids:c,count:c.length}}),this.pendingFocusIds=c.slice(),this.tree.rebuild(g),this.render();let m=c.map(B=>this.tree.get(B)).filter(B=>!!B);this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Reordered",nodes:m}),kind:"success",category:"reorder",affectedIds:c,folder:g}),this.plugin.getUndoStack(g).push({label:`Reorder (drag, ${c.length})`,undo:async()=>{if(I.length===0){let B=this.order.cache.get(g)??{};delete B[l],this.order.cache.set(g,B)}else this.order.setOrder(g,l,I);await this.order.save(g),await this.log.append({type:"reorder",id:l,payload:{dir:"undo",parent:l,ids:c,count:c.length}}),this.pendingFocusIds=c.slice(),this.tree.rebuild(g),this.render()},redo:async()=>{this.order.setOrder(g,l,f),await this.order.save(g),await this.log.append({type:"reorder",id:l,payload:{dir:"redo:drag",parent:l,ids:c,count:c.length}}),this.pendingFocusIds=c.slice(),this.tree.rebuild(g),this.render()}})}cmdMoveUp(){this.reorderSelection("up")}cmdMoveDown(){this.reorderSelection("down")}cmdMoveToTop(){this.reorderSelection("top")}cmdMoveToBottom(){this.reorderSelection("bottom")}async reorderSelection(e){let t=[];if(this.selection.size>0){let h=[...this.selection].map(u=>this.tree.get(u)).filter(u=>!!u&&!!u.file);if(h.length===0)return;if(new Set(h.map(u=>u.parent)).size>1){new b.Notice("Reorder requires a single-parent selection.");return}t=h}else this.cursorIdx>=0&&this.currentChildren[this.cursorIdx]&&(t=[this.currentChildren[this.cursorIdx]]);if(t.length===0){new b.Notice("Nothing to reorder.");return}let i=t[0].parent??k,s=this.tree.getChildren(i).map(h=>h.id);if(s.length===0)return;let n=new Set(t.map(h=>h.id)),o=s.filter(h=>n.has(h));if(o.length===0)return;let r=Mr(s,o,e);if(oo(r,s))return;let l=this.noteFolder,c=this.order.getOrder(l,i).slice();this.order.setOrder(l,i,r),await this.order.save(l),await this.forceManualMode(i),await this.log.append({type:"reorder",id:i,payload:{dir:e,parent:i,ids:o,count:o.length}}),this.pendingFocusIds=o.slice(),this.tree.rebuild(l),this.render({kind:"follow-cursor"});let A=o.map(h=>this.tree.get(h)).filter(h=>!!h);this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Moved",nodes:A,destination:e}),kind:"success",category:"reorder",affectedIds:o,folder:l}),this.plugin.getUndoStack(l).push({label:`Reorder (${e})`,undo:async()=>{if(c.length===0){let h=this.order.cache.get(l)??{};delete h[i],this.order.cache.set(l,h)}else this.order.setOrder(l,i,c);await this.order.save(l),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(l),this.render()},redo:async()=>{this.order.setOrder(l,i,r),await this.order.save(l),await this.log.append({type:"reorder",id:i,payload:{dir:`redo:${e}`,parent:i,ids:o,count:o.length}}),this.pendingFocusIds=o.slice(),this.tree.rebuild(l),this.render()}})}async cmdDeleteUnencrypted(){await this.cmdDelete({forcePlaintext:!0})}async cmdDelete(e={}){let t=this.getActionTargets();if(t.length===0){let C=this.tree.get(this.focusId);C?.file&&(t=[C])}if(t.length===0){new b.Notice("Nothing selected to delete.");return}let i=(this.noteFolder??"").replace(/\/+$/,""),s=(this.plugin.settings.folderEncPrefs??{})[i]??{},n=s.trashEncryptContent??!1,o=s.trashHandling==="obsidian";if(n&&!o&&!e.forcePlaintext){if(!this.plugin.encryption?.isConfigured?.()){new b.Notice("\u201CEncrypt items sent to trash\u201D is ON but encryption isn't set up (Settings \u2192 Stashpad \u2192 Encryption). Nothing was deleted.");return}await this.secureDeleteSources(t);return}if(!e.forcePlaintext&&!o){await this.plaintextDeleteToStashpadTrash(t);return}if(t.length===1){await this.deleteNote(t[0]);return}let r=[],l=new Set,c=C=>{if(!l.has(C.id)){l.add(C.id);for(let Q of this.tree.getChildren(C.id))c(Q);r.push(C)}};for(let C of t)c(C);let A=r.filter(C=>!!C.file),h=await Promise.all(A.map(C=>this.app.vault.read(C.file))),p=[];for(let C=0;C<A.length;C++){let Q=A[C];p.push(...this.extractAttachments(this.stripFrontmatter(h[C])));let y=this.app.metadataCache.getFileCache(Q.file)?.frontmatter;if(Array.isArray(y?.attachments))for(let E of y.attachments)typeof E=="string"&&E.trim()&&p.push(Tt(E))}let u=[...new Set(p)],f=r.length-t.length,g=async C=>{let Q=await this.snapshotNotes(r,C),y=0;if(C)for(let S of u){let P=this.app.metadataCache.getFirstLinkpathDest(S,"");if(P)try{await this.app.fileManager.trashFile(P),await this.log.append({type:"attachment_remove",id:k,payload:{path:P.path}}),this.plugin.notifications.show({message:`Deleted attachment "${P.name}"`,kind:"warning",category:"attachment",affectedPaths:[P.path],folder:this.noteFolder}),y+=1}catch{}}let E=new Set;for(let S of r)S.parent&&E.add(S.parent);let w=this.authorship.collectAuthorIds(r),v=new Set(t.map(S=>S.id)),F=this.currentChildren.map((S,P)=>v.has(S.id)?P:-1).filter(S=>S>=0),D=F.length>0?F[0]:-1,R=null;if(D>=0){for(let S=D+1;S<this.currentChildren.length;S++)if(!v.has(this.currentChildren[S].id)){R=this.currentChildren[S].id;break}if(!R){for(let S=D-1;S>=0;S--)if(!v.has(this.currentChildren[S].id)){R=this.currentChildren[S].id;break}}}for(let S of r)if(S.file){try{await this.app.fileManager.trashFile(S.file)}catch{}await this.log.append({type:"delete",id:S.id,payload:{path:S.file.path,attachmentsRemoved:C?u:[]}})}this.selection.clear(),this.cursorIdx=-1,R&&(this.pendingFocusIds=[R]),this.tree.rebuild(this.noteFolder);for(let S of E)r.some(P=>P.id===S)||this.fmSync.scheduleParentOfDeleted(S);this.render({kind:"follow-cursor"});let G=y>0?` with ${y} attachment${y===1?"":"s"}`:"",x=this.noteFolder,H=t.map(S=>S.id),U=!1,N=async()=>{U||(U=!0,this.selection.clear(),this.cursorIdx=-1,await this.restoreSnapshots(Q,H.slice()))};this.plugin.notifications.show({message:this.bulkActionMessage({verb:"Deleted",nodes:t,suffix:G.trim()||void 0}),kind:"warning",category:"delete",duration:0,affectedIds:t.map(S=>S.id),affectedAuthorIds:w,folder:this.noteFolder,actions:[{label:"Undo delete",onClick:()=>void N()}]}),this.plugin.getUndoStack(x).push({label:`Delete ${t.length} note${t.length===1?"":"s"}`,undo:async()=>{await N()},redo:async()=>{this.selection.clear(),this.cursorIdx=-1,U=!1,await this.trashNotesAndAttachments(Q)}}),this.focusView()},I=X(),m=I.confirmBulkDelete,B=u.length>0&&I.confirmAttachmentDelete;if(!m&&!B){await g(!1);return}new si(this.app,`${t.length} selected note${t.length===1?"":"s"}`,f,u.length,B,g).open()}async cmdSplit(e){let t=e??this.resolveActionTarget();if(!t?.file){new b.Notice("Pick a note to split.");return}let i=t.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 b.Notice("Note is too short to split.");return}let r=s,l=i.path,c=async(h,p,u)=>{if(!h.trim()||!p.trim()){new b.Notice("Split would leave one part empty.");return}try{let f=s.startsWith("---")?s.slice(0,s.indexOf(` +---`,3)+4):"",g=f+(f?` `:"")+h+` -`;await this.app.vault.modify(i,p);let I=t.parent??S,m=Date.parse(t.created||""),B=Number.isFinite(m)?new Date(m+1).toISOString():new Date().toISOString(),C=await this.createNoteUnder(g,I,{record:!1,createdOverride:B});await this.log.append({type:"rename",id:t.id,payload:{action:"split",into:C,...u}}),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(t)}" into two`,kind:"success",category:"split",affectedIds:[t.id],folder:this.noteFolder});let w=C?this.tree.get(C):void 0,y=w?.file?.path,v=y?await this.app.vault.read(w.file):null,E=this.noteFolder;this.plugin.getUndoStack(E).push({label:"Split note",undo:async()=>{if(y){let b=this.app.vault.getAbstractFileByPath(y);if(b)try{await this.app.fileManager.trashFile(b)}catch{}}let Q=this.app.vault.getAbstractFileByPath(l);Q&&await this.app.vault.modify(Q,r),this.tree.rebuild(E),this.render()},redo:async()=>{let Q=this.app.vault.getAbstractFileByPath(l);Q&&await this.app.vault.modify(Q,p),y&&v&&!await this.app.vault.adapter.exists(y)&&await this.app.vault.create(y,v),this.tree.rebuild(E),this.render()}})}catch(f){new F.Notice(`Stashpad: split failed (${f.message})`),console.error(f)}},A=async h=>{if(!(h.length<2))try{let g=s.startsWith("---")?s.slice(0,s.indexOf(` ----`,3)+4):"",u=h[0].replace(/\s+$/,"");if(!u.trim()){new F.Notice("Split would leave the first part empty.");return}let f=g+(g?` +`;await this.app.vault.modify(i,g);let I=t.parent??k,m=Date.parse(t.created||""),B=Number.isFinite(m)?new Date(m+1).toISOString():new Date().toISOString(),C=await this.createNoteUnder(p,I,{record:!1,createdOverride:B});await this.log.append({type:"rename",id:t.id,payload:{action:"split",into:C,...u}}),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(t)}" into two`,kind:"success",category:"split",affectedIds:[t.id],folder:this.noteFolder});let Q=C?this.tree.get(C):void 0,y=Q?.file?.path,E=y?await this.app.vault.read(Q.file):null,w=this.noteFolder;this.plugin.getUndoStack(w).push({label:"Split note",undo:async()=>{if(y){let F=this.app.vault.getAbstractFileByPath(y);if(F)try{await this.app.fileManager.trashFile(F)}catch{}}let v=this.app.vault.getAbstractFileByPath(l);v&&await this.app.vault.modify(v,r),this.tree.rebuild(w),this.render()},redo:async()=>{let v=this.app.vault.getAbstractFileByPath(l);v&&await this.app.vault.modify(v,g),y&&E&&!await this.app.vault.adapter.exists(y)&&await this.app.vault.create(y,E),this.tree.rebuild(w),this.render()}})}catch(f){new b.Notice(`Stashpad: split failed (${f.message})`),console.error(f)}},A=async h=>{if(!(h.length<2))try{let p=s.startsWith("---")?s.slice(0,s.indexOf(` +---`,3)+4):"",u=h[0].replace(/\s+$/,"");if(!u.trim()){new b.Notice("Split would leave the first part empty.");return}let f=p+(p?` `:"")+u+` -`;await this.app.vault.modify(i,f);let p=t.parent??S,I=Date.parse(t.created||""),m=Number.isFinite(I)?I:Date.now(),B=[];this.beginBulkRender();try{for(let y=1;y<h.length;y++)await this.createNoteUnder(h[y],p,{record:!1,createdOverride:new Date(m+y).toISOString(),deferRender:!0,collectInto:B})}finally{try{await this.fmSync.flush()}catch{}this.endBulkRender()}await this.log.append({type:"rename",id:t.id,payload:{action:"split-many",parts:h.length}}),this.suppressComposerFocusUntil=Date.now()+500,this.viewRoot?.focus({preventScroll:!0}),this.plugin.notifications.show({message:`Split "${this.titleForNode(t)}" into ${h.length}`,kind:"success",category:"split",affectedIds:[t.id],folder:this.noteFolder});let C=B.slice(),w=this.noteFolder;this.plugin.getUndoStack(w).push({label:`Split note into ${h.length}`,undo:async()=>{for(let{path:v}of C){let E=this.app.vault.getAbstractFileByPath(v);if(E)try{await this.app.fileManager.trashFile(E)}catch{}}let y=this.app.vault.getAbstractFileByPath(l);y&&await this.app.vault.modify(y,r),this.tree.rebuild(w),this.render()},redo:async()=>{let y=this.app.vault.getAbstractFileByPath(l);y&&await this.app.vault.modify(y,f);for(let{path:v,content:E}of C)await this.app.vault.adapter.exists(v)||await this.app.vault.create(v,E);this.tree.rebuild(w),this.render()}})}catch(g){new F.Notice(`Stashpad: split failed (${g.message})`),console.error(g)}};new Ri(this.app,n,async h=>{let g=o.slice(0,h).join(` +`;await this.app.vault.modify(i,f);let g=t.parent??k,I=Date.parse(t.created||""),m=Number.isFinite(I)?I:Date.now(),B=[];this.beginBulkRender();try{for(let y=1;y<h.length;y++)await this.createNoteUnder(h[y],g,{record:!1,createdOverride:new Date(m+y).toISOString(),deferRender:!0,collectInto:B})}finally{try{await this.fmSync.flush()}catch{}this.endBulkRender()}await this.log.append({type:"rename",id:t.id,payload:{action:"split-many",parts:h.length}}),this.suppressComposerFocusUntil=Date.now()+500,this.viewRoot?.focus({preventScroll:!0}),this.plugin.notifications.show({message:`Split "${this.titleForNode(t)}" into ${h.length}`,kind:"success",category:"split",affectedIds:[t.id],folder:this.noteFolder});let C=B.slice(),Q=this.noteFolder;this.plugin.getUndoStack(Q).push({label:`Split note into ${h.length}`,undo:async()=>{for(let{path:E}of C){let w=this.app.vault.getAbstractFileByPath(E);if(w)try{await this.app.fileManager.trashFile(w)}catch{}}let y=this.app.vault.getAbstractFileByPath(l);y&&await this.app.vault.modify(y,r),this.tree.rebuild(Q),this.render()},redo:async()=>{let y=this.app.vault.getAbstractFileByPath(l);y&&await this.app.vault.modify(y,f);for(let{path:E,content:w}of C)await this.app.vault.adapter.exists(E)||await this.app.vault.create(E,w);this.tree.rebuild(Q),this.render()}})}catch(p){new b.Notice(`Stashpad: split failed (${p.message})`),console.error(p)}};new Ui(this.app,n,async h=>{let p=o.slice(0,h).join(` `).replace(/\s+$/,""),u=o.slice(h).join(` -`).replace(/^\s+|\s+$/g,"");await c(g,u,{mode:"line",splitAtLine:h})},async h=>{let g=n.slice(0,h).replace(/\s+$/,""),u=n.slice(h).replace(/^\s+|\s+$/g,"");await c(g,u,{mode:"cursor",splitAtChar:h})},async h=>{await A(h)}).open()}cmdOpenInNewStashpadTab(e){let t=e??this.resolveActionTarget();t?.file&&this.openInNewStashpadTab(t.id)}cmdCloneStashpadTab(){let e=this.tree.get(this.focusId);e?.file?this.cmdOpenInNewStashpadTab(e):this.openInNewStashpadTab(this.focusId)}resolveActionTarget(){if(this.cursorIdx>=0&&this.currentChildren[this.cursorIdx])return this.currentChildren[this.cursorIdx];let e=this.tree.get(this.focusId);return e?.file?e:void 0}cmdExportStash(e){return pl(this,e)}cmdExportOkf(e){return ul(this,e)}cmdImportStash(){return ml(this)}processStashFile(e){return rr(this,e)}async createNoteUnder(e,t,i={record:!0}){let s=(i.targetFolder??this.noteFolder).replace(/\/+$/,""),n=s!==this.noteFolder;await this.ensureFolder(s);let o=this.plugin.mintNoteId(),r=null;{let I=(this.plugin.settings.noteTemplates??{})[s];if(I){let m=this.app.vault.getAbstractFileByPath(I);if(m&&m.extension==="md")try{let B=await this.app.vault.cachedRead(m),C=this.stripFrontmatter(B);r=this.app.metadataCache.getFileCache(m)?.frontmatter??{},C.includes("{{body}}")?e=C.replace(/\{\{body\}\}/g,e):e.trim()?C.trim()&&(e=`${e} +`).replace(/^\s+|\s+$/g,"");await c(p,u,{mode:"line",splitAtLine:h})},async h=>{let p=n.slice(0,h).replace(/\s+$/,""),u=n.slice(h).replace(/^\s+|\s+$/g,"");await c(p,u,{mode:"cursor",splitAtChar:h})},async h=>{await A(h)}).open()}cmdOpenInNewStashpadTab(e){let t=e??this.resolveActionTarget();t?.file&&this.openInNewStashpadTab(t.id)}cmdCloneStashpadTab(){let e=this.tree.get(this.focusId);e?.file?this.cmdOpenInNewStashpadTab(e):this.openInNewStashpadTab(this.focusId)}resolveActionTarget(){if(this.cursorIdx>=0&&this.currentChildren[this.cursorIdx])return this.currentChildren[this.cursorIdx];let e=this.tree.get(this.focusId);return e?.file?e:void 0}cmdExportStash(e){return Il(this,e)}cmdExportOkf(e){return Cl(this,e)}cmdImportStash(){return wl(this)}processStashFile(e){return lr(this,e)}async createNoteUnder(e,t,i={record:!0}){let s=(i.targetFolder??this.noteFolder).replace(/\/+$/,""),n=s!==this.noteFolder;await this.ensureFolder(s);let o=this.plugin.mintNoteId(),r=null;{let I=(this.plugin.settings.noteTemplates??{})[s];if(I){let m=this.app.vault.getAbstractFileByPath(I);if(m&&m.extension==="md")try{let B=await this.app.vault.cachedRead(m),C=this.stripFrontmatter(B);r=this.app.metadataCache.getFileCache(m)?.frontmatter??{},C.includes("{{body}}")?e=C.replace(/\{\{body\}\}/g,e):e.trim()?C.trim()&&(e=`${e} -${C}`):e=C}catch(B){console.warn("[Stashpad] template read failed",B)}}}let l=Se(e,this.activeStopwords()),c=be(l,o),A=`${s}/${c}`,h=t??this.focusId,g=i.createdOverride??new Date().toISOString(),u=this.extractAttachments(e),f=this.authorship.currentAuthorLink();f&&this.authorship.ensureAuthorFile(f);let p=["---",`id: ${o}`,`parent: ${h}`,`created: ${g}`,`modified: ${g}`];if(f&&p.push(`author: "${f.link.replace(/"/g,'\\"')}"`),u.length>0){p.push("attachments:");for(let I of u)p.push(` - "${I.replace(/"/g,'\\"')}"`)}else p.push("attachments: []");p.push("---",e);try{let I=p.join(` -`);this.plugin.importService.suppress(A,6e4),await ke.timeAsync("write.createNote.file",()=>this.app.vault.create(A,I)),i.collectInto?.push({path:A,content:I});try{let m=this.app.vault.getAbstractFileByPath(A);if(m&&m.extension==="md"){if(!n)this.tree.insertSynthetic({id:o,parent:h,children:[],file:m,created:g}),i.deferRender||this.render(),this.fmSync.scheduleParentChange(o,null,h);else{i.deferRender||this.render();let B=s.split("/").pop()||s,C=(e.split(` -`).find(w=>w.trim())??"note").trim().slice(0,60);i.deferUndo||this.plugin.notifications.show({message:`"${C}" 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(m,B=>{for(let[C,w]of Object.entries(r))ze.includes(C)||Wn.includes(C)||B[C]===void 0&&(B[C]=w)})}catch(B){console.warn("[Stashpad] template fm overlay failed",B)}}}catch{}if(await this.log.append({type:"create",id:o,payload:{path:A,parent:h}}),i.record!==!1&&!i.deferUndo){let m=e;this.plugin.getUndoStack(s).push({label:n?"Send note":"Create note",undo:async()=>{let B=this.fileForNote(o,A);if(B)try{await this.app.fileManager.trashFile(B)}catch{}if(!(this.composerInputEl?.value??this.composerDraft).trim()&&(this.composerDraft=m,this.saveDraft(m),this.recordLastSubmitted(""),this.composerInputEl)){this.composerInputEl.value=m;let w=m.length;this.composerInputEl.setSelectionRange(w,w),this.composerInputEl.focus()}n||this.tree.rebuild(this.noteFolder),this.render()},redo:async()=>{await this.app.vault.adapter.exists(A)||await this.app.vault.create(A,I),this.composerDraft="",this.saveDraft(""),this.recordLastSubmitted(m),this.composerInputEl&&(this.composerInputEl.value=""),n||this.tree.rebuild(this.noteFolder),this.render()}})}return o}catch(I){return new F.Notice(`Stashpad: failed to create note (${I.message})`),null}}async createNotesBatch(e,t,i,s,n){let o=e.length,r=[],l=!!i?.targetFolder&&i.targetFolder!==this.noteFolder,c=8,A=null;if(o>=c){let h=new F.Notice("",0),g=h.messageEl;g.empty(),g.createDiv({cls:"stashpad-split-progress-title",text:`Splitting into ${o} notes\u2026`});let f=g.createDiv({cls:"stashpad-split-progress-bar"}).createDiv({cls:"stashpad-split-progress-fill"}),p=g.createDiv({cls:"stashpad-split-progress-label",text:`0 / ${o}`});A={notice:h,fill:f,label:p}}this.beginBulkRender();try{for(let h=0;h<o;h++)if(await this.createNoteUnder(e[h],t,{...i??{},deferRender:!0,deferUndo:!0,collectInto:r}),A){let g=h+1;A.label.setText(`${g} / ${o}`),A.fill.setCssStyles({width:`${Math.round(g/o*100)}%`}),g%5===0&&await new Promise(u=>window.setTimeout(u,0))}}finally{A?.notice.hide();try{await this.fmSync.flush()}catch{}this.endBulkRender()}if(r.length){let h=r.slice();this.plugin.getUndoStack(n).push({label:`Create ${h.length} notes`,undo:async()=>{for(let{path:g}of h){let u=this.app.vault.getAbstractFileByPath(g);if(u)try{await this.app.fileManager.trashFile(u)}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()}l||this.tree.rebuild(this.noteFolder),this.render()},redo:async()=>{for(let{path:g,content:u}of h)await this.app.vault.adapter.exists(g)||await this.app.vault.create(g,u);this.composerDraft="",this.saveDraft(""),this.composerInputEl&&(this.composerInputEl.value=""),l||this.tree.rebuild(this.noteFolder),this.render()}})}o>=c&&this.plugin.notifications.show({message:`Created ${r.length} notes${l?` in \`${n.split("/").pop()}\``:""}.`,kind:"success",category:"create"})}extractAttachments(e){let t=[],i=/!\[\[([^\]\|]+)(?:\|[^\]]+)?\]\]/g,s;for(;(s=i.exec(e))!==null;)t.push(s[1]);return t}async ensureFolder(e){if(await this.app.vault.adapter.exists(e)){let t=this.app.vault.getAbstractFileByPath(e);if(t&&!(t instanceof F.TFolder))throw new Error(`${e} exists and is not a folder`);return}try{await this.app.vault.createFolder(e)}catch(t){let i=t?.message??"";if(!/already exists/i.test(i))throw t}}async importAttachment(e){try{let t=await e.arrayBuffer(),i=`${this.noteFolder}/_attachments`;await this.ensureFolder(i);let s=e.name.replace(/[^\w.\-]+/g,"_"),n=Date.now().toString(36),o=`${i}/${Ms(s,n)}`;return await this.app.vault.createBinary(o,t),await this.log.append({type:"attachment_add",id:S,payload:{path:o,name:e.name,size:e.size}}),this.plugin.notifications.show({message:`Attached ${e.name}`,kind:"success",category:"attachment",affectedPaths:[o],folder:this.noteFolder}),`![[${o}]]`}catch(t){return new F.Notice(`Stashpad: attachment failed (${t.message})`),null}}claimSelectedAsAuthor(){this.authorship.claimSelectedAsAuthor()}claimFolderAsAuthor(){this.authorship.claimFolderAsAuthor()}claimSelectedWithContributor(){this.authorship.claimSelectedWithContributor()}claimFolderWithContributor(){this.authorship.claimFolderWithContributor()}renderAuthorshipFooter(e,t){if(!t.file)return;let i=this.plugin.settings;if(!i.showAuthor&&!i.showContributors&&!i.showLastEdit)return;let s=this.app.metadataCache.getFileCache(t.file)?.frontmatter??{},n=typeof s.author=="string"?s.author:"",o=Array.isArray(s.contributors)?s.contributors.filter(f=>typeof f=="string"&&f.trim()!==""):[],r=typeof s.modified=="string"?s.modified:typeof s.created=="string"?s.created:"",l=i.showAuthor&&!!n,c=i.showContributors&&o.length>0,A=i.showLastEdit&&!!r;if(!l&&!c&&!A)return;let h=e.createDiv({cls:"stashpad-note-authorship"}),g=(f,p)=>{let I=p.replace(/^\[\[/,"").replace(/\]\]$/,""),m=I.indexOf("|"),B=m>=0?I.slice(0,m):I,C=m>=0?I.slice(m+1):I.split("/").pop()??I,w=f.createEl("a",{cls:"internal-link",text:C});w.setAttribute("data-href",B),w.setAttribute("href",B)},u=[];l&&u.push(f=>{f.createSpan({cls:"stashpad-authorship-label",text:"by "}),g(f,n)}),c&&u.push(f=>{f.createSpan({cls:"stashpad-authorship-label",text:"with "}),o.forEach((p,I)=>{I>0&&f.createSpan({text:", "}),g(f,p)})}),A&&u.push(f=>{f.createSpan({cls:"stashpad-authorship-label",text:"edited "}),f.createSpan({text:this.formatTimeInline(r)})}),u.forEach((f,p)=>{p>0&&h.createSpan({cls:"stashpad-authorship-sep",text:"\xB7"});let I=h.createSpan({cls:"stashpad-authorship-piece"});f(I)}),h.addEventListener("click",f=>this.handleRenderedClick(f,t))}activeStopwords(){return this.plugin.settings.slugStopWords??Ze}scheduleSlugRename(e){let t=this.slugDebouncers.get(e.path);t&&t.cancel(),t=(0,F.debounce)(()=>void this.maybeRenameForSlug(e),3e4),this.slugDebouncers.set(e.path,t),t()}async maybeRenameForSlug(e){let t=this.app.metadataCache.getFileCache(e)?.frontmatter?.id,i=typeof t=="string"?t:null,n=lt(e.basename)??(Ns(i)?i:null);if(!n||n===S||i!==n)return;let o=await this.app.vault.cachedRead(e),r=this.stripFrontmatter(o),l=Se(r,this.activeStopwords()),c=be(l,n);if(e.name===c)return;let A=e.parent?`${e.parent.path}/${c}`:c;if(this.app.vault.getAbstractFileByPath(A))return;let h=e.path;try{await this.app.fileManager.renameFile(e,A),await this.log.append({type:"rename",id:n,payload:{from:h,to:A}})}catch{}}scheduleAttachmentSync(e){let t=this.attachmentDebouncers.get(e.path);t&&t.cancel(),t=(0,F.debounce)(()=>void this.syncAttachmentsFrontmatter(e),1500),this.attachmentDebouncers.set(e.path,t),t()}async syncAttachmentsFrontmatter(e){let t=await this.app.vault.cachedRead(e),i=this.stripFrontmatter(t),s=this.extractAttachments(i),n=this.app.metadataCache.getFileCache(e)?.frontmatter,r=(Array.isArray(n?.attachments)?n.attachments:[]).filter(A=>typeof A=="string").map(A=>Mt(A));if(r.length===s.length&&r.every((A,h)=>A===s[h]))return;let c=s.map(A=>Ve(A));await this.app.fileManager.processFrontMatter(e,A=>{A.attachments=c})}stripFrontmatter(e){let t=e.replace(/^\uFEFF/,""),i=t.match(/^\s*---\s*\r?\n[\s\S]*?\r?\n---\s*(?:\r?\n|$)/);return i?t.slice(i[0].length):t}formatTime(e){if(!e)return"";let t=(0,F.moment)(e);if(!t.isValid())return"";let i=X();if(i.useTemplatesFormat){let n=js(this.app);if(n)return`${t.format(n.dateFormat)} -${t.format(n.timeFormat)}`}let s=t.valueOf();return`${wt(s,i)} -${jt(s,i)}`}formatTimeInline(e){if(!e)return"";let t=(0,F.moment)(e);if(!t.isValid())return"";if(X().useTemplatesFormat){let s=js(this.app);if(s){let n=/:ss/.test(s.timeFormat)?s.timeFormat:s.timeFormat.replace(/(:mm)/,"$1:ss");return`${t.format(s.dateFormat)} ${t.format(n)}`}}return`${t.format("YYYY.MM.DD")} ${t.format("HH:mm:ss A")}`}scrollListToBottom(){let e=this.listEl;if(!e)return;if(this.stickToListBottom=!0,e.scrollTop=e.scrollHeight,F.Platform.isMobile){let r=0,l=()=>{!this.stickToListBottom||r>=8||(r++,Date.now()>=this.keyboardTransitionUntil&&(e.scrollTop=e.scrollHeight),window.setTimeout(l,120))};window.setTimeout(l,60);return}this.stickyRowObserver?.disconnect();let t=()=>{if(!this.stickToListBottom){this.stickyRowObserver?.disconnect(),this.stickyRowObserver=null;return}e.scrollTop=e.scrollHeight},i=new ResizeObserver(t);for(let r of Array.from(e.children))r instanceof HTMLElement&&i.observe(r);this.stickyRowObserver=i;let s=performance.now(),n=e.scrollHeight,o=()=>{if(!this.stickToListBottom)return;let r=e.scrollHeight;r!==n&&(e.scrollTop=r,n=r),performance.now()-s<3e4?requestAnimationFrame(o):(this.stickToListBottom=!1,this.stickyRowObserver?.disconnect(),this.stickyRowObserver=null)};requestAnimationFrame(o)}openNoteMenu(e,t){if(!t.file)return;let i=t.file,s=new F.Menu;s.addItem(A=>A.setTitle("Open in new Stashpad tab").setIcon("layout-grid").onClick(()=>{this.openInNewStashpadTab(t.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(t.id))),s.addItem(A=>A.setTitle("Copy Stashpad link").setIcon("link").onClick(()=>void this.cmdCopyStashpadLink(t))),s.addSeparator(),s.addItem(A=>A.setTitle("Split note\u2026").setIcon("split").onClick(()=>void this.cmdSplit(t))),s.addItem(A=>A.setTitle("Copy text").setIcon("copy").onClick(()=>{l(),this.cmdCopy()})),s.addItem(A=>A.setTitle("Clone (duplicate / copy)").setIcon("files").onClick(()=>{this.selection.has(t.id)||(this.selection.clear(),this.selection.add(t.id),this.lastSelected=t.id),this.cmdClone()})),s.addItem(A=>A.setTitle("Fork into a separate note\u2026").setIcon("git-branch").onClick(()=>{this.selection.has(t.id)||(this.selection.clear(),this.selection.add(t.id),this.lastSelected=t.id),this.cmdForkNote()})),s.addItem(A=>A.setTitle("Export to .stash").setIcon("package").onClick(()=>{this.selection.has(t.id)||(this.selection.clear(),this.selection.add(t.id),this.lastSelected=t.id),this.cmdExportStash()})),this.plugin.settings.okfEnabled&&s.addItem(A=>A.setTitle("Export as OKF\u2026").setIcon("book-marked").onClick(()=>{this.selection.has(t.id)||(this.selection.clear(),this.selection.add(t.id),this.lastSelected=t.id),this.cmdExportOkf()})),this.plugin.encryption?.isConfigured?.()&&s.addItem(A=>A.setTitle("Encrypt (lock) note + children").setIcon("lock").onClick(async()=>{let h=this.order.getOrder(this.noteFolder,t.parent??S),g=h.indexOf(t.id),u=g>0?h[g-1]:null;await this.plugin.lockNoteSubtree(this.noteFolder,t.id,u)&&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(t,S),this.plugin.settings.autoNavOnMoveOut&&this.focusId!==S&&this.navigateTo(S)}));let n={folder:this.noteFolder,id:t.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)}));let r=this.isListPinned(t.id);s.addItem(A=>A.setTitle(r?"Unpin from top of list":"Pin to top of list").setIcon(r?"pin-off":"arrow-up-to-line").onClick(()=>{this.selection.has(t.id)||(this.selection.clear(),this.selection.add(t.id),this.lastSelected=t.id),this.cmdToggleListPin()})),s.addItem(A=>A.setTitle("Set color\u2026").setIcon("palette").onClick(()=>{this.selection.has(t.id)||(this.selection.clear(),this.selection.add(t.id),this.lastSelected=t.id),this.cmdSetColor()}));let l=()=>{this.selection.has(t.id)||(this.selection.clear(),this.selection.add(t.id),this.lastSelected=t.id)},c=A=>{let h=this.isTask(t);if(h){let g=this.isCompleted(t);A.addItem(u=>u.setTitle(g?"Mark incomplete":"Mark complete").setIcon(g?"circle":"check-circle").onClick(()=>{l(),this.cmdToggleComplete()}))}else A.addItem(g=>g.setTitle("Mark complete").setIcon("check-circle").onClick(()=>{l(),this.toggleCompletedForNode(t)})),A.addItem(g=>g.setTitle("Turn into task").setIcon("check-square").onClick(()=>{l(),this.cmdToggleTask()}));A.addItem(g=>g.setTitle("Assign / schedule\u2026").setIcon("user-plus").onClick(()=>{l(),this.cmdAssign()})),h&&(A.addItem(g=>g.setTitle("Snooze (reschedule)\u2026").setIcon("alarm-clock").onClick(()=>{l(),this.cmdSnooze(t)})),A.addItem(g=>g.setTitle("Remove from tasks").setIcon("square").onClick(()=>{l(),this.cmdToggleTask()})))};s.addItem(A=>{A.setTitle("Task").setIcon("check-square");let h=typeof A.setSubmenu=="function"?A.setSubmenu():null;h&&typeof h.addItem=="function"?c(h):A.onClick(()=>this.openCommandPalette())}),s.addSeparator(),s.addItem(A=>A.setTitle("Delete").setIcon("trash").onClick(async()=>{this.selection.has(t.id)||(this.selection.clear(),this.selection.add(t.id),this.lastSelected=t.id),await this.cmdDelete()})),s.addSeparator(),s.addItem(A=>A.setTitle("More commands\u2026").setIcon("terminal").onClick(()=>this.openCommandPalette())),s.showAtMouseEvent(e)}async deleteNote(e){if(!e.file)return;let t=[],i=f=>{for(let p of this.tree.getChildren(f.id))i(p),t.push(p)};i(e);let s=[...t,e],n=s.filter(f=>!!f.file),o=await Promise.all(n.map(f=>this.app.vault.cachedRead(f.file))),r=[];for(let f=0;f<n.length;f++){let p=n[f];r.push(...this.extractAttachments(this.stripFrontmatter(o[f])));let I=this.app.metadataCache.getFileCache(p.file)?.frontmatter;if(Array.isArray(I?.attachments))for(let m of I.attachments)typeof m=="string"&&m.trim()&&r.push(Mt(m))}let l=[...new Set(r)],c=this.authorship.collectAuthorIds(s),A=async f=>{let p=await this.snapshotNotes(s,f),I=0;if(f)for(let D of l){let H=this.app.metadataCache.getFirstLinkpathDest(D,"");if(H)try{await this.app.fileManager.trashFile(H),await this.log.append({type:"attachment_remove",id:S,payload:{path:H.path}}),this.plugin.notifications.show({message:`Deleted attachment "${H.name}"`,kind:"warning",category:"attachment",affectedPaths:[H.path],folder:this.noteFolder}),I+=1}catch{}}let m=new Set;for(let D of s)D.parent&&m.add(D.parent);let B=this.currentChildren.findIndex(D=>D.id===e.id),C=null;if(B>=0){for(let D=B+1;D<this.currentChildren.length;D++)if(this.currentChildren[D].id!==e.id){C=this.currentChildren[D].id;break}if(!C){for(let D=B-1;D>=0;D--)if(this.currentChildren[D].id!==e.id){C=this.currentChildren[D].id;break}}}for(let D of s)if(D.file){try{await this.app.fileManager.trashFile(D.file)}catch{}await this.log.append({type:"delete",id:D.id,payload:{path:D.file.path,attachmentsRemoved:f?l:[]}})}this.selection.clear(),this.cursorIdx=-1,C&&(this.pendingFocusIds=[C]),this.tree.rebuild(this.noteFolder),this.render({kind:"follow-cursor"});for(let D of m)s.some(H=>H.id===D)||this.fmSync.scheduleParentOfDeleted(D);let w=this.noteFolder,y=`Delete "${this.titleForNode(e)}"`,v=e.id,E=I>0?` with ${I} attachment${I===1?"":"s"}`:"",Q=!1,b=async()=>{Q||(Q=!0,this.selection.clear(),this.cursorIdx=-1,await this.restoreSnapshots(p,[v]))};this.plugin.notifications.show({message:`Deleted "${this.titleForNode(e)}"${E}`,kind:"warning",category:"delete",duration:0,affectedIds:[e.id],affectedAuthorIds:c,folder:this.noteFolder,actions:[{label:"Undo delete",onClick:()=>void b()}]}),this.plugin.getUndoStack(w).push({label:y,undo:async()=>{await b()},redo:async()=>{this.selection.clear(),this.cursorIdx=-1,Q=!1,await this.trashNotesAndAttachments(p)}})},h=X(),g=t.length>0&&h.confirmBulkDelete,u=l.length>0&&h.confirmAttachmentDelete;if(!g&&!u){await A(!1),this.focusView();return}new ii(this.app,this.titleForNode(e),t.length,l.length,u,async f=>{await A(f),this.focusView()}).open()}async cmdSwapWithParent(){let e=this.cursorIdx>=0?this.currentChildren[this.cursorIdx]:null;if(!e?.file){new F.Notice("Pick a note first (move the cursor onto it).");return}if(!e.parent||e.parent===S){new F.Notice("Already at Home \u2014 no parent to swap with.");return}let t=this.tree.get(e.parent);if(!t?.file){new F.Notice("Couldn't find the parent note.");return}let i=t.parent??S,s=this.titleForNode(e),n=this.titleForNode(t),o=this.tree.getChildren(t.id).filter(l=>l.id!==e.id).length,r=[`"${n}" becomes a child of "${s}".`];o>0&&r.push(`${o} sibling${o===1?"":"s"} move with it.`),new _(this.app,"Swap notes?",r.join(` +${C}`):e=C}catch(B){console.warn("[Stashpad] template read failed",B)}}}let l=Se(e,this.activeStopwords()),c=be(l,o),A=`${s}/${c}`,h=t??this.focusId,p=i.createdOverride??new Date().toISOString(),u=this.extractAttachments(e),f=this.authorship.currentAuthorLink();f&&this.authorship.ensureAuthorFile(f);let g=["---",`id: ${o}`,`parent: ${h}`,`created: ${p}`,`modified: ${p}`];if(f&&g.push(`author: "${f.link.replace(/"/g,'\\"')}"`),u.length>0){g.push("attachments:");for(let I of u)g.push(` - "${I.replace(/"/g,'\\"')}"`)}else g.push("attachments: []");g.push("---",e);try{let I=g.join(` +`);this.plugin.importService.suppress(A,6e4),await ke.timeAsync("write.createNote.file",()=>this.app.vault.create(A,I)),i.collectInto?.push({path:A,content:I});try{let m=this.app.vault.getAbstractFileByPath(A);if(m&&m.extension==="md"){if(!n)this.tree.insertSynthetic({id:o,parent:h,children:[],file:m,created:p}),i.deferRender||this.render(),this.fmSync.scheduleParentChange(o,null,h);else{i.deferRender||this.render();let B=s.split("/").pop()||s,C=(e.split(` +`).find(Q=>Q.trim())??"note").trim().slice(0,60);i.deferUndo||this.plugin.notifications.show({message:`"${C}" 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(m,B=>{for(let[C,Q]of Object.entries(r))Ve.includes(C)||jn.includes(C)||B[C]===void 0&&(B[C]=Q)})}catch(B){console.warn("[Stashpad] template fm overlay failed",B)}}}catch{}if(await this.log.append({type:"create",id:o,payload:{path:A,parent:h}}),i.record!==!1&&!i.deferUndo){let m=e;this.plugin.getUndoStack(s).push({label:n?"Send note":"Create note",undo:async()=>{let B=this.fileForNote(o,A);if(B)try{await this.app.fileManager.trashFile(B)}catch{}if(!(this.composerInputEl?.value??this.composerDraft).trim()&&(this.composerDraft=m,this.saveDraft(m),this.recordLastSubmitted(""),this.composerInputEl)){this.composerInputEl.value=m;let Q=m.length;this.composerInputEl.setSelectionRange(Q,Q),this.composerInputEl.focus()}n||this.tree.rebuild(this.noteFolder),this.render()},redo:async()=>{await this.app.vault.adapter.exists(A)||await this.app.vault.create(A,I),this.composerDraft="",this.saveDraft(""),this.recordLastSubmitted(m),this.composerInputEl&&(this.composerInputEl.value=""),n||this.tree.rebuild(this.noteFolder),this.render()}})}return o}catch(I){return new b.Notice(`Stashpad: failed to create note (${I.message})`),null}}async createNotesBatch(e,t,i,s,n){let o=e.length,r=[],l=!!i?.targetFolder&&i.targetFolder!==this.noteFolder,c=8,A=null;if(o>=c){let h=new b.Notice("",0),p=h.messageEl;p.empty(),p.createDiv({cls:"stashpad-split-progress-title",text:`Splitting into ${o} notes\u2026`});let f=p.createDiv({cls:"stashpad-split-progress-bar"}).createDiv({cls:"stashpad-split-progress-fill"}),g=p.createDiv({cls:"stashpad-split-progress-label",text:`0 / ${o}`});A={notice:h,fill:f,label:g}}this.beginBulkRender();try{for(let h=0;h<o;h++)if(await this.createNoteUnder(e[h],t,{...i??{},deferRender:!0,deferUndo:!0,collectInto:r}),A){let p=h+1;A.label.setText(`${p} / ${o}`),A.fill.setCssStyles({width:`${Math.round(p/o*100)}%`}),p%5===0&&await new Promise(u=>window.setTimeout(u,0))}}finally{A?.notice.hide();try{await this.fmSync.flush()}catch{}this.endBulkRender()}if(r.length){let h=r.slice();this.plugin.getUndoStack(n).push({label:`Create ${h.length} notes`,undo:async()=>{for(let{path:p}of h){let u=this.app.vault.getAbstractFileByPath(p);if(u)try{await this.app.fileManager.trashFile(u)}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()}l||this.tree.rebuild(this.noteFolder),this.render()},redo:async()=>{for(let{path:p,content:u}of h)await this.app.vault.adapter.exists(p)||await this.app.vault.create(p,u);this.composerDraft="",this.saveDraft(""),this.composerInputEl&&(this.composerInputEl.value=""),l||this.tree.rebuild(this.noteFolder),this.render()}})}o>=c&&this.plugin.notifications.show({message:`Created ${r.length} notes${l?` in \`${n.split("/").pop()}\``:""}.`,kind:"success",category:"create"})}extractAttachments(e){let t=[],i=/!\[\[([^\]\|]+)(?:\|[^\]]+)?\]\]/g,s;for(;(s=i.exec(e))!==null;)t.push(s[1]);return t}async ensureFolder(e){if(await this.app.vault.adapter.exists(e)){let t=this.app.vault.getAbstractFileByPath(e);if(t&&!(t instanceof b.TFolder))throw new Error(`${e} exists and is not a folder`);return}try{await this.app.vault.createFolder(e)}catch(t){let i=t?.message??"";if(!/already exists/i.test(i))throw t}}async importAttachment(e){try{let t=await e.arrayBuffer(),i=`${this.noteFolder}/_attachments`;await this.ensureFolder(i);let s=e.name.replace(/[^\w.\-]+/g,"_"),n=Date.now().toString(36),o=`${i}/${Ts(s,n)}`;return await this.app.vault.createBinary(o,t),await this.log.append({type:"attachment_add",id:k,payload:{path:o,name:e.name,size:e.size}}),this.plugin.notifications.show({message:`Attached ${e.name}`,kind:"success",category:"attachment",affectedPaths:[o],folder:this.noteFolder}),`![[${o}]]`}catch(t){return new b.Notice(`Stashpad: attachment failed (${t.message})`),null}}claimSelectedAsAuthor(){this.authorship.claimSelectedAsAuthor()}claimFolderAsAuthor(){this.authorship.claimFolderAsAuthor()}claimSelectedWithContributor(){this.authorship.claimSelectedWithContributor()}claimFolderWithContributor(){this.authorship.claimFolderWithContributor()}renderAuthorshipFooter(e,t){if(!t.file)return;let i=this.plugin.settings;if(!i.showAuthor&&!i.showContributors&&!i.showLastEdit)return;let s=this.app.metadataCache.getFileCache(t.file)?.frontmatter??{},n=typeof s.author=="string"?s.author:"",o=Array.isArray(s.contributors)?s.contributors.filter(f=>typeof f=="string"&&f.trim()!==""):[],r=typeof s.modified=="string"?s.modified:typeof s.created=="string"?s.created:"",l=i.showAuthor&&!!n,c=i.showContributors&&o.length>0,A=i.showLastEdit&&!!r;if(!l&&!c&&!A)return;let h=e.createDiv({cls:"stashpad-note-authorship"}),p=(f,g)=>{let I=g.replace(/^\[\[/,"").replace(/\]\]$/,""),m=I.indexOf("|"),B=m>=0?I.slice(0,m):I,C=m>=0?I.slice(m+1):I.split("/").pop()??I,Q=f.createEl("a",{cls:"internal-link",text:C});Q.setAttribute("data-href",B),Q.setAttribute("href",B)},u=[];l&&u.push(f=>{f.createSpan({cls:"stashpad-authorship-label",text:"by "}),p(f,n)}),c&&u.push(f=>{f.createSpan({cls:"stashpad-authorship-label",text:"with "}),o.forEach((g,I)=>{I>0&&f.createSpan({text:", "}),p(f,g)})}),A&&u.push(f=>{f.createSpan({cls:"stashpad-authorship-label",text:"edited "}),f.createSpan({text:this.formatTimeInline(r)})}),u.forEach((f,g)=>{g>0&&h.createSpan({cls:"stashpad-authorship-sep",text:"\xB7"});let I=h.createSpan({cls:"stashpad-authorship-piece"});f(I)}),h.addEventListener("click",f=>this.handleRenderedClick(f,t))}activeStopwords(){return this.plugin.settings.slugStopWords??je}scheduleSlugRename(e){let t=this.slugDebouncers.get(e.path);t&&t.cancel(),t=(0,b.debounce)(()=>void this.maybeRenameForSlug(e),3e4),this.slugDebouncers.set(e.path,t),t()}async maybeRenameForSlug(e){let t=this.app.metadataCache.getFileCache(e)?.frontmatter?.id,i=typeof t=="string"?t:null,n=ct(e.basename)??(Ms(i)?i:null);if(!n||n===k||i!==n)return;let o=await this.app.vault.cachedRead(e),r=this.stripFrontmatter(o),l=Se(r,this.activeStopwords()),c=be(l,n);if(e.name===c)return;let A=e.parent?`${e.parent.path}/${c}`:c;if(this.app.vault.getAbstractFileByPath(A))return;let h=e.path;try{await this.app.fileManager.renameFile(e,A),await this.log.append({type:"rename",id:n,payload:{from:h,to:A}})}catch{}}scheduleAttachmentSync(e){let t=this.attachmentDebouncers.get(e.path);t&&t.cancel(),t=(0,b.debounce)(()=>void this.syncAttachmentsFrontmatter(e),1500),this.attachmentDebouncers.set(e.path,t),t()}async syncAttachmentsFrontmatter(e){let t=await this.app.vault.cachedRead(e),i=this.stripFrontmatter(t),s=this.extractAttachments(i),n=this.app.metadataCache.getFileCache(e)?.frontmatter,r=(Array.isArray(n?.attachments)?n.attachments:[]).filter(A=>typeof A=="string").map(A=>Tt(A));if(r.length===s.length&&r.every((A,h)=>A===s[h]))return;let c=s.map(A=>We(A));await this.app.fileManager.processFrontMatter(e,A=>{A.attachments=c})}stripFrontmatter(e){let t=e.replace(/^\uFEFF/,""),i=t.match(/^\s*---\s*\r?\n[\s\S]*?\r?\n---\s*(?:\r?\n|$)/);return i?t.slice(i[0].length):t}formatTime(e){if(!e)return"";let t=(0,b.moment)(e);if(!t.isValid())return"";let i=X();if(i.useTemplatesFormat){let n=_s(this.app);if(n)return`${t.format(n.dateFormat)} +${t.format(n.timeFormat)}`}let s=t.valueOf();return`${Et(s,i)} +${_t(s,i)}`}formatTimeInline(e){if(!e)return"";let t=(0,b.moment)(e);if(!t.isValid())return"";if(X().useTemplatesFormat){let s=_s(this.app);if(s){let n=/:ss/.test(s.timeFormat)?s.timeFormat:s.timeFormat.replace(/(:mm)/,"$1:ss");return`${t.format(s.dateFormat)} ${t.format(n)}`}}return`${t.format("YYYY.MM.DD")} ${t.format("HH:mm:ss A")}`}scrollListToBottom(){let e=this.listEl;if(!e)return;if(this.stickToListBottom=!0,e.scrollTop=e.scrollHeight,b.Platform.isMobile){let r=0,l=()=>{!this.stickToListBottom||r>=8||(r++,Date.now()>=this.keyboardTransitionUntil&&(e.scrollTop=e.scrollHeight),window.setTimeout(l,120))};window.setTimeout(l,60);return}this.stickyRowObserver?.disconnect();let t=()=>{if(!this.stickToListBottom){this.stickyRowObserver?.disconnect(),this.stickyRowObserver=null;return}e.scrollTop=e.scrollHeight},i=new ResizeObserver(t);for(let r of Array.from(e.children))r instanceof HTMLElement&&i.observe(r);this.stickyRowObserver=i;let s=performance.now(),n=e.scrollHeight,o=()=>{if(!this.stickToListBottom)return;let r=e.scrollHeight;r!==n&&(e.scrollTop=r,n=r),performance.now()-s<3e4?requestAnimationFrame(o):(this.stickToListBottom=!1,this.stickyRowObserver?.disconnect(),this.stickyRowObserver=null)};requestAnimationFrame(o)}addShareExportSubmenu(e,t,i){let s=()=>{i.normalizeToNode&&t&&!this.selection.has(t.id)&&(this.selection.clear(),this.selection.add(t.id),this.lastSelected=t.id)},n=o=>{o.addItem(r=>{r.setTitle("Copy Stashpad link").setIcon("link"),t?r.onClick(()=>void this.cmdCopyStashpadLink(i.normalizeToNode?t:void 0)):r.setDisabled(!0)}),o.addItem(r=>r.setTitle("Export to .stash\u2026").setIcon("package").onClick(()=>{s(),this.cmdExportStash()})),this.plugin.settings.okfEnabled&&o.addItem(r=>r.setTitle("Export as OKF\u2026").setIcon("book-marked").onClick(()=>{s(),this.cmdExportOkf()}))};e.addItem(o=>{o.setTitle("Share & export").setIcon("share-2");let r=typeof o.setSubmenu=="function"?o.setSubmenu():null;r&&typeof r.addItem=="function"?n(r):o.onClick(()=>this.openCommandPalette())})}openNoteMenu(e,t){if(!t.file)return;let i=t.file,s=new b.Menu;s.addItem(A=>A.setTitle("Open in new Stashpad tab").setIcon("layout-grid").onClick(()=>{this.openInNewStashpadTab(t.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(t.id))),s.addSeparator(),s.addItem(A=>A.setTitle("Split note\u2026").setIcon("split").onClick(()=>void this.cmdSplit(t))),s.addItem(A=>A.setTitle("Copy text").setIcon("copy").onClick(()=>{l(),this.cmdCopy()})),s.addItem(A=>A.setTitle("Clone (duplicate / copy)").setIcon("files").onClick(()=>{this.selection.has(t.id)||(this.selection.clear(),this.selection.add(t.id),this.lastSelected=t.id),this.cmdClone()})),s.addItem(A=>A.setTitle("Fork into a separate note\u2026").setIcon("git-branch").onClick(()=>{this.selection.has(t.id)||(this.selection.clear(),this.selection.add(t.id),this.lastSelected=t.id),this.cmdForkNote()})),this.addShareExportSubmenu(s,t,{normalizeToNode:!0}),this.plugin.encryption?.isConfigured?.()&&s.addItem(A=>A.setTitle("Encrypt (lock) note + children").setIcon("lock").onClick(async()=>{let h=this.order.getOrder(this.noteFolder,t.parent??k),p=h.indexOf(t.id),u=p>0?h[p-1]:null;await this.plugin.lockNoteSubtree(this.noteFolder,t.id,u)&&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(t,k),this.plugin.settings.autoNavOnMoveOut&&this.focusId!==k&&this.navigateTo(k)}));let n={folder:this.noteFolder,id:t.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)}));let r=this.isListPinned(t.id);s.addItem(A=>A.setTitle(r?"Unpin from top of list":"Pin to top of list").setIcon(r?"pin-off":"arrow-up-to-line").onClick(()=>{this.selection.has(t.id)||(this.selection.clear(),this.selection.add(t.id),this.lastSelected=t.id),this.cmdToggleListPin()})),s.addItem(A=>A.setTitle("Set color\u2026").setIcon("palette").onClick(()=>{this.selection.has(t.id)||(this.selection.clear(),this.selection.add(t.id),this.lastSelected=t.id),this.cmdSetColor()}));let l=()=>{this.selection.has(t.id)||(this.selection.clear(),this.selection.add(t.id),this.lastSelected=t.id)},c=A=>{let h=this.isTask(t);if(h){let p=this.isCompleted(t);A.addItem(u=>u.setTitle(p?"Mark incomplete":"Mark complete").setIcon(p?"circle":"check-circle").onClick(()=>{l(),this.cmdToggleComplete()}))}else A.addItem(p=>p.setTitle("Mark complete").setIcon("check-circle").onClick(()=>{l(),this.toggleCompletedForNode(t)})),A.addItem(p=>p.setTitle("Turn into task").setIcon("check-square").onClick(()=>{l(),this.cmdToggleTask()}));A.addItem(p=>p.setTitle("Assign / schedule\u2026").setIcon("user-plus").onClick(()=>{l(),this.cmdAssign()})),h&&(A.addItem(p=>p.setTitle("Snooze (reschedule)\u2026").setIcon("alarm-clock").onClick(()=>{l(),this.cmdSnooze(t)})),A.addItem(p=>p.setTitle("Remove from tasks").setIcon("square").onClick(()=>{l(),this.cmdToggleTask()})))};s.addItem(A=>{A.setTitle("Task").setIcon("check-square");let h=typeof A.setSubmenu=="function"?A.setSubmenu():null;h&&typeof h.addItem=="function"?c(h):A.onClick(()=>this.openCommandPalette())}),s.addSeparator(),s.addItem(A=>A.setTitle("Delete").setIcon("trash").onClick(async()=>{this.selection.has(t.id)||(this.selection.clear(),this.selection.add(t.id),this.lastSelected=t.id),await this.cmdDelete()})),s.addSeparator(),s.addItem(A=>A.setTitle("More commands\u2026").setIcon("terminal").onClick(()=>this.openCommandPalette())),s.showAtMouseEvent(e)}async deleteNote(e){if(!e.file)return;let t=[],i=f=>{for(let g of this.tree.getChildren(f.id))i(g),t.push(g)};i(e);let s=[...t,e],n=s.filter(f=>!!f.file),o=await Promise.all(n.map(f=>this.app.vault.cachedRead(f.file))),r=[];for(let f=0;f<n.length;f++){let g=n[f];r.push(...this.extractAttachments(this.stripFrontmatter(o[f])));let I=this.app.metadataCache.getFileCache(g.file)?.frontmatter;if(Array.isArray(I?.attachments))for(let m of I.attachments)typeof m=="string"&&m.trim()&&r.push(Tt(m))}let l=[...new Set(r)],c=this.authorship.collectAuthorIds(s),A=async f=>{let g=await this.snapshotNotes(s,f),I=0;if(f)for(let D of l){let R=this.app.metadataCache.getFirstLinkpathDest(D,"");if(R)try{await this.app.fileManager.trashFile(R),await this.log.append({type:"attachment_remove",id:k,payload:{path:R.path}}),this.plugin.notifications.show({message:`Deleted attachment "${R.name}"`,kind:"warning",category:"attachment",affectedPaths:[R.path],folder:this.noteFolder}),I+=1}catch{}}let m=new Set;for(let D of s)D.parent&&m.add(D.parent);let B=this.currentChildren.findIndex(D=>D.id===e.id),C=null;if(B>=0){for(let D=B+1;D<this.currentChildren.length;D++)if(this.currentChildren[D].id!==e.id){C=this.currentChildren[D].id;break}if(!C){for(let D=B-1;D>=0;D--)if(this.currentChildren[D].id!==e.id){C=this.currentChildren[D].id;break}}}for(let D of s)if(D.file){try{await this.app.fileManager.trashFile(D.file)}catch{}await this.log.append({type:"delete",id:D.id,payload:{path:D.file.path,attachmentsRemoved:f?l:[]}})}this.selection.clear(),this.cursorIdx=-1,C&&(this.pendingFocusIds=[C]),this.tree.rebuild(this.noteFolder),this.render({kind:"follow-cursor"});for(let D of m)s.some(R=>R.id===D)||this.fmSync.scheduleParentOfDeleted(D);let Q=this.noteFolder,y=`Delete "${this.titleForNode(e)}"`,E=e.id,w=I>0?` with ${I} attachment${I===1?"":"s"}`:"",v=!1,F=async()=>{v||(v=!0,this.selection.clear(),this.cursorIdx=-1,await this.restoreSnapshots(g,[E]))};this.plugin.notifications.show({message:`Deleted "${this.titleForNode(e)}"${w}`,kind:"warning",category:"delete",duration:0,affectedIds:[e.id],affectedAuthorIds:c,folder:this.noteFolder,actions:[{label:"Undo delete",onClick:()=>void F()}]}),this.plugin.getUndoStack(Q).push({label:y,undo:async()=>{await F()},redo:async()=>{this.selection.clear(),this.cursorIdx=-1,v=!1,await this.trashNotesAndAttachments(g)}})},h=X(),p=t.length>0&&h.confirmBulkDelete,u=l.length>0&&h.confirmAttachmentDelete;if(!p&&!u){await A(!1),this.focusView();return}new si(this.app,this.titleForNode(e),t.length,l.length,u,async f=>{await A(f),this.focusView()}).open()}async cmdSwapWithParent(){let e=this.cursorIdx>=0?this.currentChildren[this.cursorIdx]:null;if(!e?.file){new b.Notice("Pick a note first (move the cursor onto it).");return}if(!e.parent||e.parent===k){new b.Notice("Already at Home \u2014 no parent to swap with.");return}let t=this.tree.get(e.parent);if(!t?.file){new b.Notice("Couldn't find the parent note.");return}let i=t.parent??k,s=this.titleForNode(e),n=this.titleForNode(t),o=this.tree.getChildren(t.id).filter(l=>l.id!==e.id).length,r=[`"${n}" becomes a child of "${s}".`];o>0&&r.push(`${o} sibling${o===1?"":"s"} move with it.`),new _(this.app,"Swap notes?",r.join(` `),"Swap",async l=>{l&&await this.swapParentChild(t,e,i)}).open()}offerSwapForDescendantMove(e,t){let i=this.tree.get(t);if(!i?.file){this.plugin.notifications.show({message:`Can't nest "${this.titleForNode(e)}" under one of its own descendants \u2014 that would create a cycle.`,kind:"warning",category:"move",affectedIds:[e.id],folder:this.noteFolder});return}if(i.parent!==e.id){this.plugin.notifications.show({message:`Can't nest "${this.titleForNode(e)}" 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:[e.id,i.id],folder:this.noteFolder});return}let s=this.titleForNode(e),n=this.titleForNode(i),o=this.tree.getChildren(e.id).filter(l=>l.id!==i.id).length,r=[`"${s}" becomes a child of "${n}".`];o>0&&r.push(`${o} sibling${o===1?"":"s"} move with it.`),new _(this.app,"Confirm Note Swap",r.join(` -`),"Swap",async l=>{if(!l)return;let c=e.parent??S;await this.swapParentChild(e,i,c)}).open()}async swapParentChild(e,t,i){if(!e.file||!t.file)return;if(t.parent!==e.id){new F.Notice("Swap aborted: parent/child relationship changed.");return}let s=this.noteFolder,n=e.parent,o=this.tree.getChildren(e.id).filter(u=>u.id!==t.id).filter(u=>!!u.file),r=o.map(u=>({id:u.id,path:u.file.path,was:u.parent})),l=this.order.getOrder(s,i).slice(),c=this.order.getOrder(s,t.id).slice(),A=this.order.getOrder(s,e.id).slice();await this.app.fileManager.processFrontMatter(t.file,u=>{u.parent=i}),this.fmSync.scheduleParentChange(t.id,e.id,i),await this.app.fileManager.processFrontMatter(e.file,u=>{u.parent=t.id}),this.fmSync.scheduleParentChange(e.id,n,t.id);for(let u of o)await this.app.fileManager.processFrontMatter(u.file,f=>{f.parent=t.id}),this.fmSync.scheduleParentChange(u.id,e.id,t.id);if(l.length>0){let u=l.includes(e.id)?l.map(f=>f===e.id?t.id:f):[...l.filter(f=>f!==t.id),t.id];this.order.setOrder(s,i,u)}let h=o.map(u=>u.id),g=[e.id,...c.filter(u=>u!==e.id&&!h.includes(u)),...h];this.order.setOrder(s,t.id,g),this.order.setOrder(s,e.id,[]),await this.order.save(s),await this.log.append({type:"parent_change",id:t.id,payload:{from:e.id,to:i,reason:"swap"}}),await this.log.append({type:"parent_change",id:e.id,payload:{from:n,to:t.id,reason:"swap"}});for(let u of r)await this.log.append({type:"parent_change",id:u.id,payload:{from:u.was,to:t.id,reason:"swap"}});this.tree.rebuild(s),this.pendingFocusIds=[t.id],this.render({kind:"follow-cursor"}),this.plugin.notifications.show({message:`Swapped "${this.titleForNode(t)}" \u2194 "${this.titleForNode(e)}".`,kind:"success",category:"move",affectedIds:[t.id,e.id,...h],folder:s}),this.plugin.getUndoStack(s).push({label:`Swap "${this.titleForNode(t)}" \u2194 parent`,undo:async()=>{let u=this.tree.get(e.id),f=this.tree.get(t.id);u?.file&&await this.app.fileManager.processFrontMatter(u.file,p=>{n==null||n===S?(delete p.parent,p.parent=S):p.parent=n}),f?.file&&await this.app.fileManager.processFrontMatter(f.file,p=>{p.parent=e.id});for(let p of r){let I=this.app.vault.getAbstractFileByPath(p.path);I&&await this.app.fileManager.processFrontMatter(I,m=>{p.was==null?m.parent=S:m.parent=p.was})}this.order.setOrder(s,i,l),this.order.setOrder(s,t.id,c),this.order.setOrder(s,e.id,A),await this.order.save(s),this.tree.rebuild(s),this.pendingFocusIds=[e.id],this.render({kind:"follow-cursor"})},redo:async()=>{await this.swapParentChild(e,t,i)}})}async changeParent(e,t,i={record:!0}){if(!e.file)return!1;let s=e.file,n=e.parent,o=l=>l??S;if(o(n)===o(t)){if(!i.quiet){let l=this.titleForNode(e),c=t===S?"Home":`"${this.titleForNode(this.tree.get(t)??e)}"`;this.plugin.notifications.show({message:`"${l}" is already under ${c}.`,kind:"info",category:"move",affectedIds:[e.id],folder:this.noteFolder})}return!1}if(t===e.id)return i.quiet||this.plugin.notifications.show({message:`Can't move "${this.titleForNode(e)}" into itself.`,kind:"warning",category:"move",affectedIds:[e.id],folder:this.noteFolder}),!1;if(t!==S&&this.isDescendant(t,e.id))return i.quiet||this.offerSwapForDescendantMove(e,t),!1;let r=this.authorship.collectAuthorIds([e]);if(await this.app.fileManager.processFrontMatter(s,l=>{l.parent=t}),this.fmSync.scheduleParentChange(e.id,n,t),await this.log.append({type:"parent_change",id:e.id,payload:{from:n,to:t}}),this.pendingFocusIds=[e.id],this.focusId!==t&&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 l=this.tree.get(t),c=l?this.titleForNode(l):"(root)";this.plugin.notifications.show({message:`Reparented "${this.titleForNode(e)}" \u2192 "${c}"`,kind:"success",category:"move",affectedIds:[e.id],affectedAuthorIds:r,folder:this.noteFolder,actions:t===S?[]:[{label:"Jump to parent",onClick:()=>this.navigateTo(t)}]})}if(i.record!==!1){let l=this.noteFolder,c=s.path,A=e.id;this.plugin.getUndoStack(l).push({label:"Move note",undo:async()=>{let h=this.fileForNote(A,c);if(h){await this.app.fileManager.processFrontMatter(h,g=>{g.parent=n}),this.pendingFocusIds=[A],this.focusId!==n&&this.focusId!==t?(this.selection.clear(),this.cursorIdx=-1):this.focusId===t&&(this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=null),this.tree.rebuild(l),this.render({kind:"follow-cursor"});{let g=this.selectionGuardKey,u=()=>{if(this.selectionGuardKey!==g||this.selection.has(A))return;let f=this.currentChildren.findIndex(p=>p.id===A);f<0||(this.selection.add(A),this.cursorIdx=f,this.render({kind:"follow-cursor"}))};setTimeout(u,120),setTimeout(u,400)}}},redo:async()=>{let h=this.fileForNote(A,c);if(h){await this.app.fileManager.processFrontMatter(h,g=>{g.parent=t}),this.pendingFocusIds=[A],this.focusId!==t&&this.focusId!==n?(this.selection.clear(),this.cursorIdx=-1):this.focusId===n&&(this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=null),this.tree.rebuild(l),this.render({kind:"follow-cursor"});{let g=this.selectionGuardKey,u=()=>{if(this.selectionGuardKey!==g||this.selection.has(A))return;let f=this.currentChildren.findIndex(p=>p.id===A);f<0||(this.selection.add(A),this.cursorIdx=f,this.render({kind:"follow-cursor"}))};setTimeout(u,120),setTimeout(u,400)}}}})}return!0}notifyBatchMove(e,t,i){if(!e.length)return;let s=this.tree.get(t),n=t===S?"Home":`"${s?this.titleForNode(s):"the destination"}"`,o=l=>i.get(l.id)??0,r;if(e.length===1){let l=this.titleForNode(e[0]),c=o(e[0]);r=c>0?`Moved "${l}" and its ${c} ${c===1?"child":"children"} \u2192 ${n}`:`Moved "${l}" \u2192 ${n}`}else{let l=e.reduce((c,A)=>c+o(A),0);r=l>0?`Moved ${e.length} notes (${l} nested) \u2192 ${n}`:`Moved ${e.length} notes \u2192 ${n}`}this.plugin.notifications.show({message:r,kind:"success",category:"move",duration:t===S?void 0:0,affectedIds:e.map(l=>l.id),affectedAuthorIds:this.authorship.collectAuthorIds(e),folder:this.noteFolder,actions:t===S?[]:[{label:"Jump to destination",onClick:()=>this.navigateTo(t)}]})}};us.AIMED_TAP_WINDOW_MS=600;var Sn=us,bn=class extends F.SuggestModal{constructor(e,t,i){super(e);this.entries=t;this.onPick=i;this.setPlaceholder("Restore which deleted note?")}getSuggestions(e){let t=e.toLowerCase();return this.entries.filter(i=>`${i.label} ${i.folder}`.toLowerCase().includes(t))}renderSuggestion(e,t){t.createDiv({text:e.label}),t.createEl("small",{text:`from ${e.folder}`,cls:"stashpad-suggest-path"})}onChooseSuggestion(e){this.onPick(e.blob)}};var ue=require("obsidian");ae();we();var Dn=ue.moment,xn=class extends ue.ItemView{constructor(e,t){super(e);this.plugin=t;this.renderPending=!1;this.renderGen=0;this.selected=new Set;this.order=[];this.anchorBlob=null;this.trashMode="byfolder"}getViewType(){return Wt}getDisplayText(){return"Trash"}getIcon(){return"trash-2"}async onOpen(){this.containerEl.addClass("stashpad-trash-view"),this.registerEvent(this.app.vault.on("create",e=>{e.path.startsWith("_deleted/")&&this.scheduleRender()})),this.registerEvent(this.app.vault.on("delete",e=>{e.path.startsWith("_deleted/")&&this.scheduleRender()})),this.registerDomEvent(document,"keydown",e=>{if(this.app.workspace.activeLeaf!==this.leaf)return;let t=e.target;if(!(t&&(t.tagName==="INPUT"||t.tagName==="TEXTAREA"||t.isContentEditable))&&(e.metaKey||e.ctrlKey)&&!e.altKey&&(e.key==="a"||e.key==="A")){if(this.order.length===0)return;e.preventDefault(),this.selectAll()}}),await this.render()}scheduleRender(){this.renderPending||(this.renderPending=!0,window.setTimeout(()=>{this.renderPending=!1,this.render()},150))}async render(){let e=++this.renderGen,t=this.contentEl;t.empty(),t.addClass("stashpad-trash-view-body"),this.order=[];let i=t.createDiv({cls:"stashpad-trash-view-header"});i.createEl("h3",{text:"Trash"});let s=i.createEl("button",{cls:"stashpad-trash-iconbtn"});(0,ue.setIcon)(s,"refresh-cw"),s.setAttr("aria-label","Refresh"),s.onclick=()=>void this.render();let n=this.plugin.encryption?.isConfigured?.()?await this.plugin.listDeletedTrash():[];if(e!==this.renderGen)return;let o=await this.plugin.listPlaintextTrash();if(e!==this.renderGen)return;let r=[...n,...o],l=await this.plugin.listRawTrashStashpadNotes();if(e!==this.renderGen)return;if(r.length===0&&l.length===0){t.createDiv({cls:"stashpad-trash-empty",text:"Trash is empty. Securely-deleted notes land in the encrypted trash; plain deletes go to Obsidian's trash \u2014 both show here."});return}if(An(t,this.trashMode,{total:r.length+l.length,enc:r.length,dec:l.length},h=>{this.trashMode=h,this.clearSelection(),this.render()}),this.trashMode==="mixed"){this.renderMixed(t,r,l);return}let c=this.trashMode!=="unencrypted"&&r.length>0,A=this.trashMode!=="encrypted"&&l.length>0;if(!c&&!A){t.createDiv({cls:"stashpad-trash-empty",text:"Nothing in this view."});return}if(c){let h=i.createEl("button",{cls:"stashpad-trash-restore",text:"Restore all"});(0,ue.setIcon)(h.createSpan({cls:"stashpad-btn-icon"}),"rotate-ccw"),h.onclick=async()=>{h.disabled=!0,await this.plugin.restoreAllTrash(),this.clearSelection(),await this.render()};let g=new Set(r.map(u=>u.blob));for(let u of[...this.selected])g.has(u)||this.selected.delete(u);if(this.selected.size>0){let u=t.createDiv({cls:"stashpad-trash-selbar"});u.createSpan({cls:"stashpad-trash-selcount",text:`${this.selected.size} selected`});let f=u.createEl("button",{cls:"stashpad-trash-restore",text:"Restore selected"});f.onclick=async()=>{f.disabled=!0;let m=0;for(let B of[...this.selected])await this.plugin.restoreDeletedAt(B,{silent:!0})||m++;m>0&&new ue.Notice(`${m} item${m===1?"":"s"} couldn't be restored (locked key?) \u2014 still in trash.`),this.clearSelection(),await this.render()};let p=u.createEl("button",{cls:"stashpad-trash-delete mod-warning",text:"Delete selected"});p.onclick=()=>this.confirmPurge([...this.selected]);let I=u.createEl("button",{cls:"stashpad-trash-iconbtn",text:"Clear"});I.onclick=()=>{this.clearSelection(),this.render()}}}if(this.order=[],c)if(this.trashMode==="byfolder"){let h=new Map;for(let u of r){let f=u.meta?.title?u.meta.originalFolder||"(unknown folder)":" hidden";(h.get(f)??h.set(f,[]).get(f)).push(u)}let g=[...h.keys()].sort((u,f)=>u===" hidden"?1:f===" hidden"?-1:u.localeCompare(f));for(let u of g){let f=u===" hidden",p=t.createDiv({cls:"stashpad-trash-group"}),I=p.createDiv({cls:"stashpad-trash-group-head"});(0,ue.setIcon)(I.createSpan({cls:"stashpad-trash-group-icon"}),f?"lock":"folder"),I.createSpan({text:f?"Hidden (title obscured)":u.split("/").pop()||u}),I.createSpan({cls:"stashpad-trash-group-count",text:String(h.get(u).length)});for(let m of h.get(u))this.encRow(p,m,f)}}else{let h=t.createDiv({cls:"stashpad-trash-group"}),g=h.createDiv({cls:"stashpad-trash-group-head"});(0,ue.setIcon)(g.createSpan({cls:"stashpad-trash-group-icon"}),"trash-2"),g.createSpan({text:"Stashpad trash"}),g.createSpan({cls:"stashpad-trash-group-count",text:String(r.length)});for(let u of r)this.encRow(h,u,!u.meta?.title)}A&&this.renderRawSection(t,l)}encRow(e,t,i){let s=this.order.length;this.order.push(t.blob);let n=e.createDiv({cls:"stashpad-trash-row"});this.selected.has(t.blob)&&n.addClass("is-selected"),n.addEventListener("click",h=>{h.target.closest("button")||this.onRowClick(s,t.blob,h)});let o=n.createDiv({cls:"stashpad-trash-row-main"});o.createSpan({cls:"stashpad-trash-title",text:i?"Locked note":t.meta?.title||"Locked note"});let r=t.meta?.deletedAt?`deleted ${Dn(t.meta.deletedAt).fromNow()}`:"deleted",l=t.meta&&t.meta.count>1?` \xB7 ${t.meta.count} ${t.meta.kind==="rawtrash"?"files":"notes"}`:"";o.createSpan({cls:"stashpad-trash-sub",text:r+l});let c=n.createEl("button",{cls:"stashpad-trash-restore",text:"Restore"});(0,ue.setIcon)(c.createSpan({cls:"stashpad-btn-icon"}),"rotate-ccw"),c.onclick=async()=>{c.disabled=!0,await this.plugin.restoreDeletedAt(t.blob)?await this.render():c.disabled=!1};let A=n.createEl("button",{cls:"stashpad-trash-delete",attr:{"aria-label":"Delete permanently"}});(0,ue.setIcon)(A,"trash-2"),A.onclick=()=>this.confirmPurge([t.blob])}renderMixed(e,t,i){let s=[];for(let o of t)s.push({ts:o.meta?.deletedAt&&Date.parse(String(o.meta.deletedAt))||0,kind:"enc",enc:o});for(let o of i)s.push({ts:o.mtime||0,kind:"raw",raw:o});s.sort((o,r)=>r.ts-o.ts);let n=e.createDiv({cls:"stashpad-trash-group"});for(let o of s){let r=n.createDiv({cls:"stashpad-trash-row"}),l=r.createDiv({cls:"stashpad-trash-row-main"}),c=o.kind==="enc"&&o.enc?.meta?.encrypted===!1,A=l.createSpan({cls:`stashpad-trash-kind is-${o.kind}`});if((0,ue.setIcon)(A,o.kind==="enc"&&!c?"lock":"trash"),o.kind==="enc"&&o.enc){let h=o.enc,g=!h.meta?.title&&!c;l.createSpan({cls:"stashpad-trash-title",text:h.meta?.title||(c?"Deleted note":"Locked note")});let u=h.meta?.deletedAt?`deleted ${Dn(h.meta.deletedAt).fromNow()}`:"deleted";l.createSpan({cls:"stashpad-trash-sub",text:`${u} \xB7 ${c?"unencrypted":"encrypted"}`});let f=r.createEl("button",{cls:"stashpad-trash-restore",text:"Restore"});(0,ue.setIcon)(f.createSpan({cls:"stashpad-btn-icon"}),"rotate-ccw"),f.onclick=async()=>{f.disabled=!0,await this.plugin.restoreDeletedAt(h.blob)?await this.render():f.disabled=!1};let p=r.createEl("button",{cls:"stashpad-trash-delete",attr:{"aria-label":"Delete permanently"}});(0,ue.setIcon)(p,"trash-2"),p.onclick=()=>this.confirmPurge([h.blob])}else if(o.raw){let h=o.raw;l.createSpan({cls:"stashpad-trash-title",text:h.title});let g=h.mtime?`deleted ${Dn(h.mtime).fromNow()}`:"in Obsidian trash";l.createSpan({cls:"stashpad-trash-sub",text:`${g} \xB7 unencrypted`});let u=r.createEl("button",{cls:"stashpad-trash-restore",text:"Restore"});(0,ue.setIcon)(u.createSpan({cls:"stashpad-btn-icon"}),"rotate-ccw"),u.onclick=async()=>{u.disabled=!0,await this.plugin.restoreRawTrashNote(h.path)?await this.render():u.disabled=!1}}}}renderRawSection(e,t){if(t.length===0)return;let i=e.createDiv({cls:"stashpad-trash-group"}),s=i.createDiv({cls:"stashpad-trash-group-head"});(0,ue.setIcon)(s.createSpan({cls:"stashpad-trash-group-icon"}),"trash"),s.createSpan({text:"Obsidian trash (unencrypted)"}),s.createSpan({cls:"stashpad-trash-group-count",text:String(t.length)});for(let n of t){let o=i.createDiv({cls:"stashpad-trash-row"}),r=o.createDiv({cls:"stashpad-trash-row-main"});r.createSpan({cls:"stashpad-trash-title",text:n.title});let l=n.mtime?`deleted ${Dn(n.mtime).fromNow()}`:"in Obsidian trash";r.createSpan({cls:"stashpad-trash-sub",text:l});let c=o.createEl("button",{cls:"stashpad-trash-restore",text:"Restore"});(0,ue.setIcon)(c.createSpan({cls:"stashpad-btn-icon"}),"rotate-ccw"),c.onclick=async()=>{c.disabled=!0,await this.plugin.restoreRawTrashNote(n.path)?await this.render():c.disabled=!1}}}clearSelection(){this.selected.clear(),this.anchorBlob=null}selectAll(){if(this.order.length!==0){for(let e of this.order)this.selected.add(e);this.anchorBlob=this.order[this.order.length-1]??null,this.render()}}onRowClick(e,t,i){let s=this.anchorBlob!==null?this.order.indexOf(this.anchorBlob):-1;if(i.shiftKey&&s>=0){let[n,o]=s<e?[s,e]:[e,s];this.selected.clear();for(let r=n;r<=o;r++)this.selected.add(this.order[r])}else i.metaKey||i.ctrlKey?(this.selected.has(t)?this.selected.delete(t):this.selected.add(t),this.anchorBlob=t):(this.selected.size===1&&this.selected.has(t)?this.selected.clear():(this.selected.clear(),this.selected.add(t)),this.anchorBlob=t);this.render()}confirmPurge(e){if(e.length===0)return;let t=e.length;new _(this.app,t===1?"Delete permanently?":`Delete ${t} items permanently?`,`${t===1?"This encrypted item":`These ${t} encrypted items`} will be PERMANENTLY deleted and CANNOT be restored \u2014 there is no decrypted copy. Continue?`,"Delete forever",async i=>{if(i){for(let s of e)await this.plugin.purgeDeletedAt(s);this.clearSelection(),await this.render()}},"Cancel",!0).open()}async onClose(){this.contentEl.empty()}};async function Cl(d){let{workspace:a}=d.app,e=a.getLeavesOfType(Wt);if(e.length>0){a.revealLeaf(e[0]);return}let t=a.getMostRecentLeaf(),i=a.getLeaf("tab");await i.setViewState({type:Wt,active:!0}),a.revealLeaf(i),pt(a,i,t,s=>d.registerEvent(s))}var zt=require("obsidian"),fs=class fs{constructor(a){this.plugin=a;this.tick=null;this.lastTouch=new Map;this.counting=new Set;this.countdownTimers=new Set}key(a,e){return`${a} ${e}`}delayMin(a){let e=a.peekMin;if(e!=null)return e;let i=(this.plugin.settings.folderEncPrefs??{})[a.folder.replace(/\/+$/,"")]?.reEncryptAfterMin;return i??this.plugin.settings.reEncryptAfterMin??0}anyArmed(){if((this.plugin.settings.reEncryptAfterMin??0)>0)return!0;for(let a of Object.values(this.plugin.settings.folderEncPrefs??{}))if((a?.reEncryptAfterMin??0)>0)return!0;return this.plugin.reEncryptWatching().some(a=>(a.peekMin??0)>0)}start(){let a=e=>{e&&this.lastTouch.set(e.replace(/\/+$/,""),Date.now())};this.plugin.registerEvent(this.plugin.app.vault.on("modify",e=>{e instanceof zt.TFile&&a(e.parent?.path??"")})),this.plugin.registerEvent(this.plugin.app.workspace.on("file-open",e=>{e&&a(e.parent?.path??"")})),this.tick=window.setInterval(()=>void this.poll(),3e4),this.plugin.registerInterval(this.tick)}folderHasOpenEditor(a){let e=a.replace(/\/+$/,""),t=!1;return this.plugin.app.workspace.iterateAllLeaves(i=>{let s=i.view;s instanceof zt.MarkdownView&&s.file&&(s.file.parent?.path?.replace(/\/+$/,"")??"")===e&&(t=!0)}),t}keyReady(a){let e=this.plugin.encryption;return e?.isConfigured?.()?e.hasFolderKey(a)&&e.isFolderUnlocked(a):!1}async poll(){if(!this.anyArmed())return;let a=Date.now();for(let e of this.plugin.reEncryptWatching()){let t=this.delayMin(e);if(t<=0)continue;let i=e.folder.replace(/\/+$/,""),s=this.key(i,e.rootId);if(this.counting.has(s))continue;let n=Math.max(Date.parse(e.unlockedAt)||0,this.lastTouch.get(i)??0);if(!(a<n+t*6e4)&&this.keyReady(i)){if(this.folderHasOpenEditor(i)){Bd(this.lastTouch,i,a);continue}this.countdownThenLock(e,s)}}}countdownThenLock(a,e){this.counting.add(e);let t=a.folder.replace(/\/+$/,""),i=a.title||"a note",s=Date.now(),n=fs.COUNTDOWN_SECS,o=!1,r=new zt.Notice("",0),l=()=>{window.clearInterval(h),this.countdownTimers.delete(h),r.hide(),this.counting.delete(e)},c=()=>{this.lastTouch.set(t,Date.now()),l()},A=()=>{r.noticeEl.empty(),r.noticeEl.createSpan({text:`\u{1F512} Re-encrypting \u201C${i}\u201D in ${n}s\u2026 `}),r.noticeEl.createEl("button",{text:"Keep unlocked"}).onclick=()=>{o=!0,c()}};A();let h=window.setInterval(async()=>{if(o)return;if((this.lastTouch.get(t)??0)>s){c();return}if(n-=1,n>0){A();return}if(l(),!this.plugin.reEncryptWatching().some(u=>u.folder===a.folder&&u.rootId===a.rootId))return;if(this.folderHasOpenEditor(t)){this.lastTouch.set(t,Date.now());return}if(!this.keyReady(t)){this.lastTouch.set(t,Date.now());return}await this.plugin.lockNoteSubtree(a.folder,a.rootId,null,{silent:!0})&&new zt.Notice(`Re-encrypted \u201C${i}\u201D.`)},1e3);this.countdownTimers.add(h),this.plugin.registerInterval(h)}dispose(){for(let a of this.countdownTimers)window.clearInterval(a);this.countdownTimers.clear(),this.counting.clear()}};fs.COUNTDOWN_SECS=10,fs.RECENT_EDIT_MS=2e4;var Nn=fs;function Bd(d,a,e){d.set(a.replace(/\/+$/,""),e)}ae();var W=require("obsidian");ae();we();var Mn=class d extends W.ItemView{constructor(e,t){super(e);this.plugin=t;this.renderTimer=null;this.dividerCleanup=null;this.pinExpanded=new Set;this.folderPinExpanded=new Set;this.homeColorByFolder=new Map}getViewType(){return Bt}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()))}refresh(){this.scheduleRender()}scheduleRender(){this.renderTimer==null&&(this.renderTimer=window.setTimeout(()=>{this.renderTimer=null,this.containerEl.isConnected&&this.render()},100))}render(){let e=this.contentEl;e.empty(),e.addClass("stashpad-folderpanel-root");let t=this.clampFrac(this.plugin.settings.folderPanelPinnedFraction??.5),i=e.createDiv({cls:"stashpad-folderpanel-section stashpad-folderpanel-pinned"});i.style.flex=`0 0 ${(t*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,W.setIcon)(n,"list"),n.setAttr("aria-label","Pinned view options"),n.onclick=h=>{h.stopPropagation(),this.openPinnedOptionsMenu(h)},this.renderPinned(i.createDiv({cls:"stashpad-folderpanel-list stashpad-folderpanel-pins"}));let o=e.createDiv({cls:"stashpad-folderpanel-divider"});o.createDiv({cls:"stashpad-folderpanel-divider-grip"}),this.attachDividerDrag(e,i,o);let r=e.createDiv({cls:"stashpad-folderpanel-section stashpad-folderpanel-folders"});r.setCssStyles({flex:"1 1 0"});let l=r.createDiv({cls:"stashpad-folderpanel-heading stashpad-folderpanel-heading-row"}),c=l.createSpan({cls:"stashpad-folderpanel-heading-title stashpad-folderpanel-heading-switch",text:"Folders"});c.setAttr("aria-label","Open folder switcher"),c.onmousedown=h=>{h.button===0&&(h.preventDefault(),this.plugin.openFolderPicker())};let A=l.createEl("button",{cls:"stashpad-folderpanel-iconbtn stashpad-folderpanel-heading-newfolder"});if((0,W.setIcon)(A,"folder-plus"),A.setAttr("aria-label","New Stashpad folder (folder switcher)"),A.onmousedown=h=>{h.button===0&&(h.preventDefault(),h.stopPropagation(),this.plugin.openFolderPicker())},this.plugin.encryption?.isConfigured?.()){let h=l.createEl("button",{cls:"stashpad-folderpanel-iconbtn stashpad-folderpanel-heading-trash"});(0,W.setIcon)(h,"trash-2"),h.setAttr("aria-label","Open encrypted trash"),h.onmousedown=g=>{g.button===0&&(g.preventDefault(),g.stopPropagation(),this.plugin.openEncryptedTrash())}}this.renderFolders(r.createDiv({cls:"stashpad-folderpanel-list"}))}clampFrac(e){return Number.isFinite(e)?Math.max(.15,Math.min(.85,e)):.5}attachDividerDrag(e,t,i){let s=null,n=l=>{let c=e.getBoundingClientRect();if(c.height<=0)return;let A=this.clampFrac((l.clientY-c.top)/c.height);s=A,t.style.flex=`0 0 ${(A*100).toFixed(2)}%`},o=()=>{document.removeEventListener("pointermove",n),document.removeEventListener("pointerup",r),document.removeEventListener("pointercancel",r),document.body.removeClass("stashpad-folderpanel-resizing"),this.dividerCleanup=null},r=l=>{try{i.releasePointerCapture(l.pointerId)}catch{}l.type==="pointerup"&&s!=null&&(this.plugin.settings.folderPanelPinnedFraction=s,this.plugin.saveSettings()),o()};this.registerDomEvent(i,"pointerdown",l=>{l.preventDefault(),document.body.addClass("stashpad-folderpanel-resizing");try{i.setPointerCapture(l.pointerId)}catch{}document.addEventListener("pointermove",n),document.addEventListener("pointerup",r),document.addEventListener("pointercancel",r),this.dividerCleanup=o})}openPinnedOptionsMenu(e){let t=this.plugin.settings.folderPanelPinnedGrouping??"pin-order",i=new W.Menu;i.addItem(s=>s.setTitle("Sort by pin order").setChecked(t==="pin-order").onClick(()=>void this.setPinnedGrouping("pin-order"))),i.addItem(s=>s.setTitle("Group by folder").setChecked(t==="folder").onClick(()=>void this.setPinnedGrouping("folder"))),i.showAtMouseEvent(e)}async setPinnedGrouping(e){(this.plugin.settings.folderPanelPinnedGrouping??"pin-order")!==e&&(this.plugin.settings.folderPanelPinnedGrouping=e,await this.plugin.saveSettings(),this.render())}renderPinned(e){let t=this.plugin.discoverStashpadFolders().filter(n=>this.folderState(n)==="pinned"),i=this.plugin.listPinnedNotes();if(t.length===0&&i.length===0){e.createDiv({cls:"stashpad-folderpanel-empty",text:"Nothing pinned yet \u2014 pin a note or folder from its right-click menu."});return}if(t.length>0){let n=this.openFolders();for(let o of t)this.renderFolderRow(e,o,n)}if(i.length===0)return;if((this.plugin.settings.folderPanelPinnedGrouping??"pin-order")==="folder"){let n=new Map;i.forEach((l,c)=>{let A=n.get(l.folder);A||(A=[],n.set(l.folder,A)),A.push({...l,idx:c})});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 l of r){let c=e.createDiv({cls:"stashpad-pinned-group-header"});l===o&&c.addClass("is-active-folder"),c.createSpan({cls:"stashpad-pinned-group-name",text:l.split("/").pop()||l});for(let A of n.get(l)??[])this.renderPinNote(e,A.folder,A.id,A.file,A.idx)}}else i.forEach((n,o)=>this.renderPinNote(e,n.folder,n.id,n.file,o))}async reorderPin(e,t){let i=this.plugin.listPinnedNotes();if(e<0||e>=i.length)return;let s=i[e],n=i.filter((A,h)=>h!==e),o=Math.max(0,Math.min(t>e?t-1:t,n.length)),r=n[o-1],l=n[o],c;!r&&!l?c=Date.now():r?l?c=(r.pinnedAt+l.pinnedAt)/2:c=r.pinnedAt+1e3:c=l.pinnedAt-1e3;try{await this.app.fileManager.processFrontMatter(s.file,A=>{A.pinnedAt=c})}catch(A){console.warn("[Stashpad] pin reorder failed",A)}this.render()}renderPinNote(e,t,i,s,n){let o=this.app.metadataCache.getFileCache(s)?.frontmatter??{},r=typeof o.color=="string"?o.color:null,l=o.completed===!0,c=this.childrenOf(t,i),A=c.length>0,h=`${t}|${i}`,g=this.pinExpanded.has(h),u=e.createDiv({cls:"stashpad-pinned-row"});r&&(u.addClass("has-color"),u.style.setProperty("--stashpad-note-color",r)),l&&u.addClass("is-completed"),u.draggable=!0,u.dataset.pinIdx=String(n),u.addEventListener("dragstart",m=>{m.dataTransfer?.setData("text/plain",String(n)),m.dataTransfer&&(m.dataTransfer.effectAllowed="move"),u.addClass("is-dragging")}),u.addEventListener("dragend",()=>u.removeClass("is-dragging")),u.addEventListener("dragover",m=>{m.preventDefault(),m.dataTransfer&&(m.dataTransfer.dropEffect="move");let B=u.getBoundingClientRect(),C=m.clientY-B.top<B.height/2;u.toggleClass("drop-before",C),u.toggleClass("drop-after",!C)}),u.addEventListener("dragleave",()=>{u.removeClass("drop-before"),u.removeClass("drop-after")}),u.addEventListener("drop",m=>{m.preventDefault(),u.removeClass("drop-before"),u.removeClass("drop-after");let B=parseInt(m.dataTransfer?.getData("text/plain")??"",10);if(!Number.isFinite(B)||B===n)return;let C=u.getBoundingClientRect(),w=m.clientY-C.top<C.height/2;this.reorderPin(B,w?n:n+1)});let f=u.createSpan({cls:"stashpad-pinned-toggle"});A&&(Et(f,c.length,g),f.onclick=m=>{m.stopPropagation(),this.pinExpanded.has(h)?this.pinExpanded.delete(h):this.pinExpanded.add(h),this.render()});let p=u.createSpan({cls:"stashpad-pinned-icon"});(0,W.setIcon)(p,A?"folder-tree":"file-text"),r&&(p.style.color=r);let I=u.createSpan({cls:"stashpad-pinned-label",text:this.titleFromFile(s)});if(I.onclick=()=>{this.onNavigateAway(),this.plugin.revealNoteInStashpad(s)},u.createSpan({cls:"stashpad-pinned-folder",text:t.split("/").pop()||t}),u.oncontextmenu=m=>{m.preventDefault();let B=new W.Menu;B.addItem(C=>C.setTitle("Unpin from sidebar").setIcon("pin-off").onClick(()=>void this.plugin.unpinNote({folder:t,id:i}))),B.showAtMouseEvent(m)},A&&g){let m=e.createDiv({cls:"stashpad-pinned-children"});this.renderPinSubtree(m,t,i,1)}}renderPinSubtree(e,t,i,s){for(let n of this.childrenOf(t,i)){let o=this.app.metadataCache.getFileCache(n)?.frontmatter??{},r=typeof o.id=="string"?o.id:null;if(!r)continue;let l=typeof o.color=="string"?o.color:null,c=o.completed===!0,A=this.childrenOf(t,r),h=A.length>0,g=`${t}|${r}`,u=this.pinExpanded.has(g),f=e.createDiv({cls:"stashpad-pinned-subrow"});c&&f.addClass("is-completed"),f.style.paddingLeft=`${s*16}px`;let p=f.createSpan({cls:"stashpad-pinned-toggle"});h&&(Et(p,A.length,u),p.onclick=B=>{B.stopPropagation(),this.pinExpanded.has(g)?this.pinExpanded.delete(g):this.pinExpanded.add(g),this.render()});let I=f.createSpan({cls:"stashpad-pinned-icon"});(0,W.setIcon)(I,"file-text"),l&&(I.style.color=l);let m=f.createSpan({cls:"stashpad-pinned-label",text:this.titleFromFile(n)});m.onclick=()=>{this.onNavigateAway(),this.plugin.revealNoteInStashpad(n)},h&&u&&this.renderPinSubtree(e,t,r,s+1)}}childrenOf(e,t){let i=[];for(let s of this.app.vault.getMarkdownFiles()){if((s.parent?.path?.replace(/\/+$/,"")??"")!==e)continue;let o=this.app.metadataCache.getFileCache(s)?.frontmatter;if(!o||typeof o.id!="string")continue;let r=o.parent;if(r===t||t===S&&(r==null||r===S)){if(o.id===S)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(){W.Platform.isMobile&&(this.plugin.suppressComposerAutofocusUntil=Date.now()+1500,this.app.workspace.leftSplit?.collapse?.())}titleFromFile(e){return e.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||e.basename}openFolders(){let e=new Set,t=(this.plugin.settings.folder||"Stashpad").replace(/\/+$/,"");for(let i of this.app.workspace.getLeavesOfType(z)){let s=(i.view?.noteFolder??"").replace(/\/+$/,"");s||(s=(((i.getViewState?.()?.state??{}).folderOverride??"")||t).replace(/\/+$/,"")),s&&e.add(s)}return e}static clean(e){return e.replace(/\/+$/,"")}folderState(e){let t=d.clean(e),i=this.plugin.settings;return(i.folderPanelPinned??[]).includes(t)?"pinned":(i.folderPanelDownranked??[]).includes(t)?"downranked":(i.folderPanelHidden??[]).includes(t)?"hidden":"normal"}async setFolderState(e,t){let i=d.clean(e),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),t==="pinned"?s.folderPanelPinned.push(i):t==="downranked"?s.folderPanelDownranked.push(i):t==="hidden"&&s.folderPanelHidden.push(i),await this.plugin.saveSettings(),this.render()}folderHomeColor(e){return this.homeColorByFolder.get(d.clean(e))??null}rebuildHomeColors(){this.homeColorByFolder.clear();for(let e of this.app.vault.getMarkdownFiles()){let t=this.app.metadataCache.getFileCache(e)?.frontmatter;if(!t||t.id!==S||typeof t.color!="string"||!t.color.trim())continue;let i=(e.parent?.path??"").replace(/\/+$/,"");i&&this.homeColorByFolder.set(i,t.color)}}renderFolders(e){let t=this.plugin.discoverStashpadFolders();if(t.length===0){e.createDiv({cls:"stashpad-folderpanel-empty",text:"No Stashpad folders yet."});return}this.rebuildHomeColors();let i=this.openFolders(),s=[],n=[],o=[],r=[];for(let c of t)switch(this.folderState(c)){case"pinned":s.push(c);break;case"downranked":o.push(c);break;case"hidden":r.push(c);break;default:n.push(c)}let l=[...s,...n,...o];if(l.length===0&&r.length===0){e.createDiv({cls:"stashpad-folderpanel-empty",text:"No Stashpad folders yet."});return}for(let c of l)this.renderFolderRow(e,c,i);r.length>0&&this.renderHiddenSection(e,r)}renderFolderRow(e,t,i){let s=this.folderState(t),n=i.has(d.clean(t)),o=e.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 m=o.createSpan({cls:"stashpad-folderpanel-pinmark"});(0,W.setIcon)(m,"pin"),m.setAttr("aria-label","Pinned")}let l=this.folderHomePinnedNotes(t),c=d.clean(t),A=this.folderPinExpanded.has(c);if(l.length>0){let m=o.createSpan({cls:"stashpad-folderpanel-pinreveal"});Et(m,l.length,A),m.setAttr("aria-label",A?"Hide pinned notes":`${l.length} pinned note${l.length===1?"":"s"}`),m.addEventListener("mousedown",B=>{B.stopPropagation(),B.preventDefault()}),m.onclick=B=>{B.stopPropagation(),this.folderPinExpanded.has(c)?this.folderPinExpanded.delete(c):this.folderPinExpanded.add(c),this.render()}}let h=this.plugin.isArchiveFolder(t),g=o.createSpan({cls:"stashpad-folderpanel-folder-icon"});(0,W.setIcon)(g,this.plugin.getFolderIcon(t)??(h?"archive":"folder")),h&&g.setAttr("aria-label","Archive folder \u2014 de-indexed from search");let u=this.folderHomeColor(t);u&&(g.style.color=u);let f=t.split("/").pop()||t;o.createSpan({cls:"stashpad-folderpanel-row-label",text:f});let I=o.createDiv({cls:"stashpad-folderpanel-actions"}).createEl("button",{cls:"stashpad-folderpanel-iconbtn"});if((0,W.setIcon)(I,"plus-square"),I.setAttr("aria-label","Open in new tab"),I.onmousedown=m=>{m.button===0&&(m.preventDefault(),m.stopPropagation(),this.onNavigateAway(),this.plugin.activateViewForFolder(t))},o.addEventListener("mousedown",m=>{m.button===0&&(m.target?.closest?.(".stashpad-folderpanel-actions")||(this.onNavigateAway(),this.jumpToFolder(t)))}),o.oncontextmenu=m=>{m.preventDefault(),this.openFolderMenu(m,t)},l.length>0&&A){let m=e.createDiv({cls:"stashpad-folderpanel-pinlist"});for(let B of l){let C=m.createDiv({cls:"stashpad-folderpanel-pinrow"}),w=this.app.metadataCache.getFileCache(B)?.frontmatter??{},y=C.createSpan({cls:"stashpad-folderpanel-pinrow-icon"});(0,W.setIcon)(y,"arrow-up-to-line"),typeof w.color=="string"&&(y.style.color=w.color),C.createSpan({cls:"stashpad-folderpanel-pinrow-label",text:this.titleFromFile(B)}),C.onclick=()=>{this.onNavigateAway(),this.plugin.revealNoteInStashpad(B)}}}}folderHomePinnedNotes(e){return this.childrenOf(e,S).filter(t=>this.app.metadataCache.getFileCache(t)?.frontmatter?.listPinned===!0)}renderHiddenSection(e,t){let i=e.createDiv({cls:"stashpad-folderpanel-hidden"}),s=i.createDiv({cls:"stashpad-folderpanel-hidden-header"}),n=s.createSpan({cls:"stashpad-folderpanel-hidden-caret"});(0,W.setIcon)(n,"chevron-right"),s.createSpan({cls:"stashpad-folderpanel-hidden-title",text:`Hidden (${t.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,W.setIcon)(n,r?"chevron-right":"chevron-down")};for(let r of t){let l=o.createDiv({cls:"stashpad-folderpanel-row stashpad-folderpanel-hidden-row"}),c=r.split("/").pop()||r;l.createSpan({cls:"stashpad-folderpanel-row-label",text:c});let A=l.createEl("button",{cls:"stashpad-folderpanel-iconbtn"});(0,W.setIcon)(A,"eye"),A.setAttr("aria-label","Unhide"),A.onclick=h=>{h.stopPropagation(),this.setFolderState(r,"normal")}}}jumpToFolder(e){this.plugin.openFolderInStashpad(e)}revealFolder(e){let t=this.app.vault.getAbstractFileByPath(e.replace(/\/+$/,""));if(!(t instanceof W.TFolder)){new W.Notice("Couldn't find that folder.");return}let i=this.app.workspace.getLeavesOfType("file-explorer")[0];if(!i){new W.Notice("File explorer isn't available.");return}this.app.workspace.revealLeaf(i),i.view?.revealInFolder?.(t)}openFolderMenu(e,t){let i=new W.Menu;i.addItem(n=>n.setTitle("Open in new tab").setIcon("plus-square").onClick(()=>void this.plugin.activateViewForFolder(t))),i.addItem(n=>n.setTitle("Reveal in file explorer").setIcon("folder-search").onClick(()=>this.revealFolder(t))),i.addSeparator();let s=this.folderState(t);i.addItem(n=>n.setTitle(s==="pinned"?"Unpin":"Pin to top").setIcon("pin").onClick(()=>void this.setFolderState(t,s==="pinned"?"normal":"pinned"))),i.addItem(n=>n.setTitle(s==="downranked"?"Remove downrank":"Downrank").setIcon("arrow-down").onClick(()=>void this.setFolderState(t,s==="downranked"?"normal":"downranked"))),i.addItem(n=>n.setTitle("Hide from list").setIcon("eye-off").onClick(()=>void this.setFolderState(t,"hidden"))),i.addSeparator(),i.addItem(n=>n.setTitle("Rename\u2026").setIcon("pencil").onClick(()=>this.renameFolder(t))),this.plugin.encryption?.isConfigured?.()&&(i.addSeparator(),i.addItem(n=>n.setTitle("Encrypt (lock) all notes in folder").setIcon("lock").onClick(()=>void this.plugin.lockFolder(t))),this.app.vault.getFiles().some(n=>n.extension==="stashenc"&&(n.parent?.path?.replace(/\/+$/,"")??"")===t.replace(/\/+$/,""))&&i.addItem(n=>n.setTitle("Decrypt (unlock) all notes in folder").setIcon("unlock").onClick(()=>void this.plugin.unlockFolder(t))),i.addItem(n=>n.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(t)),n.setWarning?.(!0)}),i.showAtMouseEvent(e)}renameFolder(e){let t=e.replace(/\/+$/,""),i=this.app.vault.getAbstractFileByPath(t);if(!(i instanceof W.TFolder)){new W.Notice("Couldn't find that folder.");return}let s=i.name;new ar(this.app,s,async n=>{let o=n.trim().replace(/[\\/:]+/g,"").trim();if(!o||o===s)return;let l=`${i.parent?.path&&i.parent.path!=="/"?`${i.parent.path}/`:""}${o}`;if(this.app.vault.getAbstractFileByPath(l)){new W.Notice(`"${o}" already exists.`);return}if(!(this.app.vault.getAbstractFileByPath(t)instanceof W.TFolder)){new W.Notice("That folder no longer exists.");return}try{await this.app.fileManager.renameFile(i,l),await this.plugin.remapFolderPathInSettings(t,l),new W.Notice(`Renamed to "${o}".`)}catch(c){console.warn("[Stashpad] folder rename failed",c),new W.Notice("Rename failed (see console).")}}).open()}deleteFolder(e){let t=e.replace(/\/+$/,""),i=this.app.vault.getAbstractFileByPath(t);if(!(i instanceof W.TFolder)){new W.Notice("Couldn't find that folder.");return}let s=this.app.vault.getMarkdownFiles().filter(o=>(o.parent?.path?.replace(/\/+$/,"")??"")===t||o.path.startsWith(t+"/")).length,n=i.name;new _(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()}async onClose(){this.dividerCleanup?.(),this.contentEl.empty()}},ar=class extends W.Modal{constructor(e,t,i){super(e);this.current=t;this.onSubmit=i;this.delivered=!1}onOpen(){this.modalEl.addClass("stashpad-compact-modal"),this.contentEl.empty(),this.titleEl.setText("Rename folder");let e=this.contentEl.createEl("input",{type:"text"});e.addClass("stashpad-folderpanel-rename-input"),e.value=this.current;let t=this.contentEl.createDiv({cls:"stashpad-folderpanel-rename-footer"});t.createEl("button",{text:"Cancel"}).onclick=()=>this.close();let i=t.createEl("button",{cls:"mod-cta",text:"Rename"}),s=()=>{this.delivered=!0;let n=e.value;this.close(),this.onSubmit(n)};i.onclick=s,this.scope.register([],"Enter",n=>{n.preventDefault(),e.value.trim()&&s()}),requestAnimationFrame(()=>{e.focus(),e.select()})}onClose(){this.contentEl.empty()}};async function Tn(d){let a=d.workspace.getLeavesOfType(Bt);if(a.length>0){d.workspace.revealLeaf(a[0]);return}let e=d.workspace.getLeftLeaf(!1);if(!e){new W.Notice("Stashpad: couldn't open the folder panel.");return}await e.setViewState({type:Bt,active:!0}),d.workspace.revealLeaf(e)}we();ri();ae();var lr="OKF Template.md",yd=`--- +`),"Swap",async l=>{if(!l)return;let c=e.parent??k;await this.swapParentChild(e,i,c)}).open()}async swapParentChild(e,t,i){if(!e.file||!t.file)return;if(t.parent!==e.id){new b.Notice("Swap aborted: parent/child relationship changed.");return}let s=this.noteFolder,n=e.parent,o=this.tree.getChildren(e.id).filter(u=>u.id!==t.id).filter(u=>!!u.file),r=o.map(u=>({id:u.id,path:u.file.path,was:u.parent})),l=this.order.getOrder(s,i).slice(),c=this.order.getOrder(s,t.id).slice(),A=this.order.getOrder(s,e.id).slice();await this.app.fileManager.processFrontMatter(t.file,u=>{u.parent=i}),this.fmSync.scheduleParentChange(t.id,e.id,i),await this.app.fileManager.processFrontMatter(e.file,u=>{u.parent=t.id}),this.fmSync.scheduleParentChange(e.id,n,t.id);for(let u of o)await this.app.fileManager.processFrontMatter(u.file,f=>{f.parent=t.id}),this.fmSync.scheduleParentChange(u.id,e.id,t.id);if(l.length>0){let u=l.includes(e.id)?l.map(f=>f===e.id?t.id:f):[...l.filter(f=>f!==t.id),t.id];this.order.setOrder(s,i,u)}let h=o.map(u=>u.id),p=[e.id,...c.filter(u=>u!==e.id&&!h.includes(u)),...h];this.order.setOrder(s,t.id,p),this.order.setOrder(s,e.id,[]),await this.order.save(s),await this.log.append({type:"parent_change",id:t.id,payload:{from:e.id,to:i,reason:"swap"}}),await this.log.append({type:"parent_change",id:e.id,payload:{from:n,to:t.id,reason:"swap"}});for(let u of r)await this.log.append({type:"parent_change",id:u.id,payload:{from:u.was,to:t.id,reason:"swap"}});this.tree.rebuild(s),this.pendingFocusIds=[t.id],this.render({kind:"follow-cursor"}),this.plugin.notifications.show({message:`Swapped "${this.titleForNode(t)}" \u2194 "${this.titleForNode(e)}".`,kind:"success",category:"move",affectedIds:[t.id,e.id,...h],folder:s}),this.plugin.getUndoStack(s).push({label:`Swap "${this.titleForNode(t)}" \u2194 parent`,undo:async()=>{let u=this.tree.get(e.id),f=this.tree.get(t.id);u?.file&&await this.app.fileManager.processFrontMatter(u.file,g=>{n==null||n===k?(delete g.parent,g.parent=k):g.parent=n}),f?.file&&await this.app.fileManager.processFrontMatter(f.file,g=>{g.parent=e.id});for(let g of r){let I=this.app.vault.getAbstractFileByPath(g.path);I&&await this.app.fileManager.processFrontMatter(I,m=>{g.was==null?m.parent=k:m.parent=g.was})}this.order.setOrder(s,i,l),this.order.setOrder(s,t.id,c),this.order.setOrder(s,e.id,A),await this.order.save(s),this.tree.rebuild(s),this.pendingFocusIds=[e.id],this.render({kind:"follow-cursor"})},redo:async()=>{await this.swapParentChild(e,t,i)}})}async changeParent(e,t,i={record:!0}){if(!e.file)return!1;let s=e.file,n=e.parent,o=l=>l??k;if(o(n)===o(t)){if(!i.quiet){let l=this.titleForNode(e),c=t===k?"Home":`"${this.titleForNode(this.tree.get(t)??e)}"`;this.plugin.notifications.show({message:`"${l}" is already under ${c}.`,kind:"info",category:"move",affectedIds:[e.id],folder:this.noteFolder})}return!1}if(t===e.id)return i.quiet||this.plugin.notifications.show({message:`Can't move "${this.titleForNode(e)}" into itself.`,kind:"warning",category:"move",affectedIds:[e.id],folder:this.noteFolder}),!1;if(t!==k&&this.isDescendant(t,e.id))return i.quiet||this.offerSwapForDescendantMove(e,t),!1;let r=this.authorship.collectAuthorIds([e]);if(await this.app.fileManager.processFrontMatter(s,l=>{l.parent=t}),this.fmSync.scheduleParentChange(e.id,n,t),await this.log.append({type:"parent_change",id:e.id,payload:{from:n,to:t}}),this.pendingFocusIds=[e.id],this.focusId!==t&&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 l=this.tree.get(t),c=l?this.titleForNode(l):"(root)";this.plugin.notifications.show({message:`Reparented "${this.titleForNode(e)}" \u2192 "${c}"`,kind:"success",category:"move",affectedIds:[e.id],affectedAuthorIds:r,folder:this.noteFolder,actions:t===k?[]:[{label:"Jump to parent",onClick:()=>this.navigateTo(t)}]})}if(i.record!==!1){let l=this.noteFolder,c=s.path,A=e.id;this.plugin.getUndoStack(l).push({label:"Move note",undo:async()=>{let h=this.fileForNote(A,c);if(h){await this.app.fileManager.processFrontMatter(h,p=>{p.parent=n}),this.pendingFocusIds=[A],this.focusId!==n&&this.focusId!==t?(this.selection.clear(),this.cursorIdx=-1):this.focusId===t&&(this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=null),this.tree.rebuild(l),this.render({kind:"follow-cursor"});{let p=this.selectionGuardKey,u=()=>{if(this.selectionGuardKey!==p||this.selection.has(A))return;let f=this.currentChildren.findIndex(g=>g.id===A);f<0||(this.selection.add(A),this.cursorIdx=f,this.render({kind:"follow-cursor"}))};setTimeout(u,120),setTimeout(u,400)}}},redo:async()=>{let h=this.fileForNote(A,c);if(h){await this.app.fileManager.processFrontMatter(h,p=>{p.parent=t}),this.pendingFocusIds=[A],this.focusId!==t&&this.focusId!==n?(this.selection.clear(),this.cursorIdx=-1):this.focusId===n&&(this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=null),this.tree.rebuild(l),this.render({kind:"follow-cursor"});{let p=this.selectionGuardKey,u=()=>{if(this.selectionGuardKey!==p||this.selection.has(A))return;let f=this.currentChildren.findIndex(g=>g.id===A);f<0||(this.selection.add(A),this.cursorIdx=f,this.render({kind:"follow-cursor"}))};setTimeout(u,120),setTimeout(u,400)}}}})}return!0}notifyBatchMove(e,t,i){if(!e.length)return;let s=this.tree.get(t),n=t===k?"Home":`"${s?this.titleForNode(s):"the destination"}"`,o=l=>i.get(l.id)??0,r;if(e.length===1){let l=this.titleForNode(e[0]),c=o(e[0]);r=c>0?`Moved "${l}" and its ${c} ${c===1?"child":"children"} \u2192 ${n}`:`Moved "${l}" \u2192 ${n}`}else{let l=e.reduce((c,A)=>c+o(A),0);r=l>0?`Moved ${e.length} notes (${l} nested) \u2192 ${n}`:`Moved ${e.length} notes \u2192 ${n}`}this.plugin.notifications.show({message:r,kind:"success",category:"move",duration:t===k?void 0:0,affectedIds:e.map(l=>l.id),affectedAuthorIds:this.authorship.collectAuthorIds(e),folder:this.noteFolder,actions:t===k?[]:[{label:"Jump to destination",onClick:()=>this.navigateTo(t)}]})}};fs.AIMED_TAP_WINDOW_MS=600;var xn=fs,Nn=class extends b.SuggestModal{constructor(e,t,i){super(e);this.entries=t;this.onPick=i;this.setPlaceholder("Restore which deleted note?")}getSuggestions(e){let t=e.toLowerCase();return this.entries.filter(i=>`${i.label} ${i.folder}`.toLowerCase().includes(t))}renderSuggestion(e,t){t.createDiv({text:e.label}),t.createEl("small",{text:`from ${e.folder}`,cls:"stashpad-suggest-path"})}onChooseSuggestion(e){this.onPick(e.blob)}};var fe=require("obsidian");le();me();var Mn=fe.moment,Tn=class extends fe.ItemView{constructor(e,t){super(e);this.plugin=t;this.renderPending=!1;this.renderGen=0;this.selected=new Set;this.order=[];this.anchorBlob=null;this.trashMode="byfolder"}getViewType(){return Xt}getDisplayText(){return"Trash"}getIcon(){return"trash-2"}async onOpen(){this.containerEl.addClass("stashpad-trash-view"),this.registerEvent(this.app.vault.on("create",e=>{e.path.startsWith("_deleted/")&&this.scheduleRender()})),this.registerEvent(this.app.vault.on("delete",e=>{e.path.startsWith("_deleted/")&&this.scheduleRender()})),this.registerDomEvent(document,"keydown",e=>{if(this.app.workspace.activeLeaf!==this.leaf)return;let t=e.target;if(!(t&&(t.tagName==="INPUT"||t.tagName==="TEXTAREA"||t.isContentEditable))&&(e.metaKey||e.ctrlKey)&&!e.altKey&&(e.key==="a"||e.key==="A")){if(this.order.length===0)return;e.preventDefault(),this.selectAll()}}),await this.render()}scheduleRender(){this.renderPending||(this.renderPending=!0,window.setTimeout(()=>{this.renderPending=!1,this.render()},150))}async render(){let e=++this.renderGen,t=this.contentEl;t.empty(),t.addClass("stashpad-trash-view-body"),this.order=[];let i=t.createDiv({cls:"stashpad-trash-view-header"});i.createEl("h3",{text:"Trash"});let s=i.createEl("button",{cls:"stashpad-trash-iconbtn"});(0,fe.setIcon)(s,"refresh-cw"),s.setAttr("aria-label","Refresh"),s.onclick=()=>void this.render();let n=this.plugin.encryption?.isConfigured?.()?await this.plugin.listDeletedTrash():[];if(e!==this.renderGen)return;let o=await this.plugin.listPlaintextTrash();if(e!==this.renderGen)return;let r=[...n,...o],l=await this.plugin.listRawTrashStashpadNotes();if(e!==this.renderGen)return;if(r.length===0&&l.length===0){t.createDiv({cls:"stashpad-trash-empty",text:"Trash is empty. Securely-deleted notes land in the encrypted trash; plain deletes go to Obsidian's trash \u2014 both show here."});return}if(gn(t,this.trashMode,{total:r.length+l.length,enc:r.length,dec:l.length},h=>{this.trashMode=h,this.clearSelection(),this.render()}),this.trashMode==="mixed"){this.renderMixed(t,r,l);return}let c=this.trashMode!=="unencrypted"&&r.length>0,A=this.trashMode!=="encrypted"&&l.length>0;if(!c&&!A){t.createDiv({cls:"stashpad-trash-empty",text:"Nothing in this view."});return}if(c){let h=i.createEl("button",{cls:"stashpad-trash-restore",text:"Restore all"});(0,fe.setIcon)(h.createSpan({cls:"stashpad-btn-icon"}),"rotate-ccw"),h.onclick=async()=>{h.disabled=!0,await this.plugin.restoreAllTrash(),this.clearSelection(),await this.render()};let p=new Set(r.map(u=>u.blob));for(let u of[...this.selected])p.has(u)||this.selected.delete(u);if(this.selected.size>0){let u=t.createDiv({cls:"stashpad-trash-selbar"});u.createSpan({cls:"stashpad-trash-selcount",text:`${this.selected.size} selected`});let f=u.createEl("button",{cls:"stashpad-trash-restore",text:"Restore selected"});f.onclick=async()=>{f.disabled=!0;let m=0;for(let B of[...this.selected])await this.plugin.restoreDeletedAt(B,{silent:!0})||m++;m>0&&new fe.Notice(`${m} item${m===1?"":"s"} couldn't be restored (locked key?) \u2014 still in trash.`),this.clearSelection(),await this.render()};let g=u.createEl("button",{cls:"stashpad-trash-delete mod-warning",text:"Delete selected"});g.onclick=()=>this.confirmPurge([...this.selected]);let I=u.createEl("button",{cls:"stashpad-trash-iconbtn",text:"Clear"});I.onclick=()=>{this.clearSelection(),this.render()}}}if(this.order=[],c)if(this.trashMode==="byfolder"){let h=new Map;for(let u of r){let f=u.meta?.title?u.meta.originalFolder||"(unknown folder)":" hidden";(h.get(f)??h.set(f,[]).get(f)).push(u)}let p=[...h.keys()].sort((u,f)=>u===" hidden"?1:f===" hidden"?-1:u.localeCompare(f));for(let u of p){let f=u===" hidden",g=t.createDiv({cls:"stashpad-trash-group"}),I=g.createDiv({cls:"stashpad-trash-group-head"});(0,fe.setIcon)(I.createSpan({cls:"stashpad-trash-group-icon"}),f?"lock":"folder"),I.createSpan({text:f?"Hidden (title obscured)":u.split("/").pop()||u}),I.createSpan({cls:"stashpad-trash-group-count",text:String(h.get(u).length)});for(let m of h.get(u))this.encRow(g,m,f)}}else{let h=t.createDiv({cls:"stashpad-trash-group"}),p=h.createDiv({cls:"stashpad-trash-group-head"});(0,fe.setIcon)(p.createSpan({cls:"stashpad-trash-group-icon"}),"trash-2"),p.createSpan({text:"Stashpad trash"}),p.createSpan({cls:"stashpad-trash-group-count",text:String(r.length)});for(let u of r)this.encRow(h,u,!u.meta?.title)}A&&this.renderRawSection(t,l)}encRow(e,t,i){let s=this.order.length;this.order.push(t.blob);let n=e.createDiv({cls:"stashpad-trash-row"});this.selected.has(t.blob)&&n.addClass("is-selected"),n.addEventListener("click",h=>{h.target.closest("button")||this.onRowClick(s,t.blob,h)});let o=n.createDiv({cls:"stashpad-trash-row-main"});o.createSpan({cls:"stashpad-trash-title",text:i?"Locked note":t.meta?.title||"Locked note"});let r=t.meta?.deletedAt?`deleted ${Mn(t.meta.deletedAt).fromNow()}`:"deleted",l=t.meta&&t.meta.count>1?` \xB7 ${t.meta.count} ${t.meta.kind==="rawtrash"?"files":"notes"}`:"";o.createSpan({cls:"stashpad-trash-sub",text:r+l});let c=n.createEl("button",{cls:"stashpad-trash-restore",text:"Restore"});(0,fe.setIcon)(c.createSpan({cls:"stashpad-btn-icon"}),"rotate-ccw"),c.onclick=async()=>{c.disabled=!0,await this.plugin.restoreDeletedAt(t.blob)?await this.render():c.disabled=!1};let A=n.createEl("button",{cls:"stashpad-trash-delete",attr:{"aria-label":"Delete permanently"}});(0,fe.setIcon)(A,"trash-2"),A.onclick=()=>this.confirmPurge([t.blob])}renderMixed(e,t,i){let s=[];for(let o of t)s.push({ts:o.meta?.deletedAt&&Date.parse(String(o.meta.deletedAt))||0,kind:"enc",enc:o});for(let o of i)s.push({ts:o.mtime||0,kind:"raw",raw:o});s.sort((o,r)=>r.ts-o.ts);let n=e.createDiv({cls:"stashpad-trash-group"});for(let o of s){let r=n.createDiv({cls:"stashpad-trash-row"}),l=r.createDiv({cls:"stashpad-trash-row-main"}),c=o.kind==="enc"&&o.enc?.meta?.encrypted===!1,A=l.createSpan({cls:`stashpad-trash-kind is-${o.kind}`});if((0,fe.setIcon)(A,o.kind==="enc"&&!c?"lock":"trash"),o.kind==="enc"&&o.enc){let h=o.enc,p=!h.meta?.title&&!c;l.createSpan({cls:"stashpad-trash-title",text:h.meta?.title||(c?"Deleted note":"Locked note")});let u=h.meta?.deletedAt?`deleted ${Mn(h.meta.deletedAt).fromNow()}`:"deleted";l.createSpan({cls:"stashpad-trash-sub",text:`${u} \xB7 ${c?"unencrypted":"encrypted"}`});let f=r.createEl("button",{cls:"stashpad-trash-restore",text:"Restore"});(0,fe.setIcon)(f.createSpan({cls:"stashpad-btn-icon"}),"rotate-ccw"),f.onclick=async()=>{f.disabled=!0,await this.plugin.restoreDeletedAt(h.blob)?await this.render():f.disabled=!1};let g=r.createEl("button",{cls:"stashpad-trash-delete",attr:{"aria-label":"Delete permanently"}});(0,fe.setIcon)(g,"trash-2"),g.onclick=()=>this.confirmPurge([h.blob])}else if(o.raw){let h=o.raw;l.createSpan({cls:"stashpad-trash-title",text:h.title});let p=h.mtime?`deleted ${Mn(h.mtime).fromNow()}`:"in Obsidian trash";l.createSpan({cls:"stashpad-trash-sub",text:`${p} \xB7 unencrypted`});let u=r.createEl("button",{cls:"stashpad-trash-restore",text:"Restore"});(0,fe.setIcon)(u.createSpan({cls:"stashpad-btn-icon"}),"rotate-ccw"),u.onclick=async()=>{u.disabled=!0,await this.plugin.restoreRawTrashNote(h.path)?await this.render():u.disabled=!1}}}}renderRawSection(e,t){if(t.length===0)return;let i=e.createDiv({cls:"stashpad-trash-group"}),s=i.createDiv({cls:"stashpad-trash-group-head"});(0,fe.setIcon)(s.createSpan({cls:"stashpad-trash-group-icon"}),"trash"),s.createSpan({text:"Obsidian trash (unencrypted)"}),s.createSpan({cls:"stashpad-trash-group-count",text:String(t.length)});for(let n of t){let o=i.createDiv({cls:"stashpad-trash-row"}),r=o.createDiv({cls:"stashpad-trash-row-main"});r.createSpan({cls:"stashpad-trash-title",text:n.title});let l=n.mtime?`deleted ${Mn(n.mtime).fromNow()}`:"in Obsidian trash";r.createSpan({cls:"stashpad-trash-sub",text:l});let c=o.createEl("button",{cls:"stashpad-trash-restore",text:"Restore"});(0,fe.setIcon)(c.createSpan({cls:"stashpad-btn-icon"}),"rotate-ccw"),c.onclick=async()=>{c.disabled=!0,await this.plugin.restoreRawTrashNote(n.path)?await this.render():c.disabled=!1}}}clearSelection(){this.selected.clear(),this.anchorBlob=null}selectAll(){if(this.order.length!==0){for(let e of this.order)this.selected.add(e);this.anchorBlob=this.order[this.order.length-1]??null,this.render()}}onRowClick(e,t,i){let s=this.anchorBlob!==null?this.order.indexOf(this.anchorBlob):-1;if(i.shiftKey&&s>=0){let[n,o]=s<e?[s,e]:[e,s];this.selected.clear();for(let r=n;r<=o;r++)this.selected.add(this.order[r])}else i.metaKey||i.ctrlKey?(this.selected.has(t)?this.selected.delete(t):this.selected.add(t),this.anchorBlob=t):(this.selected.size===1&&this.selected.has(t)?this.selected.clear():(this.selected.clear(),this.selected.add(t)),this.anchorBlob=t);this.render()}confirmPurge(e){if(e.length===0)return;let t=e.length;new _(this.app,t===1?"Delete permanently?":`Delete ${t} items permanently?`,`${t===1?"This encrypted item":`These ${t} encrypted items`} will be PERMANENTLY deleted and CANNOT be restored \u2014 there is no decrypted copy. Continue?`,"Delete forever",async i=>{if(i){for(let s of e)await this.plugin.purgeDeletedAt(s);this.clearSelection(),await this.render()}},"Cancel",!0).open()}async onClose(){this.contentEl.empty()}};async function El(d){let{workspace:a}=d.app,e=a.getLeavesOfType(Xt);if(e.length>0){a.revealLeaf(e[0]);return}let t=a.getMostRecentLeaf(),i=a.getLeaf("tab");await i.setViewState({type:Xt,active:!0}),a.revealLeaf(i),gt(a,i,t,s=>d.registerEvent(s))}var Vt=require("obsidian"),Is=class Is{constructor(a){this.plugin=a;this.tick=null;this.lastTouch=new Map;this.counting=new Set;this.countdownTimers=new Set}key(a,e){return`${a} ${e}`}delayMin(a){let e=a.peekMin;if(e!=null)return e;let i=(this.plugin.settings.folderEncPrefs??{})[a.folder.replace(/\/+$/,"")]?.reEncryptAfterMin;return i??this.plugin.settings.reEncryptAfterMin??0}anyArmed(){if((this.plugin.settings.reEncryptAfterMin??0)>0)return!0;for(let a of Object.values(this.plugin.settings.folderEncPrefs??{}))if((a?.reEncryptAfterMin??0)>0)return!0;return this.plugin.reEncryptWatching().some(a=>(a.peekMin??0)>0)}start(){let a=e=>{e&&this.lastTouch.set(e.replace(/\/+$/,""),Date.now())};this.plugin.registerEvent(this.plugin.app.vault.on("modify",e=>{e instanceof Vt.TFile&&a(e.parent?.path??"")})),this.plugin.registerEvent(this.plugin.app.workspace.on("file-open",e=>{e&&a(e.parent?.path??"")})),this.tick=window.setInterval(()=>void this.poll(),3e4),this.plugin.registerInterval(this.tick)}folderHasOpenEditor(a){let e=a.replace(/\/+$/,""),t=!1;return this.plugin.app.workspace.iterateAllLeaves(i=>{let s=i.view;s instanceof Vt.MarkdownView&&s.file&&(s.file.parent?.path?.replace(/\/+$/,"")??"")===e&&(t=!0)}),t}keyReady(a){let e=this.plugin.encryption;return e?.isConfigured?.()?e.hasFolderKey(a)&&e.isFolderUnlocked(a):!1}async poll(){if(!this.anyArmed())return;let a=Date.now();for(let e of this.plugin.reEncryptWatching()){let t=this.delayMin(e);if(t<=0)continue;let i=e.folder.replace(/\/+$/,""),s=this.key(i,e.rootId);if(this.counting.has(s))continue;let n=Math.max(Date.parse(e.unlockedAt)||0,this.lastTouch.get(i)??0);if(!(a<n+t*6e4)&&this.keyReady(i)){if(this.folderHasOpenEditor(i)){Qd(this.lastTouch,i,a);continue}this.countdownThenLock(e,s)}}}countdownThenLock(a,e){this.counting.add(e);let t=a.folder.replace(/\/+$/,""),i=a.title||"a note",s=Date.now(),n=Is.COUNTDOWN_SECS,o=!1,r=new Vt.Notice("",0),l=()=>{window.clearInterval(h),this.countdownTimers.delete(h),r.hide(),this.counting.delete(e)},c=()=>{this.lastTouch.set(t,Date.now()),l()},A=()=>{r.noticeEl.empty(),r.noticeEl.createSpan({text:`\u{1F512} Re-encrypting \u201C${i}\u201D in ${n}s\u2026 `}),r.noticeEl.createEl("button",{text:"Keep unlocked"}).onclick=()=>{o=!0,c()}};A();let h=window.setInterval(async()=>{if(o)return;if((this.lastTouch.get(t)??0)>s){c();return}if(n-=1,n>0){A();return}if(l(),!this.plugin.reEncryptWatching().some(u=>u.folder===a.folder&&u.rootId===a.rootId))return;if(this.folderHasOpenEditor(t)){this.lastTouch.set(t,Date.now());return}if(!this.keyReady(t)){this.lastTouch.set(t,Date.now());return}await this.plugin.lockNoteSubtree(a.folder,a.rootId,null,{silent:!0})&&new Vt.Notice(`Re-encrypted \u201C${i}\u201D.`)},1e3);this.countdownTimers.add(h),this.plugin.registerInterval(h)}dispose(){for(let a of this.countdownTimers)window.clearInterval(a);this.countdownTimers.clear(),this.counting.clear()}};Is.COUNTDOWN_SECS=10,Is.RECENT_EDIT_MS=2e4;var Pn=Is;function Qd(d,a,e){d.set(a.replace(/\/+$/,""),e)}le();var W=require("obsidian");le();me();var Hn=class d extends W.ItemView{constructor(e,t){super(e);this.plugin=t;this.renderTimer=null;this.dividerCleanup=null;this.pinExpanded=new Set;this.folderPinExpanded=new Set;this.homeColorByFolder=new Map}getViewType(){return yt}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()))}refresh(){this.scheduleRender()}scheduleRender(){this.renderTimer==null&&(this.renderTimer=window.setTimeout(()=>{this.renderTimer=null,this.containerEl.isConnected&&this.render()},100))}render(){let e=this.contentEl;e.empty(),e.addClass("stashpad-folderpanel-root");let t=this.clampFrac(this.plugin.settings.folderPanelPinnedFraction??.5),i=e.createDiv({cls:"stashpad-folderpanel-section stashpad-folderpanel-pinned"});i.style.flex=`0 0 ${(t*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,W.setIcon)(n,"list"),n.setAttr("aria-label","Pinned view options"),n.onclick=h=>{h.stopPropagation(),this.openPinnedOptionsMenu(h)},this.renderPinned(i.createDiv({cls:"stashpad-folderpanel-list stashpad-folderpanel-pins"}));let o=e.createDiv({cls:"stashpad-folderpanel-divider"});o.createDiv({cls:"stashpad-folderpanel-divider-grip"}),this.attachDividerDrag(e,i,o);let r=e.createDiv({cls:"stashpad-folderpanel-section stashpad-folderpanel-folders"});r.setCssStyles({flex:"1 1 0"});let l=r.createDiv({cls:"stashpad-folderpanel-heading stashpad-folderpanel-heading-row"}),c=l.createSpan({cls:"stashpad-folderpanel-heading-title stashpad-folderpanel-heading-switch",text:"Folders"});c.setAttr("aria-label","Open folder switcher"),c.onmousedown=h=>{h.button===0&&(h.preventDefault(),this.plugin.openFolderPicker())};let A=l.createEl("button",{cls:"stashpad-folderpanel-iconbtn stashpad-folderpanel-heading-newfolder"});if((0,W.setIcon)(A,"folder-plus"),A.setAttr("aria-label","New Stashpad folder (folder switcher)"),A.onmousedown=h=>{h.button===0&&(h.preventDefault(),h.stopPropagation(),this.plugin.openFolderPicker())},this.plugin.encryption?.isConfigured?.()){let h=l.createEl("button",{cls:"stashpad-folderpanel-iconbtn stashpad-folderpanel-heading-trash"});(0,W.setIcon)(h,"trash-2"),h.setAttr("aria-label","Open encrypted trash"),h.onmousedown=p=>{p.button===0&&(p.preventDefault(),p.stopPropagation(),this.plugin.openEncryptedTrash())}}this.renderFolders(r.createDiv({cls:"stashpad-folderpanel-list"}))}clampFrac(e){return Number.isFinite(e)?Math.max(.15,Math.min(.85,e)):.5}attachDividerDrag(e,t,i){let s=null,n=l=>{let c=e.getBoundingClientRect();if(c.height<=0)return;let A=this.clampFrac((l.clientY-c.top)/c.height);s=A,t.style.flex=`0 0 ${(A*100).toFixed(2)}%`},o=()=>{document.removeEventListener("pointermove",n),document.removeEventListener("pointerup",r),document.removeEventListener("pointercancel",r),document.body.removeClass("stashpad-folderpanel-resizing"),this.dividerCleanup=null},r=l=>{try{i.releasePointerCapture(l.pointerId)}catch{}l.type==="pointerup"&&s!=null&&(this.plugin.settings.folderPanelPinnedFraction=s,this.plugin.saveSettings()),o()};this.registerDomEvent(i,"pointerdown",l=>{l.preventDefault(),document.body.addClass("stashpad-folderpanel-resizing");try{i.setPointerCapture(l.pointerId)}catch{}document.addEventListener("pointermove",n),document.addEventListener("pointerup",r),document.addEventListener("pointercancel",r),this.dividerCleanup=o})}openPinnedOptionsMenu(e){let t=this.plugin.settings.folderPanelPinnedGrouping??"pin-order",i=new W.Menu;i.addItem(s=>s.setTitle("Sort by pin order").setChecked(t==="pin-order").onClick(()=>void this.setPinnedGrouping("pin-order"))),i.addItem(s=>s.setTitle("Group by folder").setChecked(t==="folder").onClick(()=>void this.setPinnedGrouping("folder"))),i.showAtMouseEvent(e)}async setPinnedGrouping(e){(this.plugin.settings.folderPanelPinnedGrouping??"pin-order")!==e&&(this.plugin.settings.folderPanelPinnedGrouping=e,await this.plugin.saveSettings(),this.render())}renderPinned(e){let t=this.plugin.discoverStashpadFolders().filter(n=>this.folderState(n)==="pinned"),i=this.plugin.listPinnedNotes();if(t.length===0&&i.length===0){e.createDiv({cls:"stashpad-folderpanel-empty",text:"Nothing pinned yet \u2014 pin a note or folder from its right-click menu."});return}if(t.length>0){let n=this.openFolders();for(let o of t)this.renderFolderRow(e,o,n)}if(i.length===0)return;if((this.plugin.settings.folderPanelPinnedGrouping??"pin-order")==="folder"){let n=new Map;i.forEach((l,c)=>{let A=n.get(l.folder);A||(A=[],n.set(l.folder,A)),A.push({...l,idx:c})});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 l of r){let c=e.createDiv({cls:"stashpad-pinned-group-header"});l===o&&c.addClass("is-active-folder"),c.createSpan({cls:"stashpad-pinned-group-name",text:l.split("/").pop()||l});for(let A of n.get(l)??[])this.renderPinNote(e,A.folder,A.id,A.file,A.idx)}}else i.forEach((n,o)=>this.renderPinNote(e,n.folder,n.id,n.file,o))}async reorderPin(e,t){let i=this.plugin.listPinnedNotes();if(e<0||e>=i.length)return;let s=i[e],n=i.filter((A,h)=>h!==e),o=Math.max(0,Math.min(t>e?t-1:t,n.length)),r=n[o-1],l=n[o],c;!r&&!l?c=Date.now():r?l?c=(r.pinnedAt+l.pinnedAt)/2:c=r.pinnedAt+1e3:c=l.pinnedAt-1e3;try{await this.app.fileManager.processFrontMatter(s.file,A=>{A.pinnedAt=c})}catch(A){console.warn("[Stashpad] pin reorder failed",A)}this.render()}renderPinNote(e,t,i,s,n){let o=this.app.metadataCache.getFileCache(s)?.frontmatter??{},r=typeof o.color=="string"?o.color:null,l=o.completed===!0,c=this.childrenOf(t,i),A=c.length>0,h=`${t}|${i}`,p=this.pinExpanded.has(h),u=e.createDiv({cls:"stashpad-pinned-row"});r&&(u.addClass("has-color"),u.style.setProperty("--stashpad-note-color",r)),l&&u.addClass("is-completed"),u.draggable=!0,u.dataset.pinIdx=String(n),u.addEventListener("dragstart",m=>{m.dataTransfer?.setData("text/plain",String(n)),m.dataTransfer&&(m.dataTransfer.effectAllowed="move"),u.addClass("is-dragging")}),u.addEventListener("dragend",()=>u.removeClass("is-dragging")),u.addEventListener("dragover",m=>{m.preventDefault(),m.dataTransfer&&(m.dataTransfer.dropEffect="move");let B=u.getBoundingClientRect(),C=m.clientY-B.top<B.height/2;u.toggleClass("drop-before",C),u.toggleClass("drop-after",!C)}),u.addEventListener("dragleave",()=>{u.removeClass("drop-before"),u.removeClass("drop-after")}),u.addEventListener("drop",m=>{m.preventDefault(),u.removeClass("drop-before"),u.removeClass("drop-after");let B=parseInt(m.dataTransfer?.getData("text/plain")??"",10);if(!Number.isFinite(B)||B===n)return;let C=u.getBoundingClientRect(),Q=m.clientY-C.top<C.height/2;this.reorderPin(B,Q?n:n+1)});let f=u.createSpan({cls:"stashpad-pinned-toggle"});A&&(Qt(f,c.length,p),f.onclick=m=>{m.stopPropagation(),this.pinExpanded.has(h)?this.pinExpanded.delete(h):this.pinExpanded.add(h),this.render()});let g=u.createSpan({cls:"stashpad-pinned-icon"});(0,W.setIcon)(g,A?"folder-tree":"file-text"),r&&(g.style.color=r);let I=u.createSpan({cls:"stashpad-pinned-label",text:this.titleFromFile(s)});if(I.onclick=()=>{this.onNavigateAway(),this.plugin.revealNoteInStashpad(s)},u.createSpan({cls:"stashpad-pinned-folder",text:t.split("/").pop()||t}),u.oncontextmenu=m=>{m.preventDefault();let B=new W.Menu;B.addItem(C=>C.setTitle("Unpin from sidebar").setIcon("pin-off").onClick(()=>void this.plugin.unpinNote({folder:t,id:i}))),B.showAtMouseEvent(m)},A&&p){let m=e.createDiv({cls:"stashpad-pinned-children"});this.renderPinSubtree(m,t,i,1)}}renderPinSubtree(e,t,i,s){for(let n of this.childrenOf(t,i)){let o=this.app.metadataCache.getFileCache(n)?.frontmatter??{},r=typeof o.id=="string"?o.id:null;if(!r)continue;let l=typeof o.color=="string"?o.color:null,c=o.completed===!0,A=this.childrenOf(t,r),h=A.length>0,p=`${t}|${r}`,u=this.pinExpanded.has(p),f=e.createDiv({cls:"stashpad-pinned-subrow"});c&&f.addClass("is-completed"),f.style.paddingLeft=`${s*16}px`;let g=f.createSpan({cls:"stashpad-pinned-toggle"});h&&(Qt(g,A.length,u),g.onclick=B=>{B.stopPropagation(),this.pinExpanded.has(p)?this.pinExpanded.delete(p):this.pinExpanded.add(p),this.render()});let I=f.createSpan({cls:"stashpad-pinned-icon"});(0,W.setIcon)(I,"file-text"),l&&(I.style.color=l);let m=f.createSpan({cls:"stashpad-pinned-label",text:this.titleFromFile(n)});m.onclick=()=>{this.onNavigateAway(),this.plugin.revealNoteInStashpad(n)},h&&u&&this.renderPinSubtree(e,t,r,s+1)}}childrenOf(e,t){let i=[];for(let s of this.app.vault.getMarkdownFiles()){if((s.parent?.path?.replace(/\/+$/,"")??"")!==e)continue;let o=this.app.metadataCache.getFileCache(s)?.frontmatter;if(!o||typeof o.id!="string")continue;let r=o.parent;if(r===t||t===k&&(r==null||r===k)){if(o.id===k)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(){W.Platform.isMobile&&(this.plugin.suppressComposerAutofocusUntil=Date.now()+1500,this.app.workspace.leftSplit?.collapse?.())}titleFromFile(e){return e.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||e.basename}openFolders(){let e=new Set,t=(this.plugin.settings.folder||"Stashpad").replace(/\/+$/,"");for(let i of this.app.workspace.getLeavesOfType(z)){let s=(i.view?.noteFolder??"").replace(/\/+$/,"");s||(s=(((i.getViewState?.()?.state??{}).folderOverride??"")||t).replace(/\/+$/,"")),s&&e.add(s)}return e}static clean(e){return e.replace(/\/+$/,"")}folderState(e){let t=d.clean(e),i=this.plugin.settings;return(i.folderPanelPinned??[]).includes(t)?"pinned":(i.folderPanelDownranked??[]).includes(t)?"downranked":(i.folderPanelHidden??[]).includes(t)?"hidden":"normal"}async setFolderState(e,t){let i=d.clean(e),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),t==="pinned"?s.folderPanelPinned.push(i):t==="downranked"?s.folderPanelDownranked.push(i):t==="hidden"&&s.folderPanelHidden.push(i),await this.plugin.saveSettings(),this.render()}folderHomeColor(e){return this.homeColorByFolder.get(d.clean(e))??null}rebuildHomeColors(){this.homeColorByFolder.clear();for(let e of this.app.vault.getMarkdownFiles()){let t=this.app.metadataCache.getFileCache(e)?.frontmatter;if(!t||t.id!==k||typeof t.color!="string"||!t.color.trim())continue;let i=(e.parent?.path??"").replace(/\/+$/,"");i&&this.homeColorByFolder.set(i,t.color)}}renderFolders(e){let t=this.plugin.discoverStashpadFolders();if(t.length===0){e.createDiv({cls:"stashpad-folderpanel-empty",text:"No Stashpad folders yet."});return}this.rebuildHomeColors();let i=this.openFolders(),s=[],n=[],o=[],r=[];for(let c of t)switch(this.folderState(c)){case"pinned":s.push(c);break;case"downranked":o.push(c);break;case"hidden":r.push(c);break;default:n.push(c)}let l=[...s,...n,...o];if(l.length===0&&r.length===0){e.createDiv({cls:"stashpad-folderpanel-empty",text:"No Stashpad folders yet."});return}for(let c of l)this.renderFolderRow(e,c,i);r.length>0&&this.renderHiddenSection(e,r)}renderFolderRow(e,t,i){let s=this.folderState(t),n=i.has(d.clean(t)),o=e.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 m=o.createSpan({cls:"stashpad-folderpanel-pinmark"});(0,W.setIcon)(m,"pin"),m.setAttr("aria-label","Pinned")}let l=this.folderHomePinnedNotes(t),c=d.clean(t),A=this.folderPinExpanded.has(c);if(l.length>0){let m=o.createSpan({cls:"stashpad-folderpanel-pinreveal"});Qt(m,l.length,A),m.setAttr("aria-label",A?"Hide pinned notes":`${l.length} pinned note${l.length===1?"":"s"}`),m.addEventListener("mousedown",B=>{B.stopPropagation(),B.preventDefault()}),m.onclick=B=>{B.stopPropagation(),this.folderPinExpanded.has(c)?this.folderPinExpanded.delete(c):this.folderPinExpanded.add(c),this.render()}}let h=this.plugin.isArchiveFolder(t),p=o.createSpan({cls:"stashpad-folderpanel-folder-icon"});(0,W.setIcon)(p,this.plugin.getFolderIcon(t)??(h?"archive":"folder")),h&&p.setAttr("aria-label","Archive folder \u2014 de-indexed from search");let u=this.folderHomeColor(t);u&&(p.style.color=u);let f=t.split("/").pop()||t;o.createSpan({cls:"stashpad-folderpanel-row-label",text:f});let I=o.createDiv({cls:"stashpad-folderpanel-actions"}).createEl("button",{cls:"stashpad-folderpanel-iconbtn"});if((0,W.setIcon)(I,"plus-square"),I.setAttr("aria-label","Open in new tab"),I.onmousedown=m=>{m.button===0&&(m.preventDefault(),m.stopPropagation(),this.onNavigateAway(),this.plugin.activateViewForFolder(t))},o.addEventListener("mousedown",m=>{m.button===0&&(m.target?.closest?.(".stashpad-folderpanel-actions")||(this.onNavigateAway(),this.jumpToFolder(t)))}),o.oncontextmenu=m=>{m.preventDefault(),this.openFolderMenu(m,t)},l.length>0&&A){let m=e.createDiv({cls:"stashpad-folderpanel-pinlist"});for(let B of l){let C=m.createDiv({cls:"stashpad-folderpanel-pinrow"}),Q=this.app.metadataCache.getFileCache(B)?.frontmatter??{},y=C.createSpan({cls:"stashpad-folderpanel-pinrow-icon"});(0,W.setIcon)(y,"arrow-up-to-line"),typeof Q.color=="string"&&(y.style.color=Q.color),C.createSpan({cls:"stashpad-folderpanel-pinrow-label",text:this.titleFromFile(B)}),C.onclick=()=>{this.onNavigateAway(),this.plugin.revealNoteInStashpad(B)}}}}folderHomePinnedNotes(e){return this.childrenOf(e,k).filter(t=>this.app.metadataCache.getFileCache(t)?.frontmatter?.listPinned===!0)}renderHiddenSection(e,t){let i=e.createDiv({cls:"stashpad-folderpanel-hidden"}),s=i.createDiv({cls:"stashpad-folderpanel-hidden-header"}),n=s.createSpan({cls:"stashpad-folderpanel-hidden-caret"});(0,W.setIcon)(n,"chevron-right"),s.createSpan({cls:"stashpad-folderpanel-hidden-title",text:`Hidden (${t.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,W.setIcon)(n,r?"chevron-right":"chevron-down")};for(let r of t){let l=o.createDiv({cls:"stashpad-folderpanel-row stashpad-folderpanel-hidden-row"}),c=r.split("/").pop()||r;l.createSpan({cls:"stashpad-folderpanel-row-label",text:c});let A=l.createEl("button",{cls:"stashpad-folderpanel-iconbtn"});(0,W.setIcon)(A,"eye"),A.setAttr("aria-label","Unhide"),A.onclick=h=>{h.stopPropagation(),this.setFolderState(r,"normal")}}}jumpToFolder(e){this.plugin.openFolderInStashpad(e)}revealFolder(e){let t=this.app.vault.getAbstractFileByPath(e.replace(/\/+$/,""));if(!(t instanceof W.TFolder)){new W.Notice("Couldn't find that folder.");return}let i=this.app.workspace.getLeavesOfType("file-explorer")[0];if(!i){new W.Notice("File explorer isn't available.");return}this.app.workspace.revealLeaf(i),i.view?.revealInFolder?.(t)}openFolderMenu(e,t){let i=new W.Menu;i.addItem(n=>n.setTitle("Open in new tab").setIcon("plus-square").onClick(()=>void this.plugin.activateViewForFolder(t))),i.addItem(n=>n.setTitle("Reveal in file explorer").setIcon("folder-search").onClick(()=>this.revealFolder(t))),i.addSeparator();let s=this.folderState(t);i.addItem(n=>n.setTitle(s==="pinned"?"Unpin":"Pin to top").setIcon("pin").onClick(()=>void this.setFolderState(t,s==="pinned"?"normal":"pinned"))),i.addItem(n=>n.setTitle(s==="downranked"?"Remove downrank":"Downrank").setIcon("arrow-down").onClick(()=>void this.setFolderState(t,s==="downranked"?"normal":"downranked"))),i.addItem(n=>n.setTitle("Hide from list").setIcon("eye-off").onClick(()=>void this.setFolderState(t,"hidden"))),i.addSeparator(),i.addItem(n=>n.setTitle("Rename\u2026").setIcon("pencil").onClick(()=>this.renameFolder(t))),this.plugin.encryption?.isConfigured?.()&&(i.addSeparator(),i.addItem(n=>n.setTitle("Encrypt (lock) all notes in folder").setIcon("lock").onClick(()=>void this.plugin.lockFolder(t))),this.app.vault.getFiles().some(n=>n.extension==="stashenc"&&(n.parent?.path?.replace(/\/+$/,"")??"")===t.replace(/\/+$/,""))&&i.addItem(n=>n.setTitle("Decrypt (unlock) all notes in folder").setIcon("unlock").onClick(()=>void this.plugin.unlockFolder(t))),i.addItem(n=>n.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(t)),n.setWarning?.(!0)}),i.showAtMouseEvent(e)}renameFolder(e){let t=e.replace(/\/+$/,""),i=this.app.vault.getAbstractFileByPath(t);if(!(i instanceof W.TFolder)){new W.Notice("Couldn't find that folder.");return}let s=i.name;new cr(this.app,s,async n=>{let o=n.trim().replace(/[\\/:]+/g,"").trim();if(!o||o===s)return;let l=`${i.parent?.path&&i.parent.path!=="/"?`${i.parent.path}/`:""}${o}`;if(this.app.vault.getAbstractFileByPath(l)){new W.Notice(`"${o}" already exists.`);return}if(!(this.app.vault.getAbstractFileByPath(t)instanceof W.TFolder)){new W.Notice("That folder no longer exists.");return}try{await this.app.fileManager.renameFile(i,l),await this.plugin.remapFolderPathInSettings(t,l),new W.Notice(`Renamed to "${o}".`)}catch(c){console.warn("[Stashpad] folder rename failed",c),new W.Notice("Rename failed (see console).")}}).open()}deleteFolder(e){let t=e.replace(/\/+$/,""),i=this.app.vault.getAbstractFileByPath(t);if(!(i instanceof W.TFolder)){new W.Notice("Couldn't find that folder.");return}let s=this.app.vault.getMarkdownFiles().filter(o=>(o.parent?.path?.replace(/\/+$/,"")??"")===t||o.path.startsWith(t+"/")).length,n=i.name;new _(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()}async onClose(){this.dividerCleanup?.(),this.contentEl.empty()}},cr=class extends W.Modal{constructor(e,t,i){super(e);this.current=t;this.onSubmit=i;this.delivered=!1}onOpen(){this.modalEl.addClass("stashpad-compact-modal"),this.contentEl.empty(),this.titleEl.setText("Rename folder");let e=this.contentEl.createEl("input",{type:"text"});e.addClass("stashpad-folderpanel-rename-input"),e.value=this.current;let t=this.contentEl.createDiv({cls:"stashpad-folderpanel-rename-footer"});t.createEl("button",{text:"Cancel"}).onclick=()=>this.close();let i=t.createEl("button",{cls:"mod-cta",text:"Rename"}),s=()=>{this.delivered=!0;let n=e.value;this.close(),this.onSubmit(n)};i.onclick=s,this.scope.register([],"Enter",n=>{n.preventDefault(),e.value.trim()&&s()}),requestAnimationFrame(()=>{e.focus(),e.select()})}onClose(){this.contentEl.empty()}};async function Rn(d){let a=d.workspace.getLeavesOfType(yt);if(a.length>0){d.workspace.revealLeaf(a[0]);return}let e=d.workspace.getLeftLeaf(!1);if(!e){new W.Notice("Stashpad: couldn't open the folder panel.");return}await e.setViewState({type:yt,active:!0}),d.workspace.revealLeaf(e)}me();ai();le();var dr="OKF Template.md",vd=`--- okfType: concept --- {{body}} -`,cr=["> 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 Is(d){return d.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||d.basename}function Bl(d){return`[${Is(d)}](${encodeURI(d.name)})`}async function yl(d,a=lr){try{await d.vault.adapter.exists(a)||await d.vault.create(a,yd)}catch{}return a}function wl(d,a){if(!a)return[];let e=a.replace(/^\/+/,"");return Object.entries(d??{}).filter(([,t])=>(t??"").replace(/^\/+/,"")===e).map(([t])=>t.replace(/\/+$/,""))}async function dr(d,a){let e=a.replace(/\/+$/,""),t=new Map,i=new Map;for(let o of d.vault.getMarkdownFiles()){if((o.parent?.path?.replace(/\/+$/,"")??"")!==e)continue;let r;try{r=de(await d.vault.read(o)).fm}catch{continue}let l=typeof r.id=="string"?r.id:null;if(!l)continue;let c=typeof r.parent=="string"?r.parent:S;t.set(l,{file:o,id:l,parent:c,modified:typeof r.modified=="string"?r.modified:"",created:typeof r.created=="string"?r.created:""});let A=i.get(c)??[];A.push(l),i.set(c,A)}let s=0,n=0;for(let o of t.values()){if(o.id===S)continue;s+=1;let r=o.parent&&o.parent!==S&&t.get(o.parent)?Bl(t.get(o.parent).file):null,l=(i.get(o.id)??[]).map(c=>t.get(c)).filter(c=>!!c).map(c=>Bl(c.file));try{let c=!1;await d.fileManager.processFrontMatter(o.file,A=>{r?A.okfParent!==r&&(A.okfParent=r,c=!0):A.okfParent!==void 0&&(delete A.okfParent,c=!0);let h=Array.isArray(A.okfChildren)?A.okfChildren:[],g=h.length===l.length&&h.every((u,f)=>u===l[f]);if(l.length?g||(A.okfChildren=l,c=!0):A.okfChildren!==void 0&&(delete A.okfChildren,c=!0),A.okfType===void 0&&(A.okfType="concept",c=!0),A.okfTitle===void 0&&(A.okfTitle=Is(o.file),c=!0),A.okfTimestamp===void 0){let u=o.modified||o.created;u&&(A.okfTimestamp=u,c=!0)}}),c&&(n+=1,await new Promise(A=>setTimeout(A,50)))}catch(c){console.warn("[Stashpad] OKF rebuild failed",o.file.path,c)}}try{await d.vault.adapter.write(`${e}/index.md`,await Ar(d,e))}catch(o){console.warn("[Stashpad] OKF index.md write failed",e,o)}return{checked:s,written:n}}async function Ar(d,a,e){let t=a.replace(/\/+$/,""),i=new Map,s=new Map;for(let A of d.vault.getMarkdownFiles()){if((A.parent?.path?.replace(/\/+$/,"")??"")!==t||A.name==="index.md")continue;let h;try{h=de(await d.vault.read(A)).fm}catch{continue}let g=typeof h.id=="string"?h.id:null;!g||g===S||e&&!e.has(g)||i.set(g,{id:g,file:A,parent:typeof h.parent=="string"?h.parent:S,title:typeof h.okfTitle=="string"&&h.okfTitle?h.okfTitle:Is(A),type:typeof h.okfType=="string"&&h.okfType?h.okfType:"concept",position:typeof h.position=="number"?h.position:Number.MAX_SAFE_INTEGER,created:typeof h.created=="string"?h.created:""})}for(let A of i.values()){let h=s.get(A.parent)??[];h.push(A),s.set(A.parent,h)}for(let A of s.values())A.sort((h,g)=>h.position-g.position||h.created.localeCompare(g.created));let n=[],o=(A,h,g)=>{if(!g.has(A.id)){g.add(A.id),n.push(`${" ".repeat(h)}- [${A.title}](${encodeURI(A.file.name)}) \u2014 ${A.type}`);for(let u of s.get(A.id)??[])o(u,h+1,g)}},r=new Set,l=[...i.values()].filter(A=>A.parent===S||!i.has(A.parent)).sort((A,h)=>A.position-h.position||A.created.localeCompare(h.created));for(let A of l)o(A,0,r);let c=t.split("/").pop()||t;return["---","type: index",`title: ${c} (OKF index)`,"---","",`# ${c}`,"",cr,"","## Concepts",n.length?n.join(` +`,Ar=["> 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 ms(d){return d.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||d.basename}function Ql(d){return`[${ms(d)}](${encodeURI(d.name)})`}async function vl(d,a=dr){try{await d.vault.adapter.exists(a)||await d.vault.create(a,vd)}catch{}return a}function Fl(d,a){if(!a)return[];let e=a.replace(/^\/+/,"");return Object.entries(d??{}).filter(([,t])=>(t??"").replace(/^\/+/,"")===e).map(([t])=>t.replace(/\/+$/,""))}async function hr(d,a){let e=a.replace(/\/+$/,""),t=new Map,i=new Map;for(let o of d.vault.getMarkdownFiles()){if((o.parent?.path?.replace(/\/+$/,"")??"")!==e)continue;let r;try{r=Ae(await d.vault.read(o)).fm}catch{continue}let l=typeof r.id=="string"?r.id:null;if(!l)continue;let c=typeof r.parent=="string"?r.parent:k;t.set(l,{file:o,id:l,parent:c,modified:typeof r.modified=="string"?r.modified:"",created:typeof r.created=="string"?r.created:""});let A=i.get(c)??[];A.push(l),i.set(c,A)}let s=0,n=0;for(let o of t.values()){if(o.id===k)continue;s+=1;let r=o.parent&&o.parent!==k&&t.get(o.parent)?Ql(t.get(o.parent).file):null,l=(i.get(o.id)??[]).map(c=>t.get(c)).filter(c=>!!c).map(c=>Ql(c.file));try{let c=!1;await d.fileManager.processFrontMatter(o.file,A=>{r?A.okfParent!==r&&(A.okfParent=r,c=!0):A.okfParent!==void 0&&(delete A.okfParent,c=!0);let h=Array.isArray(A.okfChildren)?A.okfChildren:[],p=h.length===l.length&&h.every((u,f)=>u===l[f]);if(l.length?p||(A.okfChildren=l,c=!0):A.okfChildren!==void 0&&(delete A.okfChildren,c=!0),A.okfType===void 0&&(A.okfType="concept",c=!0),A.okfTitle===void 0&&(A.okfTitle=ms(o.file),c=!0),A.okfTimestamp===void 0){let u=o.modified||o.created;u&&(A.okfTimestamp=u,c=!0)}}),c&&(n+=1,await new Promise(A=>setTimeout(A,50)))}catch(c){console.warn("[Stashpad] OKF rebuild failed",o.file.path,c)}}try{await d.vault.adapter.write(`${e}/index.md`,await pr(d,e))}catch(o){console.warn("[Stashpad] OKF index.md write failed",e,o)}return{checked:s,written:n}}async function pr(d,a,e){let t=a.replace(/\/+$/,""),i=new Map,s=new Map;for(let A of d.vault.getMarkdownFiles()){if((A.parent?.path?.replace(/\/+$/,"")??"")!==t||A.name==="index.md")continue;let h;try{h=Ae(await d.vault.read(A)).fm}catch{continue}let p=typeof h.id=="string"?h.id:null;!p||p===k||e&&!e.has(p)||i.set(p,{id:p,file:A,parent:typeof h.parent=="string"?h.parent:k,title:typeof h.okfTitle=="string"&&h.okfTitle?h.okfTitle:ms(A),type:typeof h.okfType=="string"&&h.okfType?h.okfType:"concept",position:typeof h.position=="number"?h.position:Number.MAX_SAFE_INTEGER,created:typeof h.created=="string"?h.created:""})}for(let A of i.values()){let h=s.get(A.parent)??[];h.push(A),s.set(A.parent,h)}for(let A of s.values())A.sort((h,p)=>h.position-p.position||h.created.localeCompare(p.created));let n=[],o=(A,h,p)=>{if(!p.has(A.id)){p.add(A.id),n.push(`${" ".repeat(h)}- [${A.title}](${encodeURI(A.file.name)}) \u2014 ${A.type}`);for(let u of s.get(A.id)??[])o(u,h+1,p)}},r=new Set,l=[...i.values()].filter(A=>A.parent===k||!i.has(A.parent)).sort((A,h)=>A.position-h.position||A.created.localeCompare(h.created));for(let A of l)o(A,0,r);let c=t.split("/").pop()||t;return["---","type: index",`title: ${c} (OKF index)`,"---","",`# ${c}`,"",Ar,"","## Concepts",n.length?n.join(` `):"_No concepts yet._",""].join(` -`)}var wd=new TextEncoder,Pn=d=>wd.encode(d);function ms(d){if(typeof d=="number"||typeof d=="boolean")return String(d);let a=String(d??"");return/[:#[\]{}",&*!|>%@`]|^\s|\s$|^$/.test(a)?JSON.stringify(a):a}function Ed(d,a){let{fm:e}=de(d),t=[];t.push(`type: ${ms(typeof e.okfType=="string"&&e.okfType?e.okfType:"concept")}`),t.push(`title: ${ms(typeof e.okfTitle=="string"&&e.okfTitle?e.okfTitle:Is(a))}`),typeof e.okfDescription=="string"&&e.okfDescription&&t.push(`description: ${ms(e.okfDescription)}`);let i=e.okfTags;if(Array.isArray(i)&&i.length){t.push("tags:");for(let r of i)t.push(` - ${ms(r)}`)}let s=typeof e.okfTimestamp=="string"&&e.okfTimestamp||typeof e.modified=="string"&&e.modified||typeof e.created=="string"&&e.created||"";s&&t.push(`timestamp: ${ms(s)}`);let n=t.join(` +`)}var Fd=new TextEncoder,Un=d=>Fd.encode(d);function Cs(d){if(typeof d=="number"||typeof d=="boolean")return String(d);let a=String(d??"");return/[:#[\]{}",&*!|>%@`]|^\s|\s$|^$/.test(a)?JSON.stringify(a):a}function kd(d,a){let{fm:e}=Ae(d),t=[];t.push(`type: ${Cs(typeof e.okfType=="string"&&e.okfType?e.okfType:"concept")}`),t.push(`title: ${Cs(typeof e.okfTitle=="string"&&e.okfTitle?e.okfTitle:ms(a))}`),typeof e.okfDescription=="string"&&e.okfDescription&&t.push(`description: ${Cs(e.okfDescription)}`);let i=e.okfTags;if(Array.isArray(i)&&i.length){t.push("tags:");for(let r of i)t.push(` - ${Cs(r)}`)}let s=typeof e.okfTimestamp=="string"&&e.okfTimestamp||typeof e.modified=="string"&&e.modified||typeof e.created=="string"&&e.created||"";s&&t.push(`timestamp: ${Cs(s)}`);let n=t.join(` `),o=d.match(/^---\r?\n/);return o?d.slice(0,o[0].length)+n+` `+d.slice(o[0].length):`--- ${n} --- -${d}`}async function El(d,a,e,t){let i=[],s=new Map;for(let n of a){let o=await d.vault.read(n);i.push({name:n.name,data:Pn(Ed(o,n))});for(let r of o.match(/!\[\[([^\]]+?)\]\]/g)??[]){let l=r.slice(3,-2).split("|")[0].split("#")[0].trim(),c=d.metadataCache.getFirstLinkpathDest(l,n.path);c&&!s.has(c.name)&&s.set(c.name,c)}}for(let[n,o]of s)i.push({name:`_attachments/${n}`,data:new Uint8Array(await d.vault.readBinary(o))});return i.push({name:"index.md",data:Pn(await Ar(d,e,t))}),i.push({name:"_okf.md",data:Pn(`# About this bundle +${d}`}async function kl(d,a,e,t){let i=[],s=new Map;for(let n of a){let o=await d.vault.read(n);i.push({name:n.name,data:Un(kd(o,n))});for(let r of o.match(/!\[\[([^\]]+?)\]\]/g)??[]){let l=r.slice(3,-2).split("|")[0].split("#")[0].trim(),c=d.metadataCache.getFirstLinkpathDest(l,n.path);c&&!s.has(c.name)&&s.set(c.name,c)}}for(let[n,o]of s)i.push({name:`_attachments/${n}`,data:new Uint8Array(await d.vault.readBinary(o))});return i.push({name:"index.md",data:Un(await pr(d,e,t))}),i.push({name:"_okf.md",data:Un(`# About this bundle -${cr.replace(/^> /gm,"")} -`)}),i}async function Ql(d){let{zipFiles:a}=await Promise.resolve().then(()=>(yn(),Va));return a(d.map(e=>({name:e.name,data:e.data})))}function vi(d,a){return d.toString(8).padStart(a-1,"0")+"\0"}function Qd(d,a){let e=new Uint8Array(512),t=(s,n,o)=>{let r=Pn(s);e.set(r.subarray(0,o),n)};t(d.slice(0,100),0,100),t(vi(420,8),100,8),t(vi(0,8),108,8),t(vi(0,8),116,8),t(vi(a,12),124,12),t(vi(0,12),136,12),t(" ",148,8),e[156]=48,t("ustar\0",257,6),t("00",263,2);let i=0;for(let s=0;s<512;s++)i+=e[s];return t(vi(i,8),148,8),e}function vd(d){let a=[],e=0;for(let s of d){let n=Qd(s.name,s.data.length);a.push(n,s.data),e+=512+s.data.length;let o=(512-s.data.length%512)%512;o&&(a.push(new Uint8Array(o)),e+=o)}a.push(new Uint8Array(1024)),e+=1024;let t=new Uint8Array(e),i=0;for(let s of a)t.set(s,i),i+=s.length;return t}async function Fd(d){let a=new CompressionStream("gzip"),e=new Response(d).body.pipeThrough(a);return new Uint8Array(await new Response(e).arrayBuffer())}async function vl(d){return Fd(vd(d))}var Hn=class{constructor(a,e,t){this.app=a;this.dirOk=!1;this.writeChain=Promise.resolve();this.baseDir=e.replace(/\/+$/,""),this.logPath=`${this.baseDir}/log.jsonl`,this.statePath=`${this.baseDir}/state.json`,this.getAuthor=t??(()=>"")}getLogPath(){return this.logPath}getDir(){return this.baseDir}async ensureDir(){if(this.dirOk)return;let a=this.app.vault.adapter,e=this.baseDir.split("/").filter(Boolean),t="";for(let i of e)t=t?`${t}/${i}`:i,await a.exists(t)||await a.mkdir(t);this.dirOk=!0}append(a){let e=a.author??this.getAuthor()??"",t={ts:new Date().toISOString(),...a};e?t.author=e:delete t.author;let i=JSON.stringify(t)+` -`;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))}};ae();var Rn=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(e){throw this.undoStack.push(a),console.error("Stashpad: undo failed",e),e}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(e){throw this.redoStack.push(a),console.error("Stashpad: redo failed",e),e}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 Un=class{constructor(a,e){this.app=a;this.data={version:1,authors:{}};this.loaded=!1;this.dirOk=!1;this.writeChain=Promise.resolve();this.path=`${e.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 e=JSON.parse(await a.read(this.path));e&&typeof e=="object"&&e.authors&&(this.data={version:typeof e.version=="number"?e.version:1,authors:e.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,e)=>(e.lastSeen??"").localeCompare(a.lastSeen??""))}get(a){return this.data.authors[a]??null}record(a){let e=(a.id??"").trim();if(!e)return!1;let t=a.at??new Date().toISOString(),i=(a.name??"").trim(),s=this.data.authors[e],n=!1;if(!s)this.data.authors[e]={id:e,name:i,role:a.role?.trim()||void 0,department:a.department?.trim()||void 0,firstSeen:t,lastSeen:t,renames:[]},n=!0;else{if(i&&i!==s.name&&(s.renames.push({from:s.name,to:i,at:t}),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=t}return n&&this.save(),n}replaceAll(a,e){let t=e??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||"",l=o?.renames?[...o.renames]:[];o&&r&&r!==o.name&&l.push({from:o.name,to:r,at:t}),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??t,lastSeen:t,renames:l}}this.data={version:1,authors:i},this.save()}async ensureDir(){if(this.dirOk)return;let a=this.app.vault.adapter,t=this.path.slice(0,this.path.lastIndexOf("/")).split("/").filter(Boolean),i="";for(let s of t)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 ee=require("obsidian");ae();ri();Fs();we();var Gn=new Set(["_attachments","_authors","_exports","_imports","_processed","_archive",".archive","archive","trash"]),Fl=new Set([tt,"edtz","stashenc","stashmeta"]),Fi=class Fi{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}importedOriginalsDir(a){let t=wt(Date.now(),this.plugin.settings).replace(/[/\\:]+/g,"-").replace(/\s+/g," ").trim()||"undated";return`${a}/archive/_imported/${t}`}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 e=a.parent?.path?.replace(/\/+$/,"")??"";this.plugin.discoverStashpadFolders().includes(e)&&(Gn.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(),Fi.DEBOUNCE_MS)}suppress(a,e=4e3){this.suppressed.add(a),window.setTimeout(()=>this.suppressed.delete(a),e)}async createNote(a,e){this.suppress(a,6e4),await this.app.vault.create(a,e)}isEligiblePath(a){if(this.suppressed.has(a.path)||Fl.has(a.extension))return!1;let e=a.parent?.path?.replace(/\/+$/,"")??"",t=e.split("/").pop()??"";return Gn.has(t)?!1:this.plugin.discoverStashpadFolders().includes(e)}async isStillImportable(a){if(!this.isEligiblePath(a))return!1;if(a.extension==="md")try{let{fm:e}=de(await this.app.vault.read(a));if(e&&typeof e.id=="string"&&e.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 e=a.map(h=>this.app.vault.getAbstractFileByPath(h)).filter(h=>h instanceof ee.TFile),t=[];for(let h of e)await this.isStillImportable(h)&&t.push(h);let i=[...this.pendingFolders.keys()];this.pendingFolders.clear();let s=i.map(h=>this.app.vault.getAbstractFileByPath(h)).filter(h=>h instanceof ee.TFolder).map(h=>({folder:h,files:this.filesUnder(h.path)})).filter(h=>h.files.length>0),n=s.reduce((h,g)=>h+g.files.length,0),o=t.length+n;if(o===0)return;await this.plugin.importLog.load();let r=t,l=[],c=t.filter(h=>this.plugin.importLog.findDuplicate(h.name,h.stat?.size??null));if(c.length>0){let h=c.slice(0,5).map(f=>`\u2022 ${f.name}`).join(` -`),g=c.length>5?` +${Ar.replace(/^> /gm,"")} +`)}),i}async function Sl(d){let{zipFiles:a}=await Promise.resolve().then(()=>(Qn(),ja));return a(d.map(e=>({name:e.name,data:e.data})))}function Fi(d,a){return d.toString(8).padStart(a-1,"0")+"\0"}function Sd(d,a){let e=new Uint8Array(512),t=(s,n,o)=>{let r=Un(s);e.set(r.subarray(0,o),n)};t(d.slice(0,100),0,100),t(Fi(420,8),100,8),t(Fi(0,8),108,8),t(Fi(0,8),116,8),t(Fi(a,12),124,12),t(Fi(0,12),136,12),t(" ",148,8),e[156]=48,t("ustar\0",257,6),t("00",263,2);let i=0;for(let s=0;s<512;s++)i+=e[s];return t(Fi(i,8),148,8),e}function bd(d){let a=[],e=0;for(let s of d){let n=Sd(s.name,s.data.length);a.push(n,s.data),e+=512+s.data.length;let o=(512-s.data.length%512)%512;o&&(a.push(new Uint8Array(o)),e+=o)}a.push(new Uint8Array(1024)),e+=1024;let t=new Uint8Array(e),i=0;for(let s of a)t.set(s,i),i+=s.length;return t}async function Dd(d){let a=new CompressionStream("gzip"),e=new Response(d).body.pipeThrough(a);return new Uint8Array(await new Response(e).arrayBuffer())}async function bl(d){return Dd(bd(d))}var Gn=class{constructor(a,e,t){this.app=a;this.dirOk=!1;this.writeChain=Promise.resolve();this.baseDir=e.replace(/\/+$/,""),this.logPath=`${this.baseDir}/log.jsonl`,this.statePath=`${this.baseDir}/state.json`,this.getAuthor=t??(()=>"")}getLogPath(){return this.logPath}getDir(){return this.baseDir}async ensureDir(){if(this.dirOk)return;let a=this.app.vault.adapter,e=this.baseDir.split("/").filter(Boolean),t="";for(let i of e)t=t?`${t}/${i}`:i,await a.exists(t)||await a.mkdir(t);this.dirOk=!0}append(a){let e=a.author??this.getAuthor()??"",t={ts:new Date().toISOString(),...a};e?t.author=e:delete t.author;let i=JSON.stringify(t)+` +`;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))}};le();var Ln=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(e){throw this.undoStack.push(a),console.error("Stashpad: undo failed",e),e}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(e){throw this.redoStack.push(a),console.error("Stashpad: redo failed",e),e}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 On=class{constructor(a,e){this.app=a;this.data={version:1,authors:{}};this.loaded=!1;this.dirOk=!1;this.writeChain=Promise.resolve();this.path=`${e.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 e=JSON.parse(await a.read(this.path));e&&typeof e=="object"&&e.authors&&(this.data={version:typeof e.version=="number"?e.version:1,authors:e.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,e)=>(e.lastSeen??"").localeCompare(a.lastSeen??""))}get(a){return this.data.authors[a]??null}record(a){let e=(a.id??"").trim();if(!e)return!1;let t=a.at??new Date().toISOString(),i=(a.name??"").trim(),s=this.data.authors[e],n=!1;if(!s)this.data.authors[e]={id:e,name:i,role:a.role?.trim()||void 0,department:a.department?.trim()||void 0,firstSeen:t,lastSeen:t,renames:[]},n=!0;else{if(i&&i!==s.name&&(s.renames.push({from:s.name,to:i,at:t}),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=t}return n&&this.save(),n}replaceAll(a,e){let t=e??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||"",l=o?.renames?[...o.renames]:[];o&&r&&r!==o.name&&l.push({from:o.name,to:r,at:t}),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??t,lastSeen:t,renames:l}}this.data={version:1,authors:i},this.save()}async ensureDir(){if(this.dirOk)return;let a=this.app.vault.adapter,t=this.path.slice(0,this.path.lastIndexOf("/")).split("/").filter(Boolean),i="";for(let s of t)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 ee=require("obsidian");le();ai();ks();me();var Kn=new Set(["_attachments","_authors","_exports","_imports","_processed","_archive",".archive","archive","trash"]),Dl=new Set([it,"edtz","stashenc","stashmeta"]),ki=class ki{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}importedOriginalsDir(a){let t=Et(Date.now(),this.plugin.settings).replace(/[/\\:]+/g,"-").replace(/\s+/g," ").trim()||"undated";return`${a}/archive/_imported/${t}`}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 e=a.parent?.path?.replace(/\/+$/,"")??"";this.plugin.discoverStashpadFolders().includes(e)&&(Kn.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(),ki.DEBOUNCE_MS)}suppress(a,e=4e3){this.suppressed.add(a),window.setTimeout(()=>this.suppressed.delete(a),e)}async createNote(a,e){this.suppress(a,6e4),await this.app.vault.create(a,e)}isEligiblePath(a){if(this.suppressed.has(a.path)||Dl.has(a.extension))return!1;let e=a.parent?.path?.replace(/\/+$/,"")??"",t=e.split("/").pop()??"";return Kn.has(t)?!1:this.plugin.discoverStashpadFolders().includes(e)}async isStillImportable(a){if(!this.isEligiblePath(a))return!1;if(a.extension==="md")try{let{fm:e}=Ae(await this.app.vault.read(a));if(e&&typeof e.id=="string"&&e.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 e=a.map(h=>this.app.vault.getAbstractFileByPath(h)).filter(h=>h instanceof ee.TFile),t=[];for(let h of e)await this.isStillImportable(h)&&t.push(h);let i=[...this.pendingFolders.keys()];this.pendingFolders.clear();let s=i.map(h=>this.app.vault.getAbstractFileByPath(h)).filter(h=>h instanceof ee.TFolder).map(h=>({folder:h,files:this.filesUnder(h.path)})).filter(h=>h.files.length>0),n=s.reduce((h,p)=>h+p.files.length,0),o=t.length+n;if(o===0)return;await this.plugin.importLog.load();let r=t,l=[],c=t.filter(h=>this.plugin.importLog.findDuplicate(h.name,h.stat?.size??null));if(c.length>0){let h=c.slice(0,5).map(f=>`\u2022 ${f.name}`).join(` +`),p=c.length>5?` \u2026and ${c.length-5} more`:"",u=await this.dupChoice(`${c.length} of these look like files you've imported before: -${h}${g} +${h}${p} -Replace the existing notes, skip the duplicates, or import them anyway as new notes?`);if(u==="skip"){let f=new Set(c.map(p=>p.path));if(r=t.filter(p=>!f.has(p.path)),r.length===0&&s.length===0){new ee.Notice(`Skipped ${c.length} duplicate file(s) \u2014 nothing new to import.`);return}}else if(u==="replace")for(let f of c){let p=this.plugin.importLog.findDuplicate(f.name,f.stat?.size??null);for(let I of p?.notePaths??[]){let m=this.app.vault.getAbstractFileByPath(I);if(m instanceof ee.TFile)try{l.push({path:I,content:await this.app.vault.read(m)}),await this.app.fileManager.trashFile(m)}catch(B){console.warn("[Stashpad] replace: couldn't remove prior note",I,B)}}}}if(o=r.length+n,o>=Fi.BATCH_CONFIRM_AT){let h=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${h}. Proceed? -Markdown becomes notes (originals archived); other files move to _attachments with a linking note. Dropped folders move to _archive.`,"Import all")){new ee.Notice(`Import cancelled \u2014 ${o} file(s) left as-is.`);return}}let A=[];for(let h of r)try{let g=h.stat?.size??null,u=h.extension==="md"?await this.importMarkdown(h):await this.importOtherFile(h);u&&(A.push(u),this.plugin.importLog.append({ts:new Date().toISOString(),folder:u.folder,kind:u.kind,originalName:h.name,size:g,sourcePath:h.path,notePaths:u.kind==="folder"?u.notePaths:[u.notePath]}))}catch(g){console.warn("[Stashpad] import failed",h.path,g)}for(let{folder:h}of s)try{let g=await this.importFolder(h);g&&g.kind==="folder"&&(A.push(g),this.plugin.importLog.append({ts:new Date().toISOString(),folder:g.folder,kind:"folder",originalName:g.originalName,size:null,sourcePath:h.path,notePaths:g.notePaths}))}catch(g){console.warn("[Stashpad] folder import failed",h.path,g)}(A.length>0||l.length>0)&&this.announce(A,l)}finally{this.draining=!1}}}async importMarkdown(a){let e=a.parent.path.replace(/\/+$/,""),t=await this.app.vault.read(a),{fm:i,body:s}=de(t),n=this.importedOriginalsDir(e);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 ee.TFile))throw new Error(`archive move failed for ${a.path} \u2014 import aborted to avoid data loss`);let r={};for(let[h,g]of Object.entries(i))ze.includes(h)||(r[h]=g);r.id=this.plugin.mintNoteId(),r.parent=S;let l=this.preservedTimes(i,a);r.created=l.created,l.modified&&(r.modified=l.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 c=Se(s)||a.basename,A=await this.uniquePath(e,be(c,r.id));return await this.createNote(A,bt(r,s)),{kind:"md",folder:e,archivePath:o,notePath:A,originalName:a.name}}async importOtherFile(a){let e=a.parent.path.replace(/\/+$/,""),t=`${e}/_attachments`;await this.ensureFolder(t);let i=await this.uniquePath(t,a.name);await this.app.fileManager.renameFile(a,i);let s=a.basename,n=this.plugin.mintNoteId(),o={id:n,parent:S,created:new Date().toISOString(),attachments:[Ve(i)],imported:!0},r=`${s} +Replace the existing notes, skip the duplicates, or import them anyway as new notes?`);if(u==="skip"){let f=new Set(c.map(g=>g.path));if(r=t.filter(g=>!f.has(g.path)),r.length===0&&s.length===0){new ee.Notice(`Skipped ${c.length} duplicate file(s) \u2014 nothing new to import.`);return}}else if(u==="replace")for(let f of c){let g=this.plugin.importLog.findDuplicate(f.name,f.stat?.size??null);for(let I of g?.notePaths??[]){let m=this.app.vault.getAbstractFileByPath(I);if(m instanceof ee.TFile)try{l.push({path:I,content:await this.app.vault.read(m)}),await this.app.fileManager.trashFile(m)}catch(B){console.warn("[Stashpad] replace: couldn't remove prior note",I,B)}}}}if(o=r.length+n,o>=ki.BATCH_CONFIRM_AT){let h=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${h}. Proceed? +Markdown becomes notes (originals archived); other files move to _attachments with a linking note. Dropped folders move to _archive.`,"Import all")){new ee.Notice(`Import cancelled \u2014 ${o} file(s) left as-is.`);return}}let A=[];for(let h of r)try{let p=h.stat?.size??null,u=h.extension==="md"?await this.importMarkdown(h):await this.importOtherFile(h);u&&(A.push(u),this.plugin.importLog.append({ts:new Date().toISOString(),folder:u.folder,kind:u.kind,originalName:h.name,size:p,sourcePath:h.path,notePaths:u.kind==="folder"?u.notePaths:[u.notePath]}))}catch(p){console.warn("[Stashpad] import failed",h.path,p)}for(let{folder:h}of s)try{let p=await this.importFolder(h);p&&p.kind==="folder"&&(A.push(p),this.plugin.importLog.append({ts:new Date().toISOString(),folder:p.folder,kind:"folder",originalName:p.originalName,size:null,sourcePath:h.path,notePaths:p.notePaths}))}catch(p){console.warn("[Stashpad] folder import failed",h.path,p)}(A.length>0||l.length>0)&&this.announce(A,l)}finally{this.draining=!1}}}async importMarkdown(a){let e=a.parent.path.replace(/\/+$/,""),t=await this.app.vault.read(a),{fm:i,body:s}=Ae(t),n=this.importedOriginalsDir(e);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 ee.TFile))throw new Error(`archive move failed for ${a.path} \u2014 import aborted to avoid data loss`);let r={};for(let[h,p]of Object.entries(i))Ve.includes(h)||(r[h]=p);r.id=this.plugin.mintNoteId(),r.parent=k;let l=this.preservedTimes(i,a);r.created=l.created,l.modified&&(r.modified=l.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 c=Se(s)||a.basename,A=await this.uniquePath(e,be(c,r.id));return await this.createNote(A,Dt(r,s)),{kind:"md",folder:e,archivePath:o,notePath:A,originalName:a.name}}async importOtherFile(a){let e=a.parent.path.replace(/\/+$/,""),t=`${e}/_attachments`;await this.ensureFolder(t);let i=await this.uniquePath(t,a.name);await this.app.fileManager.renameFile(a,i);let s=a.basename,n=this.plugin.mintNoteId(),o={id:n,parent:k,created:new Date().toISOString(),attachments:[We(i)],imported:!0},r=`${s} ![[${i}]] -`,l=Se(s)||s,c=await this.uniquePath(e,be(l,n));return await this.createNote(c,bt(o,r)),{kind:"file",folder:e,attachmentPath:i,notePath:c,originalName:a.name}}preservedTimes(a,e){let t=n=>typeof n=="string"&&n.trim().length>0&&!Number.isNaN(Date.parse(n)),i=t(a.created)?a.created:e.stat?.ctime?new Date(e.stat.ctime).toISOString():new Date().toISOString(),s=t(a.modified)?a.modified:e.stat?.mtime?new Date(e.stat.mtime).toISOString():null;return{created:i,modified:s}}filesUnder(a){let e=a.replace(/\/+$/,"")+"/";return this.app.vault.getFiles().filter(t=>t.path.startsWith(e))}async importFolder(a){let e=a.parent.path.replace(/\/+$/,""),t=a.name,i=this.importedOriginalsDir(e);await this.ensureFolder(i);let s=await this.uniquePath(i,t);await this.app.fileManager.renameFile(a,s);let n=this.app.vault.getAbstractFileByPath(s),o=new Set;for(let A of this.app.vault.getMarkdownFiles()){if((A.parent?.path?.replace(/\/+$/,"")??"")!==e)continue;let h=this.app.metadataCache.getFileCache(A)?.frontmatter?.id;typeof h=="string"&&h&&o.add(h)}let r=[],l=[],c=await this.createFolderNote(e,t,S,l,o);return n instanceof ee.TFolder&&await this.buildNotesFromArchive(n,e,c,l,o,r),r.length&&new ee.Notice(`Stashpad: ${r.length} attachment name collision(s) renamed on import \u2014 check ![[links]] in the imported notes.`),{kind:"folder",folder:e,archivePath:s,notePaths:l,attachmentPaths:[],originalName:t}}async createFolderNote(a,e,t,i,s){let n=this.plugin.mintNoteId();s.add(n);let o={id:n,parent:t,created:new Date().toISOString(),attachments:[]},r=Se(e)||e,l=await this.uniquePath(a,be(r,n));return await this.createNote(l,bt(o,`${e} -`)),i.push(l),n}async mergeReservedFolder(a,e,t){await this.ensureFolder(e);for(let i of[...a.children])if(i instanceof ee.TFolder)await this.mergeReservedFolder(i,`${e}/${i.name}`,t);else if(i instanceof ee.TFile){let s=`${e}/${i.name}`;await this.app.vault.adapter.exists(s)&&(s=await this.uniquePath(e,i.name),t.push(`${i.name} \u2192 ${s.split("/").pop()}`)),await this.app.fileManager.renameFile(i,s)}}async buildNotesFromArchive(a,e,t,i,s,n){for(let o of[...a.children])if(o instanceof ee.TFolder)if(Gn.has(o.name))await this.mergeReservedFolder(o,`${e}/${o.name}`,n);else{let r=await this.createFolderNote(e,o.name,t,i,s);await this.buildNotesFromArchive(o,e,r,i,s,n)}else if(o instanceof ee.TFile)if(o.extension==="md"){let r=await this.app.vault.read(o),{fm:l,body:c}=de(r),A={};for(let[I,m]of Object.entries(l))ze.includes(I)||(A[I]=m);let h=typeof l.id=="string"&&l.id?l.id:null,g=h&&!s.has(h)?h:this.plugin.mintNoteId();s.add(g),A.id=g,A.parent=t;let u=this.preservedTimes(l,o);A.created=u.created,u.modified&&(A.modified=u.modified),A.attachments=Array.isArray(l.attachments)?l.attachments:[];let f=Se(c)||o.basename,p=await this.uniquePath(e,be(f,A.id));await this.createNote(p,bt(A,c)),i.push(p)}else{if(Fl.has(o.extension))continue;{let r=this.plugin.mintNoteId(),l={id:r,parent:t,created:new Date().toISOString(),attachments:[Ve(o.path)]},c=`${o.basename} +`,l=Se(s)||s,c=await this.uniquePath(e,be(l,n));return await this.createNote(c,Dt(o,r)),{kind:"file",folder:e,attachmentPath:i,notePath:c,originalName:a.name}}preservedTimes(a,e){let t=n=>typeof n=="string"&&n.trim().length>0&&!Number.isNaN(Date.parse(n)),i=t(a.created)?a.created:e.stat?.ctime?new Date(e.stat.ctime).toISOString():new Date().toISOString(),s=t(a.modified)?a.modified:e.stat?.mtime?new Date(e.stat.mtime).toISOString():null;return{created:i,modified:s}}filesUnder(a){let e=a.replace(/\/+$/,"")+"/";return this.app.vault.getFiles().filter(t=>t.path.startsWith(e))}async importFolder(a){let e=a.parent.path.replace(/\/+$/,""),t=a.name,i=this.importedOriginalsDir(e);await this.ensureFolder(i);let s=await this.uniquePath(i,t);await this.app.fileManager.renameFile(a,s);let n=this.app.vault.getAbstractFileByPath(s),o=new Set;for(let A of this.app.vault.getMarkdownFiles()){if((A.parent?.path?.replace(/\/+$/,"")??"")!==e)continue;let h=this.app.metadataCache.getFileCache(A)?.frontmatter?.id;typeof h=="string"&&h&&o.add(h)}let r=[],l=[],c=await this.createFolderNote(e,t,k,l,o);return n instanceof ee.TFolder&&await this.buildNotesFromArchive(n,e,c,l,o,r),r.length&&new ee.Notice(`Stashpad: ${r.length} attachment name collision(s) renamed on import \u2014 check ![[links]] in the imported notes.`),{kind:"folder",folder:e,archivePath:s,notePaths:l,attachmentPaths:[],originalName:t}}async createFolderNote(a,e,t,i,s){let n=this.plugin.mintNoteId();s.add(n);let o={id:n,parent:t,created:new Date().toISOString(),attachments:[]},r=Se(e)||e,l=await this.uniquePath(a,be(r,n));return await this.createNote(l,Dt(o,`${e} +`)),i.push(l),n}async mergeReservedFolder(a,e,t){await this.ensureFolder(e);for(let i of[...a.children])if(i instanceof ee.TFolder)await this.mergeReservedFolder(i,`${e}/${i.name}`,t);else if(i instanceof ee.TFile){let s=`${e}/${i.name}`;await this.app.vault.adapter.exists(s)&&(s=await this.uniquePath(e,i.name),t.push(`${i.name} \u2192 ${s.split("/").pop()}`)),await this.app.fileManager.renameFile(i,s)}}async buildNotesFromArchive(a,e,t,i,s,n){for(let o of[...a.children])if(o instanceof ee.TFolder)if(Kn.has(o.name))await this.mergeReservedFolder(o,`${e}/${o.name}`,n);else{let r=await this.createFolderNote(e,o.name,t,i,s);await this.buildNotesFromArchive(o,e,r,i,s,n)}else if(o instanceof ee.TFile)if(o.extension==="md"){let r=await this.app.vault.read(o),{fm:l,body:c}=Ae(r),A={};for(let[I,m]of Object.entries(l))Ve.includes(I)||(A[I]=m);let h=typeof l.id=="string"&&l.id?l.id:null,p=h&&!s.has(h)?h:this.plugin.mintNoteId();s.add(p),A.id=p,A.parent=t;let u=this.preservedTimes(l,o);A.created=u.created,u.modified&&(A.modified=u.modified),A.attachments=Array.isArray(l.attachments)?l.attachments:[];let f=Se(c)||o.basename,g=await this.uniquePath(e,be(f,A.id));await this.createNote(g,Dt(A,c)),i.push(g)}else{if(Dl.has(o.extension))continue;{let r=this.plugin.mintNoteId(),l={id:r,parent:t,created:new Date().toISOString(),attachments:[We(o.path)]},c=`${o.basename} ![[${o.path}]] -`,A=Se(o.basename)||o.basename,h=await this.uniquePath(e,be(A,r));await this.createNote(h,bt(l,c)),i.push(h)}}}recordNotePaths(a){return a.kind==="folder"?a.notePaths:[a.notePath]}announce(a,e=[]){let t=a[0]?.folder??"",i=a.length,s=e.length?`, replaced ${e.length}`:"",n=!1,o=async()=>{n||(n=!0,await this.undo(a,e))};this.plugin.notifications.show({message:`Imported ${i} file${i===1?"":"s"}${s} into \`${t.split("/").pop()}\`.`,kind:"success",category:"import",duration:0,folder:t,affectedPaths:a.flatMap(r=>this.recordNotePaths(r)),actions:[...t?[{label:"Go to folder",onClick:()=>void this.plugin.activateViewForFolder(t)}]:[],{label:"Undo import",onClick:()=>void o()}]}),t&&this.plugin.getUndoStack(t).push({label:`Import ${i} file${i===1?"":"s"}`,undo:async()=>{await o()},redo:async()=>{}})}async undo(a,e=[]){for(let t of a)try{if(t.kind==="md"){let i=this.app.vault.getAbstractFileByPath(t.notePath);i instanceof ee.TFile&&await this.app.fileManager.trashFile(i);let s=this.app.vault.getAbstractFileByPath(t.archivePath);if(s instanceof ee.TFile){let n=await this.uniquePath(t.folder,t.originalName);this.suppress(n),await this.app.fileManager.renameFile(s,n)}}else if(t.kind==="file"){let i=this.app.vault.getAbstractFileByPath(t.notePath);i instanceof ee.TFile&&await this.app.fileManager.trashFile(i);let s=this.app.vault.getAbstractFileByPath(t.attachmentPath);if(s instanceof ee.TFile){let n=await this.uniquePath(t.folder,t.originalName);this.suppress(n),await this.app.fileManager.renameFile(s,n)}}else{for(let s of t.notePaths){let n=this.app.vault.getAbstractFileByPath(s);n instanceof ee.TFile&&await this.app.fileManager.trashFile(n)}for(let s of t.attachmentPaths){let n=this.app.vault.getAbstractFileByPath(s);n instanceof ee.TFile&&await this.app.fileManager.trashFile(n)}let i=this.app.vault.getAbstractFileByPath(t.archivePath);if(i instanceof ee.TFolder){let s=await this.uniquePath(t.folder,t.originalName);this.suppress(s),await this.app.fileManager.renameFile(i,s)}}}catch(i){console.warn("[Stashpad] import undo failed",t,i)}for(let t of e)try{await this.app.vault.adapter.exists(t.path)||await this.app.vault.create(t.path,t.content)}catch(i){console.warn("[Stashpad] import undo: couldn't restore replaced note",t.path,i)}new ee.Notice(`Undid import of ${a.length} file(s).`)}pickFilesInto(a){let e=document.createElement("input");e.type="file",e.multiple=!0,e.setCssStyles({display:"none"}),e.onchange=async()=>{let t=Array.from(e.files??[]);if(e.remove(),t.length===0)return;let i=[];for(let n of t)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 l=this.app.vault.getAbstractFileByPath(r);l instanceof ee.TFile&&i.push(l)}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(e),e.click()}async importLooseFilesIn(a){let e=a.replace(/\/+$/,""),t=this.app.vault.getFiles().filter(n=>(n.parent?.path?.replace(/\/+$/,"")??"")===e),i=[];for(let n of t)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 e=a.replace(/\/+$/,""),t=this.app.vault.getAbstractFileByPath(e);if(!(t instanceof ee.TFolder))return 0;let i=t.children.filter(n=>n instanceof ee.TFolder&&!Gn.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 ee.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,e=!1;for(let t of this.pendingEncryptedPaths()){let i=this.app.vault.getAbstractFileByPath(t);if(!(i instanceof ee.TFile))continue;let s=i.parent?.path?.replace(/\/+$/,"")??"";if(await this.importOneStash(i,s,this.liveRootIds(s),!1,{allowLater:!0,onLater:()=>{e=!0,this.snoozeEncryptedNotify(60*60*1e3)}})&&a++,e)break}return{imported:a,rescheduled:e}}liveRootIds(a){let e=new Set;for(let t of this.app.vault.getMarkdownFiles()){if((t.parent?.path?.replace(/\/+$/,"")??"")!==a)continue;let i=this.app.metadataCache.getFileCache(t)?.frontmatter?.id;typeof i=="string"&&i&&e.add(i)}return e}async importOneStash(a,e,t,i,s={}){try{let n=new Uint8Array(await this.app.vault.readBinary(a));if(i&&Me(n))return this.pendingEncryptedStashes.add(a.path),!1;let o=await pi(this.app,n,{...s,secretId:ei(a.basename)});if(!o)return!1;let r=await Je(this.app,o,e,t,{stripReserved:!0});if(r.colorAliases)for(let[l,c]of Object.entries(r.colorAliases))try{await this.plugin.setColorAlias(e,l,c)}catch{}try{await this.app.fileManager.trashFile(a)}catch{}this.pendingEncryptedStashes.delete(a.path);try{await this.plugin.newLog().append({type:"stash_import",id:S,payload:{from:a.path,into:e,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,e={}){let t=a.replace(/\/+$/,""),i=this.app.vault.getFiles().filter(o=>(o.parent?.path?.replace(/\/+$/,"")??"")===t&&o.extension===tt);if(i.length===0)return 0;let s=this.liveRootIds(t),n=0;for(let o of i)await this.importOneStash(o,t,s,!!e.auto)&&n++;return n}async importLooseInto(a,e={}){let t=await this.importLooseFilesIn(a),i=await this.importLooseFoldersIn(a),s=await this.importLooseStashesIn(a,e);return{files:t,folders:i,stashes:s}}defaultDestination(){let e=this.plugin.lastActiveStashpadLeaf?.view?.noteFolder;return e&&this.plugin.discoverStashpadFolders().includes(e)?e:this.plugin.discoverStashpadFolders()[0]??null}confirm(a,e,t){return new Promise(i=>{new _(this.app,a,e,t,i).open()})}dupChoice(a){return new Promise(e=>{new Ki(this.app,a,e).open()})}async ensureFolder(a){let e=this.app.vault.adapter,t=a.split("/").filter(Boolean),i="";for(let s of t){i=i?`${i}/${s}`:s;try{await e.exists(i)||await e.mkdir(i)}catch(n){if(!/already exists/i.test(n.message))throw n}}}async uniquePath(a,e){let t=this.app.vault.adapter,i=e.lastIndexOf("."),s=i>0?e.slice(0,i):e,n=i>0?e.slice(i):"",o=`${a}/${e}`,r=0;for(;await t.exists(o);)r+=1,o=`${a}/${s}-${r}${n}`;return o}};Fi.DEBOUNCE_MS=900,Fi.BATCH_CONFIRM_AT=8;var Ln=Fi;var Cs=class Cs{constructor(a,e){this.app=a;this.entries=[];this.loaded=!1;this.dirOk=!1;this.writeChain=Promise.resolve();this.path=`${e.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 e=await a.read(this.path);for(let t of e.split(/\r?\n/))if(t.trim())try{this.entries.push(JSON.parse(t))}catch{}}}catch(a){console.warn("[Stashpad] import log load failed",a)}}}recent(){return[...this.entries].reverse()}findDuplicate(a,e){for(let t=this.entries.length-1;t>=0;t--){let i=this.entries[t];if(i.originalName===a&&(e==null||i.size==null||i.size===e))return i}return null}append(a){this.entries.push(a);let e=this.entries.length>Cs.MAX_ENTRIES;e&&(this.entries=this.entries.slice(-Cs.MAX_ENTRIES)),this.writeChain=this.writeChain.then(async()=>{try{if(await this.ensureDir(),e){let t=this.entries.map(i=>JSON.stringify(i)).join(` +`,A=Se(o.basename)||o.basename,h=await this.uniquePath(e,be(A,r));await this.createNote(h,Dt(l,c)),i.push(h)}}}recordNotePaths(a){return a.kind==="folder"?a.notePaths:[a.notePath]}announce(a,e=[]){let t=a[0]?.folder??"",i=a.length,s=e.length?`, replaced ${e.length}`:"",n=!1,o=async()=>{n||(n=!0,await this.undo(a,e))};this.plugin.notifications.show({message:`Imported ${i} file${i===1?"":"s"}${s} into \`${t.split("/").pop()}\`.`,kind:"success",category:"import",duration:0,folder:t,affectedPaths:a.flatMap(r=>this.recordNotePaths(r)),actions:[...t?[{label:"Go to folder",onClick:()=>void this.plugin.activateViewForFolder(t)}]:[],{label:"Undo import",onClick:()=>void o()}]}),t&&this.plugin.getUndoStack(t).push({label:`Import ${i} file${i===1?"":"s"}`,undo:async()=>{await o()},redo:async()=>{}})}async undo(a,e=[]){for(let t of a)try{if(t.kind==="md"){let i=this.app.vault.getAbstractFileByPath(t.notePath);i instanceof ee.TFile&&await this.app.fileManager.trashFile(i);let s=this.app.vault.getAbstractFileByPath(t.archivePath);if(s instanceof ee.TFile){let n=await this.uniquePath(t.folder,t.originalName);this.suppress(n),await this.app.fileManager.renameFile(s,n)}}else if(t.kind==="file"){let i=this.app.vault.getAbstractFileByPath(t.notePath);i instanceof ee.TFile&&await this.app.fileManager.trashFile(i);let s=this.app.vault.getAbstractFileByPath(t.attachmentPath);if(s instanceof ee.TFile){let n=await this.uniquePath(t.folder,t.originalName);this.suppress(n),await this.app.fileManager.renameFile(s,n)}}else{for(let s of t.notePaths){let n=this.app.vault.getAbstractFileByPath(s);n instanceof ee.TFile&&await this.app.fileManager.trashFile(n)}for(let s of t.attachmentPaths){let n=this.app.vault.getAbstractFileByPath(s);n instanceof ee.TFile&&await this.app.fileManager.trashFile(n)}let i=this.app.vault.getAbstractFileByPath(t.archivePath);if(i instanceof ee.TFolder){let s=await this.uniquePath(t.folder,t.originalName);this.suppress(s),await this.app.fileManager.renameFile(i,s)}}}catch(i){console.warn("[Stashpad] import undo failed",t,i)}for(let t of e)try{await this.app.vault.adapter.exists(t.path)||await this.app.vault.create(t.path,t.content)}catch(i){console.warn("[Stashpad] import undo: couldn't restore replaced note",t.path,i)}new ee.Notice(`Undid import of ${a.length} file(s).`)}pickFilesInto(a){let e=document.createElement("input");e.type="file",e.multiple=!0,e.setCssStyles({display:"none"}),e.onchange=async()=>{let t=Array.from(e.files??[]);if(e.remove(),t.length===0)return;let i=[];for(let n of t)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 l=this.app.vault.getAbstractFileByPath(r);l instanceof ee.TFile&&i.push(l)}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(e),e.click()}async importLooseFilesIn(a){let e=a.replace(/\/+$/,""),t=this.app.vault.getFiles().filter(n=>(n.parent?.path?.replace(/\/+$/,"")??"")===e),i=[];for(let n of t)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 e=a.replace(/\/+$/,""),t=this.app.vault.getAbstractFileByPath(e);if(!(t instanceof ee.TFolder))return 0;let i=t.children.filter(n=>n instanceof ee.TFolder&&!Kn.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 ee.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,e=!1;for(let t of this.pendingEncryptedPaths()){let i=this.app.vault.getAbstractFileByPath(t);if(!(i instanceof ee.TFile))continue;let s=i.parent?.path?.replace(/\/+$/,"")??"";if(await this.importOneStash(i,s,this.liveRootIds(s),!1,{allowLater:!0,onLater:()=>{e=!0,this.snoozeEncryptedNotify(60*60*1e3)}})&&a++,e)break}return{imported:a,rescheduled:e}}liveRootIds(a){let e=new Set;for(let t of this.app.vault.getMarkdownFiles()){if((t.parent?.path?.replace(/\/+$/,"")??"")!==a)continue;let i=this.app.metadataCache.getFileCache(t)?.frontmatter?.id;typeof i=="string"&&i&&e.add(i)}return e}async importOneStash(a,e,t,i,s={}){try{let n=new Uint8Array(await this.app.vault.readBinary(a));if(i&&Me(n))return this.pendingEncryptedStashes.add(a.path),!1;let o=await gi(this.app,n,{...s,secretId:ti(a.basename)});if(!o)return!1;let r=await qe(this.app,o,e,t,{stripReserved:!0});if(r.colorAliases)for(let[l,c]of Object.entries(r.colorAliases))try{await this.plugin.setColorAlias(e,l,c)}catch{}try{await this.app.fileManager.trashFile(a)}catch{}this.pendingEncryptedStashes.delete(a.path);try{await this.plugin.newLog().append({type:"stash_import",id:k,payload:{from:a.path,into:e,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,e={}){let t=a.replace(/\/+$/,""),i=this.app.vault.getFiles().filter(o=>(o.parent?.path?.replace(/\/+$/,"")??"")===t&&o.extension===it);if(i.length===0)return 0;let s=this.liveRootIds(t),n=0;for(let o of i)await this.importOneStash(o,t,s,!!e.auto)&&n++;return n}async importLooseInto(a,e={}){let t=await this.importLooseFilesIn(a),i=await this.importLooseFoldersIn(a),s=await this.importLooseStashesIn(a,e);return{files:t,folders:i,stashes:s}}defaultDestination(){let e=this.plugin.lastActiveStashpadLeaf?.view?.noteFolder;return e&&this.plugin.discoverStashpadFolders().includes(e)?e:this.plugin.discoverStashpadFolders()[0]??null}confirm(a,e,t){return new Promise(i=>{new _(this.app,a,e,t,i).open()})}dupChoice(a){return new Promise(e=>{new Ji(this.app,a,e).open()})}async ensureFolder(a){let e=this.app.vault.adapter,t=a.split("/").filter(Boolean),i="";for(let s of t){i=i?`${i}/${s}`:s;try{await e.exists(i)||await e.mkdir(i)}catch(n){if(!/already exists/i.test(n.message))throw n}}}async uniquePath(a,e){let t=this.app.vault.adapter,i=e.lastIndexOf("."),s=i>0?e.slice(0,i):e,n=i>0?e.slice(i):"",o=`${a}/${e}`,r=0;for(;await t.exists(o);)r+=1,o=`${a}/${s}-${r}${n}`;return o}};ki.DEBOUNCE_MS=900,ki.BATCH_CONFIRM_AT=8;var Jn=ki;var Bs=class Bs{constructor(a,e){this.app=a;this.entries=[];this.loaded=!1;this.dirOk=!1;this.writeChain=Promise.resolve();this.path=`${e.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 e=await a.read(this.path);for(let t of e.split(/\r?\n/))if(t.trim())try{this.entries.push(JSON.parse(t))}catch{}}}catch(a){console.warn("[Stashpad] import log load failed",a)}}}recent(){return[...this.entries].reverse()}findDuplicate(a,e){for(let t=this.entries.length-1;t>=0;t--){let i=this.entries[t];if(i.originalName===a&&(e==null||i.size==null||i.size===e))return i}return null}append(a){this.entries.push(a);let e=this.entries.length>Bs.MAX_ENTRIES;e&&(this.entries=this.entries.slice(-Bs.MAX_ENTRIES)),this.writeChain=this.writeChain.then(async()=>{try{if(await this.ensureDir(),e){let t=this.entries.map(i=>JSON.stringify(i)).join(` `);await this.app.vault.adapter.write(this.path,t+` `)}else 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,t=this.path.slice(0,this.path.lastIndexOf("/")).split("/").filter(Boolean),i="";for(let s of t)i=i?`${i}/${s}`:s,await a.exists(i)||await a.mkdir(i);this.dirOk=!0}};Cs.MAX_ENTRIES=5e3;var On=Cs;var Jn=class Jn{constructor(a,e){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=`${e.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 e=JSON.parse(await a.read(this.path));if(e?.schema===1&&e.entries){for(let[t,i]of Object.entries(e.entries))this.map.set(t,i);for(let t of[...this.map.keys()])this.app.vault.getAbstractFileByPath(t)||(this.map.delete(t),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,e){this.map.set(a,e),this.dirty=!0,this.scheduleSave()}scheduleSave(){this.saveTimer==null&&(this.saveTimer=window.setTimeout(()=>{this.saveTimer=null,this.save()},Jn.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){this.dirty=!0,console.warn("[Stashpad] render cache save failed",a)}}),this.writeChain):this.writeChain}async ensureDir(){if(this.dirOk)return;let a=this.app.vault.adapter,t=this.path.slice(0,this.path.lastIndexOf("/")).split("/").filter(Boolean),i="";for(let s of t)i=i?`${i}/${s}`:s,await a.exists(i)||await a.mkdir(i);this.dirOk=!0}};Jn.SAVE_DEBOUNCE_MS=8e3;var Kn=Jn;var hr="stashpad:unghost-after-reload",mt=class mt extends N.Plugin{constructor(){super(...arguments);this.settings={...Qt};this.reEncryptScheduler=null;this.usedNoteIds=null;this.debugBuffer=[];this.undoStacks=new Map;this.lastActiveStashpadLeaf=null;this.rebootstrapInProgress=!1;this.pendingEncBlobs=new Set;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.archiveMigrationInFlight=!1;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.pendingForkDeletes=new Set;this.writeChain=Promise.resolve();this.lastSeenSettingsRev=0;this.settingsBaseline={};this.externalReloadDebounced=(0,N.debounce)(()=>void this.onExternalDataJsonChange(),600,!1)}trace(e,t){if(!this.settings.debugTrace)return;let i="";if(t)try{i=" "+JSON.stringify(t)}catch{i=" [unserializable]"}let s=Math.round(performance.now());this.debugBuffer.push(`+${s}ms ${e}${i}`),this.debugBuffer.length>mt.DEBUG_BUFFER_MAX&&this.debugBuffer.splice(0,this.debugBuffer.length-mt.DEBUG_BUFFER_MAX)}getDebugTrace(){return this.debugBuffer.join(` -`)}clearDebugTrace(){this.debugBuffer=[]}get notifications(){return this._notifications||(this._notifications=new Gs(this.app)),this._notifications}get authorRegistry(){return this._authorRegistry||(this._authorRegistry=new Un(this.app,this.pluginPrivatePath())),this._authorRegistry}get importService(){return this._importService||(this._importService=new Ln(this)),this._importService}get importLog(){return this._importLog||(this._importLog=new On(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 Kn(this.app,this.pluginPrivatePath())),this._renderCacheStore}async onunload(){try{this.encryption?.dispose()}catch{}try{for(let e of this.archivePending.values())window.clearTimeout(e.timer);this.archivePending.clear()}catch{}try{this.reEncryptScheduler?.dispose()}catch{}try{await this._renderCacheStore?.save()}catch{}}pluginPrivatePath(e=""){let i=`${this.manifest.dir.replace(/\/+$/,"")}/.stashpad`;return e?`${i}/${e.replace(/^\/+/,"")}`:i}newLog(){return new Hn(this.app,this.pluginPrivatePath(),()=>(this.settings?.authorName??"").trim())}async migrateLegacyPaths(){let e=this.app.vault.adapter,t=this.pluginPrivatePath(),i=async()=>{let r=t.split("/").filter(Boolean),l="";for(let c of r)l=l?`${l}/${c}`:c,await e.exists(l)||await e.mkdir(l)},s=`${this.manifest.dir.replace(/\/+$/,"")}/data.json`,n=this.pluginPrivatePath("data.json");if(await e.exists(n))try{let r=await e.read(n);await e.write(s,r),await e.write(`${n}.bak`,r),await e.remove(n),console.debug("[Stashpad] relocated data.json \u2192 standard path (for Obsidian Sync)")}catch(r){console.warn("Stashpad: data.json relocation failed",r)}let o=".stashpad";if(await e.exists(o))try{await i();let r=await e.list(o);for(let l of r.files){let c=l.replace(/^.*\//,""),A=this.pluginPrivatePath(c);if(!await e.exists(A))try{let h=await e.read(l);await e.write(A,h),console.debug("[Stashpad] migrated",l,"\u2192",A)}catch(h){console.warn(`Stashpad: failed to migrate ${l}`,h)}}}catch(r){console.warn("Stashpad: .stashpad migration scan failed",r)}}async createNewStashpad(e){let t=e.trim().replace(/^\/+|\/+$/g,"");if(!t)throw new Error("Folder name is empty");let i=this.app.vault.adapter,s=t.split("/").filter(Boolean),n="";for(let c of s)n=n?`${n}/${c}`:c,await i.exists(n)||await i.mkdir(n);let o=`${t}/Home.md`;if(await i.exists(o)){let c=this.app.vault.getAbstractFileByPath(o);c&&await this.app.fileManager.processFrontMatter(c,A=>{(typeof A.id!="string"||!A.id)&&(A.id=S),"parent"in A||(A.parent=null),(typeof A.created!="string"||!A.created)&&(A.created=new Date().toISOString())});return}let r=new Date().toISOString(),l=["---",`id: ${S}`,"parent: null",`created: ${r}`,"---","Home"].join(` -`);await this.app.vault.create(o,l);try{await this.seedLocalAuthorStub(t)}catch{}try{await this.seedKnownAuthorsInFolder(t)}catch{}}collectColorsInFolder(e){let t=new Map,i=e.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,l=typeof r?.color=="string"?r.color.trim():"";if(!l||!/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(l))continue;let c=l.toLowerCase();t.set(c,(t.get(c)??0)+1)}let s=[...t.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(e,t,i){let s=e.replace(/\/+$/,""),n=t.toLowerCase(),o=0;for(let l of this.app.vault.getMarkdownFiles()){let c=l.parent?.path?.replace(/\/+$/,"")??"";if(c!==s&&!c.startsWith(s+"/"))continue;let A=this.app.metadataCache.getFileCache(l)?.frontmatter;if((typeof A?.color=="string"?A.color.trim().toLowerCase():"")===n)try{await this.app.fileManager.processFrontMatter(l,g=>{i?g.color=i:delete g.color}),o++}catch(g){console.warn(`Stashpad: recolor failed for ${l.path}`,g)}}let r=this.settings.colorAliases?.[s];if(r){let l=r[n];l&&(delete r[n],i&&(r[i.toLowerCase()]=l),Object.keys(r).length===0&&delete this.settings.colorAliases[s],await this.saveSettings())}return o}getColorAlias(e,t){let i=e.replace(/\/+$/,""),s=this.settings.colorAliases?.[i];if(!s)return;let n=s[t.toLowerCase()];return n&&n.trim()?n:void 0}async setColorAlias(e,t,i){let s=e.replace(/\/+$/,""),n=t.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(e,t=2e3){let i=e.trim().replace(/^\/+|\/+$/g,"");if(!i)return;let s=Date.now();for(;Date.now()-s<t;){if(this.discoverStashpadFolders().includes(i))return;await new Promise(n=>setTimeout(n,80))}}importExcludePrefixList(){return(this.settings.importExcludePrefixes??"_").split(",").map(e=>e.trim()).filter(Boolean)}pathHasExcludedSegment(e){let t=this.importExcludePrefixList();return t.length?e.replace(/\/+$/,"").split("/").some(i=>t.some(s=>i.startsWith(s))):!1}discoverStashpadFolders(){let e=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&&!this.pathHasExcludedSegment(n)&&!Nt(n)&&e.add(n)}let t=[...e].sort();return this.knownStashpadFolders=new Set(t),t}closeStashpadTabsFor(e){let t=0;for(let i of this.app.workspace.getLeavesOfType(z)){let s=i.view?.noteFolder??"";s||(s=((i.getViewState?.()?.state??{}).folderOverride??"")||this.settings.folder||"Stashpad"),s=(s||"").replace(/\/+$/,""),(s===e||s.startsWith(e+"/"))&&(i.detach(),t++)}return t}retargetStashpadViewsForFolderRename(e,t){let i=(e||"").replace(/\/+$/,""),s=(t||"").replace(/\/+$/,"");if(!i||i===s)return;let n=o=>{let r=(o??"").replace(/\/+$/,"");return r===i?s:r.startsWith(i+"/")?s+r.slice(i.length):null};for(let o of this.app.workspace.getLeavesOfType(z)){let r=o.getViewState(),l=r.state??{},c=o.isDeferred?void 0:o.view?.noteFolder,A=n(c??l.folderOverride);A&&o.setViewState({...r,state:{...r.state??{},folderOverride:A}})}}async remapFolderPathInSettings(e,t){let i=e.replace(/\/+$/,""),s=t.replace(/\/+$/,"");if(!i||!s||i===s)return;let n=this.settings,o=h=>h===i?s:h.startsWith(i+"/")?s+h.slice(i.length):h,r=h=>h&&h.map(o),l=h=>{if(!h)return h;let g={};for(let[u,f]of Object.entries(h))g[o(u)]=f;return g},c=JSON.stringify([n.folderPanelPinned,n.folderPanelDownranked,n.folderPanelHidden,n.archiveFolders,n.searchIncludedFolders,n.searchExcludedFolders,n.defaultArchiveFolder,n.folder,n.folderEncPrefs,n.viewModes,n.encryptionFilter]);n.folderPanelPinned=r(n.folderPanelPinned)??n.folderPanelPinned,n.folderPanelDownranked=r(n.folderPanelDownranked)??n.folderPanelDownranked,n.folderPanelHidden=r(n.folderPanelHidden)??n.folderPanelHidden,n.archiveFolders=r(n.archiveFolders)??n.archiveFolders,n.searchIncludedFolders=r(n.searchIncludedFolders)??n.searchIncludedFolders,n.searchExcludedFolders=r(n.searchExcludedFolders)??n.searchExcludedFolders,n.defaultArchiveFolder&&(n.defaultArchiveFolder=o(n.defaultArchiveFolder)),((n.folder||"").replace(/\/+$/,"")===i||(n.folder||"").startsWith(i+"/"))&&(n.folder=o((n.folder||"").replace(/\/+$/,""))),n.folderEncPrefs=l(n.folderEncPrefs)??n.folderEncPrefs,n.viewModes=l(n.viewModes)??n.viewModes,n.encryptionFilter&&(n.encryptionFilter=l(n.encryptionFilter)),JSON.stringify([n.folderPanelPinned,n.folderPanelDownranked,n.folderPanelHidden,n.archiveFolders,n.searchIncludedFolders,n.searchExcludedFolders,n.defaultArchiveFolder,n.folder,n.folderEncPrefs,n.viewModes,n.encryptionFilter])!==c&&await this.saveSettings()}async prunePlacementFor(e){let t=this.settings,i=o=>(o??[]).filter(r=>r!==e&&!r.startsWith(e+"/")),s=(t.folderPanelPinned?.length??0)+(t.folderPanelDownranked?.length??0)+(t.folderPanelHidden?.length??0);t.folderPanelPinned=i(t.folderPanelPinned),t.folderPanelDownranked=i(t.folderPanelDownranked),t.folderPanelHidden=i(t.folderPanelHidden),t.folderPanelPinned.length+t.folderPanelDownranked.length+t.folderPanelHidden.length!==s&&await this.saveSettings()}async deleteStashpadFolderWithUndo(e){let t=e.path.replace(/\/+$/,""),i=e.name,s=this.app.vault.adapter,n=".trash";try{await s.exists(n)||await s.mkdir(n)}catch(c){console.warn("[Stashpad] couldn't ensure .trash",c)}let o=`${n}/${i}`;for(let c=1;await s.exists(o);c++)o=`${n}/${i} (${c})`;this.suppressedFolderDeletes.add(t),window.setTimeout(()=>this.suppressedFolderDeletes.delete(t),5e3);let r=this.closeStashpadTabsFor(t);await this.prunePlacementFor(t),this.knownStashpadFolders.delete(t);try{await s.rename(t,o)}catch(c){console.warn("[Stashpad] folder delete failed",c),this.suppressedFolderDeletes.delete(t),new N.Notice("Delete failed (see console).");return}let l=r>0?`Deleted \u201C${i}\u201D \u2014 closed ${r} open tab${r===1?"":"s"}.`:`Deleted \u201C${i}\u201D.`;this.notifications.show({message:l,kind:"warning",category:"delete",duration:0,folder:t,actions:[{label:"Undo",onClick:async()=>{try{if(await s.exists(t)){new N.Notice(`Can't undo \u2014 \u201C${i}\u201D already exists.`);return}this.suppressedFolderDeletes.add(t),window.setTimeout(()=>this.suppressedFolderDeletes.delete(t),5e3),await s.rename(o,t),new N.Notice(`Restored \u201C${i}\u201D.`),this.activateViewForFolder(t)}catch(c){console.warn("[Stashpad] folder undo failed",c),new N.Notice("Undo failed (see console).")}}}]})}async handleStashpadFolderDeleted(e){let t=e.replace(/\/+$/,"");if(!t||this.suppressedFolderDeletes.has(t))return;let i=this.closeStashpadTabsFor(t);await this.prunePlacementFor(t),this.knownStashpadFolders.delete(t);let s=t.split("/").pop()||t;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:t})}searchableFolders(e){let t=new Set(this.settings.searchIncludedFolders),i=new Set(this.settings.searchExcludedFolders),s=new Set((this.settings.archiveFolders??[]).map(c=>(c??"").replace(/\/+$/,""))),o=this.discoverStashpadFolders().filter(c=>s.has(c)?!1:t.size>0?t.has(c):!i.has(c)),r=(e||"").trim().replace(/\/+$/,""),l=o.filter(c=>c!==r);return r&&l.unshift(r),l}async maybeSweepFolder(e){let t=(e||"").trim().replace(/\/+$/,"");!t||this.sweptFolders.has(t)||(this.sweptFolders.add(t),setTimeout(()=>{this.runSweep(t,{silent:!0})},3e3))}async runIntegrityCheckOnFolder(e){let t=(e||"").trim().replace(/\/+$/,"");t&&await this.runSweep(t,{silent:!1})}async runSweep(e,t){try{let i=this.newLog(),s={},n=this.app.vault.getMarkdownFiles().filter(c=>c.path===e||c.path.startsWith(e+"/"));for(let c of n){let A=this.app.metadataCache.getFileCache(c)?.frontmatter,h=typeof A?.id=="string"?A.id.trim():"";if(!h)continue;let g=A&&"parent"in A?A.parent??null:null;s[h]={parent:g,path:c.path}}let o=await i.readState(),r=c=>c===e||c.startsWith(e+"/");if(!t.silent){for(let[c,A]of Object.entries(s)){let h=o[c];h?h.parent!==A.parent?await i.append({type:"parent_change",id:c,payload:{from:h.parent,to:A.parent}}):h.path!==A.path&&await i.append({type:"rename",id:c,payload:{from:h.path,to:A.path}}):await i.append({type:"create",id:c,payload:{path:A.path,parent:A.parent}})}for(let[c,A]of Object.entries(o))!s[c]&&r(A.path)&&await i.append({type:"missing",id:c,payload:{lastPath:A.path}})}let l={};for(let[c,A]of Object.entries(o))r(A.path)||(l[c]=A);for(let[c,A]of Object.entries(s))l[c]=A;await i.writeState(l)}catch(i){console.warn("Stashpad: integrity sweep failed",i)}}getUndoStack(e){let t=this.undoStacks.get(e);return t||(t=new Rn,this.undoStacks.set(e,t)),t}mintNoteId(){this.usedNoteIds===null&&this.rebuildUsedNoteIds();let e=this.usedNoteIds,t=Zn(i=>e.has(i));return e.add(t),t}rebuildUsedNoteIds(){let e=new Set;for(let t of this.app.vault.getMarkdownFiles()){let i=this.app.metadataCache.getFileCache(t)?.frontmatter?.id;typeof i=="string"&&i.trim()&&e.add(i.trim())}this.usedNoteIds=e}async onload(){this.registerEvent(this.app.metadataCache.on("changed",(p,I,m)=>{let B=m?.frontmatter?.id;this.usedNoteIds&&typeof B=="string"&&B.trim()&&this.usedNoteIds.add(B.trim())})),await this.migrateLegacyPaths(),await this.loadSettings(),ke.enabled=!!this.settings.enablePerfProfiling,this.encryption=new Ys(this.app,()=>({...zs(),...this.settings.encryption??{}}),async p=>{this.settings.encryption=p,await this.saveSettings()}),this.encryption.init().then(async()=>{try{let p=await this.encryption.migrateKeyfileToStashKeys();p>0&&new N.Notice(`Stashpad: moved ${p} folder key${p===1?"":"s"} to the new per-folder format.`)}catch(p){console.warn("[Stashpad] folder-key migration failed (keyfile still works)",p)}}),this.reEncryptScheduler=new Nn(this),this.reEncryptScheduler.start(),this.settingTab=new Zs(this.app,this),this.addSettingTab(this.settingTab),await this.renderCacheStore.load(),this.registerEvent(this.app.vault.on("delete",p=>this.renderCacheStore.evict(p.path))),this.registerEvent(this.app.vault.on("rename",(p,I)=>this.renderCacheStore.evict(I)));let e=(0,N.debounce)(()=>void this.flushForkSiblingPrune(),250,!0);this.registerEvent(this.app.vault.on("delete",p=>{p instanceof N.TFile&&p.extension==="md"&&(this.pendingForkDeletes.add(p.basename),e())})),this.registerEvent(this.app.vault.on("create",p=>this.onOkfFileEvent(p.path))),this.registerEvent(this.app.vault.on("delete",p=>this.onOkfFileEvent(p.path))),this.registerEvent(this.app.vault.on("rename",(p,I)=>{this.onOkfFileEvent(p.path),this.onOkfFileEvent(I)})),await this.authorRegistry.load();{let p=(this.settings.authorId??"").trim();p&&this.authorRegistry.record({id:p,name:this.settings.authorName,role:this.settings.authorRole,department:this.settings.authorDepartment})}this.registerEvent(this.app.vault.on("create",p=>{p.path.endsWith(".stashenc")&&this.pendingEncBlobs.delete(p.path)})),this.registerEvent(this.app.vault.on("delete",p=>{p.path.endsWith(".stashenc")&&this.pendingEncBlobs.delete(p.path)})),this.app.workspace.onLayoutReady(()=>{this.reconcileLockedRegistry(),window.setTimeout(async()=>{try{await this.migrateArchiveFoldersToSubfolders()}catch(p){console.error("[Stashpad] archive migration failed",p)}try{await this.migrateDeletedToTrashSubfolders()}catch(p){console.error("[Stashpad] trash migration failed",p)}this.pruneZombieArchiveEntries()},5e3),window.setTimeout(()=>{if(!this.settings.reEncryptNudge)return;let p=this.reEncryptWatching().length;if(p===0)return;let I=new N.Notice("",0);I.noticeEl.createSpan({text:`\u{1F513} ${p} previously-encrypted note${p===1?" is":"s are"} still plaintext. `});let m=I.noticeEl.createEl("button",{text:"Review"});m.onclick=()=>{I.hide(),Te(this,"watch")}},8e3),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(z,p=>new Sn(p,this)),this.registerView(xt,p=>new _s(p,this)),this.registerView(Ct,p=>new Ds(p,this)),this.registerView(Wt,p=>new xn(p,this)),this.registerView(Xt,p=>new pn(p,this)),this.registerView(Bt,p=>new Mn(p,this)),this.registerObsidianProtocolHandler(ss,p=>{this.handleDeepLink(p)}),this.registerEvent(this.app.workspace.on("active-leaf-change",p=>{p&&p.view.getViewType()===z&&(this.lastActiveStashpadLeaf=p,this.settings.autoOpenDetailPanel&&this.app.workspace.getLeavesOfType(xt).length===0&&setTimeout(()=>{en(this.app)},0),this.notifyStashpadSelectionChanged())}));let t=()=>{let p=ht(),I=!!p&&this.app.workspace.activeLeaf&&this.app.workspace.activeLeaf.view===p,m=!!I&&this.settings.hideMobileToolbarInStashpad;document.body.classList.toggle("stashpad-hide-mobile-toolbar",m),document.body.classList.toggle("stashpad-active",!!I)};this.register(la(t)),this.registerEvent(this.app.workspace.on("active-leaf-change",t));let i=p=>{try{let I=Array.from(document.querySelectorAll("style")).filter(m=>(m.textContent??"").includes(".stashpad-"));for(let m of I){let B=m.id||"",C=B?`style[data-stashpad-source="${B}"]`:null;if(C&&p.head.querySelector(C))continue;let w=p.createElement("style");B?w.setAttribute("data-stashpad-source",B):w.setAttribute("data-stashpad-source","anon"),w.textContent=m.textContent??"",p.head.appendChild(w)}}catch(I){console.warn("[Stashpad] inject popout styles failed",I)}};this.registerEvent(this.app.workspace.on("window-open",p=>{let I=p?.doc??p?.win?.document??null;I&&i(I)})),this.registerEvent(this.app.workspace.on("file-menu",(p,I)=>{if(!(I instanceof N.TFolder))return;let m=I.path.replace(/\/+$/,"");p.addItem(C=>C.setTitle("\u{1F512} Encrypt with Stashpad").setIcon("lock").onClick(()=>void this.encryptFolderFromExplorer(m))),I.children?.some(C=>C instanceof N.TFile&&C.extension==="stashenc")&&!this.folderHasStashpadNotes(m)&&p.addItem(C=>C.setTitle("\u{1F513} Decrypt with Stashpad").setIcon("unlock").onClick(()=>void this.decryptFolderFromExplorer(m))),this.discoverStashpadFolders().includes(m)&&p.addItem(C=>{C.setTitle("Open folder in Stashpad").setIcon("layout-list").onClick(()=>void this.openFolderInStashpad(m))})})),setTimeout(()=>{try{let p=this.app.workspace;typeof p.iterateAllLeaves=="function"&&p.iterateAllLeaves(I=>{let m=I?.view?.containerEl?.ownerDocument;m&&m!==document&&i(m)})}catch{}},200),t(),this.register(()=>document.body.classList.remove("stashpad-hide-mobile-toolbar","stashpad-active"));let s=window.visualViewport,n=()=>{let p=document.querySelector(".mobile-toolbar, .mobile-toolbar-container"),I=p&&p.isConnected?p.offsetHeight:0;document.body.style.setProperty("--stashpad-toolbar-h",`${I}px`);let m=0;s&&(m=Math.max(0,window.innerHeight-s.height-s.offsetTop)),document.body.style.setProperty("--stashpad-vv-bottom-gap",`${m}px`),document.body.classList.toggle("stashpad-keyboard-open",m>100)};n(),s&&(s.addEventListener("resize",n),s.addEventListener("scroll",n),this.register(()=>{s.removeEventListener("resize",n),s.removeEventListener("scroll",n)})),window.addEventListener("resize",n),this.register(()=>window.removeEventListener("resize",n)),requestAnimationFrame(n),setTimeout(n,250),setTimeout(n,1e3),this.addRibbonIcon("list-tree","Open Stashpad",()=>{if(this.discoverStashpadFolders().length===0){this.activateView({reveal:!0});return}this.openFolderPicker()}).addEventListener("contextmenu",p=>{p.preventDefault(),this.openFolderPicker()}),this.addRibbonIcon("panel-left","Open Stashpad panels (sidebar)",()=>{xs(this.app)}),this.addRibbonIcon("folders","Open Stashpad folder panel (sidebar)",()=>{Tn(this.app)}),this.addRibbonIcon("panel-right","Open Stashpad detail panel (right sidebar)",()=>{en(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()});let r=p=>{let I=ht();I&&typeof I[p]=="function"&&I[p]()};this.addCommand({id:"stashpad-toggle-split",name:"Toggle split-on-newlines",callback:()=>r("toggleSplit")}),this.addCommand({id:"stashpad-fork-version",name:"Fork as a version (alternate draft in this sheet)",callback:()=>r("cmdForkVersion")}),this.addCommand({id:"stashpad-mark-version-final",name:"Mark version as final (sheet)",callback:()=>r("cmdMarkVersionFinal")}),this.addCommand({id:"stashpad-command-palette",name:"Command palette (Stashpad only)",callback:()=>r("openStashpadCommandPalette")}),this.addCommand({id:"stashpad-lock-selection",name:"Encrypt (lock) selection (notes + children)",callback:()=>r("cmdLockSelection")}),this.addCommand({id:"stashpad-unlock-all",name:"Decrypt (unlock) locked notes in view",callback:()=>r("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:()=>r("cmdCopyNotes")}),this.addCommand({id:"stashpad-cut-notes",name:"Cut notes (paste in list to move, in composer to extract text)",callback:()=>r("cmdCutNotes")}),this.addCommand({id:"stashpad-paste-notes",name:"Paste notes (from the note clipboard)",callback:()=>r("cmdPasteNotes")}),this.addCommand({id:"stashpad-move-to-archive",name:"Move selection to archive",callback:()=>r("cmdMoveToArchive")}),this.addCommand({id:"stashpad-encrypt-delete",name:"Encrypt (lock) & delete selection (to encrypted trash)",callback:()=>r("cmdEncryptDelete")}),this.addCommand({id:"stashpad-delete-unencrypted",name:"Delete selection to Obsidian's trash (unencrypted)",callback:()=>r("cmdDeleteUnencrypted")}),this.addCommand({id:"stashpad-restore-trash",name:"Open aggregated Trash view",callback:()=>this.openEncryptedTrash()}),this.addCommand({id:"stashpad-open-all-encrypted",name:"Open aggregated Encrypted notes view",callback:()=>void Te(this,"encrypted")}),this.addCommand({id:"stashpad-open-all-archived",name:"Open aggregated Archived view",callback:()=>void Te(this,"archived")}),this.addCommand({id:"stashpad-open-all-tasks",name:"Open aggregated Tasks view",callback:()=>void Te(this,"tasks")}),this.addCommand({id:"stashpad-open-watchlist",name:"Open aggregated Previously encrypted view",callback:()=>void Te(this,"watch")}),this.addCommand({id:"stashpad-encrypt-applicable",name:"Encrypt (lock) everything applicable (re-encrypt sweep)",callback:()=>void this.encryptEverythingApplicable()}),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:()=>r("claimSelectedAsAuthor")}),this.addCommand({id:"stashpad-claim-folder-author",name:"Claim authorship of all unauthored notes in this folder",callback:()=>r("claimFolderAsAuthor")}),this.addCommand({id:"stashpad-claim-selected-contributor",name:"Claim selected notes (author if unowned, else add me as contributor)",callback:()=>r("claimSelectedWithContributor")}),this.addCommand({id:"stashpad-claim-folder-contributor",name:"Claim all notes in this folder (author if unowned, else add me as contributor)",callback:()=>r("claimFolderWithContributor")}),this.addCommand({id:"stashpad-pick-destination",name:"Pick destination for next note",callback:()=>r("openDestinationPicker")}),this.addCommand({id:"stashpad-search",name:"Search Stashpad notes",callback:()=>r("openSearchModal")}),this.addCommand({id:"stashpad-search-in-parent",name:"Search in current parent",callback:()=>r("openSearchInParentModal")}),this.addCommand({id:"stashpad-move-picker",name:"Move selection (picker)",callback:()=>r("cmdMovePicker")}),this.addCommand({id:"stashpad-merge",name:"Merge selection",callback:()=>r("cmdMerge")}),this.addCommand({id:"stashpad-copy",name:"Copy selection",callback:()=>r("cmdCopy")}),this.addCommand({id:"stashpad-copy-tree",name:"Copy focused subtree",callback:()=>r("cmdCopyTree")}),this.addCommand({id:"stashpad-copy-link",name:"Copy Stashpad link (deep link / URL) to note",callback:()=>r("cmdCopyStashpadLink")}),this.addCommand({id:"stashpad-open-link",name:"Open Stashpad link (paste a deep link / URL)",callback:()=>this.openDeepLinkModal()}),this.addCommand({id:"stashpad-copy-outline",name:"Copy as outline (nested embeds)",callback:()=>r("cmdCopyOutline")}),this.addCommand({id:"stashpad-split",name:"Split note\u2026",callback:()=>r("cmdSplit")}),this.addCommand({id:"stashpad-edit-note",name:"Edit note in new tab (selection)",callback:()=>r("cmdOpenInEditor")}),this.addCommand({id:"stashpad-edit-parent",name:"Edit parent note in new tab",callback:()=>r("cmdOpenParentInEditor")}),this.addCommand({id:"stashpad-delete",name:"Delete selection",callback:()=>r("cmdDelete")}),this.addCommand({id:"stashpad-move-up",name:"Move note up",callback:()=>r("cmdMoveUp")}),this.addCommand({id:"stashpad-move-down",name:"Move note down",callback:()=>r("cmdMoveDown")}),this.addCommand({id:"stashpad-move-to-top",name:"Move note to top",callback:()=>r("cmdMoveToTop")}),this.addCommand({id:"stashpad-move-to-bottom",name:"Move note to bottom",callback:()=>r("cmdMoveToBottom")}),this.addCommand({id:"stashpad-outdent",name:"Outdent (move to grandparent)",callback:()=>r("cmdOutdent")}),this.addCommand({id:"stashpad-set-color",name:"Set note color\u2026",callback:()=>r("cmdSetColor")}),this.addCommand({id:"stashpad-clone",name:"Clone selection (duplicate / copy notes)",callback:()=>r("cmdClone")}),this.addCommand({id:"stashpad-fork-note",name:"Fork into a separate note (copy under a chosen parent)",callback:()=>r("cmdForkNote")}),this.addCommand({id:"stashpad-insert-template",name:"Insert template (clone an existing note)",callback:()=>r("cmdInsertTemplate")}),this.addCommand({id:"stashpad-toggle-expand",name:"Show more / show less (expand toggle)",callback:()=>r("cmdToggleExpand")}),this.addCommand({id:"stashpad-expand-all",name:"Expand all (show every note's full body)",callback:()=>r("cmdExpandAll")}),this.addCommand({id:"stashpad-collapse-all",name:"Collapse all (clamp every note's body)",callback:()=>r("cmdCollapseAll")}),this.addCommand({id:"stashpad-pick-move",name:"Move (in-list, arrow + Enter)",callback:()=>r("cmdInListPicker")}),this.addCommand({id:"stashpad-open-in-new-tab",name:"Open in new Stashpad tab",callback:()=>r("cmdOpenInNewStashpadTab")}),this.addCommand({id:"stashpad-toggle-complete",name:"Toggle complete (strikethrough)",callback:()=>r("cmdToggleComplete")}),this.addCommand({id:"stashpad-toggle-task",name:"Toggle task (todo)",callback:()=>r("cmdToggleTask")}),this.addCommand({id:"stashpad-set-due",name:"Set due date\u2026",callback:()=>r("cmdSetDue")}),this.addCommand({id:"stashpad-dump-perf",name:"Dump performance profile (copy to clipboard)",callback:async()=>{if(!this.settings.enablePerfProfiling){new N.Notice("Enable \u201CPerformance profiling\u201D in Stashpad settings first, then use the app and run this again.");return}let p=ke.report();console.log(p);try{await navigator.clipboard.writeText(p)}catch{}new N.Notice("Performance profile copied to clipboard (also in the console).")}}),this.addCommand({id:"stashpad-reset-perf",name:"Reset performance profile",callback:()=>{ke.reset(),new N.Notice("Performance profile reset.")}}),this.addCommand({id:"stashpad-jump-to-top",name:"Jump to top of list",callback:()=>r("jumpToTop")}),this.addCommand({id:"stashpad-jump-to-bottom",name:"Jump to bottom of list",callback:()=>r("jumpToBottom")}),this.addCommand({id:"stashpad-assign",name:"Assign task to\u2026",callback:()=>r("cmdAssign")}),this.addCommand({id:"stashpad-open-import-log",name:"Open import log",callback:async()=>{await this.importLog.load();let{ImportLogModal:p}=await Promise.resolve().then(()=>(we(),$i));new p(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:p=>{let I=this.importService.defaultDestination();return p?!!I:(I&&this.runImportLooseFiles(I),!0)}}),this.addCommand({id:"stashpad-rerun-slug-pass",name:"Re-run filename (slug) pass on this folder",checkCallback:p=>{let I=this.importService.defaultDestination();return p?!!I:(I&&this.runFolderSlugPass(I),!0)}}),this.addCommand({id:"stashpad-rerun-frontmatter-backfill",name:"Re-run frontmatter backfill (recovery links) on this folder",checkCallback:p=>{let I=this.importService.defaultDestination();return p?!!I:(I&&this.runFolderFrontmatterBackfill(I),!0)}}),this.addCommand({id:"stashpad-select-all",name:"Select all visible notes",callback:()=>r("cmdSelectAll")}),this.addCommand({id:"stashpad-copy-codeblock",name:"Copy code from codeblock",callback:()=>r("cmdCopyCodeBlock")}),this.addCommand({id:"stashpad-open-panels",name:"Open Stashpad panels (sidebar)",callback:()=>void xs(this.app)}),this.addCommand({id:"stashpad-open-folder-panel",name:"Open folder panel (sidebar)",callback:()=>void Tn(this.app)}),this.addCommand({id:"stashpad-open-detail",name:"Open Stashpad detail panel (right sidebar)",callback:()=>void en(this.app)}),this.addCommand({id:"stashpad-reveal-active-note",name:"Open this note in Stashpad",checkCallback:p=>{let I=this.app.workspace.getActiveFile(),m=!!I&&I.extension==="md"&&this.isStashpadNoteFile(I);return p||m&&I&&this.revealNoteInStashpad(I),m}});let l=Object.keys(zi);for(let p of l){let I=zi[p];this.addCommand({id:`stashpad-open-panels-${p}`,name:`Open Stashpad panel: ${I.label}`,callback:async()=>{await xs(this.app),this.app.workspace.getLeavesOfType(Ct)[0]?.view?.setActivePanel?.(p)}})}this.addCommand({id:"stashpad-task-review",name:"Open daily task review",callback:()=>new oi(this.app,this).open()}),this.addCommand({id:"stashpad-swap-with-parent",name:"Swap with parent (ouroboros)",callback:()=>r("cmdSwapWithParent")}),this.addCommand({id:"stashpad-toggle-pin",name:"Pin / unpin selected note (sidebar)",callback:()=>r("cmdTogglePin")}),this.addCommand({id:"stashpad-list-pin",name:"Pin / unpin to top of list",callback:()=>r("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:()=>r("cmdCloneStashpadTab")}),this.addCommand({id:"stashpad-undo",name:"Undo last Stashpad action",callback:()=>r("cmdUndo")}),this.addCommand({id:"stashpad-redo",name:"Redo last undone Stashpad action",callback:()=>r("cmdRedo")}),this.addCommand({id:"stashpad-export-stash",name:"Export selection to .stash",callback:()=>r("cmdExportStash")}),this.addCommand({id:"stashpad-export-okf",name:"Export selection as OKF bundle (.zip / .tar.gz / .stash)",callback:()=>r("cmdExportOkf")}),this.addCommand({id:"stashpad-import-stash",name:"Import .stash file\u2026",callback:()=>r("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:p=>{let I=ht(),m=I&&I.noteFolder;return m?(p||(new N.Notice(`Running integrity check on "${m}"\u2026`),this.runIntegrityCheckOnFolder(m).then(()=>{new N.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 N.Notice("Stashpad: rebuilding author registry\u2026");try{let p=await this.rebuildAuthorRegistry();this.notifications.show({message:`Author registry rebuilt: ${p.total} author(s) \u2014 ${p.fromStubs} from stubs, ${p.fromNotes} from note links.`,kind:"success",category:"system"})}catch(p){new N.Notice(`Author registry rebuild failed: ${p.message}`)}}}),this.addCommand({id:"stashpad-restore-author-stubs",name:"Restore missing author stubs (from registry)",callback:async()=>{new N.Notice("Stashpad: restoring author stubs\u2026");try{let p=await this.restoreMissingAuthorStubs();this.notifications.show({message:p.created>0?`Restored ${p.created} author stub(s) across ${p.folders} folder(s).`:`No missing author stubs \u2014 all present across ${p.folders} folder(s).`,kind:"success",category:"system"})}catch(p){new N.Notice(`Restore author stubs failed: ${p.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:()=>{this.runRebootstrapWithUI().catch(()=>{})}}),this.addCommand({id:"stashpad-adopt-note",name:"Adopt active note into Stashpad (fill missing frontmatter)",checkCallback:p=>{let I=this.app.workspace.getActiveFile();return!I||I.extension!=="md"?!1:(p||this.adoptNote(I),!0)}}),this.addCommand({id:"stashpad-open-notification-history",name:"Open notification history",callback:()=>{Promise.resolve().then(()=>(we(),$i)).then(({NotificationHistoryModal:p,LogModal:I})=>{new p(this.app,this.notifications,async()=>{let m=this.app.vault.adapter,B=this.pluginPrivatePath("log.jsonl");if(!await m.exists(B)){new N.Notice("No log yet \u2014 make some changes first.");return}let C=await m.read(B);new I(this.app,C,B).open()},this.settings.authorId||null,m=>this.lookupNoteAuthorIds(m)).open()})}});let c=[{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 p of c){let I=`stashpad-toggle-${String(p.key).replace(/[A-Z]/g,m=>`-${m.toLowerCase()}`)}`;this.addCommand({id:I,name:`Toggle: ${p.label}`,callback:async()=>{let m=!this.settings[p.key];this.settings[p.key]=m,await this.saveSettings(),new N.Notice(`${p.label}: ${m?"ON":"OFF"}`)}})}this.addCommand({id:"stashpad-open-settings",name:"Open Stashpad settings",callback:()=>{let p=this.app.setting;!p?.open||!p?.openTabById||(p.open(),p.openTabById(this.manifest.id))}}),this.addCommand({id:"stashpad-search-settings",name:"Search Stashpad settings\u2026",callback:()=>{let p=this.app.setting;!p?.open||!p?.openTabById||(p.open(),p.openTabById(this.manifest.id),setTimeout(()=>{p?.modalEl?.querySelector?.("input[type='search']")?.focus()},0))}});for(let p of Xs)this.addCommand({id:`stashpad-open-settings-${p.id}`,name:`Open Stashpad settings: ${p.label}`,callback:()=>{let I=this.app.setting;!I?.open||!I?.openTabById||(I.open(),I.openTabById(this.manifest.id))}});let A=()=>{let p=this.app.setting;!p?.open||!p?.openTabById||(p.open(),p.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:p}=await Promise.resolve().then(()=>(Wi(),Hs)),I=await p(this.app,this,this.settings);if(I.error==="no-dest"){new N.Notice("Set a Designated Stashpad folder for Index in settings first.",6e3),A();return}if(I.error==="no-home"){new N.Notice(`"${this.settings.jdIndexStashpadFolder}" has no Stashpad home note. Open the folder in Stashpad first to create one.`,7e3);return}let{buildJdPreviewNotice:m}=await Promise.resolve().then(()=>(Wi(),Hs));m(this.app,I)}catch(p){console.error("[stashpad] preview failed",p),new N.Notice(`Preview failed: ${p?.message??p}`,8e3)}}}),this.addCommand({id:"stashpad-decrypt-folder-bundle",name:"Decrypt a folder bundle (encrypted non-Stashpad folder)\u2026",callback:async()=>{if(!this.encryption.isConfigured()){new N.Notice("Stashpad encryption isn't set up.");return}let p=await Al(this.app);if(!p.length){new N.Notice("No encrypted folder bundles found in this vault.");return}new gr(this.app,p,I=>void this.decryptFolderFromExplorer(I.folder)).open()}}),this.addCommand({id:"stashpad-build-jd-index",name:"Build JD index notes (creates Stashpad-note hierarchy)",callback:async()=>{try{let{buildJdIndexNotes:p,scanForJdNotes:I,JdBuildConfirmModal:m}=await Promise.resolve().then(()=>(Wi(),Hs));if(!(this.settings.jdIndexStashpadFolder??"").trim().replace(/^\/+|\/+$/g,"")){new N.Notice("Set a Designated Stashpad folder for Index in settings first.",6e3),A();return}let C=I(this.app,this,this.settings);new m(this.app,this,this.settings,C.indexed.length,async()=>{try{let y=await p(this.app,this,this.settings);if(y.error==="no-dest"){new N.Notice("Set a Designated Stashpad folder for Index in settings first.",6e3),A();return}if(y.error==="dest-not-stashpad"){new N.Notice(`"${y.destFolder}" isn't a known Stashpad folder. Pick a real Stashpad folder in settings.`,7e3),A();return}this.settings.jdIndexHasBuilt=!0,await this.saveSettings(),new N.Notice(`Index built: ${y.created} created, ${y.updated} updated, ${y.skipped} skipped \u2192 ${y.destFolder}`,6e3)}catch(y){console.error("[stashpad] build failed",y),new N.Notice(`Build failed: ${y?.message??y}`,8e3)}}).open()}catch(p){console.error("[stashpad] build failed",p),new N.Notice(`Build failed: ${p?.message??p}`,8e3)}}});let h=p=>{if(p.extension!==tt)return;let I=(this.settings.importDropFolder||"").trim().replace(/^\/+|\/+$/g,""),m=(this.settings.exportFolder||"").trim().replace(/^\/+|\/+$/g,""),B=p.parent?.path||"",C=B.split("/").pop()??"";if(I&&C===I){if(m&&B.endsWith(`/${m}`))return;let w=B.slice(0,B.length-I.length).replace(/\/+$/,"")||this.settings.folder;this.autoImportStash(p,w);return}this.settings.autoImport&&this.importService.isArmed()&&(Nt(p.path)||this.discoverStashpadFolders().includes(B)&&this.autoImportStash(p,B))};this.registerEvent(this.app.vault.on("create",p=>{p instanceof N.TFile&&h(p)})),this.registerEvent(this.app.vault.on("rename",p=>{p instanceof N.TFile&&h(p)}));let g=p=>{if(p.extension!=="md")return;let I=p.parent?.path?.replace(/\/+$/,"")??"";this.discoverStashpadFolders().includes(I)&&setTimeout(()=>{this.fixOrphanParentForFile(p)},800)},u=p=>{if(p.extension!=="md")return;let I=(this.settings.importDropFolder||"").trim().replace(/^\/+|\/+$/g,"");if(!I)return;let m=p.parent?.path?.replace(/\/+$/,"")??"";if((m.split("/").pop()??"")!==I)return;let C=m.slice(0,m.length-I.length).replace(/\/+$/,"");!C||!this.discoverStashpadFolders().includes(C)||setTimeout(()=>{this.adoptMarkdownDrop(p,C)},200)};this.registerEvent(this.app.vault.on("create",p=>{p instanceof N.TFile&&(g(p),u(p))})),this.registerEvent(this.app.vault.on("rename",p=>{p instanceof N.TFile&&(g(p),u(p))})),this.registerEvent(this.app.vault.on("delete",p=>{if(!(p instanceof N.TFolder))return;let I=p.path.replace(/\/+$/,"");this.knownStashpadFolders.has(I)&&this.handleStashpadFolderDeleted(I)})),this.registerEvent(this.app.vault.on("rename",(p,I)=>{p instanceof N.TFile&&this.maybeReHomeOnCrossFolderMove(p,I)})),this.registerEvent(this.app.vault.on("rename",(p,I)=>{p instanceof N.TFile&&this.maybeArchiveOnMoveIn(p,I)})),this.registerEvent(this.app.vault.on("rename",(p,I)=>{p instanceof N.TFolder&&(this.retargetStashpadViewsForFolderRename(I,p.path),this.remapFolderPathInSettings(I,p.path))}));let f=`${this.manifest.dir.replace(/\/+$/,"")}/data.json`;this.registerEvent(this.app.vault.on("raw",p=>{p===f&&this.scheduleExternalDataJsonReload()})),this.registerEvent(this.app.vault.on("create",p=>{p instanceof N.TFile?this.importService.enqueue(p):p instanceof N.TFolder&&this.importService.enqueueFolder(p)})),this.registerEvent(this.app.vault.on("rename",p=>{p instanceof N.TFile?this.importService.enqueue(p):p instanceof N.TFolder&&this.importService.enqueueFolder(p)})),this.registerEvent(this.app.vault.on("rename",(p,I)=>{p instanceof N.TFile&&this.maybeAdoptAuthorRename(p,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 e=this.manifest.dir;if(!e)return;let t=`${e.replace(/\/+$/,"")}/manifest.json`,i=this.app.vault.adapter;if(!await i.exists(t))return;let s=JSON.parse(await i.read(t))?.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(e){console.debug("[Stashpad] synced-build check failed",e)}}reloadAppForUpdate(){try{window.localStorage?.setItem(hr,"1")}catch{}try{if(this.app.commands?.executeCommandById?.("app:reload"))return}catch(e){console.warn("[Stashpad] app:reload command failed",e)}try{window.location.reload()}catch{new N.Notice("Reload Obsidian (close + reopen) to apply the Stashpad update.")}}async unghostStashpadTabsIfFlagged(){let e=!1;try{e=window.localStorage?.getItem(hr)==="1"}catch{}if(e){try{window.localStorage?.removeItem(hr)}catch{}for(let t of this.app.workspace.getLeavesOfType(z))try{let i=t;i.isDeferred&&typeof i.loadIfDeferred=="function"&&await i.loadIfDeferred()}catch(i){console.warn("[Stashpad] un-ghost leaf failed",i)}}}isSemverGreater(e,t){let i=e.split(".").map(o=>parseInt(o,10)||0),s=t.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,l=s[o]??0;if(r!==l)return r>l}return!1}parseAuthorFilePath(e){let t=e.match(/\/_authors\/([^/]+?)-([a-z0-9]{4,12})\.md$/i);return t?{name:t[1].replace(/-/g," "),id:t[2]}:null}authorNameToSafe(e){return e.replace(/[^\w\- ]+/g,"").trim().replace(/\s+/g,"-")||"author"}async syncAuthorFilesToName(){let e=(this.settings.authorId??"").trim(),t=(this.settings.authorName??"").trim();if(!e||!t)return;let i=this.authorNameToSafe(t);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!==e)continue;let l=`${n}/${i}-${e}.md`,c=o;if(o.path!==l)try{this.authorRenameInFlight.add(o.path),this.authorRenameInFlight.add(l),await this.app.fileManager.renameFile(o,l);let A=this.app.vault.getAbstractFileByPath(l);A&&(c=A)}catch(A){this.authorRenameInFlight.delete(o.path),this.authorRenameInFlight.delete(l),console.warn("[Stashpad] author file rename failed",A);continue}try{await this.refreshAuthorStub(c)}catch{}}}}async refreshAuthorStub(e){let t=(this.settings.authorName??"").trim(),i=(this.settings.authorRole??"").trim(),s=(this.settings.authorDepartment??"").trim();if(t)try{let n=await this.app.vault.read(e),o=n.replace(/^# .*$/m,`# ${t}`);o!==n&&await this.app.vault.modify(e,o),await this.app.fileManager.processFrontMatter(e,r=>{r.aliases=[t],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(e,t){let i=this.authorRenameInFlight.delete(e.path),s=this.authorRenameInFlight.delete(t);if(i||s)return;let n=this.parseAuthorFilePath(e.path);if(!n)return;let o=(this.settings.authorId??"").trim();if(!o||n.id!==o)return;let r=n.name.trim();!r||r===(this.settings.authorName??"").trim()||(this.settings.authorName=r,await this.saveSettings(),await this.syncAuthorFilesToName())}async adoptMarkdownDrop(e,t){try{let i=this.app.vault.adapter,s=e.name,n=s.lastIndexOf("."),o=n>0?s.slice(0,n):s,r=n>0?s.slice(n):"",l=0;for(;await i.exists(`${t}/${s}`);)l+=1,s=`${o}-${l}${r}`;let c=`${t}/${s}`;await this.app.fileManager.renameFile(e,c);let A=this.app.vault.getAbstractFileByPath(c);A instanceof N.TFile&&setTimeout(()=>{this.fixOrphanParentForFile(A)},500),this.notifications.show({message:`Imported \`${e.name}\` \u2192 \`${t}\``,kind:"success",category:"import",folder:t,affectedPaths:[c]})}catch(i){console.warn("Stashpad: markdown drop adoption failed",i),this.notifications.show({message:`Couldn't import \`${e.name}\`: ${i.message}`,kind:"error",category:"import"})}}async fixOrphanParentForFile(e){try{let t=this.app.metadataCache.getFileCache(e)?.frontmatter,i=typeof t?.id=="string"?t.id.trim():"",s=t?.parent,n=typeof s=="string"?s.trim()!=="":s!=null,o=typeof t?.created=="string"&&t.created.trim()!=="",r=!i,l=!n,c=!o;if(!r&&!l&&!c)return;let A,h=!1,g=!1;if(await this.app.fileManager.processFrontMatter(e,p=>{if(r&&(typeof p.id=="string"&&p.id.trim()||(A=this.mintNoteId(),p.id=A)),l){let I=p.parent;(typeof I=="string"?I.trim()!=="":I!=null)||(p.parent=S,h=!0)}c&&(typeof p.created=="string"&&p.created.trim()||(p.created=new Date(e.stat.ctime).toISOString(),g=!0))}),!A&&!h&&!g)return;let u=this.newLog(),f=A||i;f&&await u.append({type:"parent_change",id:f,payload:{from:null,to:S,reason:"orphan_auto_fix",path:e.path,addedId:!!A,addedParent:h,addedCreated:g}}),new N.Notice(`Adopted ${e.basename} \u2192 Home`)}catch(t){console.warn("Stashpad: orphan auto-fix failed",t)}}maybeReHomeOnCrossFolderMove(e,t){if(e.extension!=="md")return;let i=e.parent?.path?.replace(/\/+$/,"")??"",s=t.lastIndexOf("/"),n=(s>=0?t.slice(0,s):"").replace(/\/+$/,"");i!==n&&this.discoverStashpadFolders().includes(i)&&(this.reHomePending.has(e.path)||(this.reHomePending.add(e.path),setTimeout(()=>{this.reHomePending.delete(e.path),this.reHomeDanglingParent(e,i)},900)))}async reHomeDanglingParent(e,t){try{let i=this.app.metadataCache.getFileCache(e)?.frontmatter,s=typeof i?.id=="string"?i.id.trim():"",n=typeof i?.parent=="string"?i.parent.trim():"";if(!s||!n||n===S||this.app.vault.getMarkdownFiles().some(r=>(r.parent?.path?.replace(/\/+$/,"")??"")===t&&this.app.metadataCache.getFileCache(r)?.frontmatter?.id===n))return;await this.app.fileManager.processFrontMatter(e,r=>{let l=typeof r.parent=="string"?r.parent.trim():"";l&&l!==S&&(r.parent=S)}),await this.newLog().append({type:"parent_change",id:s,payload:{from:n,to:S,reason:"rehome_cross_folder_move",path:e.path}}),new N.Notice(`Re-homed ${e.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(e,t){try{let i=new Uint8Array(await this.app.vault.readBinary(e));if(Me(i)){this.importService.parkEncrypted(e.path),this.notifyPendingEncrypted();return}let s=await pi(this.app,i);if(!s)return;let n=ht(),o=new Set;if(n&&typeof n.collectExistingIds=="function"&&n.noteFolder===t)for(let c of n.collectExistingIds())o.add(c);else for(let c of this.app.vault.getMarkdownFiles()){if(!c.path.startsWith(t+"/"))continue;let A=this.app.metadataCache.getFileCache(c)?.frontmatter?.id;typeof A=="string"&&o.add(A)}let r=await Je(this.app,s,t,o,{stripReserved:!0});try{await this.newLog().append({type:"stash_import",id:S,payload:{from:e.path,into:t,noteCount:r.notesWritten,attachmentsWritten:r.attachmentsWritten,collisionsRenamed:r.collisionsRenamed,auto:!0}})}catch{}try{await this.app.fileManager.trashFile(e)}catch{}let l=[`Auto-imported ${r.notesWritten} note${r.notesWritten===1?"":"s"} from ${e.name}`];r.attachmentsWritten&&l.push(`+ ${r.attachmentsWritten} attachment${r.attachmentsWritten===1?"":"s"}`),r.collisionsRenamed&&l.push(`(${r.collisionsRenamed} renamed)`),this.notifications.show({message:l.join(" "),kind:"success",category:"import",folder:t}),n&&typeof n.debouncedRender=="function"&&n.debouncedRender()}catch(i){this.notifications.show({message:`Stashpad: auto-import failed +`)}catch(t){console.warn("[Stashpad] import log append failed",t)}})}async ensureDir(){if(this.dirOk)return;let a=this.app.vault.adapter,t=this.path.slice(0,this.path.lastIndexOf("/")).split("/").filter(Boolean),i="";for(let s of t)i=i?`${i}/${s}`:s,await a.exists(i)||await a.mkdir(i);this.dirOk=!0}};Bs.MAX_ENTRIES=5e3;var qn=Bs;var Yn=class Yn{constructor(a,e){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=`${e.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 e=JSON.parse(await a.read(this.path));if(e?.schema===1&&e.entries){for(let[t,i]of Object.entries(e.entries))this.map.set(t,i);for(let t of[...this.map.keys()])this.app.vault.getAbstractFileByPath(t)||(this.map.delete(t),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,e){this.map.set(a,e),this.dirty=!0,this.scheduleSave()}scheduleSave(){this.saveTimer==null&&(this.saveTimer=window.setTimeout(()=>{this.saveTimer=null,this.save()},Yn.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){this.dirty=!0,console.warn("[Stashpad] render cache save failed",a)}}),this.writeChain):this.writeChain}async ensureDir(){if(this.dirOk)return;let a=this.app.vault.adapter,t=this.path.slice(0,this.path.lastIndexOf("/")).split("/").filter(Boolean),i="";for(let s of t)i=i?`${i}/${s}`:s,await a.exists(i)||await a.mkdir(i);this.dirOk=!0}};Yn.SAVE_DEBOUNCE_MS=8e3;var $n=Yn;var gr="stashpad:unghost-after-reload",Ct=class Ct extends M.Plugin{constructor(){super(...arguments);this.settings={...vt};this.reEncryptScheduler=null;this.usedNoteIds=null;this.debugBuffer=[];this.undoStacks=new Map;this.lastActiveStashpadLeaf=null;this.rebootstrapInProgress=!1;this.pendingEncBlobs=new Set;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.archiveMigrationInFlight=!1;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.pendingForkDeletes=new Set;this.writeChain=Promise.resolve();this.lastSeenSettingsRev=0;this.settingsBaseline={};this.externalReloadDebounced=(0,M.debounce)(()=>void this.onExternalDataJsonChange(),600,!1)}trace(e,t){if(!this.settings.debugTrace)return;let i="";if(t)try{i=" "+JSON.stringify(t)}catch{i=" [unserializable]"}let s=Math.round(performance.now());this.debugBuffer.push(`+${s}ms ${e}${i}`),this.debugBuffer.length>Ct.DEBUG_BUFFER_MAX&&this.debugBuffer.splice(0,this.debugBuffer.length-Ct.DEBUG_BUFFER_MAX)}getDebugTrace(){return this.debugBuffer.join(` +`)}clearDebugTrace(){this.debugBuffer=[]}get notifications(){return this._notifications||(this._notifications=new Ls(this.app)),this._notifications}get authorRegistry(){return this._authorRegistry||(this._authorRegistry=new On(this.app,this.pluginPrivatePath())),this._authorRegistry}get importService(){return this._importService||(this._importService=new Jn(this)),this._importService}get importLog(){return this._importLog||(this._importLog=new qn(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 $n(this.app,this.pluginPrivatePath())),this._renderCacheStore}async onunload(){try{this.encryption?.dispose()}catch{}try{for(let e of this.archivePending.values())window.clearTimeout(e.timer);this.archivePending.clear()}catch{}try{this.reEncryptScheduler?.dispose()}catch{}try{await this._renderCacheStore?.save()}catch{}}pluginPrivatePath(e=""){let i=`${this.manifest.dir.replace(/\/+$/,"")}/.stashpad`;return e?`${i}/${e.replace(/^\/+/,"")}`:i}newLog(){return new Gn(this.app,this.pluginPrivatePath(),()=>(this.settings?.authorName??"").trim())}async migrateLegacyPaths(){let e=this.app.vault.adapter,t=this.pluginPrivatePath(),i=async()=>{let r=t.split("/").filter(Boolean),l="";for(let c of r)l=l?`${l}/${c}`:c,await e.exists(l)||await e.mkdir(l)},s=`${this.manifest.dir.replace(/\/+$/,"")}/data.json`,n=this.pluginPrivatePath("data.json");if(await e.exists(n))try{let r=await e.read(n);await e.write(s,r),await e.write(`${n}.bak`,r),await e.remove(n),console.debug("[Stashpad] relocated data.json \u2192 standard path (for Obsidian Sync)")}catch(r){console.warn("Stashpad: data.json relocation failed",r)}let o=".stashpad";if(await e.exists(o))try{await i();let r=await e.list(o);for(let l of r.files){let c=l.replace(/^.*\//,""),A=this.pluginPrivatePath(c);if(!await e.exists(A))try{let h=await e.read(l);await e.write(A,h),console.debug("[Stashpad] migrated",l,"\u2192",A)}catch(h){console.warn(`Stashpad: failed to migrate ${l}`,h)}}}catch(r){console.warn("Stashpad: .stashpad migration scan failed",r)}}async createNewStashpad(e){let t=e.trim().replace(/^\/+|\/+$/g,"");if(!t)throw new Error("Folder name is empty");let i=this.app.vault.adapter,s=t.split("/").filter(Boolean),n="";for(let c of s)n=n?`${n}/${c}`:c,await i.exists(n)||await i.mkdir(n);let o=`${t}/Home.md`;if(await i.exists(o)){let c=this.app.vault.getAbstractFileByPath(o);c&&await this.app.fileManager.processFrontMatter(c,A=>{(typeof A.id!="string"||!A.id)&&(A.id=k),"parent"in A||(A.parent=null),(typeof A.created!="string"||!A.created)&&(A.created=new Date().toISOString())});return}let r=new Date().toISOString(),l=["---",`id: ${k}`,"parent: null",`created: ${r}`,"---","Home"].join(` +`);await this.app.vault.create(o,l);try{await this.seedLocalAuthorStub(t)}catch{}try{await this.seedKnownAuthorsInFolder(t)}catch{}}collectColorsInFolder(e){let t=new Map,i=e.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,l=typeof r?.color=="string"?r.color.trim():"";if(!l||!/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(l))continue;let c=l.toLowerCase();t.set(c,(t.get(c)??0)+1)}let s=[...t.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(e,t,i){let s=e.replace(/\/+$/,""),n=t.toLowerCase(),o=0;for(let l of this.app.vault.getMarkdownFiles()){let c=l.parent?.path?.replace(/\/+$/,"")??"";if(c!==s&&!c.startsWith(s+"/"))continue;let A=this.app.metadataCache.getFileCache(l)?.frontmatter;if((typeof A?.color=="string"?A.color.trim().toLowerCase():"")===n)try{await this.app.fileManager.processFrontMatter(l,p=>{i?p.color=i:delete p.color}),o++}catch(p){console.warn(`Stashpad: recolor failed for ${l.path}`,p)}}let r=this.settings.colorAliases?.[s];if(r){let l=r[n];l&&(delete r[n],i&&(r[i.toLowerCase()]=l),Object.keys(r).length===0&&delete this.settings.colorAliases[s],await this.saveSettings())}return o}getColorAlias(e,t){let i=e.replace(/\/+$/,""),s=this.settings.colorAliases?.[i];if(!s)return;let n=s[t.toLowerCase()];return n&&n.trim()?n:void 0}async setColorAlias(e,t,i){let s=e.replace(/\/+$/,""),n=t.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(e,t=2e3){let i=e.trim().replace(/^\/+|\/+$/g,"");if(!i)return;let s=Date.now();for(;Date.now()-s<t;){if(this.discoverStashpadFolders().includes(i))return;await new Promise(n=>setTimeout(n,80))}}importExcludePrefixList(){return(this.settings.importExcludePrefixes??"_").split(",").map(e=>e.trim()).filter(Boolean)}pathHasExcludedSegment(e){let t=this.importExcludePrefixList();return t.length?e.replace(/\/+$/,"").split("/").some(i=>t.some(s=>i.startsWith(s))):!1}discoverStashpadFolders(){let e=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&&!this.pathHasExcludedSegment(n)&&!Mt(n)&&e.add(n)}let t=[...e].sort();return this.knownStashpadFolders=new Set(t),t}closeStashpadTabsFor(e){let t=0;for(let i of this.app.workspace.getLeavesOfType(z)){let s=i.view?.noteFolder??"";s||(s=((i.getViewState?.()?.state??{}).folderOverride??"")||this.settings.folder||"Stashpad"),s=(s||"").replace(/\/+$/,""),(s===e||s.startsWith(e+"/"))&&(i.detach(),t++)}return t}retargetStashpadViewsForFolderRename(e,t){let i=(e||"").replace(/\/+$/,""),s=(t||"").replace(/\/+$/,"");if(!i||i===s)return;let n=o=>{let r=(o??"").replace(/\/+$/,"");return r===i?s:r.startsWith(i+"/")?s+r.slice(i.length):null};for(let o of this.app.workspace.getLeavesOfType(z)){let r=o.getViewState(),l=r.state??{},c=o.isDeferred?void 0:o.view?.noteFolder,A=n(c??l.folderOverride);A&&o.setViewState({...r,state:{...r.state??{},folderOverride:A}})}}async remapFolderPathInSettings(e,t){let i=e.replace(/\/+$/,""),s=t.replace(/\/+$/,"");if(!i||!s||i===s)return;let n=this.settings,o=h=>h===i?s:h.startsWith(i+"/")?s+h.slice(i.length):h,r=h=>h&&h.map(o),l=h=>{if(!h)return h;let p={};for(let[u,f]of Object.entries(h))p[o(u)]=f;return p},c=JSON.stringify([n.folderPanelPinned,n.folderPanelDownranked,n.folderPanelHidden,n.archiveFolders,n.searchIncludedFolders,n.searchExcludedFolders,n.defaultArchiveFolder,n.folder,n.folderEncPrefs,n.viewModes,n.encryptionFilter]);n.folderPanelPinned=r(n.folderPanelPinned)??n.folderPanelPinned,n.folderPanelDownranked=r(n.folderPanelDownranked)??n.folderPanelDownranked,n.folderPanelHidden=r(n.folderPanelHidden)??n.folderPanelHidden,n.archiveFolders=r(n.archiveFolders)??n.archiveFolders,n.searchIncludedFolders=r(n.searchIncludedFolders)??n.searchIncludedFolders,n.searchExcludedFolders=r(n.searchExcludedFolders)??n.searchExcludedFolders,n.defaultArchiveFolder&&(n.defaultArchiveFolder=o(n.defaultArchiveFolder)),((n.folder||"").replace(/\/+$/,"")===i||(n.folder||"").startsWith(i+"/"))&&(n.folder=o((n.folder||"").replace(/\/+$/,""))),n.folderEncPrefs=l(n.folderEncPrefs)??n.folderEncPrefs,n.viewModes=l(n.viewModes)??n.viewModes,n.encryptionFilter&&(n.encryptionFilter=l(n.encryptionFilter)),JSON.stringify([n.folderPanelPinned,n.folderPanelDownranked,n.folderPanelHidden,n.archiveFolders,n.searchIncludedFolders,n.searchExcludedFolders,n.defaultArchiveFolder,n.folder,n.folderEncPrefs,n.viewModes,n.encryptionFilter])!==c&&await this.saveSettings()}async prunePlacementFor(e){let t=this.settings,i=o=>(o??[]).filter(r=>r!==e&&!r.startsWith(e+"/")),s=(t.folderPanelPinned?.length??0)+(t.folderPanelDownranked?.length??0)+(t.folderPanelHidden?.length??0);t.folderPanelPinned=i(t.folderPanelPinned),t.folderPanelDownranked=i(t.folderPanelDownranked),t.folderPanelHidden=i(t.folderPanelHidden),t.folderPanelPinned.length+t.folderPanelDownranked.length+t.folderPanelHidden.length!==s&&await this.saveSettings()}async deleteStashpadFolderWithUndo(e){let t=e.path.replace(/\/+$/,""),i=e.name,s=this.app.vault.adapter,n=".trash";try{await s.exists(n)||await s.mkdir(n)}catch(c){console.warn("[Stashpad] couldn't ensure .trash",c)}let o=`${n}/${i}`;for(let c=1;await s.exists(o);c++)o=`${n}/${i} (${c})`;this.suppressedFolderDeletes.add(t),window.setTimeout(()=>this.suppressedFolderDeletes.delete(t),5e3);let r=this.closeStashpadTabsFor(t);await this.prunePlacementFor(t),this.knownStashpadFolders.delete(t);try{await s.rename(t,o)}catch(c){console.warn("[Stashpad] folder delete failed",c),this.suppressedFolderDeletes.delete(t),new M.Notice("Delete failed (see console).");return}let l=r>0?`Deleted \u201C${i}\u201D \u2014 closed ${r} open tab${r===1?"":"s"}.`:`Deleted \u201C${i}\u201D.`;this.notifications.show({message:l,kind:"warning",category:"delete",duration:0,folder:t,actions:[{label:"Undo",onClick:async()=>{try{if(await s.exists(t)){new M.Notice(`Can't undo \u2014 \u201C${i}\u201D already exists.`);return}this.suppressedFolderDeletes.add(t),window.setTimeout(()=>this.suppressedFolderDeletes.delete(t),5e3),await s.rename(o,t),new M.Notice(`Restored \u201C${i}\u201D.`),this.activateViewForFolder(t)}catch(c){console.warn("[Stashpad] folder undo failed",c),new M.Notice("Undo failed (see console).")}}}]})}async handleStashpadFolderDeleted(e){let t=e.replace(/\/+$/,"");if(!t||this.suppressedFolderDeletes.has(t))return;let i=this.closeStashpadTabsFor(t);await this.prunePlacementFor(t),this.knownStashpadFolders.delete(t);let s=t.split("/").pop()||t;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:t})}searchableFolders(e){let t=new Set(this.settings.searchIncludedFolders),i=new Set(this.settings.searchExcludedFolders),s=new Set((this.settings.archiveFolders??[]).map(c=>(c??"").replace(/\/+$/,""))),o=this.discoverStashpadFolders().filter(c=>s.has(c)?!1:t.size>0?t.has(c):!i.has(c)),r=(e||"").trim().replace(/\/+$/,""),l=o.filter(c=>c!==r);return r&&l.unshift(r),l}async maybeSweepFolder(e){let t=(e||"").trim().replace(/\/+$/,"");!t||this.sweptFolders.has(t)||(this.sweptFolders.add(t),setTimeout(()=>{this.runSweep(t,{silent:!0})},3e3))}async runIntegrityCheckOnFolder(e){let t=(e||"").trim().replace(/\/+$/,"");t&&await this.runSweep(t,{silent:!1})}async runSweep(e,t){try{let i=this.newLog(),s={},n=this.app.vault.getMarkdownFiles().filter(c=>c.path===e||c.path.startsWith(e+"/"));for(let c of n){let A=this.app.metadataCache.getFileCache(c)?.frontmatter,h=typeof A?.id=="string"?A.id.trim():"";if(!h)continue;let p=A&&"parent"in A?A.parent??null:null;s[h]={parent:p,path:c.path}}let o=await i.readState(),r=c=>c===e||c.startsWith(e+"/");if(!t.silent){for(let[c,A]of Object.entries(s)){let h=o[c];h?h.parent!==A.parent?await i.append({type:"parent_change",id:c,payload:{from:h.parent,to:A.parent}}):h.path!==A.path&&await i.append({type:"rename",id:c,payload:{from:h.path,to:A.path}}):await i.append({type:"create",id:c,payload:{path:A.path,parent:A.parent}})}for(let[c,A]of Object.entries(o))!s[c]&&r(A.path)&&await i.append({type:"missing",id:c,payload:{lastPath:A.path}})}let l={};for(let[c,A]of Object.entries(o))r(A.path)||(l[c]=A);for(let[c,A]of Object.entries(s))l[c]=A;await i.writeState(l)}catch(i){console.warn("Stashpad: integrity sweep failed",i)}}getUndoStack(e){let t=this.undoStacks.get(e);return t||(t=new Ln,this.undoStacks.set(e,t)),t}mintNoteId(){this.usedNoteIds===null&&this.rebuildUsedNoteIds();let e=this.usedNoteIds,t=eo(i=>e.has(i));return e.add(t),t}rebuildUsedNoteIds(){let e=new Set;for(let t of this.app.vault.getMarkdownFiles()){let i=this.app.metadataCache.getFileCache(t)?.frontmatter?.id;typeof i=="string"&&i.trim()&&e.add(i.trim())}this.usedNoteIds=e}async onload(){this.registerEvent(this.app.metadataCache.on("changed",(g,I,m)=>{let B=m?.frontmatter?.id;this.usedNoteIds&&typeof B=="string"&&B.trim()&&this.usedNoteIds.add(B.trim())})),await this.migrateLegacyPaths(),await this.loadSettings(),ke.enabled=!!this.settings.enablePerfProfiling,this.encryption=new zs(this.app,()=>({...Vs(),...this.settings.encryption??{}}),async g=>{this.settings.encryption=g,await this.saveSettings()}),this.encryption.init().then(async()=>{try{let g=await this.encryption.migrateKeyfileToStashKeys();g>0&&new M.Notice(`Stashpad: moved ${g} folder key${g===1?"":"s"} to the new per-folder format.`)}catch(g){console.warn("[Stashpad] folder-key migration failed (keyfile still works)",g)}}),this.reEncryptScheduler=new Pn(this),this.reEncryptScheduler.start(),this.settingTab=new js(this.app,this),this.addSettingTab(this.settingTab),await this.renderCacheStore.load(),this.registerEvent(this.app.vault.on("delete",g=>this.renderCacheStore.evict(g.path))),this.registerEvent(this.app.vault.on("rename",(g,I)=>this.renderCacheStore.evict(I)));let e=(0,M.debounce)(()=>void this.flushForkSiblingPrune(),250,!0);this.registerEvent(this.app.vault.on("delete",g=>{g instanceof M.TFile&&g.extension==="md"&&(this.pendingForkDeletes.add(g.basename),e())})),this.registerEvent(this.app.vault.on("create",g=>this.onOkfFileEvent(g.path))),this.registerEvent(this.app.vault.on("delete",g=>this.onOkfFileEvent(g.path))),this.registerEvent(this.app.vault.on("rename",(g,I)=>{this.onOkfFileEvent(g.path),this.onOkfFileEvent(I)})),await this.authorRegistry.load();{let g=(this.settings.authorId??"").trim();g&&this.authorRegistry.record({id:g,name:this.settings.authorName,role:this.settings.authorRole,department:this.settings.authorDepartment})}this.registerEvent(this.app.vault.on("create",g=>{g.path.endsWith(".stashenc")&&this.pendingEncBlobs.delete(g.path)})),this.registerEvent(this.app.vault.on("delete",g=>{g.path.endsWith(".stashenc")&&this.pendingEncBlobs.delete(g.path)})),this.app.workspace.onLayoutReady(()=>{this.reconcileLockedRegistry(),window.setTimeout(async()=>{try{await this.migrateArchiveFoldersToSubfolders()}catch(g){console.error("[Stashpad] archive migration failed",g)}try{await this.migrateDeletedToTrashSubfolders()}catch(g){console.error("[Stashpad] trash migration failed",g)}this.pruneZombieArchiveEntries()},5e3),window.setTimeout(()=>{if(!this.settings.reEncryptNudge)return;let g=this.reEncryptWatching().length;if(g===0)return;let I=new M.Notice("",0);I.noticeEl.createSpan({text:`\u{1F513} ${g} previously-encrypted note${g===1?" is":"s are"} still plaintext. `});let m=I.noticeEl.createEl("button",{text:"Review"});m.onclick=()=>{I.hide(),Pe(this,"watch")}},8e3),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(z,g=>new xn(g,this)),this.registerView(Nt,g=>new en(g,this)),this.registerView(Bt,g=>new xs(g,this)),this.registerView(Xt,g=>new Tn(g,this)),this.registerView(Zt,g=>new fn(g,this)),this.registerView(yt,g=>new Hn(g,this)),this.registerObsidianProtocolHandler(ns,g=>{this.handleDeepLink(g)}),this.registerEvent(this.app.workspace.on("active-leaf-change",g=>{g&&g.view.getViewType()===z&&(this.lastActiveStashpadLeaf=g,this.settings.autoOpenDetailPanel&&this.app.workspace.getLeavesOfType(Nt).length===0&&setTimeout(()=>{tn(this.app)},0),this.notifyStashpadSelectionChanged())}));let t=()=>{let g=pt(),I=!!g&&this.app.workspace.activeLeaf&&this.app.workspace.activeLeaf.view===g,m=!!I&&this.settings.hideMobileToolbarInStashpad;document.body.classList.toggle("stashpad-hide-mobile-toolbar",m),document.body.classList.toggle("stashpad-active",!!I)};this.register(Aa(t)),this.registerEvent(this.app.workspace.on("active-leaf-change",t));let i=g=>{try{let I=Array.from(document.querySelectorAll("style")).filter(m=>(m.textContent??"").includes(".stashpad-"));for(let m of I){let B=m.id||"",C=B?`style[data-stashpad-source="${B}"]`:null;if(C&&g.head.querySelector(C))continue;let Q=g.createElement("style");B?Q.setAttribute("data-stashpad-source",B):Q.setAttribute("data-stashpad-source","anon"),Q.textContent=m.textContent??"",g.head.appendChild(Q)}}catch(I){console.warn("[Stashpad] inject popout styles failed",I)}};this.registerEvent(this.app.workspace.on("window-open",g=>{let I=g?.doc??g?.win?.document??null;I&&i(I)})),this.registerEvent(this.app.workspace.on("file-menu",(g,I)=>{if(!(I instanceof M.TFolder))return;let m=I.path.replace(/\/+$/,"");g.addItem(C=>C.setTitle("\u{1F512} Encrypt with Stashpad").setIcon("lock").onClick(()=>void this.encryptFolderFromExplorer(m))),I.children?.some(C=>C instanceof M.TFile&&C.extension==="stashenc")&&!this.folderHasStashpadNotes(m)&&g.addItem(C=>C.setTitle("\u{1F513} Decrypt with Stashpad").setIcon("unlock").onClick(()=>void this.decryptFolderFromExplorer(m))),this.discoverStashpadFolders().includes(m)&&g.addItem(C=>{C.setTitle("Open folder in Stashpad").setIcon("layout-list").onClick(()=>void this.openFolderInStashpad(m))})})),setTimeout(()=>{try{let g=this.app.workspace;typeof g.iterateAllLeaves=="function"&&g.iterateAllLeaves(I=>{let m=I?.view?.containerEl?.ownerDocument;m&&m!==document&&i(m)})}catch{}},200),t(),this.register(()=>document.body.classList.remove("stashpad-hide-mobile-toolbar","stashpad-active"));let s=window.visualViewport,n=()=>{let g=document.querySelector(".mobile-toolbar, .mobile-toolbar-container"),I=g&&g.isConnected?g.offsetHeight:0;document.body.style.setProperty("--stashpad-toolbar-h",`${I}px`);let m=0;s&&(m=Math.max(0,window.innerHeight-s.height-s.offsetTop)),document.body.style.setProperty("--stashpad-vv-bottom-gap",`${m}px`),document.body.classList.toggle("stashpad-keyboard-open",m>100)};n(),s&&(s.addEventListener("resize",n),s.addEventListener("scroll",n),this.register(()=>{s.removeEventListener("resize",n),s.removeEventListener("scroll",n)})),window.addEventListener("resize",n),this.register(()=>window.removeEventListener("resize",n)),requestAnimationFrame(n),setTimeout(n,250),setTimeout(n,1e3),this.addRibbonIcon("list-tree","Open Stashpad",()=>{if(this.discoverStashpadFolders().length===0){this.activateView({reveal:!0});return}this.openFolderPicker()}).addEventListener("contextmenu",g=>{g.preventDefault(),this.openFolderPicker()}),this.addRibbonIcon("panel-left","Open Stashpad panels (sidebar)",()=>{Ns(this.app)}),this.addRibbonIcon("folders","Open Stashpad folder panel (sidebar)",()=>{Rn(this.app)}),this.addRibbonIcon("panel-right","Open Stashpad detail panel (right sidebar)",()=>{tn(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()});let r=g=>{let I=pt();I&&typeof I[g]=="function"&&I[g]()};this.addCommand({id:"stashpad-toggle-split",name:"Toggle split-on-newlines",callback:()=>r("toggleSplit")}),this.addCommand({id:"stashpad-fork-version",name:"Fork as a version (alternate draft in this sheet)",callback:()=>r("cmdForkVersion")}),this.addCommand({id:"stashpad-mark-version-final",name:"Mark version as final (sheet)",callback:()=>r("cmdMarkVersionFinal")}),this.addCommand({id:"stashpad-command-palette",name:"Command palette (Stashpad only)",callback:()=>r("openStashpadCommandPalette")}),this.addCommand({id:"stashpad-lock-selection",name:"Encrypt (lock) selection (notes + children)",callback:()=>r("cmdLockSelection")}),this.addCommand({id:"stashpad-lock-selection-hide-name",name:"Encrypt (lock) selection + hide filename (override folder setting)",callback:()=>r("cmdLockSelectionHideName")}),this.addCommand({id:"stashpad-unlock-all",name:"Decrypt (unlock) locked notes in view",callback:()=>r("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:()=>r("cmdCopyNotes")}),this.addCommand({id:"stashpad-cut-notes",name:"Cut notes (paste in list to move, in composer to extract text)",callback:()=>r("cmdCutNotes")}),this.addCommand({id:"stashpad-paste-notes",name:"Paste notes (from the note clipboard)",callback:()=>r("cmdPasteNotes")}),this.addCommand({id:"stashpad-move-to-archive",name:"Move selection to archive",callback:()=>r("cmdMoveToArchive")}),this.addCommand({id:"stashpad-encrypt-delete",name:"Encrypt (lock) & delete selection (to encrypted trash)",callback:()=>r("cmdEncryptDelete")}),this.addCommand({id:"stashpad-delete-unencrypted",name:"Delete selection to Obsidian's trash (unencrypted)",callback:()=>r("cmdDeleteUnencrypted")}),this.addCommand({id:"stashpad-restore-trash",name:"Open aggregated Trash view",callback:()=>this.openEncryptedTrash()}),this.addCommand({id:"stashpad-open-all-encrypted",name:"Open aggregated Encrypted notes view",callback:()=>void Pe(this,"encrypted")}),this.addCommand({id:"stashpad-open-all-archived",name:"Open aggregated Archived view",callback:()=>void Pe(this,"archived")}),this.addCommand({id:"stashpad-open-all-tasks",name:"Open aggregated Tasks view",callback:()=>void Pe(this,"tasks")}),this.addCommand({id:"stashpad-open-watchlist",name:"Open aggregated Previously encrypted view",callback:()=>void Pe(this,"watch")}),this.addCommand({id:"stashpad-encrypt-applicable",name:"Encrypt (lock) everything applicable (re-encrypt sweep)",callback:()=>void this.encryptEverythingApplicable()}),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:()=>r("claimSelectedAsAuthor")}),this.addCommand({id:"stashpad-claim-folder-author",name:"Claim authorship of all unauthored notes in this folder",callback:()=>r("claimFolderAsAuthor")}),this.addCommand({id:"stashpad-claim-selected-contributor",name:"Claim selected notes (author if unowned, else add me as contributor)",callback:()=>r("claimSelectedWithContributor")}),this.addCommand({id:"stashpad-claim-folder-contributor",name:"Claim all notes in this folder (author if unowned, else add me as contributor)",callback:()=>r("claimFolderWithContributor")}),this.addCommand({id:"stashpad-pick-destination",name:"Pick destination for next note",callback:()=>r("openDestinationPicker")}),this.addCommand({id:"stashpad-search",name:"Search Stashpad notes",callback:()=>r("openSearchModal")}),this.addCommand({id:"stashpad-search-in-parent",name:"Search in current parent",callback:()=>r("openSearchInParentModal")}),this.addCommand({id:"stashpad-move-picker",name:"Move selection (picker)",callback:()=>r("cmdMovePicker")}),this.addCommand({id:"stashpad-merge",name:"Merge selection",callback:()=>r("cmdMerge")}),this.addCommand({id:"stashpad-copy",name:"Copy selection",callback:()=>r("cmdCopy")}),this.addCommand({id:"stashpad-copy-tree",name:"Copy focused subtree",callback:()=>r("cmdCopyTree")}),this.addCommand({id:"stashpad-copy-link",name:"Copy Stashpad link (deep link / URL) to note",callback:()=>r("cmdCopyStashpadLink")}),this.addCommand({id:"stashpad-open-link",name:"Open Stashpad link (paste a deep link / URL)",callback:()=>this.openDeepLinkModal()}),this.addCommand({id:"stashpad-copy-outline",name:"Copy as outline (nested embeds)",callback:()=>r("cmdCopyOutline")}),this.addCommand({id:"stashpad-split",name:"Split note\u2026",callback:()=>r("cmdSplit")}),this.addCommand({id:"stashpad-edit-note",name:"Edit note in new tab (selection)",callback:()=>r("cmdOpenInEditor")}),this.addCommand({id:"stashpad-edit-parent",name:"Edit parent note in new tab",callback:()=>r("cmdOpenParentInEditor")}),this.addCommand({id:"stashpad-delete",name:"Delete selection",callback:()=>r("cmdDelete")}),this.addCommand({id:"stashpad-move-up",name:"Move note up",callback:()=>r("cmdMoveUp")}),this.addCommand({id:"stashpad-move-down",name:"Move note down",callback:()=>r("cmdMoveDown")}),this.addCommand({id:"stashpad-move-to-top",name:"Move note to top",callback:()=>r("cmdMoveToTop")}),this.addCommand({id:"stashpad-move-to-bottom",name:"Move note to bottom",callback:()=>r("cmdMoveToBottom")}),this.addCommand({id:"stashpad-outdent",name:"Outdent (move to grandparent)",callback:()=>r("cmdOutdent")}),this.addCommand({id:"stashpad-set-color",name:"Set note color\u2026",callback:()=>r("cmdSetColor")}),this.addCommand({id:"stashpad-clone",name:"Clone selection (duplicate / copy notes)",callback:()=>r("cmdClone")}),this.addCommand({id:"stashpad-fork-note",name:"Fork into a separate note (copy under a chosen parent)",callback:()=>r("cmdForkNote")}),this.addCommand({id:"stashpad-insert-template",name:"Insert template (clone an existing note)",callback:()=>r("cmdInsertTemplate")}),this.addCommand({id:"stashpad-toggle-expand",name:"Show more / show less (expand toggle)",callback:()=>r("cmdToggleExpand")}),this.addCommand({id:"stashpad-expand-all",name:"Expand all (show every note's full body)",callback:()=>r("cmdExpandAll")}),this.addCommand({id:"stashpad-collapse-all",name:"Collapse all (clamp every note's body)",callback:()=>r("cmdCollapseAll")}),this.addCommand({id:"stashpad-pick-move",name:"Move (in-list, arrow + Enter)",callback:()=>r("cmdInListPicker")}),this.addCommand({id:"stashpad-open-in-new-tab",name:"Open in new Stashpad tab",callback:()=>r("cmdOpenInNewStashpadTab")}),this.addCommand({id:"stashpad-toggle-complete",name:"Toggle complete (strikethrough)",callback:()=>r("cmdToggleComplete")}),this.addCommand({id:"stashpad-toggle-task",name:"Toggle task (todo)",callback:()=>r("cmdToggleTask")}),this.addCommand({id:"stashpad-set-due",name:"Set due date\u2026",callback:()=>r("cmdSetDue")}),this.addCommand({id:"stashpad-dump-perf",name:"Dump performance profile (copy to clipboard)",callback:async()=>{if(!this.settings.enablePerfProfiling){new M.Notice("Enable \u201CPerformance profiling\u201D in Stashpad settings first, then use the app and run this again.");return}let g=ke.report();console.log(g);try{await navigator.clipboard.writeText(g)}catch{}new M.Notice("Performance profile copied to clipboard (also in the console).")}}),this.addCommand({id:"stashpad-reset-perf",name:"Reset performance profile",callback:()=>{ke.reset(),new M.Notice("Performance profile reset.")}}),this.addCommand({id:"stashpad-jump-to-top",name:"Jump to top of list",callback:()=>r("jumpToTop")}),this.addCommand({id:"stashpad-jump-to-bottom",name:"Jump to bottom of list",callback:()=>r("jumpToBottom")}),this.addCommand({id:"stashpad-assign",name:"Assign task to\u2026",callback:()=>r("cmdAssign")}),this.addCommand({id:"stashpad-open-import-log",name:"Open import log",callback:async()=>{await this.importLog.load();let{ImportLogModal:g}=await Promise.resolve().then(()=>(me(),Yi));new g(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:g=>{let I=this.importService.defaultDestination();return g?!!I:(I&&this.runImportLooseFiles(I),!0)}}),this.addCommand({id:"stashpad-rerun-slug-pass",name:"Re-run filename (slug) pass on this folder",checkCallback:g=>{let I=this.importService.defaultDestination();return g?!!I:(I&&this.runFolderSlugPass(I),!0)}}),this.addCommand({id:"stashpad-rerun-frontmatter-backfill",name:"Re-run frontmatter backfill (recovery links) on this folder",checkCallback:g=>{let I=this.importService.defaultDestination();return g?!!I:(I&&this.runFolderFrontmatterBackfill(I),!0)}}),this.addCommand({id:"stashpad-select-all",name:"Select all visible notes",callback:()=>r("cmdSelectAll")}),this.addCommand({id:"stashpad-copy-codeblock",name:"Copy code from codeblock",callback:()=>r("cmdCopyCodeBlock")}),this.addCommand({id:"stashpad-open-panels",name:"Open Stashpad panels (sidebar)",callback:()=>void Ns(this.app)}),this.addCommand({id:"stashpad-open-folder-panel",name:"Open folder panel (sidebar)",callback:()=>void Rn(this.app)}),this.addCommand({id:"stashpad-open-detail",name:"Open Stashpad detail panel (right sidebar)",callback:()=>void tn(this.app)}),this.addCommand({id:"stashpad-reveal-active-note",name:"Open this note in Stashpad",checkCallback:g=>{let I=this.app.workspace.getActiveFile(),m=!!I&&I.extension==="md"&&this.isStashpadNoteFile(I);return g||m&&I&&this.revealNoteInStashpad(I),m}});let l=Object.keys(Vi);for(let g of l){let I=Vi[g];this.addCommand({id:`stashpad-open-panels-${g}`,name:`Open Stashpad panel: ${I.label}`,callback:async()=>{await Ns(this.app),this.app.workspace.getLeavesOfType(Bt)[0]?.view?.setActivePanel?.(g)}})}this.addCommand({id:"stashpad-task-review",name:"Open daily task review",callback:()=>new ri(this.app,this).open()}),this.addCommand({id:"stashpad-swap-with-parent",name:"Swap with parent (ouroboros)",callback:()=>r("cmdSwapWithParent")}),this.addCommand({id:"stashpad-toggle-pin",name:"Pin / unpin selected note (sidebar)",callback:()=>r("cmdTogglePin")}),this.addCommand({id:"stashpad-list-pin",name:"Pin / unpin to top of list",callback:()=>r("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:()=>r("cmdCloneStashpadTab")}),this.addCommand({id:"stashpad-undo",name:"Undo last Stashpad action",callback:()=>r("cmdUndo")}),this.addCommand({id:"stashpad-redo",name:"Redo last undone Stashpad action",callback:()=>r("cmdRedo")}),this.addCommand({id:"stashpad-export-stash",name:"Export selection to .stash",callback:()=>r("cmdExportStash")}),this.addCommand({id:"stashpad-export-okf",name:"Export selection as OKF bundle (.zip / .tar.gz / .stash)",callback:()=>r("cmdExportOkf")}),this.addCommand({id:"stashpad-import-stash",name:"Import .stash file\u2026",callback:()=>r("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:g=>{let I=pt(),m=I&&I.noteFolder;return m?(g||(new M.Notice(`Running integrity check on "${m}"\u2026`),this.runIntegrityCheckOnFolder(m).then(()=>{new M.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 M.Notice("Stashpad: rebuilding author registry\u2026");try{let g=await this.rebuildAuthorRegistry();this.notifications.show({message:`Author registry rebuilt: ${g.total} author(s) \u2014 ${g.fromStubs} from stubs, ${g.fromNotes} from note links.`,kind:"success",category:"system"})}catch(g){new M.Notice(`Author registry rebuild failed: ${g.message}`)}}}),this.addCommand({id:"stashpad-restore-author-stubs",name:"Restore missing author stubs (from registry)",callback:async()=>{new M.Notice("Stashpad: restoring author stubs\u2026");try{let g=await this.restoreMissingAuthorStubs();this.notifications.show({message:g.created>0?`Restored ${g.created} author stub(s) across ${g.folders} folder(s).`:`No missing author stubs \u2014 all present across ${g.folders} folder(s).`,kind:"success",category:"system"})}catch(g){new M.Notice(`Restore author stubs failed: ${g.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:()=>{this.runRebootstrapWithUI().catch(()=>{})}}),this.addCommand({id:"stashpad-adopt-note",name:"Adopt active note into Stashpad (fill missing frontmatter)",checkCallback:g=>{let I=this.app.workspace.getActiveFile();return!I||I.extension!=="md"?!1:(g||this.adoptNote(I),!0)}}),this.addCommand({id:"stashpad-open-notification-history",name:"Open notification history",callback:()=>{Promise.resolve().then(()=>(me(),Yi)).then(({NotificationHistoryModal:g,LogModal:I})=>{new g(this.app,this.notifications,async()=>{let m=this.app.vault.adapter,B=this.pluginPrivatePath("log.jsonl");if(!await m.exists(B)){new M.Notice("No log yet \u2014 make some changes first.");return}let C=await m.read(B);new I(this.app,C,B).open()},this.settings.authorId||null,m=>this.lookupNoteAuthorIds(m)).open()})}});let c=[{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 g of c){let I=`stashpad-toggle-${String(g.key).replace(/[A-Z]/g,m=>`-${m.toLowerCase()}`)}`;this.addCommand({id:I,name:`Toggle: ${g.label}`,callback:async()=>{let m=!this.settings[g.key];this.settings[g.key]=m,await this.saveSettings(),new M.Notice(`${g.label}: ${m?"ON":"OFF"}`)}})}this.addCommand({id:"stashpad-open-settings",name:"Open Stashpad settings",callback:()=>{let g=this.app.setting;!g?.open||!g?.openTabById||(g.open(),g.openTabById(this.manifest.id))}}),this.addCommand({id:"stashpad-search-settings",name:"Search Stashpad settings\u2026",callback:()=>{let g=this.app.setting;!g?.open||!g?.openTabById||(g.open(),g.openTabById(this.manifest.id),setTimeout(()=>{g?.modalEl?.querySelector?.("input[type='search']")?.focus()},0))}});for(let g of Zs)this.addCommand({id:`stashpad-open-settings-${g.id}`,name:`Open Stashpad settings: ${g.label}`,callback:()=>{let I=this.app.setting;!I?.open||!I?.openTabById||(I.open(),I.openTabById(this.manifest.id))}});let A=()=>{let g=this.app.setting;!g?.open||!g?.openTabById||(g.open(),g.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:g}=await Promise.resolve().then(()=>(Xi(),Rs)),I=await g(this.app,this,this.settings);if(I.error==="no-dest"){new M.Notice("Set a Designated Stashpad folder for Index in settings first.",6e3),A();return}if(I.error==="no-home"){new M.Notice(`"${this.settings.jdIndexStashpadFolder}" has no Stashpad home note. Open the folder in Stashpad first to create one.`,7e3);return}let{buildJdPreviewNotice:m}=await Promise.resolve().then(()=>(Xi(),Rs));m(this.app,I)}catch(g){console.error("[stashpad] preview failed",g),new M.Notice(`Preview failed: ${g?.message??g}`,8e3)}}}),this.addCommand({id:"stashpad-decrypt-folder-bundle",name:"Decrypt a folder bundle (encrypted non-Stashpad folder)\u2026",callback:async()=>{if(!this.encryption.isConfigured()){new M.Notice("Stashpad encryption isn't set up.");return}let g=await ul(this.app);if(!g.length){new M.Notice("No encrypted folder bundles found in this vault.");return}new fr(this.app,g,I=>void this.decryptFolderFromExplorer(I.folder)).open()}}),this.addCommand({id:"stashpad-build-jd-index",name:"Build JD index notes (creates Stashpad-note hierarchy)",callback:async()=>{try{let{buildJdIndexNotes:g,scanForJdNotes:I,JdBuildConfirmModal:m}=await Promise.resolve().then(()=>(Xi(),Rs));if(!(this.settings.jdIndexStashpadFolder??"").trim().replace(/^\/+|\/+$/g,"")){new M.Notice("Set a Designated Stashpad folder for Index in settings first.",6e3),A();return}let C=I(this.app,this,this.settings);new m(this.app,this,this.settings,C.indexed.length,async()=>{try{let y=await g(this.app,this,this.settings);if(y.error==="no-dest"){new M.Notice("Set a Designated Stashpad folder for Index in settings first.",6e3),A();return}if(y.error==="dest-not-stashpad"){new M.Notice(`"${y.destFolder}" isn't a known Stashpad folder. Pick a real Stashpad folder in settings.`,7e3),A();return}this.settings.jdIndexHasBuilt=!0,await this.saveSettings(),new M.Notice(`Index built: ${y.created} created, ${y.updated} updated, ${y.skipped} skipped \u2192 ${y.destFolder}`,6e3)}catch(y){console.error("[stashpad] build failed",y),new M.Notice(`Build failed: ${y?.message??y}`,8e3)}}).open()}catch(g){console.error("[stashpad] build failed",g),new M.Notice(`Build failed: ${g?.message??g}`,8e3)}}});let h=g=>{if(g.extension!==it)return;let I=(this.settings.importDropFolder||"").trim().replace(/^\/+|\/+$/g,""),m=(this.settings.exportFolder||"").trim().replace(/^\/+|\/+$/g,""),B=g.parent?.path||"",C=B.split("/").pop()??"";if(I&&C===I){if(m&&B.endsWith(`/${m}`))return;let Q=B.slice(0,B.length-I.length).replace(/\/+$/,"")||this.settings.folder;this.autoImportStash(g,Q);return}this.settings.autoImport&&this.importService.isArmed()&&(Mt(g.path)||this.discoverStashpadFolders().includes(B)&&this.autoImportStash(g,B))};this.registerEvent(this.app.vault.on("create",g=>{g instanceof M.TFile&&h(g)})),this.registerEvent(this.app.vault.on("rename",g=>{g instanceof M.TFile&&h(g)}));let p=g=>{if(g.extension!=="md")return;let I=g.parent?.path?.replace(/\/+$/,"")??"";this.discoverStashpadFolders().includes(I)&&setTimeout(()=>{this.fixOrphanParentForFile(g)},800)},u=g=>{if(g.extension!=="md")return;let I=(this.settings.importDropFolder||"").trim().replace(/^\/+|\/+$/g,"");if(!I)return;let m=g.parent?.path?.replace(/\/+$/,"")??"";if((m.split("/").pop()??"")!==I)return;let C=m.slice(0,m.length-I.length).replace(/\/+$/,"");!C||!this.discoverStashpadFolders().includes(C)||setTimeout(()=>{this.adoptMarkdownDrop(g,C)},200)};this.registerEvent(this.app.vault.on("create",g=>{g instanceof M.TFile&&(p(g),u(g))})),this.registerEvent(this.app.vault.on("rename",g=>{g instanceof M.TFile&&(p(g),u(g))})),this.registerEvent(this.app.vault.on("delete",g=>{if(!(g instanceof M.TFolder))return;let I=g.path.replace(/\/+$/,"");this.knownStashpadFolders.has(I)&&this.handleStashpadFolderDeleted(I)})),this.registerEvent(this.app.vault.on("rename",(g,I)=>{g instanceof M.TFile&&this.maybeReHomeOnCrossFolderMove(g,I)})),this.registerEvent(this.app.vault.on("rename",(g,I)=>{g instanceof M.TFile&&this.maybeArchiveOnMoveIn(g,I)})),this.registerEvent(this.app.vault.on("rename",(g,I)=>{g instanceof M.TFolder&&(this.retargetStashpadViewsForFolderRename(I,g.path),this.remapFolderPathInSettings(I,g.path))}));let f=`${this.manifest.dir.replace(/\/+$/,"")}/data.json`;this.registerEvent(this.app.vault.on("raw",g=>{g===f&&this.scheduleExternalDataJsonReload()})),this.registerEvent(this.app.vault.on("create",g=>{g instanceof M.TFile?this.importService.enqueue(g):g instanceof M.TFolder&&this.importService.enqueueFolder(g)})),this.registerEvent(this.app.vault.on("rename",g=>{g instanceof M.TFile?this.importService.enqueue(g):g instanceof M.TFolder&&this.importService.enqueueFolder(g)})),this.registerEvent(this.app.vault.on("rename",(g,I)=>{g instanceof M.TFile&&this.maybeAdoptAuthorRename(g,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 e=this.manifest.dir;if(!e)return;let t=`${e.replace(/\/+$/,"")}/manifest.json`,i=this.app.vault.adapter;if(!await i.exists(t))return;let s=JSON.parse(await i.read(t))?.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(e){console.debug("[Stashpad] synced-build check failed",e)}}reloadAppForUpdate(){try{window.localStorage?.setItem(gr,"1")}catch{}try{if(this.app.commands?.executeCommandById?.("app:reload"))return}catch(e){console.warn("[Stashpad] app:reload command failed",e)}try{window.location.reload()}catch{new M.Notice("Reload Obsidian (close + reopen) to apply the Stashpad update.")}}async unghostStashpadTabsIfFlagged(){let e=!1;try{e=window.localStorage?.getItem(gr)==="1"}catch{}if(e){try{window.localStorage?.removeItem(gr)}catch{}for(let t of this.app.workspace.getLeavesOfType(z))try{let i=t;i.isDeferred&&typeof i.loadIfDeferred=="function"&&await i.loadIfDeferred()}catch(i){console.warn("[Stashpad] un-ghost leaf failed",i)}}}isSemverGreater(e,t){let i=e.split(".").map(o=>parseInt(o,10)||0),s=t.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,l=s[o]??0;if(r!==l)return r>l}return!1}parseAuthorFilePath(e){let t=e.match(/\/_authors\/([^/]+?)-([a-z0-9]{4,12})\.md$/i);return t?{name:t[1].replace(/-/g," "),id:t[2]}:null}authorNameToSafe(e){return e.replace(/[^\w\- ]+/g,"").trim().replace(/\s+/g,"-")||"author"}async syncAuthorFilesToName(){let e=(this.settings.authorId??"").trim(),t=(this.settings.authorName??"").trim();if(!e||!t)return;let i=this.authorNameToSafe(t);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!==e)continue;let l=`${n}/${i}-${e}.md`,c=o;if(o.path!==l)try{this.authorRenameInFlight.add(o.path),this.authorRenameInFlight.add(l),await this.app.fileManager.renameFile(o,l);let A=this.app.vault.getAbstractFileByPath(l);A&&(c=A)}catch(A){this.authorRenameInFlight.delete(o.path),this.authorRenameInFlight.delete(l),console.warn("[Stashpad] author file rename failed",A);continue}try{await this.refreshAuthorStub(c)}catch{}}}}async refreshAuthorStub(e){let t=(this.settings.authorName??"").trim(),i=(this.settings.authorRole??"").trim(),s=(this.settings.authorDepartment??"").trim();if(t)try{let n=await this.app.vault.read(e),o=n.replace(/^# .*$/m,`# ${t}`);o!==n&&await this.app.vault.modify(e,o),await this.app.fileManager.processFrontMatter(e,r=>{r.aliases=[t],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(e,t){let i=this.authorRenameInFlight.delete(e.path),s=this.authorRenameInFlight.delete(t);if(i||s)return;let n=this.parseAuthorFilePath(e.path);if(!n)return;let o=(this.settings.authorId??"").trim();if(!o||n.id!==o)return;let r=n.name.trim();!r||r===(this.settings.authorName??"").trim()||(this.settings.authorName=r,await this.saveSettings(),await this.syncAuthorFilesToName())}async adoptMarkdownDrop(e,t){try{let i=this.app.vault.adapter,s=e.name,n=s.lastIndexOf("."),o=n>0?s.slice(0,n):s,r=n>0?s.slice(n):"",l=0;for(;await i.exists(`${t}/${s}`);)l+=1,s=`${o}-${l}${r}`;let c=`${t}/${s}`;await this.app.fileManager.renameFile(e,c);let A=this.app.vault.getAbstractFileByPath(c);A instanceof M.TFile&&setTimeout(()=>{this.fixOrphanParentForFile(A)},500),this.notifications.show({message:`Imported \`${e.name}\` \u2192 \`${t}\``,kind:"success",category:"import",folder:t,affectedPaths:[c]})}catch(i){console.warn("Stashpad: markdown drop adoption failed",i),this.notifications.show({message:`Couldn't import \`${e.name}\`: ${i.message}`,kind:"error",category:"import"})}}async fixOrphanParentForFile(e){try{let t=this.app.metadataCache.getFileCache(e)?.frontmatter,i=typeof t?.id=="string"?t.id.trim():"",s=t?.parent,n=typeof s=="string"?s.trim()!=="":s!=null,o=typeof t?.created=="string"&&t.created.trim()!=="",r=!i,l=!n,c=!o;if(!r&&!l&&!c)return;let A,h=!1,p=!1;if(await this.app.fileManager.processFrontMatter(e,g=>{if(r&&(typeof g.id=="string"&&g.id.trim()||(A=this.mintNoteId(),g.id=A)),l){let I=g.parent;(typeof I=="string"?I.trim()!=="":I!=null)||(g.parent=k,h=!0)}c&&(typeof g.created=="string"&&g.created.trim()||(g.created=new Date(e.stat.ctime).toISOString(),p=!0))}),!A&&!h&&!p)return;let u=this.newLog(),f=A||i;f&&await u.append({type:"parent_change",id:f,payload:{from:null,to:k,reason:"orphan_auto_fix",path:e.path,addedId:!!A,addedParent:h,addedCreated:p}}),new M.Notice(`Adopted ${e.basename} \u2192 Home`)}catch(t){console.warn("Stashpad: orphan auto-fix failed",t)}}maybeReHomeOnCrossFolderMove(e,t){if(e.extension!=="md")return;let i=e.parent?.path?.replace(/\/+$/,"")??"",s=t.lastIndexOf("/"),n=(s>=0?t.slice(0,s):"").replace(/\/+$/,"");i!==n&&this.discoverStashpadFolders().includes(i)&&(this.reHomePending.has(e.path)||(this.reHomePending.add(e.path),setTimeout(()=>{this.reHomePending.delete(e.path),this.reHomeDanglingParent(e,i)},900)))}async reHomeDanglingParent(e,t){try{let i=this.app.metadataCache.getFileCache(e)?.frontmatter,s=typeof i?.id=="string"?i.id.trim():"",n=typeof i?.parent=="string"?i.parent.trim():"";if(!s||!n||n===k||this.app.vault.getMarkdownFiles().some(r=>(r.parent?.path?.replace(/\/+$/,"")??"")===t&&this.app.metadataCache.getFileCache(r)?.frontmatter?.id===n))return;await this.app.fileManager.processFrontMatter(e,r=>{let l=typeof r.parent=="string"?r.parent.trim():"";l&&l!==k&&(r.parent=k)}),await this.newLog().append({type:"parent_change",id:s,payload:{from:n,to:k,reason:"rehome_cross_folder_move",path:e.path}}),new M.Notice(`Re-homed ${e.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(e,t){try{let i=new Uint8Array(await this.app.vault.readBinary(e));if(Me(i)){this.importService.parkEncrypted(e.path),this.notifyPendingEncrypted();return}let s=await gi(this.app,i);if(!s)return;let n=pt(),o=new Set;if(n&&typeof n.collectExistingIds=="function"&&n.noteFolder===t)for(let c of n.collectExistingIds())o.add(c);else for(let c of this.app.vault.getMarkdownFiles()){if(!c.path.startsWith(t+"/"))continue;let A=this.app.metadataCache.getFileCache(c)?.frontmatter?.id;typeof A=="string"&&o.add(A)}let r=await qe(this.app,s,t,o,{stripReserved:!0});try{await this.newLog().append({type:"stash_import",id:k,payload:{from:e.path,into:t,noteCount:r.notesWritten,attachmentsWritten:r.attachmentsWritten,collisionsRenamed:r.collisionsRenamed,auto:!0}})}catch{}try{await this.app.fileManager.trashFile(e)}catch{}let l=[`Auto-imported ${r.notesWritten} note${r.notesWritten===1?"":"s"} from ${e.name}`];r.attachmentsWritten&&l.push(`+ ${r.attachmentsWritten} attachment${r.attachmentsWritten===1?"":"s"}`),r.collisionsRenamed&&l.push(`(${r.collisionsRenamed} renamed)`),this.notifications.show({message:l.join(" "),kind:"success",category:"import",folder:t}),n&&typeof n.debouncedRender=="function"&&n.debouncedRender()}catch(i){this.notifications.show({message:`Stashpad: auto-import failed File: \`${e.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:[e.path],actions:Ls(this.app,e.path,N.Platform.isMobile)}),console.error(i)}}lookupNoteAuthorIds(e){let t=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!==e)continue;let o=i(n?.author);o&&t.add(o);let r=n?.contributors;if(Array.isArray(r))for(let l of r){let c=i(l);c&&t.add(c)}break}return Array.from(t)}lookupNoteAuthorId(e){return this.lookupNoteAuthorIds(e)[0]??null}async runRebootstrapWithUI(){let t=new N.Notice("",0).noticeEl;t.empty(),t.addClass("stashpad-progress-notice"),t.createDiv({cls:"stashpad-progress-title",text:"Rebootstrapping Stashpad folders\u2026"});let s=t.createDiv({cls:"stashpad-progress-bar"}).createDiv({cls:"stashpad-progress-fill"}),n=t.createDiv({cls:"stashpad-progress-sub",text:"Counting notes\u2026"}),o=(r,l,c)=>{let A=l>0?Math.min(100,Math.round(r/l*100)):0;s.style.width=`${A}%`,n.setText(c?`${c} \xB7 ${A}%`:`${A}%`)};try{let r=await this.rebootstrapAllFolders(o),l=r.imported+r.attachmentsLinked+r.attachmentsRenamed+r.fmWritten+r.slugsRenamed,c=[];return c.push(`Checked ${r.touched.length} folder${r.touched.length===1?"":"s"} (${r.fmChecked} note${r.fmChecked===1?"":"s"})`),l===0?c.push("everything already in sync \u2014 no changes needed"):(r.fmWritten>0&&c.push(`updated frontmatter on ${r.fmWritten} note${r.fmWritten===1?"":"s"}`),r.slugsRenamed>0&&c.push(`renamed ${r.slugsRenamed} note${r.slugsRenamed===1?"":"s"} to match body`),r.imported>0&&c.push(`imported ${r.imported} loose file${r.imported===1?"":"s"}`),r.attachmentsLinked>0&&c.push(`linked attachments on ${r.attachmentsLinked} note${r.attachmentsLinked===1?"":"s"}`),r.attachmentsRenamed>0&&c.push(`renamed ${r.attachmentsRenamed} attachment${r.attachmentsRenamed===1?"":"s"}`)),r.authors>0&&c.push(`${r.authors} author${r.authors===1?"":"s"} in registry`),t.empty(),t.removeClass("stashpad-progress-notice"),t.addClass("stashpad-progress-done"),t.createDiv({cls:"stashpad-progress-title",text:"\u2713 Rebootstrap complete"}),t.createDiv({cls:"stashpad-progress-sub",text:`${c.join("; ")}.`}),r.attachmentsSkipped>0&&new N.Notice(`Stashpad: ${r.attachmentsSkipped} attachment${r.attachmentsSkipped===1?"":"s"} need renaming, but skipped to protect links. Enable Settings \u2192 Files & Links \u2192 \u201CAutomatically update internal links\u201D, then rebootstrap again.`,12e3),r}catch(r){throw t.empty(),t.removeClass("stashpad-progress-notice"),t.addClass("stashpad-progress-error"),t.createDiv({cls:"stashpad-progress-title",text:"Rebootstrap failed"}),t.createDiv({cls:"stashpad-progress-sub",text:r.message}),r}}async rebootstrapAllFolders(e){this.rebootstrapInProgress=!0;try{return await this.rebootstrapAllFoldersInner(e)}finally{window.setTimeout(()=>{this.rebootstrapInProgress=!1;for(let t of this.app.workspace.getLeavesOfType(z))t.view?.forceReconcileRender?.()},2500)}}async rebootstrapAllFoldersInner(e){let t="__root__",i=new Set;for(let y of this.app.vault.getMarkdownFiles()){if(this.app.metadataCache.getFileCache(y)?.frontmatter?.id!==t)continue;let E=y.parent?.path;E&&i.add(E)}let s=new Map;for(let y of this.app.vault.getMarkdownFiles()){let v=y.parent?.path;v&&i.has(v)&&s.set(v,(s.get(v)??0)+1)}let n=Math.max(1,[...s.values()].reduce((y,v)=>y+v,0)),o=0;e?.(0,n,"Starting\u2026");let r=(this.settings.importDropFolder||"").trim().replace(/^\/+|\/+$/g,""),l=(this.settings.exportFolder||"").trim().replace(/^\/+|\/+$/g,""),c=[],A=async y=>{if(y&&!await this.app.vault.adapter.exists(y))try{await this.app.vault.createFolder(y)}catch(v){let E=v?.message??"";if(!/already exists/i.test(E))throw v}},h=0,g=0,u=0,f=0,p=0,I=0,m=!!this.app.vault.getConfig?.("alwaysUpdateLinks"),B=new Set(this.okfActiveFolders());for(let y of i){let v=s.get(y)??1;e?.(o,n,`Processing \u201C${y.split("/").pop()||y}\u201D (${v} note${v===1?"":"s"})`);try{if(r&&await A(`${y}/${r}`),l&&await A(`${y}/${l}`),this.settings.autoImport)try{let b=await this.importService.importLooseInto(y);f+=b.files+b.folders+b.stashes}catch(b){console.warn("Stashpad: loose sweep failed",y,b)}let E=await Ci(this.app,y);h+=E.checked,g+=E.written,u+=await this.rebootstrapFolderSlugs(y);let Q=await this.rebootstrapFolderAttachments(y,m);if(p+=Q.renamed,I+=Q.skipped,B.has(y.replace(/\/+$/,"")))try{await dr(this.app,y)}catch(b){console.warn("Stashpad: OKF rebuild during rebootstrap failed",y,b)}c.push(y)}catch(E){console.warn(`Stashpad: rebootstrap skipped ${y}`,E)}finally{o+=v,e?.(o,n,`Processing \u201C${y.split("/").pop()||y}\u201D`)}}e?.(n,n,"Finalizing\u2026");let C=0;try{C=(await this.rebuildAuthorRegistry()).total}catch(y){console.warn("Stashpad: rebootstrap author-registry rebuild failed",y)}let w=0;try{w=await this.convertAttachmentsToLinks()}catch(y){console.warn("Stashpad: attachment-link conversion failed",y)}return{touched:c,fmChecked:h,fmWritten:g,slugsRenamed:u,authors:C,imported:f,attachmentsLinked:w,attachmentsRenamed:p,attachmentsSkipped:I}}async rebootstrapFolderSlugs(e){let t="__root__",i=e.replace(/\/+$/,""),s=this.settings.slugStopWords??Ze,n=0,o=this.app.vault.getMarkdownFiles().filter(r=>(r.parent?.path?.replace(/\/+$/,"")??"")===i);for(let r of o){let l=this.app.metadataCache.getFileCache(r)?.frontmatter?.id,c=typeof l=="string"?l:null,h=lt(r.basename)??(Ns(c)?c:null);if(!(!h||h===t)&&c===h)try{let g=await this.app.vault.cachedRead(r),u=g.startsWith("---")?g.slice(g.indexOf(` ----`,3)+4).replace(/^\r?\n/,""):g,f=Se(u,s),p=be(f,h);if(r.name===p)continue;let I=r.parent?`${r.parent.path}/${p}`:p;if(this.app.vault.getAbstractFileByPath(I))continue;await this.app.fileManager.renameFile(r,I),n+=1}catch(g){console.warn(`Stashpad: slug rebootstrap skipped ${r.path}`,g)}}return n}async rebootstrapFolderAttachments(e,t){let i=`${e.replace(/\/+$/,"")}/_attachments`,s=this.app.vault.getAbstractFileByPath(i);if(!(s instanceof N.TFolder))return{renamed:0,skipped:0};let n=s.children.filter(l=>l instanceof N.TFile),o=0,r=0;for(let l of n){let c=Lr(l.name);if(!c)continue;let A=Ms(c.rest,c.stamp);if(l.name===A)continue;if(!t){r+=1;continue}let h=`${i}/${A}`;if(!this.app.vault.getAbstractFileByPath(h))try{await this.app.fileManager.renameFile(l,h),o+=1,await new Promise(g=>setTimeout(g,30))}catch(g){console.warn(`Stashpad: attachment rebootstrap skipped ${l.path}`,g)}}return{renamed:o,skipped:r}}onStashpadSelectionChange(e){return this.stashpadSelectionListeners.add(e),()=>this.stashpadSelectionListeners.delete(e)}notifyStashpadSelectionChanged(){for(let e of this.stashpadSelectionListeners)try{e()}catch(t){console.warn("[Stashpad] selection listener failed",t)}}onStashpadContentChange(e){return this.stashpadContentListeners.add(e),()=>this.stashpadContentListeners.delete(e)}notifyStashpadContentChanged(){for(let e of this.stashpadContentListeners)try{e()}catch(t){console.warn("[Stashpad] content listener failed",t)}}getActiveStashpadSelection(){let t=this.lastActiveStashpadLeaf?.view;if(!t||t.getViewType?.()!==z)return null;let i=t.noteFolder??"";if(!i)return null;let s=t.currentChildren??[],n;if(typeof t.cursorIdx=="number"&&t.cursorIdx>=0&&(n=s[t.cursorIdx]),!n&&t.selection?.size>0){let o=t.firstSelectedId??[...t.selection][0];n=s.find(r=>r.id===o)}return n?.file?{folder:i,id:n.id,file:n.file}:null}fileForPin(e,t){let i=e.replace(/\/+$/,"");for(let s of this.app.vault.getMarkdownFiles())if((s.parent?.path?.replace(/\/+$/,"")??"")===i&&this.app.metadataCache.getFileCache(s)?.frontmatter?.id===t)return s;return null}async pinNote(e){let t=this.fileForPin(e.folder,e.id);t&&this.app.metadataCache.getFileCache(t)?.frontmatter?.pinned!==!0&&(await this.app.fileManager.processFrontMatter(t,i=>{i.pinned=!0,i.pinnedAt=Date.now()}),this.refreshPanelsView())}async unpinNote(e){let t=this.fileForPin(e.folder,e.id);t&&this.app.metadataCache.getFileCache(t)?.frontmatter?.pinned===!0&&(await this.app.fileManager.processFrontMatter(t,i=>{delete i.pinned,delete i.pinnedAt}),this.refreshPanelsView())}isPinned(e){let t=this.fileForPin(e.folder,e.id);return t?this.app.metadataCache.getFileCache(t)?.frontmatter?.pinned===!0:!1}listPinnedNotes(){let e=new Set(this.discoverStashpadFolders()),t=[];for(let i of this.app.vault.getMarkdownFiles()){let s=i.parent?.path?.replace(/\/+$/,"")??"";if(!e.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;t.push({folder:s,id:n.id,pinnedAt:o,file:i})}return t.sort((i,s)=>i.pinnedAt-s.pinnedAt||i.file.path.localeCompare(s.file.path)),t}async migratePinnedNotesToFrontmatter(){let e=this.settings.pinnedNotes??[];if(e.length===0)return;let t=Date.now()-e.length*1e3;for(let i of e){let s=this.fileForPin(i.folder,i.id);if(!s){t+=1e3;continue}try{if(this.app.metadataCache.getFileCache(s)?.frontmatter?.pinned!==!0){let n=t;await this.app.fileManager.processFrontMatter(s,o=>{o.pinned=!0,o.pinnedAt=n})}}catch(n){console.warn("[Stashpad] pin migration failed for",i,n)}t+=1e3}this.settings.pinnedNotes=[],await this.saveSettings(),this.refreshPanelsView()}refreshPanelsView(){let e=this.app.workspace.getLeavesOfType(Ct);for(let t of e){let i=t.view;i&&typeof i.render=="function"&&i.render()}}refreshAllStashpadViews(){for(let e of this.app.workspace.getLeavesOfType(z)){let t=e.view;t&&typeof t.render=="function"&&t.render()}}refreshFolderPanels(){for(let e of this.app.workspace.getLeavesOfType(Bt)){let t=e.view;t&&typeof t.refresh=="function"&&t.refresh()}}getFolderIcon(e){let t=(e||"").replace(/\/+$/,""),i=this.settings.folderIcons?.[t];return i&&i.trim()?i.trim():void 0}async setFolderIcon(e,t){let i=(e||"").replace(/\/+$/,""),s={...this.settings.folderIcons??{}};t&&t.trim()?s[i]=t.trim():delete s[i],this.settings.folderIcons=s,await this.saveSettings(),this.refreshFolderIconFor(i)}refreshFolderIconFor(e){let t=(e||"").replace(/\/+$/,"");for(let i of this.app.workspace.getLeavesOfType(z)){let s=i.view;if(s&&(s.noteFolder||"").replace(/\/+$/,"")===t){try{i.updateHeader?.()}catch{}try{s.refreshFolderSwitcherIcon?.()}catch{}}}this.refreshFolderPanels()}openFolderPicker(){let e=I=>{let B=I.getViewState().state?.folderOverride;return typeof B=="string"&&B.trim()?B.trim().replace(/^\/+|\/+$/g,""):(this.settings.folder||"Stashpad").trim().replace(/^\/+|\/+$/g,"")},t=this.app.workspace.getLeavesOfType(z),i=this.discoverStashpadFolders(),s=ht(),n=s?(s.noteFolder??"").trim().replace(/^\/+|\/+$/g,""):"",o=new Set;for(let I of this.app.vault.getAllLoadedFiles())if(I.children){let m=I.path;m&&m!=="/"&&!m.startsWith(".")&&o.add(m)}let r=I=>{let m=I.split("/").filter(Boolean).pop()??"";return m?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(m):!1},l=new Set,c=[],A=[],h=new Set;for(let I of t){let m=e(I);if(h.has(m))continue;h.add(m),l.add(m);let B=m.split("/").pop()||m;c.push({kind:"reveal",folder:m,label:`Reveal "${B}" tab`,leaf:I,icon:this.isArchiveFolder(m)?"archive":"layout-grid"}),A.push({kind:"open-anyway",folder:m,label:`Open "${B}" in another new tab`,icon:"layout-template"})}for(let I of i.filter(m=>!l.has(m))){let m=I.split("/").pop()||I;c.push({kind:"open",folder:I,label:`Open "${m}" in new tab`,icon:this.isArchiveFolder(I)?"archive":"layout-template"})}let g=I=>I.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||I.basename,u=this.settings.folderSwitcherIncludePinned?this.listPinnedNotes().map(I=>({kind:"pinned",folder:I.folder,file:I.file,label:g(I.file),icon:"pin"})):[],f=this,p=new class extends N.SuggestModal{getSuggestions(I){let m=I.trim().toLowerCase(),B=m?m.split(/\s+/).filter(Boolean):[],C=E=>{if(!B.length)return!0;let Q=E.toLowerCase();for(let b of B)if(!Q.includes(b))return!1;return!0},w=m?c.filter(E=>{let Q="folder"in E?E.folder:"";return C(E.label)||C(Q)}):c.slice();if(m&&s&&n)for(let E of i){if(E.toLowerCase()===n.toLowerCase())continue;let Q=E.split("/").pop()??E,b=`${E} ${Q}`;C(b)&&w.push({kind:"switch-current",folder:E,label:`Switch this tab to "${Q}"`,icon:"folder-input"})}for(let E of u)(C(E.label)||C("folder"in E?E.folder:""))&&w.push(E);let y=I.trim().replace(/^\/+|\/+$/g,"");if(y&&!r(y)){let E=Array.from(o).find(b=>b.toLowerCase()===y.toLowerCase()),Q=i.some(b=>b.toLowerCase()===y.toLowerCase());if(E&&!Q)w.push({kind:"convert",folder:E,label:`Convert \u201C${Ti(E)}\u201D into a Stashpad\u2026`,icon:"folder-cog"});else if(!E){let b=Ti(y);w.push({kind:"create",folder:y,label:`+ Create new Stashpad \u201C${b}\u201D`,icon:"folder-plus"})}}let v=A.filter(E=>C(E.label)||C("folder"in E?E.folder:""));return w.push(...v),C("trash deleted encrypted")&&w.push({kind:"trash",label:"Open Trash",icon:"trash-2"}),w}renderSuggestion(I,m){m.addClass("stashpad-suggest-item"),m.addClass("stashpad-ribbon-suggest-item"),I.kind==="create"&&m.addClass("stashpad-suggest-create");let B=m.createSpan({cls:"stashpad-ribbon-suggest-icon"});(0,N.setIcon)(B,I.icon);let C=m.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"){f.openEncryptedTrash();return}if(I.kind==="pinned"){await f.revealNoteInStashpad(I.file);return}if(I.kind==="reveal"){f.app.workspace.revealLeaf(I.leaf);return}if(I.kind==="open"||I.kind==="open-anyway"){await f.activateViewForFolder(I.folder);return}if(I.kind==="switch-current"){let m=s;m&&typeof m.setFolderOverride=="function"&&(await m.setFolderOverride(I.folder),f.app.workspace.revealLeaf(m.leaf));return}if(I.kind==="create"){try{let m=Ti(I.folder);await f.app.vault.adapter.exists(m)||await f.app.vault.createFolder(m),await f.activateViewForFolder(m)}catch(m){new N.Notice(`Stashpad: couldn't create folder (${m.message})`)}return}if(I.kind==="convert"){let{ConfirmModal:m}=await Promise.resolve().then(()=>(we(),$i)),B=I.folder,C=[`\u201C${B}\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 m(f.app,"Convert into a Stashpad?",C.join(` -`),"Convert & import",async w=>{if(w)try{await f.activateViewForFolder(B),await f.runImportLooseFiles(B)}catch(y){new N.Notice(`Stashpad: couldn't convert folder (${y.message})`)}}).open();return}}}(this.app);p.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"),p.open()}async openTinyWindow(){let e=ht(),t=e?.folderOverride??null,i=e?.focusId??"__root__",s=!!e?.compactMode,n=this.app.workspace.openPopoutLeaf?.();if(!n){new N.Notice("Stashpad: couldn't open popout window on this build.");return}await n.setViewState({type:z,active:!0,state:{folderOverride:t,focusId:i,tinyMode:!0,tinyAlwaysOnTop:!1,compactMode:s}});try{this.app.workspace.revealLeaf(n)}catch{}}async activateView(e={reveal:!0}){let{workspace:t}=this.app;if(e.reveal){let s=t.getLeavesOfType(z);if(s.length>0){t.revealLeaf(s[0]);return}}let i=t.getLeaf("tab");await i.setViewState({type:z,active:!0}),t.revealLeaf(i)}async focusLastStashpadTab(){let e=this.app.workspace,t=e.getLeavesOfType(z),i=this.lastActiveStashpadLeaf&&t.includes(this.lastActiveStashpadLeaf)?this.lastActiveStashpadLeaf:t[0]??null;if(!i){await this.activateView({reveal:!0});return}e.revealLeaf(i),e.setActiveLeaf(i,{focus:!0})}async focusFolderPanel(){await Tn(this.app);let e=this.app.workspace.getLeavesOfType(Bt)[0];e&&this.app.workspace.setActiveLeaf(e,{focus:!0})}async reconcileLockedRegistry(){let e=this.settings.lockedSubtrees??[],t=[];for(let n of e){let o=(n.folder??"").replace(/\/+$/,"");if(!(o==="_deleted"||o.startsWith("_deleted/")))try{await this.app.vault.adapter.exists(n.blob)&&t.push(n)}catch{t.push(n)}}let i=t.length!==e.length,s=new Set(t.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 vn(this.app,n.path);r&&(t.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=t,await this.saveSettings(),this.refreshAllStashpadViews?.())}lockedSubtreesFor(e,t){let i=e.replace(/\/+$/,""),s=[],n=new Set;for(let o of this.settings.lockedSubtrees??[])(o.folder??"").replace(/\/+$/,"")===i&&(o.parentId??S)===t&&(s.push({blob:o.blob,title:o.title??"",count:o.count??0,created:o.created??"",rootId:o.rootId,parentId:o.parentId??S,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/")||t===S&&s.push({blob:o.path,title:o.basename,count:0,created:"",rootId:void 0,parentId:S,prevSibling:null})}return s}lockedSubtreesInFolder(e){let t=e.replace(/\/+$/,""),i=[],s=new Set;for(let n of this.settings.lockedSubtrees??[])(n.folder??"").replace(/\/+$/,"")===t&&(i.push({blob:n.blob,title:n.title??"",count:n.count??0,created:n.created??"",rootId:n.rootId,parentId:n.parentId??S}),s.add(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(/\/+$/,"")??"";o!==t||o==="_deleted"||o.startsWith("_deleted/")||i.push({blob:n.path,title:n.basename,count:0,created:"",rootId:void 0,parentId:S})}return i}async ensureFolderUnlocked(e){if(!this.encryption.hasFolderKey(e))return new N.Notice("This folder isn't encrypted. Give it a password in Settings \u2192 Stashpad \u2192 Encryption \u2192 Per-Folder Passwords."),null;if(this.encryption.isFolderUnlocked(e))return this.encryption.getFolderKey(e);if(await this.encryption.tryAutoUnlockFolder(e))return this.encryption.getFolderKey(e);let t=e.split("/").pop()||e;return await new Promise(s=>{new Ne(this.app,{mode:"unlock",offerKeychain:!0,title:`Unlock \u201C${t}\u201D`,intro:"Enter this folder's password.",onSubmit:async({current:n,remember:o})=>await this.encryption.unlockFolder(e,n,o)?(s(!0),null):"Wrong password. Try again.",onCancel:()=>s(!1)}).open()})?this.encryption.getFolderKey(e):null}isTrashBlobPath(e){let t=e.replace(/\/[^/]*$/,"").replace(/\/+$/,"");return t==="_deleted"||t.startsWith("_deleted/")||t==="trash"||t.endsWith("/trash")}encryptionState(){let e=s=>this.isTrashBlobPath(s),t=!1,i=!1;for(let s of this.app.vault.getFiles())if(s.extension==="stashenc"&&(e(s.path)?i=!0:t=!0,t&&i))return{live:t,trash:i};for(let s of this.pendingEncBlobs)if(e(s)?i=!0:t=!0,t&&i)break;return{live:t,trash:i}}async encryptionStateStrict(){let e=this.encryptionState(),t=e.trash;if(!t)try{t=(await kn(this.app,this.trashSubfolderDirs())).length>0}catch{}if(!t)try{t=(await this.app.vault.adapter.list(Yt)).files.some(s=>s.endsWith(".stashenc"))}catch{}return{live:e.live,trash:t}}watchReEncrypt(e){let t=e.folder.replace(/\/+$/,""),i=(this.settings.reEncryptWatch??[]).filter(s=>!(s.folder===t&&s.rootId===e.rootId));this.settings.reEncryptWatch=[...i,{folder:t,rootId:e.rootId,title:e.title,count:e.count,via:e.via,unlockedAt:new Date().toISOString()}]}reEncryptDisplayTitle(e){if(e.title&&e.title.trim())return e.title.trim();if(e.rootId){let t=e.folder.replace(/\/+$/,""),i=this.app.vault.getMarkdownFiles().find(s=>(s.parent?.path?.replace(/\/+$/,"")??"")===t&<(s.name)===e.rootId);if(i){let s=this.app.metadataCache.getFileCache(i)?.headings?.find(o=>o.level===1)?.heading;if(s&&s.trim())return s.trim();let n=i.basename.replace(new RegExp(`[-_]+${e.rootId}$`),"").replace(/[-_]+/g," ").trim();if(n)return n}}return"(untitled)"}unwatchReEncrypt(e,t){let i=e.replace(/\/+$/,""),s=this.settings.reEncryptWatch??[],n=s.filter(o=>!(o.folder===i&&o.rootId===t));n.length!==s.length&&(this.settings.reEncryptWatch=n)}reEncryptWatching(){return(this.settings.reEncryptWatch??[]).filter(e=>!e.removed)}pruneReEncryptWatch(){let e=this.settings.reEncryptWatch??[];if(e.length===0)return!1;let t=n=>{let o=new Set;for(let r of this.app.vault.getMarkdownFiles()){if((r.parent?.path?.replace(/\/+$/,"")??"")!==n)continue;let l=this.app.metadataCache.getFileCache(r)?.frontmatter?.id;typeof l=="string"&&o.add(l)}return o},i=new Map,s=e.filter(n=>{let o=n.folder.replace(/\/+$/,"");return i.has(o)||i.set(o,t(o)),i.get(o).has(n.rootId)});return s.length===e.length?!1:(this.settings.reEncryptWatch=s,!0)}async encryptEverythingApplicable(){this.pruneReEncryptWatch()&&await this.saveSettings();let e=[];for(let i of this.reEncryptWatching())e.push({label:this.reEncryptDisplayTitle(i),detail:`${i.folder} \u2014 ${i.via==="restore"?"restored from trash":"unlocked"} (was encrypted)`,run:async()=>!!await this.lockNoteSubtree(i.folder,i.rootId,null,{silent:!0})});let t=new Set((this.settings.lockedSubtrees??[]).map(i=>i.rootId));for(let[i,s]of Object.entries(this.settings.folderEncPrefs??{})){if(!s?.encryptContent)continue;let n=this.app.vault.getMarkdownFiles().filter(o=>{if((o.parent?.path?.replace(/\/+$/,"")??"")!==i)return!1;let r=this.app.metadataCache.getFileCache(o)?.frontmatter?.id;return typeof r=="string"&&r!==S&&!t.has(r)}).length;n>0&&e.push({label:`Everything in \u201C${i.split("/").pop()||i}\u201D (${n} plaintext note${n===1?"":"s"})`,detail:`${i} \u2014 the folder is set to encrypt its notes`,run:async()=>(await this.lockFolder(i),!0)})}for(let[i,s]of Object.entries(this.settings.folderEncPrefs??{})){if(!s?.archiveEncryptContent)continue;let n=this.archivedPlainNotesIn(yt(i)).length;n>0&&e.push({label:`${n} archived note${n===1?"":"s"} in \u201C${i.split("/").pop()||i}/archive\u201D`,detail:`${i} \u2014 the folder encrypts its archive`,run:async()=>(await this.encryptExistingArchiveNotes(i),!0)})}if(e.length===0){new N.Notice("Nothing needs re-encrypting \u2014 everything applicable is already locked.");return}new qi(this.app,e.map(({label:i,detail:s})=>({label:i,detail:s})),async i=>{let s=0,n=0,o=i.length>2?new N.Notice("",0):null;for(let r=0;r<i.length;r++){o?.setMessage(`\u{1F512} Re-encrypting ${r+1}/${i.length}\u2026`);try{await e[i[r]].run()?s++:n++}catch(l){n++,console.warn("[Stashpad] sweep item failed",e[i[r]].label,l)}}o?.hide(),this.notifications.show({message:`Re-encrypt sweep: ${s} done${n?`, ${n} FAILED (see console)`:""}, ${e.length-i.length} skipped.`,kind:n?"warning":"success",category:"system",folder:""})}).open()}async lockNoteSubtree(e,t,i=null,s={}){let n=(s.blobFolder??e).replace(/\/+$/,""),o=await this.ensureFolderUnlocked(n);if(!o)return null;try{let r=!!s.blobFolder&&s.blobFolder.replace(/\/+$/,"")!==e.replace(/\/+$/,""),l=(this.settings.folderEncPrefs??{})[n]??{},c=(r?l.archiveEncryptFilenames:l.encryptFilenames)??!1,A=await el(this.app,e,t,o,i,c,s.blobFolder);this.pendingEncBlobs.add(A.blobPath);let h=(s.blobFolder??e).replace(/\/+$/,"");return this.settings.lockedSubtrees=[...(this.settings.lockedSubtrees??[]).filter(g=>g.blob!==A.blobPath),{folder:h,blob:A.blobPath,parentId:A.parentId,title:A.title,count:A.noteCount,created:A.created,rootId:A.rootId,prevSibling:i}],this.unwatchReEncrypt(e,A.rootId),this.unwatchReEncrypt(h,A.rootId),await this.saveSettings(),A.unpurged.length>0?new N.Notice(`\u26A0\uFE0F Locked, but ${A.unpurged.length} file${A.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:[e.path],actions:Os(this.app,e.path,M.Platform.isMobile)}),console.error(i)}}lookupNoteAuthorIds(e){let t=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!==e)continue;let o=i(n?.author);o&&t.add(o);let r=n?.contributors;if(Array.isArray(r))for(let l of r){let c=i(l);c&&t.add(c)}break}return Array.from(t)}lookupNoteAuthorId(e){return this.lookupNoteAuthorIds(e)[0]??null}async runRebootstrapWithUI(){let t=new M.Notice("",0).noticeEl;t.empty(),t.addClass("stashpad-progress-notice"),t.createDiv({cls:"stashpad-progress-title",text:"Rebootstrapping Stashpad folders\u2026"});let s=t.createDiv({cls:"stashpad-progress-bar"}).createDiv({cls:"stashpad-progress-fill"}),n=t.createDiv({cls:"stashpad-progress-sub",text:"Counting notes\u2026"}),o=(r,l,c)=>{let A=l>0?Math.min(100,Math.round(r/l*100)):0;s.style.width=`${A}%`,n.setText(c?`${c} \xB7 ${A}%`:`${A}%`)};try{let r=await this.rebootstrapAllFolders(o),l=r.imported+r.attachmentsLinked+r.attachmentsRenamed+r.fmWritten+r.slugsRenamed,c=[];return c.push(`Checked ${r.touched.length} folder${r.touched.length===1?"":"s"} (${r.fmChecked} note${r.fmChecked===1?"":"s"})`),l===0?c.push("everything already in sync \u2014 no changes needed"):(r.fmWritten>0&&c.push(`updated frontmatter on ${r.fmWritten} note${r.fmWritten===1?"":"s"}`),r.slugsRenamed>0&&c.push(`renamed ${r.slugsRenamed} note${r.slugsRenamed===1?"":"s"} to match body`),r.imported>0&&c.push(`imported ${r.imported} loose file${r.imported===1?"":"s"}`),r.attachmentsLinked>0&&c.push(`linked attachments on ${r.attachmentsLinked} note${r.attachmentsLinked===1?"":"s"}`),r.attachmentsRenamed>0&&c.push(`renamed ${r.attachmentsRenamed} attachment${r.attachmentsRenamed===1?"":"s"}`)),r.authors>0&&c.push(`${r.authors} author${r.authors===1?"":"s"} in registry`),t.empty(),t.removeClass("stashpad-progress-notice"),t.addClass("stashpad-progress-done"),t.createDiv({cls:"stashpad-progress-title",text:"\u2713 Rebootstrap complete"}),t.createDiv({cls:"stashpad-progress-sub",text:`${c.join("; ")}.`}),r.attachmentsSkipped>0&&new M.Notice(`Stashpad: ${r.attachmentsSkipped} attachment${r.attachmentsSkipped===1?"":"s"} need renaming, but skipped to protect links. Enable Settings \u2192 Files & Links \u2192 \u201CAutomatically update internal links\u201D, then rebootstrap again.`,12e3),r}catch(r){throw t.empty(),t.removeClass("stashpad-progress-notice"),t.addClass("stashpad-progress-error"),t.createDiv({cls:"stashpad-progress-title",text:"Rebootstrap failed"}),t.createDiv({cls:"stashpad-progress-sub",text:r.message}),r}}async rebootstrapAllFolders(e){this.rebootstrapInProgress=!0;try{return await this.rebootstrapAllFoldersInner(e)}finally{window.setTimeout(()=>{this.rebootstrapInProgress=!1;for(let t of this.app.workspace.getLeavesOfType(z))t.view?.forceReconcileRender?.()},2500)}}async rebootstrapAllFoldersInner(e){let t="__root__",i=new Set;for(let y of this.app.vault.getMarkdownFiles()){if(this.app.metadataCache.getFileCache(y)?.frontmatter?.id!==t)continue;let w=y.parent?.path;w&&i.add(w)}let s=new Map;for(let y of this.app.vault.getMarkdownFiles()){let E=y.parent?.path;E&&i.has(E)&&s.set(E,(s.get(E)??0)+1)}let n=Math.max(1,[...s.values()].reduce((y,E)=>y+E,0)),o=0;e?.(0,n,"Starting\u2026");let r=(this.settings.importDropFolder||"").trim().replace(/^\/+|\/+$/g,""),l=(this.settings.exportFolder||"").trim().replace(/^\/+|\/+$/g,""),c=[],A=async y=>{if(y&&!await this.app.vault.adapter.exists(y))try{await this.app.vault.createFolder(y)}catch(E){let w=E?.message??"";if(!/already exists/i.test(w))throw E}},h=0,p=0,u=0,f=0,g=0,I=0,m=!!this.app.vault.getConfig?.("alwaysUpdateLinks"),B=new Set(this.okfActiveFolders());for(let y of i){let E=s.get(y)??1;e?.(o,n,`Processing \u201C${y.split("/").pop()||y}\u201D (${E} note${E===1?"":"s"})`);try{if(r&&await A(`${y}/${r}`),l&&await A(`${y}/${l}`),this.settings.autoImport)try{let F=await this.importService.importLooseInto(y);f+=F.files+F.folders+F.stashes}catch(F){console.warn("Stashpad: loose sweep failed",y,F)}let w=await Bi(this.app,y);h+=w.checked,p+=w.written,u+=await this.rebootstrapFolderSlugs(y);let v=await this.rebootstrapFolderAttachments(y,m);if(g+=v.renamed,I+=v.skipped,B.has(y.replace(/\/+$/,"")))try{await hr(this.app,y)}catch(F){console.warn("Stashpad: OKF rebuild during rebootstrap failed",y,F)}c.push(y)}catch(w){console.warn(`Stashpad: rebootstrap skipped ${y}`,w)}finally{o+=E,e?.(o,n,`Processing \u201C${y.split("/").pop()||y}\u201D`)}}e?.(n,n,"Finalizing\u2026");let C=0;try{C=(await this.rebuildAuthorRegistry()).total}catch(y){console.warn("Stashpad: rebootstrap author-registry rebuild failed",y)}let Q=0;try{Q=await this.convertAttachmentsToLinks()}catch(y){console.warn("Stashpad: attachment-link conversion failed",y)}return{touched:c,fmChecked:h,fmWritten:p,slugsRenamed:u,authors:C,imported:f,attachmentsLinked:Q,attachmentsRenamed:g,attachmentsSkipped:I}}async rebootstrapFolderSlugs(e){let t="__root__",i=e.replace(/\/+$/,""),s=this.settings.slugStopWords??je,n=0,o=this.app.vault.getMarkdownFiles().filter(r=>(r.parent?.path?.replace(/\/+$/,"")??"")===i);for(let r of o){let l=this.app.metadataCache.getFileCache(r)?.frontmatter?.id,c=typeof l=="string"?l:null,h=ct(r.basename)??(Ms(c)?c:null);if(!(!h||h===t)&&c===h)try{let p=await this.app.vault.cachedRead(r),u=p.startsWith("---")?p.slice(p.indexOf(` +---`,3)+4).replace(/^\r?\n/,""):p,f=Se(u,s),g=be(f,h);if(r.name===g)continue;let I=r.parent?`${r.parent.path}/${g}`:g;if(this.app.vault.getAbstractFileByPath(I))continue;await this.app.fileManager.renameFile(r,I),n+=1}catch(p){console.warn(`Stashpad: slug rebootstrap skipped ${r.path}`,p)}}return n}async rebootstrapFolderAttachments(e,t){let i=`${e.replace(/\/+$/,"")}/_attachments`,s=this.app.vault.getAbstractFileByPath(i);if(!(s instanceof M.TFolder))return{renamed:0,skipped:0};let n=s.children.filter(l=>l instanceof M.TFile),o=0,r=0;for(let l of n){let c=Jr(l.name);if(!c)continue;let A=Ts(c.rest,c.stamp);if(l.name===A)continue;if(!t){r+=1;continue}let h=`${i}/${A}`;if(!this.app.vault.getAbstractFileByPath(h))try{await this.app.fileManager.renameFile(l,h),o+=1,await new Promise(p=>setTimeout(p,30))}catch(p){console.warn(`Stashpad: attachment rebootstrap skipped ${l.path}`,p)}}return{renamed:o,skipped:r}}onStashpadSelectionChange(e){return this.stashpadSelectionListeners.add(e),()=>this.stashpadSelectionListeners.delete(e)}notifyStashpadSelectionChanged(){for(let e of this.stashpadSelectionListeners)try{e()}catch(t){console.warn("[Stashpad] selection listener failed",t)}}onStashpadContentChange(e){return this.stashpadContentListeners.add(e),()=>this.stashpadContentListeners.delete(e)}notifyStashpadContentChanged(){for(let e of this.stashpadContentListeners)try{e()}catch(t){console.warn("[Stashpad] content listener failed",t)}}getActiveStashpadSelection(){let t=this.lastActiveStashpadLeaf?.view;if(!t||t.getViewType?.()!==z)return null;let i=t.noteFolder??"";if(!i)return null;let s=t.currentChildren??[],n;if(typeof t.cursorIdx=="number"&&t.cursorIdx>=0&&(n=s[t.cursorIdx]),!n&&t.selection?.size>0){let o=t.firstSelectedId??[...t.selection][0];n=s.find(r=>r.id===o)}return n?.file?{folder:i,id:n.id,file:n.file}:null}fileForPin(e,t){let i=e.replace(/\/+$/,"");for(let s of this.app.vault.getMarkdownFiles())if((s.parent?.path?.replace(/\/+$/,"")??"")===i&&this.app.metadataCache.getFileCache(s)?.frontmatter?.id===t)return s;return null}async pinNote(e){let t=this.fileForPin(e.folder,e.id);t&&this.app.metadataCache.getFileCache(t)?.frontmatter?.pinned!==!0&&(await this.app.fileManager.processFrontMatter(t,i=>{i.pinned=!0,i.pinnedAt=Date.now()}),this.refreshPanelsView())}async unpinNote(e){let t=this.fileForPin(e.folder,e.id);t&&this.app.metadataCache.getFileCache(t)?.frontmatter?.pinned===!0&&(await this.app.fileManager.processFrontMatter(t,i=>{delete i.pinned,delete i.pinnedAt}),this.refreshPanelsView())}isPinned(e){let t=this.fileForPin(e.folder,e.id);return t?this.app.metadataCache.getFileCache(t)?.frontmatter?.pinned===!0:!1}listPinnedNotes(){let e=new Set(this.discoverStashpadFolders()),t=[];for(let i of this.app.vault.getMarkdownFiles()){let s=i.parent?.path?.replace(/\/+$/,"")??"";if(!e.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;t.push({folder:s,id:n.id,pinnedAt:o,file:i})}return t.sort((i,s)=>i.pinnedAt-s.pinnedAt||i.file.path.localeCompare(s.file.path)),t}async migratePinnedNotesToFrontmatter(){let e=this.settings.pinnedNotes??[];if(e.length===0)return;let t=Date.now()-e.length*1e3;for(let i of e){let s=this.fileForPin(i.folder,i.id);if(!s){t+=1e3;continue}try{if(this.app.metadataCache.getFileCache(s)?.frontmatter?.pinned!==!0){let n=t;await this.app.fileManager.processFrontMatter(s,o=>{o.pinned=!0,o.pinnedAt=n})}}catch(n){console.warn("[Stashpad] pin migration failed for",i,n)}t+=1e3}this.settings.pinnedNotes=[],await this.saveSettings(),this.refreshPanelsView()}refreshPanelsView(){let e=this.app.workspace.getLeavesOfType(Bt);for(let t of e){let i=t.view;i&&typeof i.render=="function"&&i.render()}}refreshAllStashpadViews(){for(let e of this.app.workspace.getLeavesOfType(z)){let t=e.view;t&&typeof t.render=="function"&&t.render()}}refreshFolderPanels(){for(let e of this.app.workspace.getLeavesOfType(yt)){let t=e.view;t&&typeof t.refresh=="function"&&t.refresh()}}getFolderIcon(e){let t=(e||"").replace(/\/+$/,""),i=this.settings.folderIcons?.[t];return i&&i.trim()?i.trim():void 0}async setFolderIcon(e,t){let i=(e||"").replace(/\/+$/,""),s={...this.settings.folderIcons??{}};t&&t.trim()?s[i]=t.trim():delete s[i],this.settings.folderIcons=s,await this.saveSettings(),this.refreshFolderIconFor(i)}refreshFolderIconFor(e){let t=(e||"").replace(/\/+$/,"");for(let i of this.app.workspace.getLeavesOfType(z)){let s=i.view;if(s&&(s.noteFolder||"").replace(/\/+$/,"")===t){try{i.updateHeader?.()}catch{}try{s.refreshFolderSwitcherIcon?.()}catch{}}}this.refreshFolderPanels()}openFolderPicker(){let e=I=>{let B=I.getViewState().state?.folderOverride;return typeof B=="string"&&B.trim()?B.trim().replace(/^\/+|\/+$/g,""):(this.settings.folder||"Stashpad").trim().replace(/^\/+|\/+$/g,"")},t=this.app.workspace.getLeavesOfType(z),i=this.discoverStashpadFolders(),s=pt(),n=s?(s.noteFolder??"").trim().replace(/^\/+|\/+$/g,""):"",o=new Set;for(let I of this.app.vault.getAllLoadedFiles())if(I.children){let m=I.path;m&&m!=="/"&&!m.startsWith(".")&&o.add(m)}let r=I=>{let m=I.split("/").filter(Boolean).pop()??"";return m?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(m):!1},l=new Set,c=[],A=[],h=new Set;for(let I of t){let m=e(I);if(h.has(m))continue;h.add(m),l.add(m);let B=m.split("/").pop()||m;c.push({kind:"reveal",folder:m,label:`Reveal "${B}" tab`,leaf:I,icon:this.isArchiveFolder(m)?"archive":"layout-grid"}),A.push({kind:"open-anyway",folder:m,label:`Open "${B}" in another new tab`,icon:"layout-template"})}for(let I of i.filter(m=>!l.has(m))){let m=I.split("/").pop()||I;c.push({kind:"open",folder:I,label:`Open "${m}" in new tab`,icon:this.isArchiveFolder(I)?"archive":"layout-template"})}let p=I=>I.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||I.basename,u=this.settings.folderSwitcherIncludePinned?this.listPinnedNotes().map(I=>({kind:"pinned",folder:I.folder,file:I.file,label:p(I.file),icon:"pin"})):[],f=this,g=new class extends M.SuggestModal{getSuggestions(I){let m=I.trim().toLowerCase(),B=m?m.split(/\s+/).filter(Boolean):[],C=w=>{if(!B.length)return!0;let v=w.toLowerCase();for(let F of B)if(!v.includes(F))return!1;return!0},Q=m?c.filter(w=>{let v="folder"in w?w.folder:"";return C(w.label)||C(v)}):c.slice();if(m&&s&&n)for(let w of i){if(w.toLowerCase()===n.toLowerCase())continue;let v=w.split("/").pop()??w,F=`${w} ${v}`;C(F)&&Q.push({kind:"switch-current",folder:w,label:`Switch this tab to "${v}"`,icon:"folder-input"})}for(let w of u)(C(w.label)||C("folder"in w?w.folder:""))&&Q.push(w);let y=I.trim().replace(/^\/+|\/+$/g,"");if(y&&!r(y)){let w=Array.from(o).find(F=>F.toLowerCase()===y.toLowerCase()),v=i.some(F=>F.toLowerCase()===y.toLowerCase());if(w&&!v)Q.push({kind:"convert",folder:w,label:`Convert \u201C${Pi(w)}\u201D into a Stashpad\u2026`,icon:"folder-cog"});else if(!w){let F=Pi(y);Q.push({kind:"create",folder:y,label:`+ Create new Stashpad \u201C${F}\u201D`,icon:"folder-plus"})}}let E=A.filter(w=>C(w.label)||C("folder"in w?w.folder:""));return Q.push(...E),C("trash deleted encrypted")&&Q.push({kind:"trash",label:"Open Trash",icon:"trash-2"}),Q}renderSuggestion(I,m){m.addClass("stashpad-suggest-item"),m.addClass("stashpad-ribbon-suggest-item"),I.kind==="create"&&m.addClass("stashpad-suggest-create");let B=m.createSpan({cls:"stashpad-ribbon-suggest-icon"});(0,M.setIcon)(B,I.icon);let C=m.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"){f.openEncryptedTrash();return}if(I.kind==="pinned"){await f.revealNoteInStashpad(I.file);return}if(I.kind==="reveal"){f.app.workspace.revealLeaf(I.leaf);return}if(I.kind==="open"||I.kind==="open-anyway"){await f.activateViewForFolder(I.folder);return}if(I.kind==="switch-current"){let m=s;m&&typeof m.setFolderOverride=="function"&&(await m.setFolderOverride(I.folder),f.app.workspace.revealLeaf(m.leaf));return}if(I.kind==="create"){try{let m=Pi(I.folder);await f.app.vault.adapter.exists(m)||await f.app.vault.createFolder(m),await f.activateViewForFolder(m)}catch(m){new M.Notice(`Stashpad: couldn't create folder (${m.message})`)}return}if(I.kind==="convert"){let{ConfirmModal:m}=await Promise.resolve().then(()=>(me(),Yi)),B=I.folder,C=[`\u201C${B}\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 m(f.app,"Convert into a Stashpad?",C.join(` +`),"Convert & import",async Q=>{if(Q)try{await f.activateViewForFolder(B),await f.runImportLooseFiles(B)}catch(y){new M.Notice(`Stashpad: couldn't convert folder (${y.message})`)}}).open();return}}}(this.app);g.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"),g.open()}async openTinyWindow(){let e=pt(),t=e?.folderOverride??null,i=e?.focusId??"__root__",s=!!e?.compactMode,n=this.app.workspace.openPopoutLeaf?.();if(!n){new M.Notice("Stashpad: couldn't open popout window on this build.");return}await n.setViewState({type:z,active:!0,state:{folderOverride:t,focusId:i,tinyMode:!0,tinyAlwaysOnTop:!1,compactMode:s}});try{this.app.workspace.revealLeaf(n)}catch{}}async activateView(e={reveal:!0}){let{workspace:t}=this.app;if(e.reveal){let s=t.getLeavesOfType(z);if(s.length>0){t.revealLeaf(s[0]);return}}let i=t.getLeaf("tab");await i.setViewState({type:z,active:!0}),t.revealLeaf(i)}async focusLastStashpadTab(){let e=this.app.workspace,t=e.getLeavesOfType(z),i=this.lastActiveStashpadLeaf&&t.includes(this.lastActiveStashpadLeaf)?this.lastActiveStashpadLeaf:t[0]??null;if(!i){await this.activateView({reveal:!0});return}e.revealLeaf(i),e.setActiveLeaf(i,{focus:!0})}async focusFolderPanel(){await Rn(this.app);let e=this.app.workspace.getLeavesOfType(yt)[0];e&&this.app.workspace.setActiveLeaf(e,{focus:!0})}async reconcileLockedRegistry(){let e=this.settings.lockedSubtrees??[],t=[];for(let n of e){let o=(n.folder??"").replace(/\/+$/,"");if(!(o==="_deleted"||o.startsWith("_deleted/")))try{await this.app.vault.adapter.exists(n.blob)&&t.push(n)}catch{t.push(n)}}let i=t.length!==e.length,s=new Set(t.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 Sn(this.app,n.path);r&&(t.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=t,await this.saveSettings(),this.refreshAllStashpadViews?.())}lockedSubtreesFor(e,t){let i=e.replace(/\/+$/,""),s=[],n=new Set;for(let o of this.settings.lockedSubtrees??[])(o.folder??"").replace(/\/+$/,"")===i&&(o.parentId??k)===t&&(s.push({blob:o.blob,title:o.title??"",count:o.count??0,created:o.created??"",rootId:o.rootId,parentId:o.parentId??k,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/")||t===k&&s.push({blob:o.path,title:o.basename,count:0,created:"",rootId:void 0,parentId:k,prevSibling:null})}return s}lockedSubtreesInFolder(e){let t=e.replace(/\/+$/,""),i=[],s=new Set;for(let n of this.settings.lockedSubtrees??[])(n.folder??"").replace(/\/+$/,"")===t&&(i.push({blob:n.blob,title:n.title??"",count:n.count??0,created:n.created??"",rootId:n.rootId,parentId:n.parentId??k}),s.add(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(/\/+$/,"")??"";o!==t||o==="_deleted"||o.startsWith("_deleted/")||i.push({blob:n.path,title:n.basename,count:0,created:"",rootId:void 0,parentId:k})}return i}async ensureFolderUnlocked(e){if(!this.encryption.hasFolderKey(e))return new M.Notice("This folder isn't encrypted. Give it a password in Settings \u2192 Stashpad \u2192 Encryption \u2192 Per-Folder Passwords."),null;if(this.encryption.isFolderUnlocked(e))return this.encryption.getFolderKey(e);if(await this.encryption.tryAutoUnlockFolder(e))return this.encryption.getFolderKey(e);let t=e.split("/").pop()||e;return await new Promise(s=>{new Ne(this.app,{mode:"unlock",offerKeychain:!0,title:`Unlock \u201C${t}\u201D`,intro:"Enter this folder's password.",onSubmit:async({current:n,remember:o})=>await this.encryption.unlockFolder(e,n,o)?(s(!0),null):"Wrong password. Try again.",onCancel:()=>s(!1)}).open()})?this.encryption.getFolderKey(e):null}isTrashBlobPath(e){let t=e.replace(/\/[^/]*$/,"").replace(/\/+$/,"");return t==="_deleted"||t.startsWith("_deleted/")||t==="trash"||t.endsWith("/trash")}encryptionState(){let e=s=>this.isTrashBlobPath(s),t=!1,i=!1;for(let s of this.app.vault.getFiles())if(s.extension==="stashenc"&&(e(s.path)?i=!0:t=!0,t&&i))return{live:t,trash:i};for(let s of this.pendingEncBlobs)if(e(s)?i=!0:t=!0,t&&i)break;return{live:t,trash:i}}async encryptionStateStrict(){let e=this.encryptionState(),t=e.trash;if(!t)try{t=(await Dn(this.app,this.trashSubfolderDirs())).length>0}catch{}if(!t)try{t=(await this.app.vault.adapter.list(zt)).files.some(s=>s.endsWith(".stashenc"))}catch{}return{live:e.live,trash:t}}watchReEncrypt(e){let t=e.folder.replace(/\/+$/,""),i=(this.settings.reEncryptWatch??[]).filter(s=>!(s.folder===t&&s.rootId===e.rootId));this.settings.reEncryptWatch=[...i,{folder:t,rootId:e.rootId,title:e.title,count:e.count,via:e.via,unlockedAt:new Date().toISOString()}]}reEncryptDisplayTitle(e){if(e.title&&e.title.trim())return e.title.trim();if(e.rootId){let t=e.folder.replace(/\/+$/,""),i=this.app.vault.getMarkdownFiles().find(s=>(s.parent?.path?.replace(/\/+$/,"")??"")===t&&ct(s.name)===e.rootId);if(i){let s=this.app.metadataCache.getFileCache(i)?.headings?.find(o=>o.level===1)?.heading;if(s&&s.trim())return s.trim();let n=i.basename.replace(new RegExp(`[-_]+${e.rootId}$`),"").replace(/[-_]+/g," ").trim();if(n)return n}}return"(untitled)"}unwatchReEncrypt(e,t){let i=e.replace(/\/+$/,""),s=this.settings.reEncryptWatch??[],n=s.filter(o=>!(o.folder===i&&o.rootId===t));n.length!==s.length&&(this.settings.reEncryptWatch=n)}reEncryptWatching(){return(this.settings.reEncryptWatch??[]).filter(e=>!e.removed)}pruneReEncryptWatch(){let e=this.settings.reEncryptWatch??[];if(e.length===0)return!1;let t=n=>{let o=new Set;for(let r of this.app.vault.getMarkdownFiles()){if((r.parent?.path?.replace(/\/+$/,"")??"")!==n)continue;let l=this.app.metadataCache.getFileCache(r)?.frontmatter?.id;typeof l=="string"&&o.add(l)}return o},i=new Map,s=e.filter(n=>{let o=n.folder.replace(/\/+$/,"");return i.has(o)||i.set(o,t(o)),i.get(o).has(n.rootId)});return s.length===e.length?!1:(this.settings.reEncryptWatch=s,!0)}async encryptEverythingApplicable(){this.pruneReEncryptWatch()&&await this.saveSettings();let e=[];for(let i of this.reEncryptWatching())e.push({label:this.reEncryptDisplayTitle(i),detail:`${i.folder} \u2014 ${i.via==="restore"?"restored from trash":"unlocked"} (was encrypted)`,run:async()=>!!await this.lockNoteSubtree(i.folder,i.rootId,null,{silent:!0})});let t=new Set((this.settings.lockedSubtrees??[]).map(i=>i.rootId));for(let[i,s]of Object.entries(this.settings.folderEncPrefs??{})){if(!s?.encryptContent)continue;let n=this.app.vault.getMarkdownFiles().filter(o=>{if((o.parent?.path?.replace(/\/+$/,"")??"")!==i)return!1;let r=this.app.metadataCache.getFileCache(o)?.frontmatter?.id;return typeof r=="string"&&r!==k&&!t.has(r)}).length;n>0&&e.push({label:`Everything in \u201C${i.split("/").pop()||i}\u201D (${n} plaintext note${n===1?"":"s"})`,detail:`${i} \u2014 the folder is set to encrypt its notes`,run:async()=>(await this.lockFolder(i),!0)})}for(let[i,s]of Object.entries(this.settings.folderEncPrefs??{})){if(!s?.archiveEncryptContent)continue;let n=this.archivedPlainNotesIn(wt(i)).length;n>0&&e.push({label:`${n} archived note${n===1?"":"s"} in \u201C${i.split("/").pop()||i}/archive\u201D`,detail:`${i} \u2014 the folder encrypts its archive`,run:async()=>(await this.encryptExistingArchiveNotes(i),!0)})}if(e.length===0){new M.Notice("Nothing needs re-encrypting \u2014 everything applicable is already locked.");return}new $i(this.app,e.map(({label:i,detail:s})=>({label:i,detail:s})),async i=>{let s=0,n=0,o=i.length>2?new M.Notice("",0):null;for(let r=0;r<i.length;r++){o?.setMessage(`\u{1F512} Re-encrypting ${r+1}/${i.length}\u2026`);try{await e[i[r]].run()?s++:n++}catch(l){n++,console.warn("[Stashpad] sweep item failed",e[i[r]].label,l)}}o?.hide(),this.notifications.show({message:`Re-encrypt sweep: ${s} done${n?`, ${n} FAILED (see console)`:""}, ${e.length-i.length} skipped.`,kind:n?"warning":"success",category:"system",folder:""})}).open()}async lockNoteSubtree(e,t,i=null,s={}){let n=(s.blobFolder??e).replace(/\/+$/,""),o=await this.ensureFolderUnlocked(n);if(!o)return null;try{let r=!!s.blobFolder&&s.blobFolder.replace(/\/+$/,"")!==e.replace(/\/+$/,""),l=(this.settings.folderEncPrefs??{})[n]??{},c=s.hideTitle??(r?l.archiveEncryptFilenames:l.encryptFilenames)??!1,A=await nl(this.app,e,t,o,i,c,s.blobFolder);this.pendingEncBlobs.add(A.blobPath);let h=(s.blobFolder??e).replace(/\/+$/,"");return this.settings.lockedSubtrees=[...(this.settings.lockedSubtrees??[]).filter(p=>p.blob!==A.blobPath),{folder:h,blob:A.blobPath,parentId:A.parentId,title:A.title,count:A.noteCount,created:A.created,rootId:A.rootId,prevSibling:i}],this.unwatchReEncrypt(e,A.rootId),this.unwatchReEncrypt(h,A.rootId),await this.saveSettings(),A.unpurged.length>0?new M.Notice(`\u26A0\uFE0F Locked, but ${A.unpurged.length} file${A.unpurged.length===1?" is":"s are"} still in plaintext (couldn't be removed or changed during the lock): ${A.unpurged.join(` -`)}`,0):s.silent||this.notifications.show({message:`Locked ${A.title?`\u201C${A.title}\u201D`:"a note"} (${A.noteCount} note${A.noteCount===1?"":"s"}).`,kind:"success",category:"system",folder:e}),A}catch(r){return console.warn("[Stashpad] lock failed",r),new N.Notice(`Couldn't lock: ${r.message}`),null}}async unlockBundleCore(e,t,i){let s=(i??e.replace(/\/[^/]*$/,"")).replace(/\/+$/,""),n=new Set;for(let o of this.app.vault.getMarkdownFiles())if((o.parent?.path?.replace(/\/+$/,"")??"")===s)try{let r=de(await this.app.vault.read(o)).fm.id;typeof r=="string"&&n.add(r)}catch{}return tl(this.app,e,t,n,i)}async unlockBundleAt(e,t={}){let i=e.replace(/\/[^/]*$/,"").replace(/\/+$/,""),s=await this.ensureFolderUnlocked(i);if(!s)return!1;let n=(t.destFolder??e.replace(/\/[^/]*$/,"")).replace(/\/+$/,"");try{let o=await this.unlockBundleCore(e,s,t.destFolder);this.pendingEncBlobs.delete(e);let r=(this.settings.lockedSubtrees??[]).find(l=>l.blob===e);return r?.rootId&&this.watchReEncrypt({folder:n,rootId:r.rootId,title:r.title??"",count:r.count??o.notesWritten,via:"unlock"}),this.settings.lockedSubtrees=(this.settings.lockedSubtrees??[]).filter(l=>l.blob!==e),await this.saveSettings(),t.silent||this.notifications.show({message:`Unlocked ${o.notesWritten} note${o.notesWritten===1?"":"s"}.`,kind:"success",category:"system",folder:n}),!0}catch(o){return console.warn("[Stashpad] unlock failed",o),new N.Notice(`Couldn't unlock: ${o.message}`),!1}}async lockFolder(e){let t=e.replace(/\/+$/,"");if(!await this.ensureFolderUnlocked(t))return 0;let i=[];for(let A of this.app.vault.getMarkdownFiles()){if((A.parent?.path?.replace(/\/+$/,"")??"")!==t)continue;let h;try{h=de(await this.app.vault.read(A)).fm}catch{continue}let g=h.id;typeof g!="string"||g===S||(typeof h.parent=="string"?h.parent:S)!==S||i.push(g)}let s=new Set((this.settings.lockedSubtrees??[]).map(A=>A.rootId).filter(A=>!!A)),n=i.filter(A=>!s.has(A));if(n.length===0)return new N.Notice("Nothing to lock in this folder."),0;let r=(await new fi(this.app).load(t))[S]??[],l=n.length>3?new N.Notice("",0):null,c=0;for(let A=0;A<n.length;A++){let h=n[A];l?.setMessage(`\u{1F512} Encrypting ${A+1}/${n.length}\u2026`);let g=r.indexOf(h),u=g>0?r[g-1]:null;await this.lockNoteSubtree(t,h,u,{silent:!0})&&c++}return l?.hide(),c>0&&this.notifications.show({message:`Locked ${c} note${c===1?"":"s"} in \u201C${t.split("/").pop()}\u201D.`,kind:"success",category:"system",folder:t,actions:[{label:"All encrypted",onClick:()=>void Te(this,"encrypted")}]}),c}async unlockFolder(e){let t=e.replace(/\/+$/,"");if(!await this.ensureFolderUnlocked(t))return 0;let i=this.app.vault.getFiles().filter(o=>o.extension==="stashenc"&&(o.parent?.path?.replace(/\/+$/,"")??"")===t).map(o=>o.path);if(i.length===0)return new N.Notice("No locked notes in this folder."),0;let s=i.length>3?new N.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${t.split("/").pop()}\u201D.`,kind:"success",category:"system",folder:t}),n}async unlockAllInVault(){if(!this.encryption.isConfigured())return new N.Notice("Set up encryption first (Settings \u2192 Stashpad \u2192 Encryption)."),0;let e=this.app.vault.getFiles().filter(c=>c.extension==="stashenc"&&!this.isTrashBlobPath(c.path)).map(c=>c.path);if(e.length===0)return new N.Notice("No locked notes anywhere in the vault."),0;let t=e.length>3?new N.Notice("",0):null,i=new Map,s=async c=>{if(i.has(c))return i.get(c);let A=null;return this.encryption.hasFolderKey(c)&&(this.encryption.isFolderUnlocked(c)||await this.encryption.tryAutoUnlockFolder(c))&&(A=this.encryption.getFolderKey(c)),i.set(c,A),A},n=0,o=[],r=new Set;for(let c=0;c<e.length;c++){t?.setMessage(`\u{1F513} Decrypting ${c+1}/${e.length}\u2026`);let A=e[c].replace(/\/[^/]*$/,"").replace(/\/+$/,""),h=await s(A);if(!h){r.add(A||"(vault root)");continue}try{let g=await this.unlockBundleCore(e[c],h);n+=g.notesWritten,o.push(e[c])}catch(g){console.warn("[Stashpad] vault unlock skipped",e[c],g)}}if(o.length>0){let c=new Set(o);this.settings.lockedSubtrees=(this.settings.lockedSubtrees??[]).filter(A=>!c.has(A.blob)),await this.saveSettings()}t?.hide();for(let c of i.values())try{c?.fill(0)}catch{}let l=e[0].replace(/\/[^/]*$/,"");return n>0&&this.notifications.show({message:`Unlocked ${n} note${n===1?"":"s"} across the vault.`,kind:"success",category:"system",folder:l}),r.size>0&&new N.Notice(`Skipped ${r.size} locked folder${r.size===1?"":"s"} (no key unlocked): ${[...r].map(c=>c.split("/").pop()||c).join(", ")}. Open each to unlock it, then run this again.`,0),n}exportLockedSubtree(e){return gl(this,e)}folderHasStashpadNotes(e){let t=e.replace(/\/+$/,"");return this.discoverStashpadFolders().some(i=>t===i||t.startsWith(i+"/")||i.startsWith(t+"/"))}encStamp(){let e=new Date,t=i=>String(i).padStart(2,"0");return`${e.getFullYear()}${t(e.getMonth()+1)}${t(e.getDate())}-${t(e.getHours())}${t(e.getMinutes())}`}folderKeyLabelFor(e){let t=(this.settings.authorName||"").trim(),i=t?t.split(/\s+/).map(s=>s[0]).join(""):(this.settings.authorId||"anon").slice(0,4);return`${this.encStamp()} - ${e} - ${i}`}async encryptFolderFromExplorer(e){let t=e.split("/").pop()||e;if(this.folderHasStashpadNotes(e)){await this.encryptStashpadFolder(e,t);return}if(await or(this.app,e)){new N.Notice(`\u201C${t}\u201D is already encrypted as a Stashpad bundle. Use \u201CDecrypt with Stashpad\u201D to open it.`);return}await this.encryptRawFolder(e,t)}async encryptStashpadFolder(e,t){if(this.encryption.hasOwnFolderKey(e)){await this.ensureFolderUnlocked(e)&&await this.lockFolder(e);return}let i=this.folderKeyLabelFor(t);new Ne(this.app,{mode:"setup",offerKeychain:!0,title:`Encrypt \u201C${t}\u201D with Stashpad`,intro:"Give this folder its own password. Any Stashpad notes inside it get encrypted under it; you'll re-enter the password to unlock.",onSubmit:async({next:s,remember:n})=>{if(!s)return"Enter a password.";try{await this.encryption.setupFolderKey(e,s,i,n)}catch(r){return r.message}let o=await this.lockFolder(e);return new N.Notice(o>0?`Encrypted ${o} note${o===1?"":"s"} in \u201C${t}\u201D.`:`\u201C${t}\u201D now has a Stashpad password \u2014 notes added here will use it.`),this.refreshFolderPanels?.(),null}}).open()}async encryptRawFolder(e,t){let i=async s=>{let n=this.encryption.folderKeyEntry(e)?.keyId;try{let o=await cl(this.app,e,s,n,this.encStamp());o.unpurged.length?new N.Notice(`Encrypted \u201C${t}\u201D (${o.fileCount} files) \u2014 but ${o.unpurged.length} file(s) changed mid-encrypt and were left in place.`):new N.Notice(`Encrypted \u201C${t}\u201D \u2014 ${o.fileCount} file(s) bundled into one encrypted file.`)}catch(o){return o.message}return this.refreshFolderPanels?.(),null};new _(this.app,`Encrypt \u201C${t}\u201D \u2014 non-Stashpad folder`,`This isn't a Stashpad folder, so its files can't be locked individually. +`)}`,0):s.silent||this.notifications.show({message:`Locked ${A.title?`\u201C${A.title}\u201D`:"a note"} (${A.noteCount} note${A.noteCount===1?"":"s"}).`,kind:"success",category:"system",folder:e}),A}catch(r){return console.warn("[Stashpad] lock failed",r),new M.Notice(`Couldn't lock: ${r.message}`),null}}async unlockBundleCore(e,t,i){let s=(i??e.replace(/\/[^/]*$/,"")).replace(/\/+$/,""),n=new Set;for(let o of this.app.vault.getMarkdownFiles())if((o.parent?.path?.replace(/\/+$/,"")??"")===s)try{let r=Ae(await this.app.vault.read(o)).fm.id;typeof r=="string"&&n.add(r)}catch{}return ol(this.app,e,t,n,i)}async unlockBundleAt(e,t={}){let i=e.replace(/\/[^/]*$/,"").replace(/\/+$/,""),s=await this.ensureFolderUnlocked(i);if(!s)return!1;let n=(t.destFolder??e.replace(/\/[^/]*$/,"")).replace(/\/+$/,"");try{let o=await this.unlockBundleCore(e,s,t.destFolder);this.pendingEncBlobs.delete(e);let r=(this.settings.lockedSubtrees??[]).find(l=>l.blob===e);return r?.rootId&&this.watchReEncrypt({folder:n,rootId:r.rootId,title:r.title??"",count:r.count??o.notesWritten,via:"unlock"}),this.settings.lockedSubtrees=(this.settings.lockedSubtrees??[]).filter(l=>l.blob!==e),await this.saveSettings(),t.silent||this.notifications.show({message:`Unlocked ${o.notesWritten} note${o.notesWritten===1?"":"s"}.`,kind:"success",category:"system",folder:n}),!0}catch(o){return console.warn("[Stashpad] unlock failed",o),new M.Notice(`Couldn't unlock: ${o.message}`),!1}}async lockFolder(e){let t=e.replace(/\/+$/,"");if(!await this.ensureFolderUnlocked(t))return 0;let i=[];for(let A of this.app.vault.getMarkdownFiles()){if((A.parent?.path?.replace(/\/+$/,"")??"")!==t)continue;let h;try{h=Ae(await this.app.vault.read(A)).fm}catch{continue}let p=h.id;typeof p!="string"||p===k||(typeof h.parent=="string"?h.parent:k)!==k||i.push(p)}let s=new Set((this.settings.lockedSubtrees??[]).map(A=>A.rootId).filter(A=>!!A)),n=i.filter(A=>!s.has(A));if(n.length===0)return new M.Notice("Nothing to lock in this folder."),0;let r=(await new Ii(this.app).load(t))[k]??[],l=n.length>3?new M.Notice("",0):null,c=0;for(let A=0;A<n.length;A++){let h=n[A];l?.setMessage(`\u{1F512} Encrypting ${A+1}/${n.length}\u2026`);let p=r.indexOf(h),u=p>0?r[p-1]:null;await this.lockNoteSubtree(t,h,u,{silent:!0})&&c++}return l?.hide(),c>0&&this.notifications.show({message:`Locked ${c} note${c===1?"":"s"} in \u201C${t.split("/").pop()}\u201D.`,kind:"success",category:"system",folder:t,actions:[{label:"All encrypted",onClick:()=>void Pe(this,"encrypted")}]}),c}async unlockFolder(e){let t=e.replace(/\/+$/,"");if(!await this.ensureFolderUnlocked(t))return 0;let i=this.app.vault.getFiles().filter(o=>o.extension==="stashenc"&&(o.parent?.path?.replace(/\/+$/,"")??"")===t).map(o=>o.path);if(i.length===0)return new M.Notice("No locked notes in this folder."),0;let s=i.length>3?new M.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${t.split("/").pop()}\u201D.`,kind:"success",category:"system",folder:t}),n}async unlockAllInVault(){if(!this.encryption.isConfigured())return new M.Notice("Set up encryption first (Settings \u2192 Stashpad \u2192 Encryption)."),0;let e=this.app.vault.getFiles().filter(c=>c.extension==="stashenc"&&!this.isTrashBlobPath(c.path)).map(c=>c.path);if(e.length===0)return new M.Notice("No locked notes anywhere in the vault."),0;let t=e.length>3?new M.Notice("",0):null,i=new Map,s=async c=>{if(i.has(c))return i.get(c);let A=null;return this.encryption.hasFolderKey(c)&&(this.encryption.isFolderUnlocked(c)||await this.encryption.tryAutoUnlockFolder(c))&&(A=this.encryption.getFolderKey(c)),i.set(c,A),A},n=0,o=[],r=new Set;for(let c=0;c<e.length;c++){t?.setMessage(`\u{1F513} Decrypting ${c+1}/${e.length}\u2026`);let A=e[c].replace(/\/[^/]*$/,"").replace(/\/+$/,""),h=await s(A);if(!h){r.add(A||"(vault root)");continue}try{let p=await this.unlockBundleCore(e[c],h);n+=p.notesWritten,o.push(e[c])}catch(p){console.warn("[Stashpad] vault unlock skipped",e[c],p)}}if(o.length>0){let c=new Set(o);this.settings.lockedSubtrees=(this.settings.lockedSubtrees??[]).filter(A=>!c.has(A.blob)),await this.saveSettings()}t?.hide();for(let c of i.values())try{c?.fill(0)}catch{}let l=e[0].replace(/\/[^/]*$/,"");return n>0&&this.notifications.show({message:`Unlocked ${n} note${n===1?"":"s"} across the vault.`,kind:"success",category:"system",folder:l}),r.size>0&&new M.Notice(`Skipped ${r.size} locked folder${r.size===1?"":"s"} (no key unlocked): ${[...r].map(c=>c.split("/").pop()||c).join(", ")}. Open each to unlock it, then run this again.`,0),n}exportLockedSubtree(e){return ml(this,e)}folderHasStashpadNotes(e){let t=e.replace(/\/+$/,"");return this.discoverStashpadFolders().some(i=>t===i||t.startsWith(i+"/")||i.startsWith(t+"/"))}encStamp(){let e=new Date,t=i=>String(i).padStart(2,"0");return`${e.getFullYear()}${t(e.getMonth()+1)}${t(e.getDate())}-${t(e.getHours())}${t(e.getMinutes())}`}folderKeyLabelFor(e){let t=(this.settings.authorName||"").trim(),i=t?t.split(/\s+/).map(s=>s[0]).join(""):(this.settings.authorId||"anon").slice(0,4);return`${this.encStamp()} - ${e} - ${i}`}async encryptFolderFromExplorer(e){let t=e.split("/").pop()||e;if(this.folderHasStashpadNotes(e)){await this.encryptStashpadFolder(e,t);return}if(await ar(this.app,e)){new M.Notice(`\u201C${t}\u201D is already encrypted as a Stashpad bundle. Use \u201CDecrypt with Stashpad\u201D to open it.`);return}await this.encryptRawFolder(e,t)}async encryptStashpadFolder(e,t){if(this.encryption.hasOwnFolderKey(e)){await this.ensureFolderUnlocked(e)&&await this.lockFolder(e);return}let i=this.folderKeyLabelFor(t);new Ne(this.app,{mode:"setup",offerKeychain:!0,title:`Encrypt \u201C${t}\u201D with Stashpad`,intro:"Give this folder its own password. Any Stashpad notes inside it get encrypted under it; you'll re-enter the password to unlock.",onSubmit:async({next:s,remember:n})=>{if(!s)return"Enter a password.";try{await this.encryption.setupFolderKey(e,s,i,n)}catch(r){return r.message}let o=await this.lockFolder(e);return new M.Notice(o>0?`Encrypted ${o} note${o===1?"":"s"} in \u201C${t}\u201D.`:`\u201C${t}\u201D now has a Stashpad password \u2014 notes added here will use it.`),this.refreshFolderPanels?.(),null}}).open()}async encryptRawFolder(e,t){let i=async s=>{let n=this.encryption.folderKeyEntry(e)?.keyId;try{let o=await pl(this.app,e,s,n,this.encStamp());o.unpurged.length?new M.Notice(`Encrypted \u201C${t}\u201D (${o.fileCount} files) \u2014 but ${o.unpurged.length} file(s) changed mid-encrypt and were left in place.`):new M.Notice(`Encrypted \u201C${t}\u201D \u2014 ${o.fileCount} file(s) bundled into one encrypted file.`)}catch(o){return o.message}return this.refreshFolderPanels?.(),null};new _(this.app,`Encrypt \u201C${t}\u201D \u2014 non-Stashpad folder`,`This isn't a Stashpad folder, so its files can't be locked individually. Stashpad will bundle EVERY file in this folder into one encrypted file and permanently delete the originals (no copy left in Obsidian's trash \u2014 that would defeat encryption). -This can't be undone with Cmd+Z; the only way back is \u201CDecrypt with Stashpad\u201D + the password. Continue?`,"Bundle & encrypt",s=>{if(!s)return;if(this.encryption.hasOwnFolderKey(e)){(async()=>{let o=await this.ensureFolderUnlocked(e);if(!o)return;let r=await i(o);r&&new N.Notice(r)})();return}let n=this.folderKeyLabelFor(t);new Ne(this.app,{mode:"setup",offerKeychain:!0,title:`Encrypt \u201C${t}\u201D with Stashpad`,intro:"Set a password for this bundle. You'll re-enter it to decrypt the whole folder.",onSubmit:async({next:o,remember:r})=>{if(!o)return"Enter a password.";try{await this.encryption.setupFolderKey(e,o,n,r)}catch(c){return c.message}let l=this.encryption.getFolderKey(e);return l?await i(l):"Couldn't derive the folder key."}}).open()}).open()}async decryptFolderFromExplorer(e){let t=await or(this.app,e);if(!t){new N.Notice("No Stashpad bundle found in this folder.");return}let i=e.split("/").pop()||e,s=await this.ensureFolderUnlocked(e);if(s){try{let n=await dl(this.app,t,s);new N.Notice(`Decrypted \u201C${i}\u201D \u2014 restored ${n.filesWritten} file(s).`)}catch(n){new N.Notice(`Couldn't decrypt: ${n.message}`)}this.refreshFolderPanels?.()}}async encryptDeleteSubtree(e,t){let i=await this.ensureFolderUnlocked(e);if(!i)return null;try{let s=new Date().toISOString(),o=(((this.settings.folderEncPrefs??{})[e.replace(/\/+$/,"")]??{}).trashEncryptFilenames??!1)||(this.settings.encryptTrashFilenames??!1),r=this.encryption.folderKeyEntry(e)?.keyId,l=await il(this.app,e,t,i,s,o,r,hs(e));return this.pendingEncBlobs.add(l.blobPath),this.unwatchReEncrypt(e,t),await this.saveSettings(),l.unpurged.length>0&&new N.Notice(`\u26A0\uFE0F Sent to encrypted trash, but ${l.unpurged.length} file${l.unpurged.length===1?" is":"s are"} still in plaintext (couldn't be removed or changed during the delete): +This can't be undone with Cmd+Z; the only way back is \u201CDecrypt with Stashpad\u201D + the password. Continue?`,"Bundle & encrypt",s=>{if(!s)return;if(this.encryption.hasOwnFolderKey(e)){(async()=>{let o=await this.ensureFolderUnlocked(e);if(!o)return;let r=await i(o);r&&new M.Notice(r)})();return}let n=this.folderKeyLabelFor(t);new Ne(this.app,{mode:"setup",offerKeychain:!0,title:`Encrypt \u201C${t}\u201D with Stashpad`,intro:"Set a password for this bundle. You'll re-enter it to decrypt the whole folder.",onSubmit:async({next:o,remember:r})=>{if(!o)return"Enter a password.";try{await this.encryption.setupFolderKey(e,o,n,r)}catch(c){return c.message}let l=this.encryption.getFolderKey(e);return l?await i(l):"Couldn't derive the folder key."}}).open()}).open()}async decryptFolderFromExplorer(e){let t=await ar(this.app,e);if(!t){new M.Notice("No Stashpad bundle found in this folder.");return}let i=e.split("/").pop()||e,s=await this.ensureFolderUnlocked(e);if(s){try{let n=await gl(this.app,t,s);new M.Notice(`Decrypted \u201C${i}\u201D \u2014 restored ${n.filesWritten} file(s).`)}catch(n){new M.Notice(`Couldn't decrypt: ${n.message}`)}this.refreshFolderPanels?.()}}async encryptDeleteSubtree(e,t){let i=await this.ensureFolderUnlocked(e);if(!i)return null;try{let s=new Date().toISOString(),o=(((this.settings.folderEncPrefs??{})[e.replace(/\/+$/,"")]??{}).trashEncryptFilenames??!1)||(this.settings.encryptTrashFilenames??!1),r=this.encryption.folderKeyEntry(e)?.keyId,l=await rl(this.app,e,t,i,s,o,r,ps(e));return this.pendingEncBlobs.add(l.blobPath),this.unwatchReEncrypt(e,t),await this.saveSettings(),l.unpurged.length>0&&new M.Notice(`\u26A0\uFE0F Sent to encrypted trash, but ${l.unpurged.length} file${l.unpurged.length===1?" is":"s are"} still in plaintext (couldn't be removed or changed during the delete): ${l.unpurged.join(` -`)}`,0),l.blobPath}catch(s){return console.warn("[Stashpad] encrypt-delete failed",s),new N.Notice(`Couldn't encrypt-delete: ${s.message}`,0),null}}async plaintextDeleteSubtree(e,t){try{let i=new Date().toISOString(),s=await nl(this.app,e,t,i,hs(e));return this.unwatchReEncrypt(e,t),s.unpurged.length>0&&new N.Notice(`\u26A0\uFE0F Sent to trash, but ${s.unpurged.length} file${s.unpurged.length===1?" is":"s are"} still in place (couldn't be removed or changed during the delete): +`)}`,0),l.blobPath}catch(s){return console.warn("[Stashpad] encrypt-delete failed",s),new M.Notice(`Couldn't encrypt-delete: ${s.message}`,0),null}}async plaintextDeleteSubtree(e,t){try{let i=new Date().toISOString(),s=await ll(this.app,e,t,i,ps(e));return this.unwatchReEncrypt(e,t),s.unpurged.length>0&&new M.Notice(`\u26A0\uFE0F Sent to trash, but ${s.unpurged.length} file${s.unpurged.length===1?" is":"s are"} still in place (couldn't be removed or changed during the delete): ${s.unpurged.join(` -`)}`,0),s.blobPath}catch(i){return console.warn("[Stashpad] plaintext trash delete failed",i),new N.Notice(`Couldn't delete to trash: ${i.message}`,0),null}}async listPlaintextTrash(){let e=await rl(this.app,this.trashSubfolderDirs()),t=[];for(let i of e)t.push({blob:i,meta:await st(this.app,i)});return t}async restoreDeletedAt(e,t={}){let i=await st(this.app,e);if(e.endsWith(`.${ds}`)||i?.encrypted===!1)try{let n=await As(this.app,e,i),o=new Set;for(let l of this.app.vault.getMarkdownFiles())if((l.parent?.path?.replace(/\/+$/,"")??"")===n.replace(/\/+$/,""))try{let c=de(await this.app.vault.read(l)).fm.id;typeof c=="string"&&o.add(c)}catch{}let r=await ol(this.app,e,o);this.pendingEncBlobs.delete(e);try{await this.newLog().append({type:"restore",id:i?.rootId||S,payload:{to:r.restoredTo,from:"trash",encrypted:!1}})}catch{}return t.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,actions:[{label:"Go to folder",onClick:()=>void this.activateViewForFolder(r.restoredTo)}]}),!0}catch(n){return console.warn("[Stashpad] restore plaintext trash failed",n),new N.Notice(`Couldn't restore: ${n.message}`,0),!1}let s=null;if(i?.keyId){let n=this.encryption.folderPathByKeyId(i.keyId);s=n?await this.ensureFolderUnlocked(n):null}if(!s)return t.silent||new N.Notice("Couldn't unlock the folder key this trashed note was encrypted with."),!1;if(i?.kind==="rawtrash")try{let n=await ll(this.app,e,s);return this.pendingEncBlobs.delete(e),t.silent||this.notifications.show({message:`Restored ${n.filesWritten} file${n.filesWritten===1?"":"s"} to Obsidian's trash (${Yt}/).`,kind:"success",category:"system",folder:""}),!0}catch(n){return console.warn("[Stashpad] trash-backfill restore failed",n),new N.Notice(`Couldn't restore: ${n.message}`,0),!1}try{let n=await As(this.app,e,i,s),o=new Set;for(let l of this.app.vault.getMarkdownFiles())if((l.parent?.path?.replace(/\/+$/,"")??"")===n.replace(/\/+$/,""))try{let c=de(await this.app.vault.read(l)).fm.id;typeof c=="string"&&o.add(c)}catch{}let r=await sl(this.app,e,s,o);this.pendingEncBlobs.delete(e);try{await this.newLog().append({type:"restore",id:i?.rootId||S,payload:{to:r.restoredTo,from:"trash",encrypted:!0}})}catch{}return i?.rootId&&(this.watchReEncrypt({folder:r.restoredTo,rootId:i.rootId,title:i.title||"",count:i.count??r.notesWritten,via:"restore"}),await this.saveSettings()),t.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,actions:[{label:"Go to folder",onClick:()=>void this.activateViewForFolder(r.restoredTo)}]}),!0}catch(n){return console.warn("[Stashpad] restore-from-trash failed",n),new N.Notice(`Couldn't restore: ${n.message}`,0),!1}}async purgeDeletedAt(e){try{return await nr(this.app,e),this.pendingEncBlobs.delete(e),!0}catch(t){return console.warn("[Stashpad] purge-from-trash failed",e,t),new N.Notice(`Couldn't delete: ${t.message}`,0),!1}}async purgeAllLockedContent(){let e=s=>this.isTrashBlobPath(s),t=new Set;for(let s of this.app.vault.getFiles())s.extension==="stashenc"&&!e(s.path)&&t.add(s.path);for(let s of this.pendingEncBlobs)e(s)||t.add(s);let i=0;for(let s of t)try{await nr(this.app,s),this.pendingEncBlobs.delete(s),i++}catch(n){console.warn("[Stashpad] purge locked content failed",s,n)}return this.settings.lockedSubtrees=(this.settings.lockedSubtrees??[]).filter(s=>!t.has(s.blob)),await this.saveSettings(),i}async listRawTrashStashpadNotes(){let e=Yt,t=[];try{if(!await this.app.vault.adapter.exists(e))return t;let i=await this.app.vault.adapter.list(e);for(let s of i.files){if(!s.endsWith(".md"))continue;let n="";try{n=await this.app.vault.adapter.read(s)}catch{continue}let o=/^---\r?\n([\s\S]*?)\r?\n---/.exec(n);if(!o)continue;let r=o[1];if(!/^id:\s*\S/m.test(r)||!/^parent:\s*/m.test(r))continue;let l=s.split("/").pop()||s,c=l.replace(/\.md$/,"").replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||l,A=0;try{A=(await this.app.vault.adapter.stat(s))?.mtime??0}catch{}t.push({path:s,name:l,title:c,mtime:A})}}catch{}return t}async restoreRawTrashNote(e){let t=(this.settings.folder||"Stashpad").trim().replace(/^\/+|\/+$/g,"")||"Stashpad",i=e.split("/").pop()||e;try{if(!await this.app.vault.adapter.exists(t))try{await this.app.vault.createFolder(t)}catch{}let s=`${t}/${i}`;return await this.app.vault.adapter.exists(s)&&(s=`${t}/${i.replace(/\.md$/,"")}-restored-${Date.now()}.md`),await this.app.vault.adapter.rename(e,s),this.notifications.show({message:`Restored "${i}" to ${t}/. If its parent lives in another folder, move it from there.`,kind:"success",category:"system",folder:t,actions:[{label:"Go to folder",onClick:()=>void this.activateViewForFolder(t)}]}),!0}catch(s){return new N.Notice(`Couldn't restore: ${s.message}`),!1}}archivedPlainNotesIn(e){let t=e.replace(/\/+$/,""),i=t+"/",s=[];for(let n of this.app.vault.getMarkdownFiles()){let o=n.parent?.path?.replace(/\/+$/,"")??"";if(!(o===t||o.startsWith(i)))continue;let r=this.app.metadataCache.getFileCache(n)?.frontmatter?.id;typeof r=="string"&&r&&s.push(n)}return s}async unarchiveNote(e){let i=(e.parent?.path??"").replace(/\/+$/,"").split("/"),s=i.indexOf("archive"),n=s>0?i.slice(0,s).join("/"):(this.settings.folder||"Stashpad").trim().replace(/^\/+|\/+$/g,"")||"Stashpad";if((e.parent?.path??"")===n)return new N.Notice("Already in the default folder."),!1;try{if(!await this.app.vault.adapter.exists(n))try{await this.app.vault.createFolder(n)}catch{}let o=`${n}/${e.name}`;return await this.app.vault.adapter.exists(o)&&(o=`${n}/${e.basename}-restored-${Date.now()}.md`),await this.app.fileManager.renameFile(e,o),this.notifications.show({message:`Un-archived "${e.basename}" to ${n}/.`,kind:"success",category:"system",folder:n}),!0}catch(o){return new N.Notice(`Couldn't un-archive: ${o.message}`),!1}}trashSubfolderDirs(){return this.discoverStashpadFolders().map(e=>hs(e))}async listDeletedTrash(){let e=await kn(this.app,this.trashSubfolderDirs()),t=[];for(let i of e)t.push({blob:i,meta:await st(this.app,i)});return t}async restoreAllTrash(){let e=[...await this.listDeletedTrash(),...await this.listPlaintextTrash()];if(e.length===0)return new N.Notice("Nothing to restore."),0;let t=e.length>3?new N.Notice("",0):null,i=0;for(let s=0;s<e.length;s++){t?.setMessage(`\u{1F513} Restoring ${s+1}/${e.length}\u2026`);try{await this.restoreDeletedAt(e[s].blob,{silent:!0})&&i++}catch(n){console.warn("[Stashpad] restore-all skipped",e[s].blob,n)}}return t?.hide(),i>0&&this.notifications.show({message:`Restored ${i} note${i===1?"":"s"} from encrypted trash.`,kind:"success",category:"system",folder:""}),i}openEncryptedTrash(e){Cl(this)}async openRestoreTrashPicker(){if(!this.encryption.isConfigured()){new N.Notice("Set up encryption first (Settings \u2192 Stashpad \u2192 Encryption).");return}let e=await this.listDeletedTrash();if(e.length===0){new N.Notice("Encrypted trash is empty.");return}let t=e.map(({blob:i,meta:s})=>({blob:i,label:s?.title||i.split("/").pop()?.replace(/\.stashenc$/,"")||"Locked note",folder:s?.originalFolder||"(unknown)"}));new bn(this.app,t,i=>{this.restoreDeletedAt(i)}).open()}isArchiveFolder(e){let t=e.replace(/\/+$/,"");return ws(t)||(this.settings.archiveFolders??[]).includes(t)?!0:!!(this.settings.folderEncPrefs??{})[t]?.archive}archiveEncryptFor(e){let t=e.replace(/\/+$/,"");return t.endsWith("/archive")&&(t=t.slice(0,-8)),(this.settings.folderEncPrefs??{})[t]?.archiveEncryptContent??!1}async migrateArchiveFoldersToSubfolders(){if(!this.settings.migratedArchiveToSubfolders){this.archiveMigrationInFlight=!0;try{await this.migrateArchiveFoldersToSubfoldersInner()}finally{window.setTimeout(()=>{this.archiveMigrationInFlight=!1},4e3)}}}async migrateArchiveFoldersToSubfoldersInner(){let e=new Set((this.settings.archiveFolders??[]).map(l=>l.replace(/\/+$/,"")));for(let[l,c]of Object.entries(this.settings.folderEncPrefs??{}))c?.archive&&e.add(l.replace(/\/+$/,""));let t=this.newLog(),i=[],s=0,n=[],o=`${this.pluginPrivatePath()}/archive-migration-journal.json`,r=async()=>{try{await this.app.vault.adapter.write(o,JSON.stringify({ts:new Date().toISOString(),moves:n},null,1))}catch{}};for(let l of[...e].sort()){let c=this.app.vault.getAbstractFileByPath(l);if(!(c instanceof N.TFolder))continue;let A=yt(l);try{await this.app.vault.adapter.exists(A)||await this.app.vault.createFolder(A)}catch{}let h=0,g=0;for(let u of[...c.children]){if(!(u instanceof N.TFile)||u.extension!=="md")continue;let f;try{f=de(await this.app.vault.read(u)).fm.id}catch{g++,s++;continue}if(f===S)continue;let p=`${A}/${u.name}`,I=u.path;try{for(let m=1;await this.app.vault.adapter.exists(p);m++)p=`${A}/${u.basename}-${m}.md`;if(n.push({folder:l,from:I,to:p,ok:!1}),await this.app.fileManager.renameFile(u,p),!(this.app.vault.getAbstractFileByPath(p)instanceof N.TFile))throw new Error("rename did not land");n[n.length-1].ok=!0,h++}catch(m){g++,s++,console.warn("[Stashpad] archive migration move failed",I,m)}}if(await r(),g===0){let u={...this.settings.folderEncPrefs??{}},f={...u[l]??{}};delete f.archive,u[l]=f,this.settings.folderEncPrefs=u}i.push(`"${l}": ${h} note${h===1?"":"s"} \u2192 ${A}/${g?` (${g} failed \u2014 left in place)`:""}`),t.append({type:"archive_migration",id:"",payload:{folder:l,dest:A,moved:h,failed:g}})}s===0?(this.settings.archiveFolders=[],this.settings.defaultArchiveFolder=void 0,this.settings.migratedArchiveToSubfolders=!0,await this.saveSettings()):(await this.saveSettings(),new N.Notice(`Stashpad archive update: ${s} note${s===1?"":"s"} couldn't be moved (see the developer console). Nothing was deleted \u2014 the migration will retry on the next launch. A recovery journal of every move is at ${this.pluginPrivatePath()}/archive-migration-journal.json.`,0)),i.length&&new N.Notice(`Stashpad archive update: dedicated archive folders are now regular folders \u2014 archived notes moved into each folder's own "archive/" subfolder. +`)}`,0),s.blobPath}catch(i){return console.warn("[Stashpad] plaintext trash delete failed",i),new M.Notice(`Couldn't delete to trash: ${i.message}`,0),null}}async listPlaintextTrash(){let e=await dl(this.app,this.trashSubfolderDirs()),t=[];for(let i of e)t.push({blob:i,meta:await nt(this.app,i)});return t}async restoreDeletedAt(e,t={}){let i=await nt(this.app,e);if(e.endsWith(`.${As}`)||i?.encrypted===!1)try{let n=await hs(this.app,e,i),o=new Set;for(let l of this.app.vault.getMarkdownFiles())if((l.parent?.path?.replace(/\/+$/,"")??"")===n.replace(/\/+$/,""))try{let c=Ae(await this.app.vault.read(l)).fm.id;typeof c=="string"&&o.add(c)}catch{}let r=await cl(this.app,e,o);this.pendingEncBlobs.delete(e);try{await this.newLog().append({type:"restore",id:i?.rootId||k,payload:{to:r.restoredTo,from:"trash",encrypted:!1}})}catch{}return t.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,actions:[{label:"Go to folder",onClick:()=>void this.activateViewForFolder(r.restoredTo)}]}),!0}catch(n){return console.warn("[Stashpad] restore plaintext trash failed",n),new M.Notice(`Couldn't restore: ${n.message}`,0),!1}let s=null;if(i?.keyId){let n=this.encryption.folderPathByKeyId(i.keyId);s=n?await this.ensureFolderUnlocked(n):null}if(!s)return t.silent||new M.Notice("Couldn't unlock the folder key this trashed note was encrypted with."),!1;if(i?.kind==="rawtrash")try{let n=await hl(this.app,e,s);return this.pendingEncBlobs.delete(e),t.silent||this.notifications.show({message:`Restored ${n.filesWritten} file${n.filesWritten===1?"":"s"} to Obsidian's trash (${zt}/).`,kind:"success",category:"system",folder:""}),!0}catch(n){return console.warn("[Stashpad] trash-backfill restore failed",n),new M.Notice(`Couldn't restore: ${n.message}`,0),!1}try{let n=await hs(this.app,e,i,s),o=new Set;for(let l of this.app.vault.getMarkdownFiles())if((l.parent?.path?.replace(/\/+$/,"")??"")===n.replace(/\/+$/,""))try{let c=Ae(await this.app.vault.read(l)).fm.id;typeof c=="string"&&o.add(c)}catch{}let r=await al(this.app,e,s,o);this.pendingEncBlobs.delete(e);try{await this.newLog().append({type:"restore",id:i?.rootId||k,payload:{to:r.restoredTo,from:"trash",encrypted:!0}})}catch{}return i?.rootId&&(this.watchReEncrypt({folder:r.restoredTo,rootId:i.rootId,title:i.title||"",count:i.count??r.notesWritten,via:"restore"}),await this.saveSettings()),t.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,actions:[{label:"Go to folder",onClick:()=>void this.activateViewForFolder(r.restoredTo)}]}),!0}catch(n){return console.warn("[Stashpad] restore-from-trash failed",n),new M.Notice(`Couldn't restore: ${n.message}`,0),!1}}async purgeDeletedAt(e){try{return await rr(this.app,e),this.pendingEncBlobs.delete(e),!0}catch(t){return console.warn("[Stashpad] purge-from-trash failed",e,t),new M.Notice(`Couldn't delete: ${t.message}`,0),!1}}async purgeAllLockedContent(){let e=s=>this.isTrashBlobPath(s),t=new Set;for(let s of this.app.vault.getFiles())s.extension==="stashenc"&&!e(s.path)&&t.add(s.path);for(let s of this.pendingEncBlobs)e(s)||t.add(s);let i=0;for(let s of t)try{await rr(this.app,s),this.pendingEncBlobs.delete(s),i++}catch(n){console.warn("[Stashpad] purge locked content failed",s,n)}return this.settings.lockedSubtrees=(this.settings.lockedSubtrees??[]).filter(s=>!t.has(s.blob)),await this.saveSettings(),i}async listRawTrashStashpadNotes(){let e=zt,t=[];try{if(!await this.app.vault.adapter.exists(e))return t;let i=await this.app.vault.adapter.list(e);for(let s of i.files){if(!s.endsWith(".md"))continue;let n="";try{n=await this.app.vault.adapter.read(s)}catch{continue}let o=/^---\r?\n([\s\S]*?)\r?\n---/.exec(n);if(!o)continue;let r=o[1];if(!/^id:\s*\S/m.test(r)||!/^parent:\s*/m.test(r))continue;let l=s.split("/").pop()||s,c=l.replace(/\.md$/,"").replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||l,A=0;try{A=(await this.app.vault.adapter.stat(s))?.mtime??0}catch{}t.push({path:s,name:l,title:c,mtime:A})}}catch{}return t}async restoreRawTrashNote(e){let t=(this.settings.folder||"Stashpad").trim().replace(/^\/+|\/+$/g,"")||"Stashpad",i=e.split("/").pop()||e;try{if(!await this.app.vault.adapter.exists(t))try{await this.app.vault.createFolder(t)}catch{}let s=`${t}/${i}`;return await this.app.vault.adapter.exists(s)&&(s=`${t}/${i.replace(/\.md$/,"")}-restored-${Date.now()}.md`),await this.app.vault.adapter.rename(e,s),this.notifications.show({message:`Restored "${i}" to ${t}/. If its parent lives in another folder, move it from there.`,kind:"success",category:"system",folder:t,actions:[{label:"Go to folder",onClick:()=>void this.activateViewForFolder(t)}]}),!0}catch(s){return new M.Notice(`Couldn't restore: ${s.message}`),!1}}archivedPlainNotesIn(e){let t=e.replace(/\/+$/,""),i=t+"/",s=[];for(let n of this.app.vault.getMarkdownFiles()){let o=n.parent?.path?.replace(/\/+$/,"")??"";if(!(o===t||o.startsWith(i)))continue;let r=this.app.metadataCache.getFileCache(n)?.frontmatter?.id;typeof r=="string"&&r&&s.push(n)}return s}async unarchiveNote(e){let i=(e.parent?.path??"").replace(/\/+$/,"").split("/"),s=i.indexOf("archive"),n=s>0?i.slice(0,s).join("/"):(this.settings.folder||"Stashpad").trim().replace(/^\/+|\/+$/g,"")||"Stashpad";if((e.parent?.path??"")===n)return new M.Notice("Already in the default folder."),!1;try{if(!await this.app.vault.adapter.exists(n))try{await this.app.vault.createFolder(n)}catch{}let o=`${n}/${e.name}`;return await this.app.vault.adapter.exists(o)&&(o=`${n}/${e.basename}-restored-${Date.now()}.md`),await this.app.fileManager.renameFile(e,o),this.notifications.show({message:`Un-archived "${e.basename}" to ${n}/.`,kind:"success",category:"system",folder:n}),!0}catch(o){return new M.Notice(`Couldn't un-archive: ${o.message}`),!1}}trashSubfolderDirs(){return this.discoverStashpadFolders().map(e=>ps(e))}async listDeletedTrash(){let e=await Dn(this.app,this.trashSubfolderDirs()),t=[];for(let i of e)t.push({blob:i,meta:await nt(this.app,i)});return t}async restoreAllTrash(){let e=[...await this.listDeletedTrash(),...await this.listPlaintextTrash()];if(e.length===0)return new M.Notice("Nothing to restore."),0;let t=e.length>3?new M.Notice("",0):null,i=0;for(let s=0;s<e.length;s++){t?.setMessage(`\u{1F513} Restoring ${s+1}/${e.length}\u2026`);try{await this.restoreDeletedAt(e[s].blob,{silent:!0})&&i++}catch(n){console.warn("[Stashpad] restore-all skipped",e[s].blob,n)}}return t?.hide(),i>0&&this.notifications.show({message:`Restored ${i} note${i===1?"":"s"} from encrypted trash.`,kind:"success",category:"system",folder:""}),i}openEncryptedTrash(e){El(this)}async openRestoreTrashPicker(){if(!this.encryption.isConfigured()){new M.Notice("Set up encryption first (Settings \u2192 Stashpad \u2192 Encryption).");return}let e=await this.listDeletedTrash();if(e.length===0){new M.Notice("Encrypted trash is empty.");return}let t=e.map(({blob:i,meta:s})=>({blob:i,label:s?.title||i.split("/").pop()?.replace(/\.stashenc$/,"")||"Locked note",folder:s?.originalFolder||"(unknown)"}));new Nn(this.app,t,i=>{this.restoreDeletedAt(i)}).open()}isArchiveFolder(e){let t=e.replace(/\/+$/,"");return Es(t)||(this.settings.archiveFolders??[]).includes(t)?!0:!!(this.settings.folderEncPrefs??{})[t]?.archive}archiveEncryptFor(e){let t=e.replace(/\/+$/,"");return t.endsWith("/archive")&&(t=t.slice(0,-8)),(this.settings.folderEncPrefs??{})[t]?.archiveEncryptContent??!1}async migrateArchiveFoldersToSubfolders(){if(!this.settings.migratedArchiveToSubfolders){this.archiveMigrationInFlight=!0;try{await this.migrateArchiveFoldersToSubfoldersInner()}finally{window.setTimeout(()=>{this.archiveMigrationInFlight=!1},4e3)}}}async migrateArchiveFoldersToSubfoldersInner(){let e=new Set((this.settings.archiveFolders??[]).map(l=>l.replace(/\/+$/,"")));for(let[l,c]of Object.entries(this.settings.folderEncPrefs??{}))c?.archive&&e.add(l.replace(/\/+$/,""));let t=this.newLog(),i=[],s=0,n=[],o=`${this.pluginPrivatePath()}/archive-migration-journal.json`,r=async()=>{try{await this.app.vault.adapter.write(o,JSON.stringify({ts:new Date().toISOString(),moves:n},null,1))}catch{}};for(let l of[...e].sort()){let c=this.app.vault.getAbstractFileByPath(l);if(!(c instanceof M.TFolder))continue;let A=wt(l);try{await this.app.vault.adapter.exists(A)||await this.app.vault.createFolder(A)}catch{}let h=0,p=0;for(let u of[...c.children]){if(!(u instanceof M.TFile)||u.extension!=="md")continue;let f;try{f=Ae(await this.app.vault.read(u)).fm.id}catch{p++,s++;continue}if(f===k)continue;let g=`${A}/${u.name}`,I=u.path;try{for(let m=1;await this.app.vault.adapter.exists(g);m++)g=`${A}/${u.basename}-${m}.md`;if(n.push({folder:l,from:I,to:g,ok:!1}),await this.app.fileManager.renameFile(u,g),!(this.app.vault.getAbstractFileByPath(g)instanceof M.TFile))throw new Error("rename did not land");n[n.length-1].ok=!0,h++}catch(m){p++,s++,console.warn("[Stashpad] archive migration move failed",I,m)}}if(await r(),p===0){let u={...this.settings.folderEncPrefs??{}},f={...u[l]??{}};delete f.archive,u[l]=f,this.settings.folderEncPrefs=u}i.push(`"${l}": ${h} note${h===1?"":"s"} \u2192 ${A}/${p?` (${p} failed \u2014 left in place)`:""}`),t.append({type:"archive_migration",id:"",payload:{folder:l,dest:A,moved:h,failed:p}})}s===0?(this.settings.archiveFolders=[],this.settings.defaultArchiveFolder=void 0,this.settings.migratedArchiveToSubfolders=!0,await this.saveSettings()):(await this.saveSettings(),new M.Notice(`Stashpad archive update: ${s} note${s===1?"":"s"} couldn't be moved (see the developer console). Nothing was deleted \u2014 the migration will retry on the next launch. A recovery journal of every move is at ${this.pluginPrivatePath()}/archive-migration-journal.json.`,0)),i.length&&new M.Notice(`Stashpad archive update: dedicated archive folders are now regular folders \u2014 archived notes moved into each folder's own "archive/" subfolder. ${i.join(` `)} -Find everything in the aggregated Archived view. (This notice stays until dismissed.)`,0)}async migrateDeletedToTrashSubfolders(){if(this.settings.migratedTrashToSubfolders)return;let e=this.app.vault.adapter,t=this.newLog(),i=0,s=0,n=0,o=[],r=`${this.pluginPrivatePath()}/trash-migration-journal.json`;try{let l=await kn(this.app);for(let c of l){let A=await st(this.app,c),h=A?.kind==="deleted"&&A.originalFolder?A.originalFolder.replace(/\/+$/,""):"";if(!h||!(this.app.vault.getAbstractFileByPath(h)instanceof N.TFolder)){s++;continue}let g=hs(h);try{await e.exists(g)||await e.mkdir(g);let u=c.split("/").pop(),f=`${g}/${u}`;for(let C=1;await e.exists(f);C++)f=`${g}/${u.replace(/\.stashenc$/,"")} (${C}).stashenc`;o.push({from:c,to:f,ok:!1});let p=new Uint8Array(await e.readBinary(c));await e.writeBinary(f,p.slice().buffer);let I=new Uint8Array(await e.readBinary(f));if(I.length!==p.length)throw new Error("copy verify failed (length)");for(let C=0;C<p.length;C++)if(I[C]!==p[C])throw new Error("copy verify failed (content)");let m=c.replace(/\.stashenc$/,".stashmeta"),B=f.replace(/\.stashenc$/,".stashmeta");try{if(await e.exists(m)){let C=await e.read(m);if(await e.write(B,C),await e.read(B)!==C)throw new Error("sidecar verify failed");await e.remove(m)}}catch(C){throw new Error(`sidecar copy failed: ${C.message}`)}await e.remove(c),o[o.length-1].ok=!0,i++}catch(u){n++,console.warn("[Stashpad] trash migration move failed",c,u)}}try{await e.write(r,JSON.stringify({ts:new Date().toISOString(),moves:o},null,1))}catch{}}catch(l){console.error("[Stashpad] trash migration failed",l);return}t.append({type:"archive_migration",id:"",payload:{what:"trash-subfolders",moved:i,left:s,failed:n}}),n===0&&(this.settings.migratedTrashToSubfolders=!0,await this.saveSettings()),(i>0||n>0)&&new N.Notice(`Stashpad trash update: ${i} encrypted-trash item${i===1?"":"s"} moved into per-folder "trash/" subfolders${s?` (${s} stayed in _deleted/ \u2014 unknown or missing origin)`:""}${n?` \u2014 ${n} failed; will retry next launch`:""}. Everything stays visible in the Trash view.`,0)}async pruneZombieArchiveEntries(){let e=o=>this.app.vault.getAbstractFileByPath(o)instanceof N.TFolder,t=this.settings.archiveFolders??[],i=t.filter(o=>e(o.replace(/\/+$/,""))),s=i.length!==t.length,n=(this.settings.defaultArchiveFolder??"").replace(/\/+$/,"");n&&!e(n)&&(this.settings.defaultArchiveFolder=void 0,s=!0),s&&(this.settings.archiveFolders=i,await this.saveSettings(),console.info(`[Stashpad] pruned ${t.length-i.length} stale archive-folder entr${t.length-i.length===1?"y":"ies"}.`))}async ensureOkfTemplate(){let e=await yl(this.app,this.settings.okfTemplatePath||void 0);return this.settings.okfTemplatePath!==e&&(this.settings.okfTemplatePath=e,await this.saveSettings()),e}okfTemplatePathOrDefault(){return this.settings.okfTemplatePath||lr}okfActiveFolders(){return this.settings.okfEnabled?wl(this.settings.noteTemplates,this.okfTemplatePathOrDefault()).filter(e=>!this.isArchiveFolder(e)):[]}async rebuildOkfSuppressed(e){this.okfRebuildingFolders.add(e);try{return await dr(this.app,e)}finally{window.setTimeout(()=>{this.okfRebuildingFolders.delete(e);for(let t of this.app.workspace.getLeavesOfType(z)){let i=t.view;i?.noteFolder===e&&i.forceReconcileRender?.()}},600)}}onOkfFileEvent(e){if(!this.settings.okfEnabled||!e.toLowerCase().endsWith(".md"))return;let t=e.lastIndexOf("/"),i=(t>=0?e.slice(0,t):"").replace(/\/+$/,"");(t>=0?e.slice(t+1):e)!=="index.md"&&(/(^|\/)(_imports|_exports|_attachments|_deleted|\.stashpad)(\/|$)/.test(e)||this.okfActiveFolders().includes(i)&&this.scheduleOkfRebuild(i))}scheduleOkfRebuild(e){let t=this.okfRebuildTimers.get(e);t!=null&&window.clearTimeout(t),this.okfRebuildTimers.set(e,window.setTimeout(()=>{this.okfRebuildTimers.delete(e),this.okfActiveFolders().includes(e)&&this.rebuildOkfSuppressed(e).catch(i=>console.warn("[Stashpad] OKF auto-rebuild failed",e,i))},2500))}async rebuildAllOkf(){let e=this.okfActiveFolders(),t=0,i=0;for(let s of e){let n=await this.rebuildOkfSuppressed(s);t+=n.checked,i+=n.written}return{folders:e.length,checked:t,written:i}}async exportOkf(e,t,i,s){let n=e.replace(/\/+$/,""),o=[],r=[],l=[],c=new Set;for(let I of t){let m=await It(this.app,n,I);if(m){o.push({id:m.rootNote.id,file:m.rootNote.file}),l.push(m.rootNote.file),c.add(m.rootNote.id);for(let B of m.descendants)r.push({id:B.id,file:B.file}),l.push(B.file),c.add(B.id)}}if(!l.length)return[];let A=(i||"okf-export").replace(/[\\/:*?"<>|]+/g," ").replace(/\s+/g," ").trim().slice(0,80)||"okf-export",h=new Date().toISOString().replace(/\D/g,"").slice(0,14),g=(this.settings.exportFolder||"_exports").trim().replace(/^\/+|\/+$/g,""),u=`${n}/${g}`;for(let I of[n,u])try{await this.app.vault.adapter.exists(I)||await this.app.vault.adapter.mkdir(I)}catch{}let f=[],p=async(I,m)=>{let B=`${u}/${I}`;await this.app.vault.createBinary(B,m.buffer.slice(m.byteOffset,m.byteOffset+m.byteLength)),f.push(B)};if(s.zip||s.targz){let I=await El(this.app,l,n,c);s.zip&&await p(`${A}-${h}.okf.zip`,await Ql(I)),s.targz&&await p(`${A}-${h}.okf.tar.gz`,await vl(I))}if(s.stash){let I=await ft(this.app,{rootNotes:o,allDescendants:r,sourceFolder:n});await p(`${A}-${h}.${tt}`,I)}return f}async idsInFolder(e){let t=e.replace(/\/+$/,""),i=new Set;for(let s of this.app.vault.getMarkdownFiles())if((s.parent?.path?.replace(/\/+$/,"")??"")===t)try{let n=de(await this.app.vault.read(s)).fm.id;typeof n=="string"&&i.add(n)}catch{}return i}async crossFolderPaste(e,t,i,s,n){let o=i.replace(/\/+$/,"");if(this.isArchiveFolder(o))return new N.Notice(`"${o.split("/").pop()}" is an archive folder, so cross-folder paste is disabled there. Use the "Move selection to archive" command instead \u2014 it runs the proper archive flow (and encrypts, if that folder encrypts its archive).`),null;let r=[],l=[],c=[],A=[];for(let Q of t){let b=await It(this.app,e,Q);if(b){c.push(b.rootNote.id),r.push({id:b.rootNote.id,file:b.rootNote.file}),A.push(b.rootNote.file);for(let D of b.descendants)l.push({id:D.id,file:D.file}),A.push(D.file)}}if(!r.length)return null;let h=r.length+l.length,g=[],u=[];n==="cut"&&(g=await this.exclusiveAttachmentsOf(A),u=await this.snapshotPaths([...A.map(Q=>Q.path),...g.map(Q=>Q.path)]));let f=await ft(this.app,{rootNotes:r,allDescendants:l,sourceFolder:e}),p=await this.idsInFolder(o),I=new Set(this.filesUnder(o)),m=await Je(this.app,f,o,p,{dedupeExisting:!1,forceNewIds:n==="copy",reparentRootsTo:s}),B=this.filesUnder(o).filter(Q=>!I.has(Q)),C=await this.snapshotPaths(B),w=c.map(Q=>m.idRemap[Q]).filter(Q=>!!Q);if(n==="cut"){for(let Q of A)try{await this.app.fileManager.trashFile(Q)}catch(b){console.warn("[Stashpad] cross-folder move: couldn't trash source note",Q.path,b)}for(let Q of g)try{await this.app.fileManager.trashFile(Q)}catch(b){console.warn("[Stashpad] cross-folder move: couldn't trash source attachment",Q.path,b)}}let y=async()=>{for(let Q of[...B].reverse()){let b=this.app.vault.getAbstractFileByPath(Q);if(b)try{await this.app.fileManager.trashFile(b)}catch{}}};return{rootIds:w,noteCount:h,undo:n==="cut"?async()=>{await y(),await this.restoreSnapshot(u)}:async()=>{await y()},redo:n==="cut"?async()=>{await this.restoreSnapshot(C);for(let Q of u){let b=this.app.vault.getAbstractFileByPath(Q.path);if(b)try{await this.app.fileManager.trashFile(b)}catch{}}}:async()=>{await this.restoreSnapshot(C)}}}async trashSubtrees(e,t){let i=[];for(let o of t){let r=await It(this.app,e,o);r&&i.push(r.rootNote.file,...r.descendants.map(l=>l.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(e){let t=new Set(e.map(n=>n.path)),i=new Map;for(let n of e)for(let o of await $t(this.app,n))i.set(o.path,o);let s=this.app.metadataCache.resolvedLinks??{};for(let n of Object.keys(s))if(!t.has(n))for(let o of Object.keys(s[n]??{}))i.delete(o);return[...i.values()]}async subtreeFilePaths(e,t){let i=[];for(let n of t){let o=await It(this.app,e,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(e,t){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 t){let r=await It(this.app,e,o);if(!r)continue;let l=new Map;for(let A of r.descendants){if(!A.parent)continue;let h=l.get(A.parent)??[];h.push({id:A.id,file:A.file,created:A.created}),l.set(A.parent,h)}for(let A of l.values())A.sort((h,g)=>n(h.file)-n(g.file)||h.created.localeCompare(g.created));let c=(A,h)=>{if(!s.has(A.id)){s.add(A.id),i.push({file:A.file,created:A.created,depth:h});for(let g of l.get(A.id)??[])c(g,h+1)}};c({id:r.rootNote.id,file:r.rootNote.file,created:r.rootNote.created},0)}return i}filesUnder(e){let t=e.replace(/\/+$/,"")+"/";return this.app.vault.getFiles().filter(i=>i.path.startsWith(t)).map(i=>i.path)}async snapshotPaths(e){let t=[];for(let i of e){let s=this.app.vault.getAbstractFileByPath(i);if(!s)continue;let n=!i.toLowerCase().endsWith(".md");try{n?t.push({path:i,binary:n,data:await this.app.vault.readBinary(s)}):t.push({path:i,binary:n,text:await this.app.vault.read(s)})}catch(o){console.warn("[Stashpad] snapshotPaths: couldn't read",i,o)}}return t}async restoreSnapshot(e){for(let t of e){let i=t.path.split("/").slice(0,-1).join("/");await this.ensureVaultFolder(i);let s=this.app.vault.getAbstractFileByPath(t.path);try{t.binary?s?await this.app.vault.adapter.writeBinary(t.path,t.data):await this.app.vault.createBinary(t.path,t.data):s?await this.app.vault.modify(s,t.text??""):await this.app.vault.create(t.path,t.text??"")}catch(n){console.warn("[Stashpad] restoreSnapshot: couldn't write",t.path,n)}}}async ensureVaultFolder(e){if(!e)return;let t="";for(let i of e.split("/"))if(t=t?`${t}/${i}`:i,!await this.app.vault.adapter.exists(t))try{await this.app.vault.createFolder(t)}catch{}}refreshOpenViewsForFolder(e){let t=e.replace(/\/+$/,"");for(let i of this.app.workspace.getLeavesOfType(z)){let s=i.view;if((s?.noteFolder?.replace(/\/+$/,"")??"")===t)try{s.tree?.rebuild?.(e),s.render?.()}catch(n){console.warn("[Stashpad] refresh view failed",n)}}}maybeArchiveOnMoveIn(e,t){if(e.extension!=="md")return;let i=e.parent?.path?.replace(/\/+$/,"")??"",s=t.lastIndexOf("/"),n=(s>=0?t.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(e.path),window.clearTimeout(o.timer),o.timer=window.setTimeout(()=>{this.archivePending.delete(i),this.archiveSweep(i,[...o.paths])},1800)}async encryptExistingArchiveNotes(e){let t=yt(e.replace(/\/+$/,"")),i=this.archivedPlainNotesIn(t).map(s=>s.path);return i.length===0?0:(await this.archiveSweep(t,i),i.length-this.archivedPlainNotesIn(t).length)}async archiveSweep(e,t){if(this.archiveMigrationInFlight||!this.isArchiveFolder(e))return;let i=e.replace(/\/+$/,"");if(!this.archiveEncryptFor(i))return;let s=[];for(let c of t){let A=this.app.vault.getAbstractFileByPath(c);if(!(A instanceof N.TFile)||(A.parent?.path?.replace(/\/+$/,"")??"")!==i)continue;let h;try{h=de(await this.app.vault.read(A)).fm}catch{continue}let g=typeof h.id=="string"?h.id:null;!g||g===S||s.push({id:g,parent:typeof h.parent=="string"?h.parent:null})}if(s.length===0)return;let n=new Set(s.map(c=>c.id)),o=new Set((this.settings.lockedSubtrees??[]).map(c=>c.rootId).filter(c=>!!c)),r=s.filter(c=>!o.has(c.id)&&!(c.parent&&n.has(c.parent)));if(r.length===0||!this.encryption.hasFolderKey(i))return;if(!await this.ensureFolderUnlocked(i)){new N.Notice(`\u26A0\uFE0F Archive folder "${i.split("/").pop()}": ${r.length} arriving note${r.length===1?"":"s"} NOT encrypted (couldn't unlock the folder password). Unlock it and lock them manually.`,0);return}let l=0;for(let c of r)await this.lockNoteSubtree(i,c.id,null,{silent:!0})&&l++;l>0&&this.notifications.show({message:`Archived (encrypted) ${l} note${l===1?"":"s"} moved into \u201C${i.split("/").pop()}\u201D.`,kind:"success",category:"system",folder:i,actions:[{label:"All archived",onClick:()=>void Te(this,"archived")}]})}async activateViewForFolder(e){let t=(e||"").replace(/^\/+|\/+$/g,"");if(!t)return null;let i=this.app.workspace.getLeaf("tab");return await i.setViewState({type:z,active:!0,state:{folderOverride:t}}),this.app.workspace.revealLeaf(i),i}navigateLeafTo(e,t,i){let s=e?.view;if(s?.navigateTo&&(!s.tree||s.tree.get(i))){s.navigateTo(i);return}this.navigateWhenReady(t,i)}async openFolderInStashpad(e){let t=(e||"").replace(/^\/+|\/+$/g,"");if(!t)return;let i=await this.findStashpadLeafForFolder(t);if(i){this.app.workspace.revealLeaf(i),this.app.workspace.setActiveLeaf(i,{focus:!0});return}await this.activateViewForFolder(t)}async findStashpadLeafForFolder(e){let t=e.replace(/\/+$/,""),i=this.app.workspace.getLeavesOfType(z),s=i.find(o=>!o.isDeferred&&(o.view?.noteFolder??"").replace(/\/+$/,"")===t);if(s)return s;let n=i.find(o=>o.isDeferred&&(o.getViewState()?.state?.folderOverride??"").replace(/\/+$/,"")===t);if(n){try{await n.loadIfDeferred?.()}catch{}return n}return null}isStashpadNoteFile(e){let t=e.parent?.path?.replace(/\/+$/,"")??"";if(!this.discoverStashpadFolders().includes(t))return!1;let i=this.app.metadataCache.getFileCache(e)?.frontmatter?.id;return typeof i=="string"&&i.length>0}async revealNoteInStashpad(e){let t=e.parent?.path?.replace(/\/+$/,"")??"",i=this.app.metadataCache.getFileCache(e)?.frontmatter?.id;if(!t||typeof i!="string"||!i){new N.Notice("That note isn't a Stashpad note.");return}await this.revealNoteByRef(t,i)}async revealNoteByRef(e,t){let i=e.replace(/\/+$/,""),s=await this.findStashpadLeafForFolder(i);if(s){this.app.workspace.revealLeaf(s),this.app.workspace.setActiveLeaf(s,{focus:!0}),this.navigateLeafTo(s,i,t);return}let n=await this.activateViewForFolder(i);this.navigateLeafTo(n,i,t)}resolveNoteFileInFolder(e,t){let i=e.replace(/\/+$/,"");for(let s of this.app.vault.getMarkdownFiles())if((s.parent?.path?.replace(/\/+$/,"")??"")===i&&this.app.metadataCache.getFileCache(s)?.frontmatter?.id===t)return s;return null}async handleDeepLink(e){let t=(e.folder||"").replace(/^\/+|\/+$/g,""),i=(e.note||"").trim(),s=Ba(e);if(!t){new N.Notice("Stashpad link: missing \u201Cfolder\u201D.");return}if(!(this.app.vault.getAbstractFileByPath(t)instanceof N.TFolder)){new N.Notice(`Stashpad link: folder \u201C${t}\u201D not found.`);return}await new Promise(r=>this.app.workspace.onLayoutReady(()=>r()));let o=null;if(i){for(let r=0;r<12&&!o;r++)o=this.resolveNoteFileInFolder(t,i),o||await new Promise(l=>window.setTimeout(l,150));if(!o){new N.Notice(`Stashpad link: note \u201C${i}\u201D not found in ${t}.`);return}}await this.openDeepLinkTarget(t,i);for(let r of s)if(r!=="reveal"){if(r==="open"){o&&await this.app.workspace.getLeaf("tab").openFile(o);continue}console.warn(`[stashpad] deep link: unknown action \u201C${r}\u201D \u2014 skipped.`)}}async openDeepLinkTarget(e,t){let i=e.replace(/\/+$/,""),s=this.app.workspace.activeLeaf,n=await this.findStashpadLeafForFolder(i);if(n&&n!==s){this.app.workspace.revealLeaf(n),this.app.workspace.setActiveLeaf(n,{focus:!0}),t&&this.navigateLeafTo(n,i,t);return}let o=await this.activateViewForFolder(i);t&&this.navigateLeafTo(o,i,t)}openDeepLinkModal(){new Gi(this.app,e=>{let t=Ca(e);if(!t){new N.Notice("That doesn't look like a Stashpad link.");return}this.handleDeepLink(t)}).open()}async closeDuplicateStashpadTabs(){let e=this.app.workspace.getLeavesOfType(z),t=this.app.workspace.activeLeaf;for(let f of e)try{await f.loadIfDeferred?.()}catch{}let i=f=>f.getViewState()?.state??{},s=f=>{let p=i(f);return(f.isDeferred?p.folderOverride??"":f.view?.noteFolder??p.folderOverride??"").replace(/\/+$/,"")},n=f=>{let p=i(f);return(f.isDeferred?p.focusId:f.view?.focusId??p.focusId)||S},o=f=>{let p=f.view;return!!p&&p.getViewType?.()===z&&typeof p.navigateTo=="function"&&typeof p.noteFolder=="string"},r=new Map;for(let f of this.app.vault.getMarkdownFiles()){let p=(f.parent?.path??"").replace(/\/+$/,""),I=this.app.metadataCache.getFileCache(f)?.frontmatter?.id;typeof I=="string"&&I&&(r.get(p)??r.set(p,new Set).get(p)).add(I)}let l=0,c=[];for(let f of e){let p=s(f),I=n(f);if(p&&I&&I!==S){let m=!f.isDeferred&&!!f.view?.tree?.get?.(I),B=r.get(p)?.has(I)??!1;if(!m&&!B){f.detach(),l++;continue}}c.push(f)}let A=new Map;for(let f of c){let p=s(f);if(!p)continue;let I=p+" "+n(f);(A.get(I)??A.set(I,[]).get(I)).push(f)}let h=0;for(let f of A.values()){if(f.length<=1)continue;f.sort((I,m)=>{let B=C=>C===t?2:C.isDeferred?0:1;return B(m)-B(I)});let p=null;for(let I of f){try{await I.loadIfDeferred?.()}catch{}if(o(I)){p=I;break}}p||(p=f[0]);for(let I of f)I!==p&&(I.detach(),h++)}let g=this.app.workspace.getLeavesOfType(z).length,u=document.createDocumentFragment();return u.createEl("div",{text:h+l>0?"Stashpad tabs cleaned up:":"Stashpad tabs - nothing to clean up:"}),u.createEl("div",{text:`\u2022 ${h} duplicate tab${h===1?"":"s"} closed`}),u.createEl("div",{text:`\u2022 ${l} orphaned tab${l===1?"":"s"} pruned (note no longer exists)`}),u.createEl("div",{text:`\u2022 ${g} Stashpad tab${g===1?"":"s"} remaining`}),new N.Notice(u,7e3),h+l}navigateWhenReady(e,t,i=15){let s=e.replace(/\/+$/,""),n=this.app.workspace.getLeavesOfType(z).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(t))){n.navigateTo(t);return}i>0?window.setTimeout(()=>this.navigateWhenReady(e,t,i-1),90):n&&typeof n.navigateTo=="function"&&n.navigateTo(t)}collectAuthoredFolders(){let e=(this.settings.authorId??"").trim();if(!e)return[];let t=`-${e}`,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:"",l=Array.isArray(o.contributors)?o.contributors.filter(f=>typeof f=="string"):[],c=r.includes(t),A=l.some(f=>f.includes(t));if(!c&&!A)continue;let h=n.parent?.path??"",g=i.find(f=>h===f||h.startsWith(f+"/"));if(!g)continue;s.has(g)||s.set(g,{authored:0,contributed:0});let u=s.get(g);c&&u.authored++,A&&u.contributed++}return[...s.entries()].map(([n,o])=>({folder:n,...o})).sort((n,o)=>o.authored+o.contributed-(n.authored+n.contributed))}parseAuthorRef(e){return rt(e)}authorRefFor(e,t,i){let s=i.replace(/[^\w\- ]+/g,"").trim().replace(/\s+/g,"-")||"author",n=`${e.replace(/\/+$/,"")}/_authors/${s}-${t}.md`,o=i.replace(/[\[\]|]/g,"").trim()||s;return`[[${n}|${o}]]`}async ensureAuthorStubFor(e,t,i){if(!t||!i)return!1;this.authorRegistry.record({id:t,name:i});let s=`${e.replace(/\/+$/,"")}/_authors`;if(this.app.vault.getMarkdownFiles().some(c=>c.path.startsWith(s+"/")&&this.parseAuthorFilePath(c.path)?.id===t))return!1;let o=this.authorRegistry.get(t),r=this.authorNameToSafe(i),l=`${s}/${r}-${t}.md`;try{return await this.ensureFolderPath(s),await this.app.vault.adapter.exists(l)?!1:(await this.app.vault.create(l,this.buildAuthorStub({id:t,name:i,role:o?.role,department:o?.department},new Date().toISOString())),!0)}catch(c){return console.warn("[Stashpad] ensureAuthorStubFor failed",l,c),!1}}async seedKnownAuthorsInFolder(e){let t=0;for(let i of this.collectKnownAuthors())await this.ensureAuthorStubFor(e,i.id,i.name)&&t++;return t}async autoResolveDueTask(e,t,i){try{await this.app.fileManager.processFrontMatter(e,s=>{let n=s.due!=null?Date.parse(String(s.due)):NaN;if(Number.isFinite(n)&&n>i)return;let o=sn(s.repeat);o?(s.due=new Date(nn(o,Number.isFinite(n)?n:null,i)).toISOString(),delete s.completed):s.completed=!0})}catch(s){console.warn("[Stashpad] auto-resolve failed",e.path,s)}}async checkDueReminders(){let e=Date.now(),t=new Set(this.settings.notifiedDueKeys??[]),i=(this.settings.authorId??"").trim(),s=[],n={...this.settings.persistReminderLog??{}},o=!1,r=new Set;for(let c of this.app.vault.getMarkdownFiles()){if(c.path.includes("/_authors/"))continue;let A=this.app.metadataCache.getFileCache(c)?.frontmatter;if(!A||A.due==null)continue;let h=typeof A.id=="string"?A.id:"";if(!h)continue;let g=String(A.due),u=typeof A.due=="number"?A.due:Date.parse(g);if(!Number.isFinite(u)||u>e)continue;if(A.completed!==!0){let m=To(A.autoDoneAfter);if(m!=null&&e>=u+m){await this.autoResolveDueTask(c,u,e);continue}}if(A.completed===!0)continue;let f=Tt(A);if(f.length>0&&!(i&&f.some(m=>m.id===i)))continue;let p=To(A.remindEvery);if(p!=null){r.add(h);let m=n[h]??0;e-m>=p&&(n[h]=e,o=!0,s.push({id:h,folder:(c.parent?.path??"").replace(/\/+$/,""),file:c,dueMs:u,key:`${h}@persist`}));continue}let I=`${h}@${g}`;t.has(I)||s.push({id:h,folder:(c.parent?.path??"").replace(/\/+$/,""),file:c,dueMs:u,key:I})}for(let c of Object.keys(n))r.has(c)||(delete n[c],o=!0);if(o&&(this.settings.persistReminderLog=n,await this.saveSettings()),s.length===0)return;this.settings.notifiedDueKeys=[...this.settings.notifiedDueKeys??[],...s.filter(c=>!c.key.endsWith("@persist")).map(c=>c.key)].slice(-2e3),await this.saveSettings();let l=async c=>{try{let h=de(await this.app.vault.cachedRead(c)).body.split(/\r?\n/).map(g=>g.trim()).find(g=>g.length>0);if(h)return h.replace(/^[#>\-*\s]+/,"").slice(0,60)}catch{}return c.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ")};if(s.length<=3)for(let c of s){let A=await l(c.file);this.notifications.show({message:`\u23F0 Task due: \u201C${A}\u201D (${We(c.dueMs,this.settings)})`,kind:"warning",category:"reminder",duration:0,folder:c.folder,affectedIds:[c.id],actions:[{label:"Open",onClick:()=>void this.revealNoteByRef(c.folder,c.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 e=this.collectKnownAuthors(),t=this.discoverStashpadFolders();if(!e.length||!t.length){new N.Notice("No authors or Stashpad folders to sync.");return}let i=t.length*e.length>8?new N.Notice("",0):null,s=0;for(let n of t){i?.setMessage(`Syncing authors \u2192 ${n.split("/").pop()}\u2026`);for(let o of e)await this.ensureAuthorStubFor(n,o.id,o.name)&&s++}i?.hide(),this.notifications.show({message:`Synced authors across ${t.length} folder${t.length===1?"":"s"} \u2014 ${s} new stub${s===1?"":"s"} (${e.length} author${e.length===1?"":"s"} known).`,kind:"success",category:"system",folder:""})}collectKnownAuthors(){let e=new Map,t=(this.settings.authorId??"").trim(),i=(this.settings.authorName??"").trim();t&&i&&e.set(t,i);for(let s of this.authorRegistry.all())e.has(s.id)||e.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,l=((Array.isArray(o?.aliases)?o.aliases.find(c=>typeof c=="string")??"":typeof o?.aliases=="string"?o.aliases:"")||(typeof o?.name=="string"?o.name:"")||n.name).trim();e.has(n.id)||e.set(n.id,l),this.authorRegistry.record({id:n.id,name:l})}return[...e.entries()].map(([s,n])=>({id:s,name:n}))}async rebuildAuthorRegistry(){let e=this.discoverStashpadFolders(),t=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 l of o.contributors)typeof l=="string"&&r.push(l);for(let l of r){let c=this.parseAuthorRef(l);if(c)if(!t.has(c.id))t.set(c.id,{id:c.id,name:c.name,fromStub:!1}),i++;else{let A=t.get(c.id);!A.name&&c.name&&(A.name=c.name)}}}let s=0;for(let n of e){let o=`${n}/_authors`;for(let r of this.app.vault.getMarkdownFiles()){if(!r.path.startsWith(o+"/"))continue;let l=this.parseAuthorFilePath(r.path);if(!l)continue;let c=this.app.metadataCache.getFileCache(r)?.frontmatter,h=((Array.isArray(c?.aliases)?c.aliases.find(p=>typeof p=="string")??"":typeof c?.aliases=="string"?c.aliases:"")||(typeof c?.name=="string"?c.name:"")||l.name).trim(),g=typeof c?.role=="string"?c.role:void 0,u=typeof c?.department=="string"?c.department:void 0,f=t.get(l.id);f||s++,t.set(l.id,{id:l.id,name:h||f?.name,role:g??f?.role,department:u??f?.department,fromStub:!0})}}return await this.authorRegistry.load(),this.authorRegistry.replaceAll([...t.values()]),await this.authorRegistry.save(),{total:t.size,fromStubs:s,fromNotes:i}}buildAuthorStub(e,t){let i=r=>r.replace(/[\r\n]+/g," ").trim(),s=r=>i(r).replace(/\\/g,"\\\\").replace(/"/g,'\\"'),n=i(e.name),o=["---",`authorId: ${e.id}`,"aliases:",` - "${s(e.name)}"`];return e.role&&o.push(`role: "${s(e.role)}"`),e.department&&o.push(`department: "${s(e.department)}"`),o.push(`created: ${t}`,"---",`# ${n}`),o.join(` -`)}async restoreMissingAuthorStubs(){await this.authorRegistry.load();let e=this.authorRegistry.all().filter(n=>n.id&&n.name),t=this.discoverStashpadFolders(),i=this.app.vault.getMarkdownFiles(),s=0;for(let n of t){let o=`${n}/_authors`,r=new Set;for(let l of i){if(!l.path.startsWith(o+"/"))continue;let c=this.parseAuthorFilePath(l.path)?.id;c&&r.add(c)}for(let l of e){if(r.has(l.id))continue;let c=this.authorNameToSafe(l.name),A=`${o}/${c}-${l.id}.md`;try{if(await this.ensureFolderPath(o),await this.app.vault.adapter.exists(A))continue;await this.app.vault.create(A,this.buildAuthorStub(l,l.firstSeen??new Date().toISOString())),s++}catch(h){console.warn("[Stashpad] restore author stub failed",A,h)}}}return{created:s,folders:t.length}}async convertAttachmentsToLinks(){let e=0,t=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+"/")||Nt(n.path))continue;let r=this.app.metadataCache.getFileCache(n)?.frontmatter;if(!r||typeof r.id!="string"||!r.id)continue;let l=r.attachments,c=Array.isArray(l),A=typeof l=="string"&&l.trim().length>0;if(!(!c&&!A||!(A?!t(l):l.some(g=>typeof g=="string"&&g.trim()&&!t(g)))))try{await this.app.fileManager.processFrontMatter(n,g=>{Array.isArray(g.attachments)?g.attachments=g.attachments.map(u=>typeof u=="string"&&u.trim()?Ve(u):u):typeof g.attachments=="string"&&g.attachments.trim()&&(g.attachments=[Ve(g.attachments)])}),e++}catch(g){console.warn("[Stashpad] attachment-link conversion failed",n.path,g)}}}return e}syncObsidianExcludedArchives(){try{let e=this.app.vault;if(typeof e.getConfig!="function"||typeof e.setConfig!="function")return;let t=Array.isArray(e.getConfig("userIgnoreFilters"))?e.getConfig("userIgnoreFilters"):[],i=new Set(t),s=!1;for(let n of this.discoverStashpadFolders()){let o=`${n.replace(/\/+$/,"")}/_archive/`;i.has(o)||(i.add(o),s=!0)}s&&e.setConfig("userIgnoreFilters",[...i])}catch(e){console.warn("[Stashpad] couldn't update Obsidian excluded files",e)}}openImportPicker(){let e=this.discoverStashpadFolders();if(e.length===0){new N.Notice("No Stashpad folders to import into.");return}if(e.length===1){this.importService.pickFilesInto(e[0]);return}let t=this.importService.defaultDestination()??e[0];new pr(this.app,t,e,i=>this.importService.pickFilesInto(i)).open()}async runImportLooseFiles(e){let t=e.split("/").pop()||e,i=0,s=0,n=0;try{({files:i,folders:s,stashes:n}=await this.importService.importLooseInto(e))}catch(c){this.notifications.show({message:`Stashpad: import failed in \`${t}\` +Find everything in the aggregated Archived view. (This notice stays until dismissed.)`,0)}async migrateDeletedToTrashSubfolders(){if(this.settings.migratedTrashToSubfolders)return;let e=this.app.vault.adapter,t=this.newLog(),i=0,s=0,n=0,o=[],r=`${this.pluginPrivatePath()}/trash-migration-journal.json`;try{let l=await Dn(this.app);for(let c of l){let A=await nt(this.app,c),h=A?.kind==="deleted"&&A.originalFolder?A.originalFolder.replace(/\/+$/,""):"";if(!h||!(this.app.vault.getAbstractFileByPath(h)instanceof M.TFolder)){s++;continue}let p=ps(h);try{await e.exists(p)||await e.mkdir(p);let u=c.split("/").pop(),f=`${p}/${u}`;for(let C=1;await e.exists(f);C++)f=`${p}/${u.replace(/\.stashenc$/,"")} (${C}).stashenc`;o.push({from:c,to:f,ok:!1});let g=new Uint8Array(await e.readBinary(c));await e.writeBinary(f,g.slice().buffer);let I=new Uint8Array(await e.readBinary(f));if(I.length!==g.length)throw new Error("copy verify failed (length)");for(let C=0;C<g.length;C++)if(I[C]!==g[C])throw new Error("copy verify failed (content)");let m=c.replace(/\.stashenc$/,".stashmeta"),B=f.replace(/\.stashenc$/,".stashmeta");try{if(await e.exists(m)){let C=await e.read(m);if(await e.write(B,C),await e.read(B)!==C)throw new Error("sidecar verify failed");await e.remove(m)}}catch(C){throw new Error(`sidecar copy failed: ${C.message}`)}await e.remove(c),o[o.length-1].ok=!0,i++}catch(u){n++,console.warn("[Stashpad] trash migration move failed",c,u)}}try{await e.write(r,JSON.stringify({ts:new Date().toISOString(),moves:o},null,1))}catch{}}catch(l){console.error("[Stashpad] trash migration failed",l);return}t.append({type:"archive_migration",id:"",payload:{what:"trash-subfolders",moved:i,left:s,failed:n}}),n===0&&(this.settings.migratedTrashToSubfolders=!0,await this.saveSettings()),(i>0||n>0)&&new M.Notice(`Stashpad trash update: ${i} encrypted-trash item${i===1?"":"s"} moved into per-folder "trash/" subfolders${s?` (${s} stayed in _deleted/ \u2014 unknown or missing origin)`:""}${n?` \u2014 ${n} failed; will retry next launch`:""}. Everything stays visible in the Trash view.`,0)}async pruneZombieArchiveEntries(){let e=o=>this.app.vault.getAbstractFileByPath(o)instanceof M.TFolder,t=this.settings.archiveFolders??[],i=t.filter(o=>e(o.replace(/\/+$/,""))),s=i.length!==t.length,n=(this.settings.defaultArchiveFolder??"").replace(/\/+$/,"");n&&!e(n)&&(this.settings.defaultArchiveFolder=void 0,s=!0),s&&(this.settings.archiveFolders=i,await this.saveSettings(),console.info(`[Stashpad] pruned ${t.length-i.length} stale archive-folder entr${t.length-i.length===1?"y":"ies"}.`))}async ensureOkfTemplate(){let e=await vl(this.app,this.settings.okfTemplatePath||void 0);return this.settings.okfTemplatePath!==e&&(this.settings.okfTemplatePath=e,await this.saveSettings()),e}okfTemplatePathOrDefault(){return this.settings.okfTemplatePath||dr}okfActiveFolders(){return this.settings.okfEnabled?Fl(this.settings.noteTemplates,this.okfTemplatePathOrDefault()).filter(e=>!this.isArchiveFolder(e)):[]}async rebuildOkfSuppressed(e){this.okfRebuildingFolders.add(e);try{return await hr(this.app,e)}finally{window.setTimeout(()=>{this.okfRebuildingFolders.delete(e);for(let t of this.app.workspace.getLeavesOfType(z)){let i=t.view;i?.noteFolder===e&&i.forceReconcileRender?.()}},600)}}onOkfFileEvent(e){if(!this.settings.okfEnabled||!e.toLowerCase().endsWith(".md"))return;let t=e.lastIndexOf("/"),i=(t>=0?e.slice(0,t):"").replace(/\/+$/,"");(t>=0?e.slice(t+1):e)!=="index.md"&&(/(^|\/)(_imports|_exports|_attachments|_deleted|\.stashpad)(\/|$)/.test(e)||this.okfActiveFolders().includes(i)&&this.scheduleOkfRebuild(i))}scheduleOkfRebuild(e){let t=this.okfRebuildTimers.get(e);t!=null&&window.clearTimeout(t),this.okfRebuildTimers.set(e,window.setTimeout(()=>{this.okfRebuildTimers.delete(e),this.okfActiveFolders().includes(e)&&this.rebuildOkfSuppressed(e).catch(i=>console.warn("[Stashpad] OKF auto-rebuild failed",e,i))},2500))}async rebuildAllOkf(){let e=this.okfActiveFolders(),t=0,i=0;for(let s of e){let n=await this.rebuildOkfSuppressed(s);t+=n.checked,i+=n.written}return{folders:e.length,checked:t,written:i}}async exportOkf(e,t,i,s){let n=e.replace(/\/+$/,""),o=[],r=[],l=[],c=new Set;for(let I of t){let m=await mt(this.app,n,I);if(m){o.push({id:m.rootNote.id,file:m.rootNote.file}),l.push(m.rootNote.file),c.add(m.rootNote.id);for(let B of m.descendants)r.push({id:B.id,file:B.file}),l.push(B.file),c.add(B.id)}}if(!l.length)return[];let A=(i||"okf-export").replace(/[\\/:*?"<>|]+/g," ").replace(/\s+/g," ").trim().slice(0,80)||"okf-export",h=new Date().toISOString().replace(/\D/g,"").slice(0,14),p=(this.settings.exportFolder||"_exports").trim().replace(/^\/+|\/+$/g,""),u=`${n}/${p}`;for(let I of[n,u])try{await this.app.vault.adapter.exists(I)||await this.app.vault.adapter.mkdir(I)}catch{}let f=[],g=async(I,m)=>{let B=`${u}/${I}`;await this.app.vault.createBinary(B,m.buffer.slice(m.byteOffset,m.byteOffset+m.byteLength)),f.push(B)};if(s.zip||s.targz){let I=await kl(this.app,l,n,c);s.zip&&await g(`${A}-${h}.okf.zip`,await Sl(I)),s.targz&&await g(`${A}-${h}.okf.tar.gz`,await bl(I))}if(s.stash){let I=await It(this.app,{rootNotes:o,allDescendants:r,sourceFolder:n});await g(`${A}-${h}.${it}`,I)}return f}async idsInFolder(e){let t=e.replace(/\/+$/,""),i=new Set;for(let s of this.app.vault.getMarkdownFiles())if((s.parent?.path?.replace(/\/+$/,"")??"")===t)try{let n=Ae(await this.app.vault.read(s)).fm.id;typeof n=="string"&&i.add(n)}catch{}return i}async crossFolderPaste(e,t,i,s,n){let o=i.replace(/\/+$/,"");if(this.isArchiveFolder(o))return new M.Notice(`"${o.split("/").pop()}" is an archive folder, so cross-folder paste is disabled there. Use the "Move selection to archive" command instead \u2014 it runs the proper archive flow (and encrypts, if that folder encrypts its archive).`),null;let r=[],l=[],c=[],A=[];for(let v of t){let F=await mt(this.app,e,v);if(F){c.push(F.rootNote.id),r.push({id:F.rootNote.id,file:F.rootNote.file}),A.push(F.rootNote.file);for(let D of F.descendants)l.push({id:D.id,file:D.file}),A.push(D.file)}}if(!r.length)return null;let h=r.length+l.length,p=[],u=[];n==="cut"&&(p=await this.exclusiveAttachmentsOf(A),u=await this.snapshotPaths([...A.map(v=>v.path),...p.map(v=>v.path)]));let f=await It(this.app,{rootNotes:r,allDescendants:l,sourceFolder:e}),g=await this.idsInFolder(o),I=new Set(this.filesUnder(o)),m=await qe(this.app,f,o,g,{dedupeExisting:!1,forceNewIds:n==="copy",reparentRootsTo:s}),B=this.filesUnder(o).filter(v=>!I.has(v)),C=await this.snapshotPaths(B),Q=c.map(v=>m.idRemap[v]).filter(v=>!!v);if(n==="cut"){for(let v of A)try{await this.app.fileManager.trashFile(v)}catch(F){console.warn("[Stashpad] cross-folder move: couldn't trash source note",v.path,F)}for(let v of p)try{await this.app.fileManager.trashFile(v)}catch(F){console.warn("[Stashpad] cross-folder move: couldn't trash source attachment",v.path,F)}}let y=async()=>{for(let v of[...B].reverse()){let F=this.app.vault.getAbstractFileByPath(v);if(F)try{await this.app.fileManager.trashFile(F)}catch{}}};return{rootIds:Q,noteCount:h,undo:n==="cut"?async()=>{await y(),await this.restoreSnapshot(u)}:async()=>{await y()},redo:n==="cut"?async()=>{await this.restoreSnapshot(C);for(let v of u){let F=this.app.vault.getAbstractFileByPath(v.path);if(F)try{await this.app.fileManager.trashFile(F)}catch{}}}:async()=>{await this.restoreSnapshot(C)}}}async trashSubtrees(e,t){let i=[];for(let o of t){let r=await mt(this.app,e,o);r&&i.push(r.rootNote.file,...r.descendants.map(l=>l.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(e){let t=new Set(e.map(n=>n.path)),i=new Map;for(let n of e)for(let o of await Yt(this.app,n))i.set(o.path,o);let s=this.app.metadataCache.resolvedLinks??{};for(let n of Object.keys(s))if(!t.has(n))for(let o of Object.keys(s[n]??{}))i.delete(o);return[...i.values()]}async subtreeFilePaths(e,t){let i=[];for(let n of t){let o=await mt(this.app,e,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(e,t){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 t){let r=await mt(this.app,e,o);if(!r)continue;let l=new Map;for(let A of r.descendants){if(!A.parent)continue;let h=l.get(A.parent)??[];h.push({id:A.id,file:A.file,created:A.created}),l.set(A.parent,h)}for(let A of l.values())A.sort((h,p)=>n(h.file)-n(p.file)||h.created.localeCompare(p.created));let c=(A,h)=>{if(!s.has(A.id)){s.add(A.id),i.push({file:A.file,created:A.created,depth:h});for(let p of l.get(A.id)??[])c(p,h+1)}};c({id:r.rootNote.id,file:r.rootNote.file,created:r.rootNote.created},0)}return i}filesUnder(e){let t=e.replace(/\/+$/,"")+"/";return this.app.vault.getFiles().filter(i=>i.path.startsWith(t)).map(i=>i.path)}async snapshotPaths(e){let t=[];for(let i of e){let s=this.app.vault.getAbstractFileByPath(i);if(!s)continue;let n=!i.toLowerCase().endsWith(".md");try{n?t.push({path:i,binary:n,data:await this.app.vault.readBinary(s)}):t.push({path:i,binary:n,text:await this.app.vault.read(s)})}catch(o){console.warn("[Stashpad] snapshotPaths: couldn't read",i,o)}}return t}async restoreSnapshot(e){for(let t of e){let i=t.path.split("/").slice(0,-1).join("/");await this.ensureVaultFolder(i);let s=this.app.vault.getAbstractFileByPath(t.path);try{t.binary?s?await this.app.vault.adapter.writeBinary(t.path,t.data):await this.app.vault.createBinary(t.path,t.data):s?await this.app.vault.modify(s,t.text??""):await this.app.vault.create(t.path,t.text??"")}catch(n){console.warn("[Stashpad] restoreSnapshot: couldn't write",t.path,n)}}}async ensureVaultFolder(e){if(!e)return;let t="";for(let i of e.split("/"))if(t=t?`${t}/${i}`:i,!await this.app.vault.adapter.exists(t))try{await this.app.vault.createFolder(t)}catch{}}refreshOpenViewsForFolder(e){let t=e.replace(/\/+$/,"");for(let i of this.app.workspace.getLeavesOfType(z)){let s=i.view;if((s?.noteFolder?.replace(/\/+$/,"")??"")===t)try{s.tree?.rebuild?.(e),s.render?.()}catch(n){console.warn("[Stashpad] refresh view failed",n)}}}maybeArchiveOnMoveIn(e,t){if(e.extension!=="md")return;let i=e.parent?.path?.replace(/\/+$/,"")??"",s=t.lastIndexOf("/"),n=(s>=0?t.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(e.path),window.clearTimeout(o.timer),o.timer=window.setTimeout(()=>{this.archivePending.delete(i),this.archiveSweep(i,[...o.paths])},1800)}async encryptExistingArchiveNotes(e){let t=wt(e.replace(/\/+$/,"")),i=this.archivedPlainNotesIn(t).map(s=>s.path);return i.length===0?0:(await this.archiveSweep(t,i),i.length-this.archivedPlainNotesIn(t).length)}async archiveSweep(e,t){if(this.archiveMigrationInFlight||!this.isArchiveFolder(e))return;let i=e.replace(/\/+$/,"");if(!this.archiveEncryptFor(i))return;let s=[];for(let c of t){let A=this.app.vault.getAbstractFileByPath(c);if(!(A instanceof M.TFile)||(A.parent?.path?.replace(/\/+$/,"")??"")!==i)continue;let h;try{h=Ae(await this.app.vault.read(A)).fm}catch{continue}let p=typeof h.id=="string"?h.id:null;!p||p===k||s.push({id:p,parent:typeof h.parent=="string"?h.parent:null})}if(s.length===0)return;let n=new Set(s.map(c=>c.id)),o=new Set((this.settings.lockedSubtrees??[]).map(c=>c.rootId).filter(c=>!!c)),r=s.filter(c=>!o.has(c.id)&&!(c.parent&&n.has(c.parent)));if(r.length===0||!this.encryption.hasFolderKey(i))return;if(!await this.ensureFolderUnlocked(i)){new M.Notice(`\u26A0\uFE0F Archive folder "${i.split("/").pop()}": ${r.length} arriving note${r.length===1?"":"s"} NOT encrypted (couldn't unlock the folder password). Unlock it and lock them manually.`,0);return}let l=0;for(let c of r)await this.lockNoteSubtree(i,c.id,null,{silent:!0})&&l++;l>0&&this.notifications.show({message:`Archived (encrypted) ${l} note${l===1?"":"s"} moved into \u201C${i.split("/").pop()}\u201D.`,kind:"success",category:"system",folder:i,actions:[{label:"All archived",onClick:()=>void Pe(this,"archived")}]})}async activateViewForFolder(e){let t=(e||"").replace(/^\/+|\/+$/g,"");if(!t)return null;let i=this.app.workspace.getLeaf("tab");return await i.setViewState({type:z,active:!0,state:{folderOverride:t}}),this.app.workspace.revealLeaf(i),i}navigateLeafTo(e,t,i){let s=e?.view;if(s?.navigateTo&&(!s.tree||s.tree.get(i))){s.navigateTo(i);return}this.navigateWhenReady(t,i)}async openFolderInStashpad(e){let t=(e||"").replace(/^\/+|\/+$/g,"");if(!t)return;let i=await this.findStashpadLeafForFolder(t);if(i){this.app.workspace.revealLeaf(i),this.app.workspace.setActiveLeaf(i,{focus:!0});return}await this.activateViewForFolder(t)}async findStashpadLeafForFolder(e){let t=e.replace(/\/+$/,""),i=this.app.workspace.getLeavesOfType(z),s=i.find(o=>!o.isDeferred&&(o.view?.noteFolder??"").replace(/\/+$/,"")===t);if(s)return s;let n=i.find(o=>o.isDeferred&&(o.getViewState()?.state?.folderOverride??"").replace(/\/+$/,"")===t);if(n){try{await n.loadIfDeferred?.()}catch{}return n}return null}isStashpadNoteFile(e){let t=e.parent?.path?.replace(/\/+$/,"")??"";if(!this.discoverStashpadFolders().includes(t))return!1;let i=this.app.metadataCache.getFileCache(e)?.frontmatter?.id;return typeof i=="string"&&i.length>0}async revealNoteInStashpad(e){let t=e.parent?.path?.replace(/\/+$/,"")??"",i=this.app.metadataCache.getFileCache(e)?.frontmatter?.id;if(!t||typeof i!="string"||!i){new M.Notice("That note isn't a Stashpad note.");return}await this.revealNoteByRef(t,i)}async revealNoteByRef(e,t){let i=e.replace(/\/+$/,""),s=await this.findStashpadLeafForFolder(i);if(s){this.app.workspace.revealLeaf(s),this.app.workspace.setActiveLeaf(s,{focus:!0}),this.navigateLeafTo(s,i,t);return}let n=await this.activateViewForFolder(i);this.navigateLeafTo(n,i,t)}resolveNoteFileInFolder(e,t){let i=e.replace(/\/+$/,"");for(let s of this.app.vault.getMarkdownFiles())if((s.parent?.path?.replace(/\/+$/,"")??"")===i&&this.app.metadataCache.getFileCache(s)?.frontmatter?.id===t)return s;return null}async handleDeepLink(e,t={}){let i=(e.folder||"").replace(/^\/+|\/+$/g,""),s=(e.note||"").trim(),n=Ea(e);if(!i)return new M.Notice("Stashpad link: missing \u201Cfolder\u201D."),!1;if(!(this.app.vault.getAbstractFileByPath(i)instanceof M.TFolder))return new M.Notice(`Stashpad link: folder \u201C${i}\u201D not found.`),!1;await new Promise(l=>this.app.workspace.onLayoutReady(()=>l()));let r=null;if(s){for(let l=0;l<12&&!r;l++)r=this.resolveNoteFileInFolder(i,s),r||await new Promise(c=>window.setTimeout(c,150));if(!r)return new M.Notice(`Stashpad link: note \u201C${s}\u201D not found in ${i}.`),!1}await this.openDeepLinkTarget(i,s,t);for(let l of n)if(l!=="reveal"){if(l==="open"){r&&await this.app.workspace.getLeaf("tab").openFile(r);continue}console.warn(`[stashpad] deep link: unknown action \u201C${l}\u201D \u2014 skipped.`)}return!0}async openDeepLinkTarget(e,t,i={}){let s=e.replace(/\/+$/,"");if(!i.forceNewTab){let o=this.app.workspace.activeLeaf,r=await this.findStashpadLeafForFolder(s);if(r&&r!==o){this.app.workspace.revealLeaf(r),this.app.workspace.setActiveLeaf(r,{focus:!0}),t&&this.navigateLeafTo(r,s,t);return}}let n=await this.activateViewForFolder(s);t&&this.navigateLeafTo(n,s,t)}openDeepLinkModal(){new Li(this.app,e=>{let i=e.split(/\s+/).map(s=>s.trim()).filter(Boolean).map(s=>wa(s)).filter(s=>!!s);if(i.length===0){new M.Notice("That doesn't look like a Stashpad link.");return}if(i.length===1){this.handleDeepLink(i[0]);return}(async()=>{let s=0;for(let o of i)await this.handleDeepLink(o,{forceNewTab:!0})&&s++;let n=i.length-s;new M.Notice(n===0?`Opened ${s} Stashpad links in new tabs.`:`Opened ${s} of ${i.length} Stashpad links (${n} couldn't be found).`)})()}).open()}async closeDuplicateStashpadTabs(){let e=this.app.workspace.getLeavesOfType(z),t=this.app.workspace.activeLeaf;for(let f of e)try{await f.loadIfDeferred?.()}catch{}let i=f=>f.getViewState()?.state??{},s=f=>{let g=i(f);return(f.isDeferred?g.folderOverride??"":f.view?.noteFolder??g.folderOverride??"").replace(/\/+$/,"")},n=f=>{let g=i(f);return(f.isDeferred?g.focusId:f.view?.focusId??g.focusId)||k},o=f=>{let g=f.view;return!!g&&g.getViewType?.()===z&&typeof g.navigateTo=="function"&&typeof g.noteFolder=="string"},r=new Map;for(let f of this.app.vault.getMarkdownFiles()){let g=(f.parent?.path??"").replace(/\/+$/,""),I=this.app.metadataCache.getFileCache(f)?.frontmatter?.id;typeof I=="string"&&I&&(r.get(g)??r.set(g,new Set).get(g)).add(I)}let l=0,c=[];for(let f of e){let g=s(f),I=n(f);if(g&&I&&I!==k){let m=!f.isDeferred&&!!f.view?.tree?.get?.(I),B=r.get(g)?.has(I)??!1;if(!m&&!B){f.detach(),l++;continue}}c.push(f)}let A=new Map;for(let f of c){let g=s(f);if(!g)continue;let I=g+" "+n(f);(A.get(I)??A.set(I,[]).get(I)).push(f)}let h=0;for(let f of A.values()){if(f.length<=1)continue;f.sort((I,m)=>{let B=C=>C===t?2:C.isDeferred?0:1;return B(m)-B(I)});let g=null;for(let I of f){try{await I.loadIfDeferred?.()}catch{}if(o(I)){g=I;break}}g||(g=f[0]);for(let I of f)I!==g&&(I.detach(),h++)}let p=this.app.workspace.getLeavesOfType(z).length,u=document.createDocumentFragment();return u.createEl("div",{text:h+l>0?"Stashpad tabs cleaned up:":"Stashpad tabs - nothing to clean up:"}),u.createEl("div",{text:`\u2022 ${h} duplicate tab${h===1?"":"s"} closed`}),u.createEl("div",{text:`\u2022 ${l} orphaned tab${l===1?"":"s"} pruned (note no longer exists)`}),u.createEl("div",{text:`\u2022 ${p} Stashpad tab${p===1?"":"s"} remaining`}),new M.Notice(u,7e3),h+l}navigateWhenReady(e,t,i=15){let s=e.replace(/\/+$/,""),n=this.app.workspace.getLeavesOfType(z).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(t))){n.navigateTo(t);return}i>0?window.setTimeout(()=>this.navigateWhenReady(e,t,i-1),90):n&&typeof n.navigateTo=="function"&&n.navigateTo(t)}collectAuthoredFolders(){let e=(this.settings.authorId??"").trim();if(!e)return[];let t=`-${e}`,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:"",l=Array.isArray(o.contributors)?o.contributors.filter(f=>typeof f=="string"):[],c=r.includes(t),A=l.some(f=>f.includes(t));if(!c&&!A)continue;let h=n.parent?.path??"",p=i.find(f=>h===f||h.startsWith(f+"/"));if(!p)continue;s.has(p)||s.set(p,{authored:0,contributed:0});let u=s.get(p);c&&u.authored++,A&&u.contributed++}return[...s.entries()].map(([n,o])=>({folder:n,...o})).sort((n,o)=>o.authored+o.contributed-(n.authored+n.contributed))}parseAuthorRef(e){return at(e)}authorRefFor(e,t,i){let s=i.replace(/[^\w\- ]+/g,"").trim().replace(/\s+/g,"-")||"author",n=`${e.replace(/\/+$/,"")}/_authors/${s}-${t}.md`,o=i.replace(/[\[\]|]/g,"").trim()||s;return`[[${n}|${o}]]`}async ensureAuthorStubFor(e,t,i){if(!t||!i)return!1;this.authorRegistry.record({id:t,name:i});let s=`${e.replace(/\/+$/,"")}/_authors`;if(this.app.vault.getMarkdownFiles().some(c=>c.path.startsWith(s+"/")&&this.parseAuthorFilePath(c.path)?.id===t))return!1;let o=this.authorRegistry.get(t),r=this.authorNameToSafe(i),l=`${s}/${r}-${t}.md`;try{return await this.ensureFolderPath(s),await this.app.vault.adapter.exists(l)?!1:(await this.app.vault.create(l,this.buildAuthorStub({id:t,name:i,role:o?.role,department:o?.department},new Date().toISOString())),!0)}catch(c){return console.warn("[Stashpad] ensureAuthorStubFor failed",l,c),!1}}async seedKnownAuthorsInFolder(e){let t=0;for(let i of this.collectKnownAuthors())await this.ensureAuthorStubFor(e,i.id,i.name)&&t++;return t}async autoResolveDueTask(e,t,i){try{await this.app.fileManager.processFrontMatter(e,s=>{let n=s.due!=null?Date.parse(String(s.due)):NaN;if(Number.isFinite(n)&&n>i)return;let o=nn(s.repeat);o?(s.due=new Date(on(o,Number.isFinite(n)?n:null,i)).toISOString(),delete s.completed):s.completed=!0})}catch(s){console.warn("[Stashpad] auto-resolve failed",e.path,s)}}async checkDueReminders(){let e=Date.now(),t=new Set(this.settings.notifiedDueKeys??[]),i=(this.settings.authorId??"").trim(),s=[],n={...this.settings.persistReminderLog??{}},o=!1,r=new Set;for(let c of this.app.vault.getMarkdownFiles()){if(c.path.includes("/_authors/"))continue;let A=this.app.metadataCache.getFileCache(c)?.frontmatter;if(!A||A.due==null)continue;let h=typeof A.id=="string"?A.id:"";if(!h)continue;let p=String(A.due),u=typeof A.due=="number"?A.due:Date.parse(p);if(!Number.isFinite(u)||u>e)continue;if(A.completed!==!0){let m=Ro(A.autoDoneAfter);if(m!=null&&e>=u+m){await this.autoResolveDueTask(c,u,e);continue}}if(A.completed===!0)continue;let f=Pt(A);if(f.length>0&&!(i&&f.some(m=>m.id===i)))continue;let g=Ro(A.remindEvery);if(g!=null){r.add(h);let m=n[h]??0;e-m>=g&&(n[h]=e,o=!0,s.push({id:h,folder:(c.parent?.path??"").replace(/\/+$/,""),file:c,dueMs:u,key:`${h}@persist`}));continue}let I=`${h}@${p}`;t.has(I)||s.push({id:h,folder:(c.parent?.path??"").replace(/\/+$/,""),file:c,dueMs:u,key:I})}for(let c of Object.keys(n))r.has(c)||(delete n[c],o=!0);if(o&&(this.settings.persistReminderLog=n,await this.saveSettings()),s.length===0)return;this.settings.notifiedDueKeys=[...this.settings.notifiedDueKeys??[],...s.filter(c=>!c.key.endsWith("@persist")).map(c=>c.key)].slice(-2e3),await this.saveSettings();let l=async c=>{try{let h=Ae(await this.app.vault.cachedRead(c)).body.split(/\r?\n/).map(p=>p.trim()).find(p=>p.length>0);if(h)return h.replace(/^[#>\-*\s]+/,"").slice(0,60)}catch{}return c.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ")};if(s.length<=3)for(let c of s){let A=await l(c.file);this.notifications.show({message:`\u23F0 Task due: \u201C${A}\u201D (${Xe(c.dueMs,this.settings)})`,kind:"warning",category:"reminder",duration:0,folder:c.folder,affectedIds:[c.id],actions:[{label:"Open",onClick:()=>void this.revealNoteByRef(c.folder,c.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 e=this.collectKnownAuthors(),t=this.discoverStashpadFolders();if(!e.length||!t.length){new M.Notice("No authors or Stashpad folders to sync.");return}let i=t.length*e.length>8?new M.Notice("",0):null,s=0;for(let n of t){i?.setMessage(`Syncing authors \u2192 ${n.split("/").pop()}\u2026`);for(let o of e)await this.ensureAuthorStubFor(n,o.id,o.name)&&s++}i?.hide(),this.notifications.show({message:`Synced authors across ${t.length} folder${t.length===1?"":"s"} \u2014 ${s} new stub${s===1?"":"s"} (${e.length} author${e.length===1?"":"s"} known).`,kind:"success",category:"system",folder:""})}collectKnownAuthors(){let e=new Map,t=(this.settings.authorId??"").trim(),i=(this.settings.authorName??"").trim();t&&i&&e.set(t,i);for(let s of this.authorRegistry.all())e.has(s.id)||e.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,l=((Array.isArray(o?.aliases)?o.aliases.find(c=>typeof c=="string")??"":typeof o?.aliases=="string"?o.aliases:"")||(typeof o?.name=="string"?o.name:"")||n.name).trim();e.has(n.id)||e.set(n.id,l),this.authorRegistry.record({id:n.id,name:l})}return[...e.entries()].map(([s,n])=>({id:s,name:n}))}async rebuildAuthorRegistry(){let e=this.discoverStashpadFolders(),t=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 l of o.contributors)typeof l=="string"&&r.push(l);for(let l of r){let c=this.parseAuthorRef(l);if(c)if(!t.has(c.id))t.set(c.id,{id:c.id,name:c.name,fromStub:!1}),i++;else{let A=t.get(c.id);!A.name&&c.name&&(A.name=c.name)}}}let s=0;for(let n of e){let o=`${n}/_authors`;for(let r of this.app.vault.getMarkdownFiles()){if(!r.path.startsWith(o+"/"))continue;let l=this.parseAuthorFilePath(r.path);if(!l)continue;let c=this.app.metadataCache.getFileCache(r)?.frontmatter,h=((Array.isArray(c?.aliases)?c.aliases.find(g=>typeof g=="string")??"":typeof c?.aliases=="string"?c.aliases:"")||(typeof c?.name=="string"?c.name:"")||l.name).trim(),p=typeof c?.role=="string"?c.role:void 0,u=typeof c?.department=="string"?c.department:void 0,f=t.get(l.id);f||s++,t.set(l.id,{id:l.id,name:h||f?.name,role:p??f?.role,department:u??f?.department,fromStub:!0})}}return await this.authorRegistry.load(),this.authorRegistry.replaceAll([...t.values()]),await this.authorRegistry.save(),{total:t.size,fromStubs:s,fromNotes:i}}buildAuthorStub(e,t){let i=r=>r.replace(/[\r\n]+/g," ").trim(),s=r=>i(r).replace(/\\/g,"\\\\").replace(/"/g,'\\"'),n=i(e.name),o=["---",`authorId: ${e.id}`,"aliases:",` - "${s(e.name)}"`];return e.role&&o.push(`role: "${s(e.role)}"`),e.department&&o.push(`department: "${s(e.department)}"`),o.push(`created: ${t}`,"---",`# ${n}`),o.join(` +`)}async restoreMissingAuthorStubs(){await this.authorRegistry.load();let e=this.authorRegistry.all().filter(n=>n.id&&n.name),t=this.discoverStashpadFolders(),i=this.app.vault.getMarkdownFiles(),s=0;for(let n of t){let o=`${n}/_authors`,r=new Set;for(let l of i){if(!l.path.startsWith(o+"/"))continue;let c=this.parseAuthorFilePath(l.path)?.id;c&&r.add(c)}for(let l of e){if(r.has(l.id))continue;let c=this.authorNameToSafe(l.name),A=`${o}/${c}-${l.id}.md`;try{if(await this.ensureFolderPath(o),await this.app.vault.adapter.exists(A))continue;await this.app.vault.create(A,this.buildAuthorStub(l,l.firstSeen??new Date().toISOString())),s++}catch(h){console.warn("[Stashpad] restore author stub failed",A,h)}}}return{created:s,folders:t.length}}async convertAttachmentsToLinks(){let e=0,t=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+"/")||Mt(n.path))continue;let r=this.app.metadataCache.getFileCache(n)?.frontmatter;if(!r||typeof r.id!="string"||!r.id)continue;let l=r.attachments,c=Array.isArray(l),A=typeof l=="string"&&l.trim().length>0;if(!(!c&&!A||!(A?!t(l):l.some(p=>typeof p=="string"&&p.trim()&&!t(p)))))try{await this.app.fileManager.processFrontMatter(n,p=>{Array.isArray(p.attachments)?p.attachments=p.attachments.map(u=>typeof u=="string"&&u.trim()?We(u):u):typeof p.attachments=="string"&&p.attachments.trim()&&(p.attachments=[We(p.attachments)])}),e++}catch(p){console.warn("[Stashpad] attachment-link conversion failed",n.path,p)}}}return e}syncObsidianExcludedArchives(){try{let e=this.app.vault;if(typeof e.getConfig!="function"||typeof e.setConfig!="function")return;let t=Array.isArray(e.getConfig("userIgnoreFilters"))?e.getConfig("userIgnoreFilters"):[],i=new Set(t),s=!1;for(let n of this.discoverStashpadFolders()){let o=`${n.replace(/\/+$/,"")}/_archive/`;i.has(o)||(i.add(o),s=!0)}s&&e.setConfig("userIgnoreFilters",[...i])}catch(e){console.warn("[Stashpad] couldn't update Obsidian excluded files",e)}}openImportPicker(){let e=this.discoverStashpadFolders();if(e.length===0){new M.Notice("No Stashpad folders to import into.");return}if(e.length===1){this.importService.pickFilesInto(e[0]);return}let t=this.importService.defaultDestination()??e[0];new ur(this.app,t,e,i=>this.importService.pickFilesInto(i)).open()}async runImportLooseFiles(e){let t=e.split("/").pop()||e,i=0,s=0,n=0;try{({files:i,folders:s,stashes:n}=await this.importService.importLooseInto(e))}catch(c){this.notifications.show({message:`Stashpad: import failed in \`${t}\` Error: ${c.message}`,kind:"error",category:"import",folder:e}),console.error("[Stashpad] runImportLooseFiles failed",e,c);return}let o=i+s+n,r=this.lastActiveStashpadLeaf?.view;o>0&&r?.noteFolder===e&&r?.tree&&(r.tree.rebuild(e),r.render?.());let l;if(o===0)l=`Nothing to import in \`${t}\` \u2014 everything here is already a Stashpad note.`;else{let c=[];i&&c.push(`${i} loose file${i===1?"":"s"}`),s&&c.push(`${s} folder${s===1?"":"s"} (as nested notes)`),n&&c.push(`${n} .stash bundle${n===1?"":"s"}`),l=`Imported ${c.join(" + ")} in \`${t}\`.`}this.notifications.show({message:l,kind:o>0?"success":"info",category:"import",folder:e})}refreshViewIfShowing(e){let t=this.lastActiveStashpadLeaf?.view;t?.noteFolder===e&&t?.tree&&(t.tree.rebuild(e),t.render?.())}async runFolderSlugPass(e){let t=e.split("/").pop()||e,i=0;try{i=await this.rebootstrapFolderSlugs(e)}catch(s){this.notifications.show({message:`Stashpad: slug pass failed in \`${t}\` -${s.message}`,kind:"error",category:"system",folder:e}),console.error("[Stashpad] runFolderSlugPass failed",e,s);return}this.refreshViewIfShowing(e),this.notifications.show({message:i>0?`Renamed ${i} stale filename${i===1?"":"s"} in \`${t}\`.`:`No stale filenames in \`${t}\` \u2014 all slugs match their notes.`,kind:i>0?"success":"info",category:"system",folder:e})}async runFolderFrontmatterBackfill(e){let t=e.split("/").pop()||e,i=0,s=0;try{let n=await Ci(this.app,e);i=n.written,s=n.checked}catch(n){this.notifications.show({message:`Stashpad: frontmatter backfill failed in \`${t}\` -${n.message}`,kind:"error",category:"system",folder:e}),console.error("[Stashpad] runFolderFrontmatterBackfill failed",e,n);return}this.notifications.show({message:i>0?`Backfilled recovery links on ${i} note${i===1?"":"s"} in \`${t}\` (${s} checked).`:`Recovery links already up to date in \`${t}\` (${s} checked).`,kind:i>0?"success":"info",category:"system",folder:e})}async runAutoImportSweep(){if(!this.settings.autoImport||!this.importService.isArmed()||this.autoSweepInProgress)return;this.autoSweepInProgress=!0;let e=0,t=0,i=0;try{for(let n of this.discoverStashpadFolders())try{let o=await this.importService.importLooseInto(n,{auto:!0});e+=o.files,t+=o.folders,i+=o.stashes}catch(o){console.warn("[Stashpad] auto-import sweep failed",n,o)}}finally{this.autoSweepInProgress=!1}if(e+t+i>0){let n=this.lastActiveStashpadLeaf?.view;n?.tree&&n?.noteFolder&&(n.tree.rebuild(n.noteFolder),n.render?.());let o=[];e&&o.push(`${e} file${e===1?"":"s"}`),t&&o.push(`${t} folder${t===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 e=this.importService.pendingEncryptedPaths();if(e.length===0||!this.importService.shouldNotifyEncrypted())return;this.importService.snoozeEncryptedNotify(60*60*1e3);let t=e.length;this.notifications.show({message:`${t} encrypted .stash bundle${t===1?"":"s"} waiting to import. Import ${t===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:e,rescheduled:t}=await this.importService.importPendingEncrypted();if(e>0){let i=this.lastActiveStashpadLeaf?.view;i?.tree&&i?.noteFolder&&(i.tree.rebuild(i.noteFolder),i.render?.()),this.notifications.show({message:`Imported ${e} encrypted .stash bundle${e===1?"":"s"}.`,kind:"success",category:"import"})}}async seedLocalAuthorStub(e){let t=(this.settings.authorId??"").trim(),i=(this.settings.authorName??"").trim();if(!t||!i)return!1;let s=`${e.replace(/\/+$/,"")}/_authors`;if(this.app.vault.getMarkdownFiles().some(l=>l.path.startsWith(s+"/")&&this.parseAuthorFilePath(l.path)?.id===t))return!1;let o=this.authorNameToSafe(i),r=`${s}/${o}-${t}.md`;try{return await this.ensureFolderPath(s),await this.app.vault.adapter.exists(r)?!1:(await this.app.vault.create(r,this.buildAuthorStub({id:t,name:i,role:this.settings.authorRole,department:this.settings.authorDepartment},new Date().toISOString())),this.authorRegistry.record({id:t,name:i,role:this.settings.authorRole,department:this.settings.authorDepartment}),!0)}catch(l){return console.warn("[Stashpad] seedLocalAuthorStub failed",r,l),!1}}async seedLocalAuthorStubsEverywhere(){if(!(this.settings.authorName??"").trim())return 0;let t=0;for(let i of this.discoverStashpadFolders())await this.seedLocalAuthorStub(i)&&t++;return t}async ensureFolderPath(e){let t=this.app.vault.adapter,i=e.split("/").filter(Boolean),s="";for(let n of i){s=s?`${s}/${n}`:n;try{await t.exists(s)||await t.mkdir(s)}catch(o){if(!/already exists/i.test(o.message))throw o}}}async loadSettings(){let e=await this.loadData()??{};this.lastSeenSettingsRev=typeof e?.settingsRev=="number"?e.settingsRev:0,typeof e?.confirmMultiDelete=="boolean"&&(typeof e.confirmBulkDelete!="boolean"&&(e.confirmBulkDelete=e.confirmMultiDelete),typeof e.confirmAttachmentDelete!="boolean"&&(e.confirmAttachmentDelete=e.confirmMultiDelete),delete e.confirmMultiDelete),typeof e?.jdIndexDestFolder=="string"&&typeof e?.jdIndexStashpadFolder!="string"&&(e.jdIndexStashpadFolder=e.jdIndexDestFolder),this.settings={...Qt,...e,shortcuts:{...Qt.shortcuts,...e?.shortcuts??{}},mod:{...Qt.mod,...e?.mod??{}},bindings:kd(e?.bindings,e?.shortcuts,e?.mod),customPalette:Array.isArray(e?.customPalette)?e.customPalette.filter(t=>typeof t=="string"&&/^#[0-9a-f]{6}$/i.test(t)):[],colorAliases:e?.colorAliases&&typeof e.colorAliases=="object"?e.colorAliases:{},noteTemplates:e?.noteTemplates&&typeof e.noteTemplates=="object"?e.noteTemplates:{},authorName:typeof e?.authorName=="string"?e.authorName:"",authorId:typeof e?.authorId=="string"?e.authorId:"",authorRole:typeof e?.authorRole=="string"?e.authorRole:"",authorDepartment:typeof e?.authorDepartment=="string"?e.authorDepartment:"",showAuthor:typeof e?.showAuthor=="boolean"?e.showAuthor:!0,showContributors:typeof e?.showContributors=="boolean"?e.showContributors:!0,showLastEdit:typeof e?.showLastEdit=="boolean"?e.showLastEdit:!0,viewModes:e?.viewModes&&typeof e.viewModes=="object"&&!Array.isArray(e.viewModes)?e.viewModes:{},includeAttachmentsInEverything:e?.includeAttachmentsInEverything&&typeof e.includeAttachmentsInEverything=="object"&&!Array.isArray(e.includeAttachmentsInEverything)?e.includeAttachmentsInEverything:{},hideChildlessNotes:e?.hideChildlessNotes&&typeof e.hideChildlessNotes=="object"&&!Array.isArray(e.hideChildlessNotes)?e.hideChildlessNotes:{},hideCompletedNotes:e?.hideCompletedNotes&&typeof e.hideCompletedNotes=="object"&&!Array.isArray(e.hideCompletedNotes)?e.hideCompletedNotes:{},mutedNotificationCategories:Array.isArray(e?.mutedNotificationCategories)?e.mutedNotificationCategories.filter(t=>typeof t=="string"):[],notificationHistoryLimit:typeof e?.notificationHistoryLimit=="number"&&Number.isFinite(e.notificationHistoryLimit)?e.notificationHistoryLimit:5e3,notifiedDueKeys:Array.isArray(e?.notifiedDueKeys)?e.notifiedDueKeys.filter(t=>typeof t=="string").slice(-2e3):[],drafts:Sd(e?.drafts),lastSubmitted:e?.lastSubmitted&&typeof e.lastSubmitted=="object"?e.lastSubmitted:{},slugStopWords:Array.isArray(e?.slugStopWords)?e.slugStopWords:[...Ze],migratedToggleTaskG:e?.migratedToggleTaskG===!0,dueQuickAdjusts:Array.isArray(e?.dueQuickAdjusts)?e.dueQuickAdjusts.filter(t=>typeof t=="string"):["5m","15m","30m","1h","1d","1w"]},is(this.settings),this.snapshotSettingsBaseline(),this.settings.migratedToggleTaskG||(this.settings.bindings.toggleTask?.primary==="H"&&(this.settings.bindings.toggleTask.primary="G"),this.settings.migratedToggleTaskG=!0,await this.saveSettings()),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 e=this.app.vault.adapter,t=this.notificationsPath();try{if(await e.exists(t)){let i=await e.read(t),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 e=this.notifications.recent().slice().reverse(),t=this.notificationsPath(),i=t.replace(/\/[^/]+$/,""),s=this.app.vault.adapter;i&&!await s.exists(i)&&await s.mkdir(i),await s.write(t,JSON.stringify(e))}catch(e){console.warn("[Stashpad] failed to save notification history",e)}}readLastCursorFile(){try{let e=window.localStorage.getItem(this.LAST_CURSOR_LS_KEY);if(!e)return{};let t=JSON.parse(e);return t&&typeof t=="object"?t:{}}catch{return{}}}loadLastCursor(e){let i=this.readLastCursorFile()[e]??{};return new Map(Object.entries(i))}saveLastCursor(e,t,i){try{let s=this.readLastCursorFile();s[e]||(s[e]={}),s[e][t]=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 e=window.localStorage.getItem(this.LAST_SELECTION_LS_KEY);if(!e)return{};let t=JSON.parse(e);return t&&typeof t=="object"?t:{}}catch{return{}}}loadLastSelection(e){let i=this.readLastSelectionFile()[e]??{},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(e,t,i){try{let s=this.readLastSelectionFile();s[e]||(s[e]={}),i.length?s[e][t]=i:delete s[e][t],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 e=window.localStorage.getItem(this.ACTIVE_VERSIONS_LS_KEY);if(!e)return{};let t=JSON.parse(e);return t&&typeof t=="object"?t:{}}catch{return{}}}loadActiveVersions(e){let t=this.readActiveVersionsFile();return new Map(Object.entries(t[e]??{}))}saveActiveVersion(e,t,i){try{let s=this.readActiveVersionsFile();s[e]||(s[e]={}),s[e][t]=i,window.localStorage.setItem(this.ACTIVE_VERSIONS_LS_KEY,JSON.stringify(s))}catch(s){console.warn("[Stashpad] failed to save active-version",s)}}async flushForkSiblingPrune(){let e=new Set(this.pendingForkDeletes);if(this.pendingForkDeletes.clear(),!!e.size)for(let t of this.app.vault.getMarkdownFiles()){let i=this.app.metadataCache.getFileCache(t)?.frontmatter?.[$e];if(Array.isArray(i)&&i.some(s=>e.has(Bs(s)??"")))try{await this.app.fileManager.processFrontMatter(t,s=>{let o=(Array.isArray(s[$e])?s[$e]:[]).filter(r=>!e.has(Bs(r)??""));o.length?s[$e]=o:delete s[$e]})}catch{}}}queueWrite(){let e=this.writeChain.then(()=>this.guardedSave());return this.writeChain=e.catch(()=>{}),e}scheduleExternalDataJsonReload(){this.externalReloadDebounced()}async onExternalDataJsonChange(){let e=null;try{e=await this.loadData()}catch{return}if(!e)return;let t=typeof e.settingsRev=="number"?e.settingsRev:0;if(t<=this.lastSeenSettingsRev)return;let i=this.settings,s=!1,n=!1;for(let o of mt.COLLISION_PROTECTED_KEYS)e[o]!==void 0&&JSON.stringify(e[o])!==JSON.stringify(i[o])&&(i[o]=e[o],n=!0,o.startsWith("folderPanel")&&(s=!0));this.lastSeenSettingsRev=t,n&&(is(this.settings),this.snapshotSettingsBaseline(),s&&this.refreshFolderPanels())}snapshotSettingsBaseline(){for(let e of mt.COLLISION_PROTECTED_KEYS)this.settingsBaseline[e]=JSON.stringify(this.settings[e])}async guardedSave(){let e=null;try{e=await this.loadData()}catch{}let t=typeof e?.settingsRev=="number"?e.settingsRev:0;if(e){let s=[];for(let n of mt.COLLISION_PROTECTED_KEYS){let o=JSON.stringify(this.settings[n])!==this.settingsBaseline[n],r=JSON.stringify(e[n])!==this.settingsBaseline[n];!o&&r&&e[n]!==void 0&&(this.settings[n]=e[n],s.push(n))}s.length&&(console.warn(`[Stashpad] settings collision: on-disk protected keys differ from our baseline (disk rev ${t}, we knew ${this.lastSeenSettingsRev}); adopted: ${s.join(", ")}.`),new N.Notice(`Stashpad: another Obsidian instance (or a synced machine) changed this vault's settings. Merged instead of overwriting (${s.join(", ")}). If encryption behaves oddly, restart Obsidian.`,1e4),is(this.settings),s.some(n=>n.startsWith("folderPanel"))&&this.refreshFolderPanels()),t>this.lastSeenSettingsRev&&(this.lastSeenSettingsRev=t)}let i=Math.max(t,this.lastSeenSettingsRev)+1;this.settings.settingsRev=i,await this.saveData(this.settings),this.lastSeenSettingsRev=i,this.snapshotSettingsBaseline()}async saveSettings(){await this.queueWrite(),is(this.settings),ke.enabled=!!this.settings.enablePerfProfiling;let e=(this.settings.authorId??"").trim();e&&this.authorRegistry.record({id:e,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 e=new Set(this.discoverStashpadFolders());if(e.size===0){new N.Notice("No Stashpad folders found.");return}let t=new Set,i=this.app.vault.getMarkdownFiles();for(let h of i){let g=this.app.metadataCache.getFileCache(h)?.frontmatter,u=typeof g?.id=="string"?g.id.trim():"";u&&t.add(u)}let{newId:s}=await Promise.resolve().then(()=>(ot(),jn)),n=()=>{for(let h=0;h<100;h++){let g=s();if(!t.has(g))return t.add(g),g}for(let h=8;h<=16;h+=2){let g=s(h);if(!t.has(g))return t.add(g),g}throw new Error("Could not generate a unique id")},o=[];for(let h of i){let g=h.parent?.path?.replace(/\/+$/,"")??"";if(!e.has(g))continue;let u=this.app.metadataCache.getFileCache(h)?.frontmatter,f=typeof u?.id=="string"?u.id.trim():"",p=u?.parent,I=typeof p=="string"?p.trim()!=="":p!=null,m=typeof u?.created=="string"&&u.created.trim()!=="",B=!f,C=!I,w=!m;!B&&!C&&!w||o.push({file:h,addId:B,addParent:C,addCreated:w})}if(o.length===0){new N.Notice("Nothing to fix \u2014 every note in a Stashpad folder already has id + parent + created.");return}let r=0,l=0,c=this.newLog();for(let h of o)try{let g;await this.app.fileManager.processFrontMatter(h.file,p=>{if(h.addId&&(typeof p.id=="string"&&p.id.trim()||(g=n(),p.id=g)),h.addParent){let I=p.parent;(typeof I=="string"?I.trim()!=="":I!=null)||(p.parent=S)}h.addCreated&&(typeof p.created=="string"&&p.created.trim()||(p.created=new Date(h.file.stat.ctime).toISOString()))});let u=this.app.metadataCache.getFileCache(h.file)?.frontmatter,f=g??u?.id??"";f&&await c.append({type:"parent_change",id:f,payload:{from:null,to:S,reason:"orphan_fix",path:h.file.path,addedId:h.addId,addedParent:h.addParent,addedCreated:h.addCreated}}),r++}catch(g){console.warn("Stashpad: orphan fix failed for",h.file.path,g),l++}let A=l?` (${l} failed \u2014 see console)`:"";new N.Notice(`Fixed ${r} note${r===1?"":"s"} in Stashpad folders${A}.`)}async adoptNote(e){let{newId:t}=await Promise.resolve().then(()=>(ot(),jn)),i=new Set;for(let c of this.app.vault.getMarkdownFiles()){if(c.path===e.path)continue;let A=this.app.metadataCache.getFileCache(c)?.frontmatter,h=typeof A?.id=="string"?A.id.trim():"";h&&i.add(h)}let s=()=>{for(let c=0;c<50;c++){let A=t();if(!i.has(A))return A}for(let c=8;c<=16;c+=2){let A=t(c);if(!i.has(A))return A}throw new Error("Could not generate a unique id")},n=[],o=[];try{await this.app.fileManager.processFrontMatter(e,c=>{let A=typeof c.id=="string"?c.id.trim():"";!A||/\s/.test(A)||i.has(A)?(c.id=s(),n.push("id")):o.push("id"),c.parent!==void 0&&c.parent!==null&&String(c.parent).trim()!==""?o.push("parent"):(c.parent=S,n.push("parent")),typeof c.created=="string"&&c.created.trim()!==""?o.push("created"):(c.created=new Date(e.stat.ctime).toISOString(),n.push("created"))})}catch(c){new N.Notice(`Adopt failed: ${c.message}`);return}let r=!1;try{let c=this.app.metadataCache.getFileCache(e)?.frontmatter,A=typeof c?.id=="string"?c.id.trim():"";if(A&&e.basename&&!e.basename.endsWith(`-${A}`)){let h=`${e.parent?e.parent.path+"/":""}${e.basename}-${A}.md`;await this.app.vault.adapter.exists(h)||(await this.app.fileManager.renameFile(e,h),r=!0)}}catch(c){console.warn("Stashpad: adopt rename failed",c)}if(n.length===0&&!r){new N.Notice(`Already a Stashpad note (${o.join(", ")} present).`);return}let l=[];n.length&&l.push(`added: ${n.join(", ")}`),r&&l.push("renamed with id"),new N.Notice(`Adopted into Stashpad \u2014 ${l.join("; ")}.`);try{let c=this.newLog(),A=this.app.metadataCache.getFileCache(e)?.frontmatter,h=A?.id??"";h&&await c.append({type:"create",id:h,payload:{path:e.path,parent:A?.parent??S,source:"adopt",added:n}})}catch{}}};mt.DEBUG_BUFFER_MAX=300,mt.COLLISION_PROTECTED_KEYS=["encryption","lockedSubtrees","folderEncPrefs","archiveFolders","folderPanelPinned","folderPanelDownranked","folderPanelHidden","folderPanelPinnedGrouping"];var qn=mt;function kd(d,a,e){let t=No();for(let i of Jt){let s=a&&typeof a[i.id]=="string"?a[i.id]:e&&typeof e[i.id]=="string"?e[i.id]:null;s!=null&&s!==""&&(t[i.id].primary=s)}if(d&&typeof d=="object")for(let i of Jt){let s=d[i.id];!s||typeof s!="object"||(t[i.id]={primary:typeof s.primary=="string"?s.primary:t[i.id].primary,secondary:typeof s.secondary=="string"?s.secondary:"",preferRight:!!s.preferRight,useBoth:!!s.useBoth})}for(let i of Jt){if(!i.defaultSecondary&&!i.defaultUseBoth)continue;let s=t[i.id];s.primary===i.defaultPrimary&&!s.secondary&&!s.useBoth&&(s.secondary=i.defaultSecondary??"",s.useBoth=!!i.defaultUseBoth)}return t}function Sd(d){let a={};if(!d||typeof d!="object")return a;for(let[e,t]of Object.entries(d))if(typeof t=="string")a[e]=t;else if(t&&typeof t=="object"){for(let i of Object.values(t))if(typeof i=="string"&&i.length>0){a[e]=i;break}}return a}var pr=class extends N.SuggestModal{constructor(e,t,i,s){super(e);this.def=t;this.folders=i;this.onPick=s;this.setPlaceholder("Choose a Stashpad folder to import into\u2026")}getSuggestions(e){let t=e.toLowerCase();return[this.def,...this.folders.filter(s=>s!==this.def)].filter(s=>s.toLowerCase().includes(t)).map(s=>({label:s,folder:s,current:s===this.def}))}renderSuggestion(e,t){t.createDiv({text:e.label}),e.current&&(t.createDiv({cls:"stashpad-suggest-note",text:"current"}),t.addClass("is-pinned-import-target"))}onChooseSuggestion(e){this.onPick(e.folder)}},gr=class extends N.SuggestModal{constructor(e,t,i){super(e);this.bundles=t;this.onPick=i;this.setPlaceholder("Choose an encrypted folder bundle to decrypt\u2026")}getSuggestions(e){let t=e.toLowerCase();return this.bundles.filter(i=>i.folder.toLowerCase().includes(t))}renderSuggestion(e,t){t.createDiv({text:e.folder||"(vault root)"}),t.createDiv({cls:"stashpad-suggest-note",text:e.blobPath})}onChooseSuggestion(e){this.onPick(e)}}; +${s.message}`,kind:"error",category:"system",folder:e}),console.error("[Stashpad] runFolderSlugPass failed",e,s);return}this.refreshViewIfShowing(e),this.notifications.show({message:i>0?`Renamed ${i} stale filename${i===1?"":"s"} in \`${t}\`.`:`No stale filenames in \`${t}\` \u2014 all slugs match their notes.`,kind:i>0?"success":"info",category:"system",folder:e})}async runFolderFrontmatterBackfill(e){let t=e.split("/").pop()||e,i=0,s=0;try{let n=await Bi(this.app,e);i=n.written,s=n.checked}catch(n){this.notifications.show({message:`Stashpad: frontmatter backfill failed in \`${t}\` +${n.message}`,kind:"error",category:"system",folder:e}),console.error("[Stashpad] runFolderFrontmatterBackfill failed",e,n);return}this.notifications.show({message:i>0?`Backfilled recovery links on ${i} note${i===1?"":"s"} in \`${t}\` (${s} checked).`:`Recovery links already up to date in \`${t}\` (${s} checked).`,kind:i>0?"success":"info",category:"system",folder:e})}async runAutoImportSweep(){if(!this.settings.autoImport||!this.importService.isArmed()||this.autoSweepInProgress)return;this.autoSweepInProgress=!0;let e=0,t=0,i=0;try{for(let n of this.discoverStashpadFolders())try{let o=await this.importService.importLooseInto(n,{auto:!0});e+=o.files,t+=o.folders,i+=o.stashes}catch(o){console.warn("[Stashpad] auto-import sweep failed",n,o)}}finally{this.autoSweepInProgress=!1}if(e+t+i>0){let n=this.lastActiveStashpadLeaf?.view;n?.tree&&n?.noteFolder&&(n.tree.rebuild(n.noteFolder),n.render?.());let o=[];e&&o.push(`${e} file${e===1?"":"s"}`),t&&o.push(`${t} folder${t===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 e=this.importService.pendingEncryptedPaths();if(e.length===0||!this.importService.shouldNotifyEncrypted())return;this.importService.snoozeEncryptedNotify(60*60*1e3);let t=e.length;this.notifications.show({message:`${t} encrypted .stash bundle${t===1?"":"s"} waiting to import. Import ${t===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:e,rescheduled:t}=await this.importService.importPendingEncrypted();if(e>0){let i=this.lastActiveStashpadLeaf?.view;i?.tree&&i?.noteFolder&&(i.tree.rebuild(i.noteFolder),i.render?.()),this.notifications.show({message:`Imported ${e} encrypted .stash bundle${e===1?"":"s"}.`,kind:"success",category:"import"})}}async seedLocalAuthorStub(e){let t=(this.settings.authorId??"").trim(),i=(this.settings.authorName??"").trim();if(!t||!i)return!1;let s=`${e.replace(/\/+$/,"")}/_authors`;if(this.app.vault.getMarkdownFiles().some(l=>l.path.startsWith(s+"/")&&this.parseAuthorFilePath(l.path)?.id===t))return!1;let o=this.authorNameToSafe(i),r=`${s}/${o}-${t}.md`;try{return await this.ensureFolderPath(s),await this.app.vault.adapter.exists(r)?!1:(await this.app.vault.create(r,this.buildAuthorStub({id:t,name:i,role:this.settings.authorRole,department:this.settings.authorDepartment},new Date().toISOString())),this.authorRegistry.record({id:t,name:i,role:this.settings.authorRole,department:this.settings.authorDepartment}),!0)}catch(l){return console.warn("[Stashpad] seedLocalAuthorStub failed",r,l),!1}}async seedLocalAuthorStubsEverywhere(){if(!(this.settings.authorName??"").trim())return 0;let t=0;for(let i of this.discoverStashpadFolders())await this.seedLocalAuthorStub(i)&&t++;return t}async ensureFolderPath(e){let t=this.app.vault.adapter,i=e.split("/").filter(Boolean),s="";for(let n of i){s=s?`${s}/${n}`:n;try{await t.exists(s)||await t.mkdir(s)}catch(o){if(!/already exists/i.test(o.message))throw o}}}async loadSettings(){let e=await this.loadData()??{};this.lastSeenSettingsRev=typeof e?.settingsRev=="number"?e.settingsRev:0,typeof e?.confirmMultiDelete=="boolean"&&(typeof e.confirmBulkDelete!="boolean"&&(e.confirmBulkDelete=e.confirmMultiDelete),typeof e.confirmAttachmentDelete!="boolean"&&(e.confirmAttachmentDelete=e.confirmMultiDelete),delete e.confirmMultiDelete),typeof e?.jdIndexDestFolder=="string"&&typeof e?.jdIndexStashpadFolder!="string"&&(e.jdIndexStashpadFolder=e.jdIndexDestFolder),this.settings={...vt,...e,shortcuts:{...vt.shortcuts,...e?.shortcuts??{}},mod:{...vt.mod,...e?.mod??{}},bindings:xd(e?.bindings,e?.shortcuts,e?.mod),customPalette:Array.isArray(e?.customPalette)?e.customPalette.filter(t=>typeof t=="string"&&/^#[0-9a-f]{6}$/i.test(t)):[],colorAliases:e?.colorAliases&&typeof e.colorAliases=="object"?e.colorAliases:{},noteTemplates:e?.noteTemplates&&typeof e.noteTemplates=="object"?e.noteTemplates:{},authorName:typeof e?.authorName=="string"?e.authorName:"",authorId:typeof e?.authorId=="string"?e.authorId:"",authorRole:typeof e?.authorRole=="string"?e.authorRole:"",authorDepartment:typeof e?.authorDepartment=="string"?e.authorDepartment:"",showAuthor:typeof e?.showAuthor=="boolean"?e.showAuthor:!0,showContributors:typeof e?.showContributors=="boolean"?e.showContributors:!0,showLastEdit:typeof e?.showLastEdit=="boolean"?e.showLastEdit:!0,viewModes:e?.viewModes&&typeof e.viewModes=="object"&&!Array.isArray(e.viewModes)?e.viewModes:{},includeAttachmentsInEverything:e?.includeAttachmentsInEverything&&typeof e.includeAttachmentsInEverything=="object"&&!Array.isArray(e.includeAttachmentsInEverything)?e.includeAttachmentsInEverything:{},hideChildlessNotes:e?.hideChildlessNotes&&typeof e.hideChildlessNotes=="object"&&!Array.isArray(e.hideChildlessNotes)?e.hideChildlessNotes:{},hideCompletedNotes:e?.hideCompletedNotes&&typeof e.hideCompletedNotes=="object"&&!Array.isArray(e.hideCompletedNotes)?e.hideCompletedNotes:{},mutedNotificationCategories:Array.isArray(e?.mutedNotificationCategories)?e.mutedNotificationCategories.filter(t=>typeof t=="string"):[],notificationHistoryLimit:typeof e?.notificationHistoryLimit=="number"&&Number.isFinite(e.notificationHistoryLimit)?e.notificationHistoryLimit:5e3,notifiedDueKeys:Array.isArray(e?.notifiedDueKeys)?e.notifiedDueKeys.filter(t=>typeof t=="string").slice(-2e3):[],drafts:Nd(e?.drafts),lastSubmitted:e?.lastSubmitted&&typeof e.lastSubmitted=="object"?e.lastSubmitted:{},slugStopWords:Array.isArray(e?.slugStopWords)?e.slugStopWords:[...je],migratedToggleTaskG:e?.migratedToggleTaskG===!0,dueQuickAdjusts:Array.isArray(e?.dueQuickAdjusts)?e.dueQuickAdjusts.filter(t=>typeof t=="string"):["5m","15m","30m","1h","1d","1w"]},ss(this.settings),this.snapshotSettingsBaseline(),this.settings.migratedToggleTaskG||(this.settings.bindings.toggleTask?.primary==="H"&&(this.settings.bindings.toggleTask.primary="G"),this.settings.migratedToggleTaskG=!0,await this.saveSettings()),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 e=this.app.vault.adapter,t=this.notificationsPath();try{if(await e.exists(t)){let i=await e.read(t),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 e=this.notifications.recent().slice().reverse(),t=this.notificationsPath(),i=t.replace(/\/[^/]+$/,""),s=this.app.vault.adapter;i&&!await s.exists(i)&&await s.mkdir(i),await s.write(t,JSON.stringify(e))}catch(e){console.warn("[Stashpad] failed to save notification history",e)}}readLastCursorFile(){try{let e=window.localStorage.getItem(this.LAST_CURSOR_LS_KEY);if(!e)return{};let t=JSON.parse(e);return t&&typeof t=="object"?t:{}}catch{return{}}}loadLastCursor(e){let i=this.readLastCursorFile()[e]??{};return new Map(Object.entries(i))}saveLastCursor(e,t,i){try{let s=this.readLastCursorFile();s[e]||(s[e]={}),s[e][t]=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 e=window.localStorage.getItem(this.LAST_SELECTION_LS_KEY);if(!e)return{};let t=JSON.parse(e);return t&&typeof t=="object"?t:{}}catch{return{}}}loadLastSelection(e){let i=this.readLastSelectionFile()[e]??{},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(e,t,i){try{let s=this.readLastSelectionFile();s[e]||(s[e]={}),i.length?s[e][t]=i:delete s[e][t],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 e=window.localStorage.getItem(this.ACTIVE_VERSIONS_LS_KEY);if(!e)return{};let t=JSON.parse(e);return t&&typeof t=="object"?t:{}}catch{return{}}}loadActiveVersions(e){let t=this.readActiveVersionsFile();return new Map(Object.entries(t[e]??{}))}saveActiveVersion(e,t,i){try{let s=this.readActiveVersionsFile();s[e]||(s[e]={}),s[e][t]=i,window.localStorage.setItem(this.ACTIVE_VERSIONS_LS_KEY,JSON.stringify(s))}catch(s){console.warn("[Stashpad] failed to save active-version",s)}}async flushForkSiblingPrune(){let e=new Set(this.pendingForkDeletes);if(this.pendingForkDeletes.clear(),!!e.size)for(let t of this.app.vault.getMarkdownFiles()){let i=this.app.metadataCache.getFileCache(t)?.frontmatter?.[Ye];if(Array.isArray(i)&&i.some(s=>e.has(ys(s)??"")))try{await this.app.fileManager.processFrontMatter(t,s=>{let o=(Array.isArray(s[Ye])?s[Ye]:[]).filter(r=>!e.has(ys(r)??""));o.length?s[Ye]=o:delete s[Ye]})}catch{}}}queueWrite(){let e=this.writeChain.then(()=>this.guardedSave());return this.writeChain=e.catch(()=>{}),e}scheduleExternalDataJsonReload(){this.externalReloadDebounced()}async onExternalDataJsonChange(){let e=null;try{e=await this.loadData()}catch{return}if(!e)return;let t=typeof e.settingsRev=="number"?e.settingsRev:0;if(t<=this.lastSeenSettingsRev)return;let i=this.settings,s=!1,n=!1;for(let o of Ct.COLLISION_PROTECTED_KEYS)e[o]!==void 0&&JSON.stringify(e[o])!==JSON.stringify(i[o])&&(i[o]=e[o],n=!0,o.startsWith("folderPanel")&&(s=!0));this.lastSeenSettingsRev=t,n&&(ss(this.settings),this.snapshotSettingsBaseline(),s&&this.refreshFolderPanels())}snapshotSettingsBaseline(){for(let e of Ct.COLLISION_PROTECTED_KEYS)this.settingsBaseline[e]=JSON.stringify(this.settings[e])}async guardedSave(){let e=null;try{e=await this.loadData()}catch{}let t=typeof e?.settingsRev=="number"?e.settingsRev:0;if(e){let s=[];for(let n of Ct.COLLISION_PROTECTED_KEYS){let o=JSON.stringify(this.settings[n])!==this.settingsBaseline[n],r=JSON.stringify(e[n])!==this.settingsBaseline[n];!o&&r&&e[n]!==void 0&&(this.settings[n]=e[n],s.push(n))}s.length&&(console.warn(`[Stashpad] settings collision: on-disk protected keys differ from our baseline (disk rev ${t}, we knew ${this.lastSeenSettingsRev}); adopted: ${s.join(", ")}.`),new M.Notice(`Stashpad: another Obsidian instance (or a synced machine) changed this vault's settings. Merged instead of overwriting (${s.join(", ")}). If encryption behaves oddly, restart Obsidian.`,1e4),ss(this.settings),s.some(n=>n.startsWith("folderPanel"))&&this.refreshFolderPanels()),t>this.lastSeenSettingsRev&&(this.lastSeenSettingsRev=t)}let i=Math.max(t,this.lastSeenSettingsRev)+1;this.settings.settingsRev=i,await this.saveData(this.settings),this.lastSeenSettingsRev=i,this.snapshotSettingsBaseline()}async saveSettings(){await this.queueWrite(),ss(this.settings),ke.enabled=!!this.settings.enablePerfProfiling;let e=(this.settings.authorId??"").trim();e&&this.authorRegistry.record({id:e,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 e=new Set(this.discoverStashpadFolders());if(e.size===0){new M.Notice("No Stashpad folders found.");return}let t=new Set,i=this.app.vault.getMarkdownFiles();for(let h of i){let p=this.app.metadataCache.getFileCache(h)?.frontmatter,u=typeof p?.id=="string"?p.id.trim():"";u&&t.add(u)}let{newId:s}=await Promise.resolve().then(()=>(rt(),to)),n=()=>{for(let h=0;h<100;h++){let p=s();if(!t.has(p))return t.add(p),p}for(let h=8;h<=16;h+=2){let p=s(h);if(!t.has(p))return t.add(p),p}throw new Error("Could not generate a unique id")},o=[];for(let h of i){let p=h.parent?.path?.replace(/\/+$/,"")??"";if(!e.has(p))continue;let u=this.app.metadataCache.getFileCache(h)?.frontmatter,f=typeof u?.id=="string"?u.id.trim():"",g=u?.parent,I=typeof g=="string"?g.trim()!=="":g!=null,m=typeof u?.created=="string"&&u.created.trim()!=="",B=!f,C=!I,Q=!m;!B&&!C&&!Q||o.push({file:h,addId:B,addParent:C,addCreated:Q})}if(o.length===0){new M.Notice("Nothing to fix \u2014 every note in a Stashpad folder already has id + parent + created.");return}let r=0,l=0,c=this.newLog();for(let h of o)try{let p;await this.app.fileManager.processFrontMatter(h.file,g=>{if(h.addId&&(typeof g.id=="string"&&g.id.trim()||(p=n(),g.id=p)),h.addParent){let I=g.parent;(typeof I=="string"?I.trim()!=="":I!=null)||(g.parent=k)}h.addCreated&&(typeof g.created=="string"&&g.created.trim()||(g.created=new Date(h.file.stat.ctime).toISOString()))});let u=this.app.metadataCache.getFileCache(h.file)?.frontmatter,f=p??u?.id??"";f&&await c.append({type:"parent_change",id:f,payload:{from:null,to:k,reason:"orphan_fix",path:h.file.path,addedId:h.addId,addedParent:h.addParent,addedCreated:h.addCreated}}),r++}catch(p){console.warn("Stashpad: orphan fix failed for",h.file.path,p),l++}let A=l?` (${l} failed \u2014 see console)`:"";new M.Notice(`Fixed ${r} note${r===1?"":"s"} in Stashpad folders${A}.`)}async adoptNote(e){let{newId:t}=await Promise.resolve().then(()=>(rt(),to)),i=new Set;for(let c of this.app.vault.getMarkdownFiles()){if(c.path===e.path)continue;let A=this.app.metadataCache.getFileCache(c)?.frontmatter,h=typeof A?.id=="string"?A.id.trim():"";h&&i.add(h)}let s=()=>{for(let c=0;c<50;c++){let A=t();if(!i.has(A))return A}for(let c=8;c<=16;c+=2){let A=t(c);if(!i.has(A))return A}throw new Error("Could not generate a unique id")},n=[],o=[];try{await this.app.fileManager.processFrontMatter(e,c=>{let A=typeof c.id=="string"?c.id.trim():"";!A||/\s/.test(A)||i.has(A)?(c.id=s(),n.push("id")):o.push("id"),c.parent!==void 0&&c.parent!==null&&String(c.parent).trim()!==""?o.push("parent"):(c.parent=k,n.push("parent")),typeof c.created=="string"&&c.created.trim()!==""?o.push("created"):(c.created=new Date(e.stat.ctime).toISOString(),n.push("created"))})}catch(c){new M.Notice(`Adopt failed: ${c.message}`);return}let r=!1;try{let c=this.app.metadataCache.getFileCache(e)?.frontmatter,A=typeof c?.id=="string"?c.id.trim():"";if(A&&e.basename&&!e.basename.endsWith(`-${A}`)){let h=`${e.parent?e.parent.path+"/":""}${e.basename}-${A}.md`;await this.app.vault.adapter.exists(h)||(await this.app.fileManager.renameFile(e,h),r=!0)}}catch(c){console.warn("Stashpad: adopt rename failed",c)}if(n.length===0&&!r){new M.Notice(`Already a Stashpad note (${o.join(", ")} present).`);return}let l=[];n.length&&l.push(`added: ${n.join(", ")}`),r&&l.push("renamed with id"),new M.Notice(`Adopted into Stashpad \u2014 ${l.join("; ")}.`);try{let c=this.newLog(),A=this.app.metadataCache.getFileCache(e)?.frontmatter,h=A?.id??"";h&&await c.append({type:"create",id:h,payload:{path:e.path,parent:A?.parent??k,source:"adopt",added:n}})}catch{}}};Ct.DEBUG_BUFFER_MAX=300,Ct.COLLISION_PROTECTED_KEYS=["encryption","lockedSubtrees","folderEncPrefs","archiveFolders","folderPanelPinned","folderPanelDownranked","folderPanelHidden","folderPanelPinnedGrouping"];var zn=Ct;function xd(d,a,e){let t=Po();for(let i of qt){let s=a&&typeof a[i.id]=="string"?a[i.id]:e&&typeof e[i.id]=="string"?e[i.id]:null;s!=null&&s!==""&&(t[i.id].primary=s)}if(d&&typeof d=="object")for(let i of qt){let s=d[i.id];!s||typeof s!="object"||(t[i.id]={primary:typeof s.primary=="string"?s.primary:t[i.id].primary,secondary:typeof s.secondary=="string"?s.secondary:"",preferRight:!!s.preferRight,useBoth:!!s.useBoth})}for(let i of qt){if(!i.defaultSecondary&&!i.defaultUseBoth)continue;let s=t[i.id];s.primary===i.defaultPrimary&&!s.secondary&&!s.useBoth&&(s.secondary=i.defaultSecondary??"",s.useBoth=!!i.defaultUseBoth)}return t}function Nd(d){let a={};if(!d||typeof d!="object")return a;for(let[e,t]of Object.entries(d))if(typeof t=="string")a[e]=t;else if(t&&typeof t=="object"){for(let i of Object.values(t))if(typeof i=="string"&&i.length>0){a[e]=i;break}}return a}var ur=class extends M.SuggestModal{constructor(e,t,i,s){super(e);this.def=t;this.folders=i;this.onPick=s;this.setPlaceholder("Choose a Stashpad folder to import into\u2026")}getSuggestions(e){let t=e.toLowerCase();return[this.def,...this.folders.filter(s=>s!==this.def)].filter(s=>s.toLowerCase().includes(t)).map(s=>({label:s,folder:s,current:s===this.def}))}renderSuggestion(e,t){t.createDiv({text:e.label}),e.current&&(t.createDiv({cls:"stashpad-suggest-note",text:"current"}),t.addClass("is-pinned-import-target"))}onChooseSuggestion(e){this.onPick(e.folder)}},fr=class extends M.SuggestModal{constructor(e,t,i){super(e);this.bundles=t;this.onPick=i;this.setPlaceholder("Choose an encrypted folder bundle to decrypt\u2026")}getSuggestions(e){let t=e.toLowerCase();return this.bundles.filter(i=>i.folder.toLowerCase().includes(t))}renderSuggestion(e,t){t.createDiv({text:e.folder||"(vault root)"}),t.createDiv({cls:"stashpad-suggest-note",text:e.blobPath})}onChooseSuggestion(e){this.onPick(e)}}; /*! Bundled license information: hash-wasm/dist/index.esm.js: diff --git a/manifest.json b/manifest.json index b9cfbae..92a00b5 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "stashpad", "name": "Stashpad", - "version": "0.152.0", + "version": "0.157.0", "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 bf7819e..6aac413 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "stashpad-obsidian", - "version": "0.152.0", + "version": "0.157.0", "private": true, "scripts": { "dev": "node esbuild.config.mjs", diff --git a/release-notes/0.157.0.md b/release-notes/0.157.0.md new file mode 100644 index 0000000..ff329f6 --- /dev/null +++ b/release-notes/0.157.0.md @@ -0,0 +1,57 @@ +# 0.157.0 + +A menu-consistency and search pass: the note action menu, the encrypted/locked +row menu, the aggregate views, and the mobile ⚡ menu now share one set of +actions; the due-date dialog is the same from every entry point; and the note +picker finally ranks its results. + +## Search ranking (0.157.0) + +- The note picker — which backs Find, Search, Move, and the destination picker — + now **ranks** its matches instead of showing them in raw tree order. Results are + scored by a relevance band (exact title match > title starts-with > exact phrase + in title > all words in title > exact phrase in body > words in body) and, within + a band, by **most recently edited**. +- With an **empty** query the list is ordered purely by most-recently-edited. +- In the **Move / destination** picker, each folder's Home note is floated to the + top of its results — the common "move it here" target. + +## Due-date dialog unified (0.156.0) + +- The quick relative **+/- time-adjust row** (and the repeat / reminders section) + now appears no matter how you open the due-date dialog — the `D` hotkey, the + command palette, or the "Assign / schedule…" context-menu item. Previously the + Assign path opened a stripped-down dialog with the quick-adjust row missing. +- The quick-adjust presets now fall back to a sensible default when a caller + doesn't specify them, so no entry point can silently drop the row. + +## Menus unified (0.155.0 – 0.155.3) + +- **Shared menu for locked notes (0.155.0).** The encrypted/locked row menu and + the normal note context menu are now built from one implementation, so they stay + in sync. Copy Stashpad link, Export to .stash, and Export as OKF are grouped + under a single **"Share & export ▸"** submenu to keep the top level short. +- **Mobile ⚡ menu parity (0.155.1).** The mobile ⚡ actions menu gains the same + "Share & export ▸" submenu — it previously had no copy-link or export actions at + all. +- **Multi-select Copy Stashpad link (0.155.2).** Copying a link with several notes + selected now copies **one deep link per note** (newline-separated) instead of + only the first. A right-click still links just the clicked note. +- **Multi-link "Open Stashpad link" (0.155.3).** The Open-link dialog is now a + text area and accepts multiple links (one per line). A single link opens as + before; multiple links each open in their **own** tab, with a notice tallying how + many opened. + +## Aggregate-view menus + hide-filename (0.153.0) + +- **Context menus on every aggregate row.** In "All encrypted" and "All archived", + each row now has a ⋯ button and right-click menu: locked rows offer unlock / + restore, copy link, export, reveal in the file manager, copy path, and a + delete-with-undo; plain archived rows offer open, restore, reveal, and copy path. +- **New command "Encrypt (lock) selection + hide filename".** Locks the selection + with the encrypted file's name hidden, regardless of the folder's + encrypt-filenames setting. + +## Internal + +- Dev test-harness reload made more resilient (no user-facing effect). diff --git a/scripts/obs-dev.mjs b/scripts/obs-dev.mjs index 9eecc82..d70ab2e 100755 --- a/scripts/obs-dev.mjs +++ b/scripts/obs-dev.mjs @@ -210,8 +210,32 @@ async function screenshot(path) { async function reload() { await verifyVault(); - await cdp("Page.reload", { ignoreCache: true }); + // Reload from inside the page (Obsidian's own "app:reload", falling back to + // location.reload) rather than a raw CDP Page.reload. Page.reload tears the + // target down while we're still awaiting its response, which wedges the + // socket and has coincided with the dev instance dying outright. Fire it on a + // short timer so this eval returns before the navigation starts. + try { + await rawEval(wrapBody(` + const reloadNow = () => { + try { if (app.commands?.commands?.["app:reload"]) { app.commands.executeCommandById("app:reload"); return; } } catch {} + location.reload(); + }; + setTimeout(reloadNow, 50); + return "reloading"; + `)); + } catch { /* the socket may drop as the page navigates; that's expected */ } console.log("reloading dev instance renderer (picks up the latest deploy)…"); + // Poll the port + re-verify like start(), so reload only returns once the + // instance is actually back — instead of leaving the next command to trip + // over a renderer that's still mid-reload (or gone). + const deadline = Date.now() + 30000; + while (Date.now() < deadline) { + await new Promise((r) => setTimeout(r, 700)); + if (!(await portReady())) continue; + try { await verifyVault(); console.log("reload complete — instance healthy."); return; } catch { /* still booting */ } + } + throw new Error("dev instance did not come back after reload within 30s — run `obs-dev start` to relaunch."); } // ---- dispatch ------------------------------------------------------------- diff --git a/src/aggregate-view.ts b/src/aggregate-view.ts index 31f54dc..2353c71 100644 --- a/src/aggregate-view.ts +++ b/src/aggregate-view.ts @@ -1,6 +1,10 @@ -import { ItemView, TFile, WorkspaceLeaf, moment, setIcon, type ViewStateResult } from "obsidian"; +import { ItemView, Menu, Notice, Platform, TFile, WorkspaceLeaf, moment, setIcon, type ViewStateResult } from "obsidian"; import type StashpadPlugin from "./main"; +import { populateLockedMenu } from "./locked-menu"; import { STASHPAD_AGGREGATE_VIEW_TYPE, archiveSubfolderOf } from "./types"; + +/** One row of the locked-subtree registry (`settings.lockedSubtrees`). */ +type LockedEntry = { folder: string; blob: string; parentId?: string | null; title?: string; count?: number; created?: string; rootId?: string; prevSibling?: string | null }; import { renderTaskTriage, defaultTaskTriageState, type TaskTriageState } from "./task-render"; import { renderAggModeBar, type AggMode } from "./agg-modes"; import { returnToOriginOnClose } from "./leaf-return"; @@ -143,6 +147,7 @@ export class StashpadAggregateView extends ItemView { exp.onclick = () => void this.plugin.exportLockedSubtree(e.blob); const lock = row.createSpan({ cls: "stashpad-aggregate-lockbadge" }); setIcon(lock, "lock"); + this.attachLockedRowMenu(row, e, { archived: false }); } } } @@ -244,10 +249,46 @@ export class StashpadAggregateView extends ItemView { const restore = row.createEl("button", { cls: "stashpad-trash-restore", text: "Restore" }); setIcon(restore.createSpan({ cls: "stashpad-btn-icon" }), "rotate-ccw"); restore.onclick = async () => { restore.disabled = true; const ok = await this.plugin.unarchiveNote(f); if (ok) void this.render(); else restore.disabled = false; }; + this.attachPlainRowMenu(row, f, restore); + } + + /** ⋯ + right-click menu for a plain (unencrypted) archived note. Lighter than + * the locked menu — the full note menu lives in the folder view; here we just + * open, restore, and surface the file. */ + private attachPlainRowMenu(row: HTMLElement, f: TFile, restoreBtn: HTMLButtonElement): void { + const buildMenu = (): Menu => { + const menu = new Menu(); + menu.addItem((i) => i.setTitle("Open note").setIcon("file-text").onClick(() => void this.app.workspace.getLeaf(false).openFile(f))); + menu.addItem((i) => i.setTitle("Restore (un-archive)").setIcon("rotate-ccw").onClick(() => restoreBtn.click())); + menu.addSeparator(); + if (!Platform.isMobile) { + menu.addItem((i) => i.setTitle("Show in Finder").setIcon("folder-open").onClick(() => { + try { + const shell = (window as unknown as { require?: (m: string) => { shell?: { showItemInFolder?: (p: string) => void } } }).require?.("electron")?.shell; + const fullPath = (this.app.vault.adapter as unknown as { getFullPath?: (p: string) => string })?.getFullPath?.(f.path); + if (fullPath && shell?.showItemInFolder) shell.showItemInFolder(fullPath); + } catch (err) { console.warn("[Stashpad] showItemInFolder failed", err); } + })); + } + menu.addItem((i) => i.setTitle("Copy file path").setIcon("copy").onClick(() => { + let path = f.path; + if (!Platform.isMobile) { + try { path = (this.app.vault.adapter as unknown as { getFullPath?: (p: string) => string })?.getFullPath?.(f.path) || f.path; } catch { /* keep relative */ } + } + void navigator.clipboard.writeText(path); + new Notice("Path copied."); + })); + return menu; + }; + row.oncontextmenu = (evt: MouseEvent) => { evt.preventDefault(); buildMenu().showAtMouseEvent(evt); }; + const more = row.createEl("button", { cls: "stashpad-trash-iconbtn stashpad-agg-more" }); + setIcon(more, "ellipsis-vertical"); + more.setAttr("aria-label", "More actions"); + more.onclick = (evt) => { evt.stopPropagation(); buildMenu().showAtMouseEvent(evt as MouseEvent); }; } /** One locked archived subtree — Restore (unlock, needs the password) + Export. */ - private archiveLockedRow(container: HTMLElement, e: { blob: string; title?: string; count?: number; created?: string }): void { + private archiveLockedRow(container: HTMLElement, e: LockedEntry): void { const row = container.createDiv({ cls: "stashpad-trash-row" }); const main = row.createDiv({ cls: "stashpad-trash-row-main" }); main.createSpan({ cls: "stashpad-trash-title", text: e.title || "Locked note" }); @@ -278,6 +319,42 @@ export class StashpadAggregateView extends ItemView { exp.onclick = () => void this.plugin.exportLockedSubtree(e.blob); const lock = row.createSpan({ cls: "stashpad-aggregate-lockbadge" }); setIcon(lock, "lock"); + this.attachLockedRowMenu(row, e, { archived: true }); + } + + /** Attach a ⋯ button + right-click menu to a locked-bundle row. Delegates to + * the shared `populateLockedMenu` builder (locked-menu.ts) — same source of + * truth as the folder-view locked menu. `fullParity: false` gives the trimmed + * aggregate item set; archived rows unlock-and-restore to the archive parent. */ + private attachLockedRowMenu(row: HTMLElement, e: LockedEntry, opts: { archived: boolean }): void { + const buildMenu = (): Menu => { + const menu = new Menu(); + populateLockedMenu(menu, { + app: this.app, + plugin: this.plugin, + descriptor: { blob: e.blob, rootId: e.rootId, count: e.count ?? 1, folder: this.cleanFolder(e.folder) }, + unlockLabel: opts.archived ? "Unlock & restore" : "Decrypt (unlock)", + onUnlock: async () => { + let dest: string | undefined; + if (opts.archived) { + const segs = e.blob.split("/"); + const archIdx = segs.lastIndexOf("archive"); + dest = archIdx > 0 ? segs.slice(0, archIdx).join("/") : undefined; + } + const ok = await this.plugin.unlockBundleAt(e.blob, dest ? { destFolder: dest } : {}); + if (ok) void this.render(); + }, + onChange: () => void this.render(), + fullParity: false, + confirmDelete: false, + }); + return menu; + }; + row.oncontextmenu = (evt: MouseEvent) => { evt.preventDefault(); buildMenu().showAtMouseEvent(evt); }; + const more = row.createEl("button", { cls: "stashpad-trash-iconbtn stashpad-agg-more" }); + setIcon(more, "ellipsis-vertical"); + more.setAttr("aria-label", "More actions"); + more.onclick = (evt) => { evt.stopPropagation(); buildMenu().showAtMouseEvent(evt as MouseEvent); }; } /** 0.138.0 "Previously encrypted": subtrees that WERE encrypted and are now diff --git a/src/locked-menu.ts b/src/locked-menu.ts new file mode 100644 index 0000000..e35ea7d --- /dev/null +++ b/src/locked-menu.ts @@ -0,0 +1,195 @@ +import { App, Menu, Notice, Platform } from "obsidian"; +import type StashpadPlugin from "./main"; +import { buildStashpadLink } from "./deep-link"; +import { ConfirmModal } from "./modals"; + +/** Normalised descriptor for a locked (`.stashenc`) bundle, shared by every + * locked-menu site (the folder-view `openLockedMenu` and the two aggregate + * locked-row menus). Collapses the old `lk` / `LockedEntry` shapes. */ +export interface LockedDescriptor { + blob: string; + rootId?: string | null; + count: number; + /** Folder used for the deep-link target AND for undo-stack ownership. */ + folder: string; +} + +/** Delete a locked bundle — the `.stashenc` ciphertext + its `.stashmeta` + * sidecar — to Obsidian's trash, recoverable via the folder's undo stack. + * Single source of truth for all three locked-menu sites (was triplicated). + * + * Captures the bytes + sidecar + registry entry BEFORE removing anything so + * undo can fully restore. `onChange` repaints the caller's view. */ +export async function deleteLockedBundleWithUndo( + app: App, + plugin: StashpadPlugin, + d: LockedDescriptor, + onChange: () => void, +): Promise<void> { + const blobPath = d.blob; + const metaPath = blobPath.replace(/\.stashenc$/, ".stashmeta"); + const adapter = app.vault.adapter; + let blobData: ArrayBuffer | null = null; + let metaData: string | null = null; + try { blobData = await adapter.readBinary(blobPath); } catch { blobData = null; } + if (!blobData) { new Notice("Couldn't read the encrypted file to delete it."); return; } + try { if (await adapter.exists(metaPath)) metaData = await adapter.read(metaPath); } catch { metaData = null; } + const prevEntry = (plugin.settings.lockedSubtrees ?? []).find((x) => x.blob === blobPath) ?? null; + + // Trash both files: Obsidian trash when the TFile is indexed (recoverable + // there), adapter.remove as a fallback when the index lags. Contents are + // captured above, so the undo entry can restore either way. + const trashByPath = async (path: string): Promise<void> => { + const tf = app.vault.getAbstractFileByPath(path); + if (tf) { try { await app.fileManager.trashFile(tf); return; } catch { /* fall through */ } } + try { if (await adapter.exists(path)) await adapter.remove(path); } catch { /* non-fatal */ } + }; + const doDelete = async (): Promise<void> => { + await trashByPath(blobPath); + await trashByPath(metaPath); + plugin.settings.lockedSubtrees = (plugin.settings.lockedSubtrees ?? []).filter((x) => x.blob !== blobPath); + await plugin.saveSettings(); + onChange(); + }; + const doRestore = async (): Promise<void> => { + await adapter.writeBinary(blobPath, blobData!); + if (metaData != null) { try { await adapter.write(metaPath, metaData); } catch { /* non-fatal */ } } + if (prevEntry && !(plugin.settings.lockedSubtrees ?? []).some((x) => x.blob === blobPath)) { + plugin.settings.lockedSubtrees = [...(plugin.settings.lockedSubtrees ?? []), prevEntry]; + await plugin.saveSettings(); + } + onChange(); + }; + + await doDelete(); + plugin.getUndoStack(d.folder).push({ + label: d.count > 1 ? "Delete encrypted notes" : "Delete encrypted note", + undo: doRestore, + redo: doDelete, + }); + new Notice(d.count > 1 ? "Encrypted notes deleted — undo to restore." : "Encrypted note deleted — undo to restore."); +} + +export interface LockedMenuConfig { + app: App; + plugin: StashpadPlugin; + descriptor: LockedDescriptor; + /** Unlock item label — "Decrypt (unlock)" (in place) or "Unlock & restore". */ + unlockLabel: string; + /** What the unlock item does (in-place decrypt vs restore-to-parent). */ + onUnlock: () => void; + /** Repaint after a delete / change. */ + onChange: () => void; + /** Folder view (true) renders the full openNoteMenu-parity item set including + * the "unlock first" notice mirrors; the aggregate rows (false) render the + * trimmed set. This flag selects between the two exact layouts. */ + fullParity: boolean; + /** Folder view confirms before delete; aggregate relies on undo. */ + confirmDelete: boolean; +} + +/** Populate `menu` with the locked-bundle action set. The single builder behind + * `openLockedMenu` (view.ts) and `attachLockedRowMenu` (aggregate-view.ts). + * Copy-link + exports are always grouped under a "Share & export ▸" submenu. */ +export function populateLockedMenu(menu: Menu, cfg: LockedMenuConfig): void { + const { app, plugin, descriptor: d } = cfg; + const unlockFirst = (verb: string): Notice => new Notice(`Unlock this note first to ${verb}.`); + const fullPathOf = (p: string): string => { + if (Platform.isMobile) return p; + try { return (app.vault.adapter as unknown as { getFullPath?: (x: string) => string })?.getFullPath?.(p) || p; } catch { return p; } + }; + const copyLink = (): void => { + const link = buildStashpadLink({ vault: app.vault.getName(), folder: d.folder, note: d.rootId!, run: ["reveal"] }); + void navigator.clipboard.writeText(link).then(() => new Notice("Stashpad link copied."), () => new Notice("Couldn't copy the link.")); + }; + + // Shared item factories ----------------------------------------------------- + const addShareSubmenu = (): void => { + menu.addItem((i: any) => { + i.setTitle("Share & export").setIcon("share-2"); + const sub = typeof i.setSubmenu === "function" ? i.setSubmenu() : null; + if (sub && typeof sub.addItem === "function") { + sub.addItem((s: any) => { s.setTitle("Copy Stashpad link").setIcon("link"); if (d.rootId) s.onClick(() => copyLink()); else s.setDisabled(true); }); + sub.addItem((s: any) => s.setTitle("Export to .stash…").setIcon("package").onClick(() => { void plugin.exportLockedSubtree(d.blob); })); + if (plugin.settings.okfEnabled) sub.addItem((s: any) => s.setTitle("Export as OKF…").setIcon("book-marked").onClick(() => unlockFirst("export it as OKF"))); + } else if (d.rootId) { + i.onClick(() => copyLink()); // degraded (no setSubmenu — never on the 1.13 floor) + } else { + i.setDisabled(true); + } + }); + }; + const addUnlock = (): void => { menu.addItem((i: any) => i.setTitle(cfg.unlockLabel).setIcon("unlock").onClick(() => cfg.onUnlock())); }; + const addShowInFinder = (): void => { + if (Platform.isMobile) return; + const osManager = Platform.isMacOS ? "Finder" : Platform.isWin ? "File Explorer" : "file manager"; + menu.addItem((i: any) => i.setTitle(`Show in ${osManager}`).setIcon("folder-search").onClick(() => { + try { + const shell = (window as unknown as { require?: (m: string) => { shell?: { showItemInFolder?: (p: string) => void } } }).require?.("electron")?.shell; + const fullPath = (app.vault.adapter as unknown as { getFullPath?: (x: string) => string })?.getFullPath?.(d.blob); + if (fullPath && shell?.showItemInFolder) shell.showItemInFolder(fullPath); + } catch (err) { console.warn("[Stashpad] showItemInFolder failed", err); } + })); + }; + const addCopyPath = (): void => { + menu.addItem((i: any) => i.setTitle("Copy encrypted file path").setIcon("copy").onClick(() => { + void navigator.clipboard.writeText(fullPathOf(d.blob)); + new Notice("Path copied."); + })); + }; + const addDelete = (): void => { + menu.addItem((i: any) => { + i.setTitle(d.count > 1 ? "Delete encrypted notes…" : "Delete encrypted note…").setIcon("trash-2"); + i.setWarning?.(true); + i.onClick(() => { + if (cfg.confirmDelete) { + new ConfirmModal( + app, + d.count > 1 ? `Delete ${d.count} encrypted notes?` : "Delete encrypted note?", + "The encrypted file moves to Obsidian's trash (recoverable there). You'll still need your password to read it if you restore it.", + "Delete", + async (ok: boolean) => { if (ok) await deleteLockedBundleWithUndo(app, plugin, d, cfg.onChange); }, + ).open(); + } else { + void deleteLockedBundleWithUndo(app, plugin, d, cfg.onChange); + } + }); + }); + }; + + // Two exact layouts --------------------------------------------------------- + if (cfg.fullParity) { + // Folder-view locked row: full openNoteMenu parity. Actions that need the + // decrypted note show an "unlock first" notice; the rest act on ciphertext. + menu.addItem((i: any) => i.setTitle("Open in new Stashpad tab").setIcon("layout-grid").onClick(() => unlockFirst("open it in a tab"))); + menu.addItem((i: any) => i.setTitle("Open in editor").setIcon("file-text").onClick(() => unlockFirst("open it in the editor"))); + menu.addItem((i: any) => i.setTitle("Focus in Stashpad").setIcon("arrow-right").onClick(() => unlockFirst("focus it"))); + menu.addSeparator(); + menu.addItem((i: any) => i.setTitle("Split note…").setIcon("split").onClick(() => unlockFirst("split it"))); + menu.addItem((i: any) => i.setTitle("Copy text").setIcon("copy").onClick(() => unlockFirst("copy its text"))); + menu.addItem((i: any) => i.setTitle("Clone (duplicate / copy)").setIcon("files").onClick(() => unlockFirst("clone it"))); + menu.addItem((i: any) => i.setTitle("Fork into a separate note…").setIcon("git-branch").onClick(() => unlockFirst("fork it"))); + addShareSubmenu(); + addUnlock(); + addShowInFinder(); + addCopyPath(); + menu.addSeparator(); + menu.addItem((i: any) => i.setTitle("Move to…").setIcon("move").onClick(() => unlockFirst("move it"))); + menu.addItem((i: any) => i.setTitle("Move to Home").setIcon("home").onClick(() => unlockFirst("move it"))); + menu.addItem((i: any) => i.setTitle("Pin to sidebar").setIcon("pin").onClick(() => unlockFirst("pin it"))); + menu.addItem((i: any) => i.setTitle("Pin to top of list").setIcon("arrow-up-to-line").onClick(() => unlockFirst("pin it"))); + menu.addItem((i: any) => i.setTitle("Set color…").setIcon("palette").onClick(() => unlockFirst("set its color"))); + menu.addItem((i: any) => i.setTitle("Task").setIcon("check-circle-2").onClick(() => unlockFirst("change its task state"))); + menu.addSeparator(); + addDelete(); + } else { + // Aggregate locked row: trimmed set. + addUnlock(); + addShareSubmenu(); + menu.addSeparator(); + addShowInFinder(); + addCopyPath(); + menu.addSeparator(); + addDelete(); + } +} diff --git a/src/main.ts b/src/main.ts index 884d265..6be1172 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1260,6 +1260,11 @@ export default class StashpadPlugin extends Plugin { name: "Encrypt (lock) selection (notes + children)", callback: () => call("cmdLockSelection"), }); + this.addCommand({ + id: "stashpad-lock-selection-hide-name", + name: "Encrypt (lock) selection + hide filename (override folder setting)", + callback: () => call("cmdLockSelectionHideName"), + }); this.addCommand({ id: "stashpad-unlock-all", name: "Decrypt (unlock) locked notes in view", @@ -3738,7 +3743,7 @@ export default class StashpadPlugin extends Plugin { }).open(); } - async lockNoteSubtree(folder: string, rootId: StashpadId, prevSibling: StashpadId | null = null, opts: { silent?: boolean; blobFolder?: string } = {}): Promise<LockResult | null> { + async lockNoteSubtree(folder: string, rootId: StashpadId, prevSibling: StashpadId | null = null, opts: { silent?: boolean; blobFolder?: string; hideTitle?: boolean } = {}): Promise<LockResult | null> { // Encrypt under the key of the folder the BLOB will live in (archive moves put // the blob in opts.blobFolder, not the source folder), so opening that folder // later decrypts it. Falls back to the vault DEK when the folder has no own key. @@ -3751,7 +3756,8 @@ export default class StashpadPlugin extends Plugin { // else its live-notes pref — falling back to the global hide-titles setting. const isArchiveLock = !!opts.blobFolder && opts.blobFolder.replace(/\/+$/, "") !== folder.replace(/\/+$/, ""); const fp = (this.settings.folderEncPrefs ?? {})[keyFolder] ?? {}; - const hideTitle = (isArchiveLock ? fp.archiveEncryptFilenames : fp.encryptFilenames) ?? false; // 0.137.1: per-folder only + // A per-note override (the "hide filename" command) wins over the folder pref. + const hideTitle = opts.hideTitle ?? ((isArchiveLock ? fp.archiveEncryptFilenames : fp.encryptFilenames) ?? false); // 0.137.1: per-folder only const r = await lockSubtree(this.app, folder, rootId, dek, prevSibling, hideTitle, opts.blobFolder); this.pendingEncBlobs.add(r.blobPath); // fast-state index: cover the pre-vault-index window // Record a placeholder registry entry so the list shows a 🔒 stub where @@ -5251,15 +5257,16 @@ export default class StashpadPlugin extends Plugin { /** Handle an `obsidian://stashpad?…` deep link. Resolve → activate → reveal → * run macro. Any unresolved target is a LOUD failure (Notice), never a silent * no-op. See `docs/deep-links-plan.md`. */ - async handleDeepLink(params: { folder?: string; note?: string; run?: string; action?: string; vault?: string }): Promise<void> { + async handleDeepLink(params: { folder?: string; note?: string; run?: string; action?: string; vault?: string }, opts: { forceNewTab?: boolean } = {}): Promise<boolean> { const folder = (params.folder || "").replace(/^\/+|\/+$/g, ""); const noteId = (params.note || "").trim(); const actions = parseRunActions(params); - // 1. Guard + resolve. - if (!folder) { new Notice("Stashpad link: missing “folder”."); return; } + // 1. Guard + resolve. Returns false (not thrown) on a bad link so a batch + // caller can tally how many actually opened. + if (!folder) { new Notice("Stashpad link: missing “folder”."); return false; } const dir = this.app.vault.getAbstractFileByPath(folder); - if (!(dir instanceof TFolder)) { new Notice(`Stashpad link: folder “${folder}” not found.`); return; } + if (!(dir instanceof TFolder)) { new Notice(`Stashpad link: folder “${folder}” not found.`); return false; } // 2. Wait for the workspace to settle. On a cross-vault jump Obsidian may // still be laying out when the handler fires, so activate/reveal would find @@ -5277,13 +5284,14 @@ export default class StashpadPlugin extends Plugin { file = this.resolveNoteFileInFolder(folder, noteId); if (!file) await new Promise((r) => window.setTimeout(r, 150)); } - if (!file) { new Notice(`Stashpad link: note “${noteId}” not found in ${folder}.`); return; } + if (!file) { new Notice(`Stashpad link: note “${noteId}” not found in ${folder}.`); return false; } } // 3. Open the target WITHOUT hijacking the current tab. A deep link should // land in its own tab (focusing an existing background tab on that folder // if there is one), never overwrite whatever the user is currently viewing. - await this.openDeepLinkTarget(folder, noteId); + // `forceNewTab` (batch/multi-link) always opens a fresh tab per link. + await this.openDeepLinkTarget(folder, noteId, opts); // 4. Run the macro, in order. `reveal` is already satisfied by step 3. // Unknown tokens are skipped with a warning — one bad token never aborts. @@ -5295,6 +5303,7 @@ export default class StashpadPlugin extends Plugin { } console.warn(`[stashpad] deep link: unknown action “${token}” — skipped.`); } + return true; } /** Open a deep-link target without hijacking the currently-active tab. @@ -5302,17 +5311,22 @@ export default class StashpadPlugin extends Plugin { * one included), a deep link should never overwrite what the user is looking * at: focus an existing BACKGROUND tab on that folder if there is one, else * open a brand-new tab. `noteId` is optional (folder-only links). */ - async openDeepLinkTarget(folder: string, noteId: string): Promise<void> { + async openDeepLinkTarget(folder: string, noteId: string, opts: { forceNewTab?: boolean } = {}): Promise<void> { const clean = folder.replace(/\/+$/, ""); - const active = this.app.workspace.activeLeaf; - const existing = await this.findStashpadLeafForFolder(clean); - // Reuse an existing tab only if it isn't the one currently in front — - // reusing the active leaf is exactly the "opens inside it" overwrite. - if (existing && existing !== active) { - this.app.workspace.revealLeaf(existing); - this.app.workspace.setActiveLeaf(existing, { focus: true }); - if (noteId) this.navigateLeafTo(existing, clean, noteId); - return; + // 0.155.3: `forceNewTab` skips the reuse-existing-tab path so a BATCH of + // links (multi-link paste) opens each in its own tab — even several links + // into the same folder, which would otherwise collapse onto one reused tab. + if (!opts.forceNewTab) { + const active = this.app.workspace.activeLeaf; + const existing = await this.findStashpadLeafForFolder(clean); + // Reuse an existing tab only if it isn't the one currently in front — + // reusing the active leaf is exactly the "opens inside it" overwrite. + if (existing && existing !== active) { + this.app.workspace.revealLeaf(existing); + this.app.workspace.setActiveLeaf(existing, { focus: true }); + if (noteId) this.navigateLeafTo(existing, clean, noteId); + return; + } } const leaf = await this.activateViewForFolder(clean); // getLeaf("tab") → new tab if (noteId) this.navigateLeafTo(leaf, clean, noteId); @@ -5324,9 +5338,24 @@ export default class StashpadPlugin extends Plugin { * are shared. */ openDeepLinkModal(): void { new OpenDeepLinkModal(this.app, (raw) => { - const parsed = parseStashpadLink(raw); - if (!parsed) { new Notice("That doesn't look like a Stashpad link."); return; } - void this.handleDeepLink(parsed); + // 0.155.3: accept a MULTI-link paste (e.g. from a multi-select "Copy + // Stashpad link"). Links are whitespace/newline-separated and never + // contain literal spaces (URLs are percent-encoded), so split on \s+. + const candidates = raw.split(/\s+/).map((s) => s.trim()).filter(Boolean); + const parsed = candidates + .map((c) => parseStashpadLink(c)) + .filter((p): p is NonNullable<typeof p> => !!p); + if (parsed.length === 0) { new Notice("That doesn't look like a Stashpad link."); return; } + if (parsed.length === 1) { void this.handleDeepLink(parsed[0]); return; } + // Multiple → open each in its OWN new tab, then report the tally. + void (async () => { + let opened = 0; + for (const p of parsed) { if (await this.handleDeepLink(p, { forceNewTab: true })) opened++; } + const failed = parsed.length - opened; + new Notice(failed === 0 + ? `Opened ${opened} Stashpad links in new tabs.` + : `Opened ${opened} of ${parsed.length} Stashpad links (${failed} couldn't be found).`); + })(); }).open(); } diff --git a/src/modals.ts b/src/modals.ts index 2568f0b..0ac3b13 100644 --- a/src/modals.ts +++ b/src/modals.ts @@ -38,6 +38,12 @@ export interface DuePickerOptions { quickAdjusts?: string[]; } +/** 0.155.0: fallback quick-adjust presets. Mirrors DEFAULT_SETTINGS.dueQuickAdjusts. + * Used when a caller passes no `quickAdjusts` so the +/- row shows from EVERY + * entry point (the row used to silently vanish when a call site — e.g. Assign — + * forgot to pass the option). A caller can still explicitly pass `[]` to hide it. */ +export const DEFAULT_QUICK_ADJUSTS = ["5m", "15m", "30m", "1h", "1d", "1w"]; + /** 0.125.1: parse a compact duration token ("5m", "15m", "1h", "2d", "1w") into * minutes. Returns null when unparseable so callers can skip bad presets. */ export function parseAdjustMinutes(raw: string): number | null { @@ -1206,18 +1212,19 @@ export class OpenDeepLinkModal extends Modal { this.contentEl.empty(); this.modalEl.addClass("stashpad-export-modal"); this.titleEl.setText("Open Stashpad link"); - this.contentEl.createEl("p", { cls: "stashpad-export-desc", text: "Paste an obsidian://stashpad link to jump to the note it points to." }); + this.contentEl.createEl("p", { cls: "stashpad-export-desc", text: "Paste one or more obsidian://stashpad links (one per line) to jump to the notes they point to. Multiple links each open in their own tab." }); // Input + an explicit Paste button on one row. The button matters on mobile // (and anywhere clipboard auto-read is blocked) where the auto-prefill below - // can't run — one tap fills the field. + // can't run — one tap fills the field. 0.155.3: a textarea (not a single-line + // input) so a multi-link paste keeps its newlines. const row = this.contentEl.createDiv({ cls: "stashpad-open-link-row" }); // Paste on the LEFT, input fills the rest of the row. const pasteBtn = row.createEl("button", { cls: "stashpad-open-link-paste" }); setIcon(pasteBtn.createSpan({ cls: "stashpad-open-link-paste-icon" }), "clipboard-paste"); pasteBtn.createSpan({ text: "Paste" }); pasteBtn.title = "Paste from clipboard"; - const input = row.createEl("input", { type: "text" }); + const input = row.createEl("textarea", { attr: { rows: "3" } }); input.addClass("stashpad-export-name"); input.placeholder = "obsidian://stashpad?folder=…¬e=…"; pasteBtn.onclick = async () => { @@ -1783,7 +1790,7 @@ export class DueDatePickerModal extends Modal { // configured preset. Clicking nudges the entered date+time by ±amount; if no // date/time is entered yet, it bases off "now" so a single tap schedules // e.g. "+1h from now". Reschedule-friendly for Snooze. - const adjusts = (this.opts.quickAdjusts ?? []) + const adjusts = (this.opts.quickAdjusts ?? DEFAULT_QUICK_ADJUSTS) .map((s) => ({ raw: s, min: parseAdjustMinutes(s) })) .filter((a): a is { raw: string; min: number } => a.min != null); if (adjusts.length > 0) { diff --git a/src/note-picker.ts b/src/note-picker.ts index 33086c5..857bf07 100644 --- a/src/note-picker.ts +++ b/src/note-picker.ts @@ -519,43 +519,78 @@ export class StashpadSuggest extends SuggestModal<PickerItem> { locked: n.locked, }); + // 0.155.0: relevance + recency ranking. Sift alone is a boolean filter (see + // docs/sift.md) — matches used to render in raw tree order, so an exact-phrase + // title hit could sit below shallower token hits, and nothing was ordered by + // last-edited. Now each match gets a relevance BAND (exact title > title + // prefix > phrase-in-title > all-tokens-in-title > phrase-in-body > + // token-in-body) and, within a band, sorts by mtime desc. An EMPTY query + // sorts purely by most-recently-edited. In pick mode (the Move / destination + // picker) each folder's HOME note gets a small boost so it floats to the top + // of its results — homes are the common "move here" target. + const mtimeFor = (n: NoteBody): number => + n.node?.file?.stat?.mtime ?? n.cross?.file?.stat?.mtime ?? 0; + const isHome = (n: NoteBody): boolean => n.node?.id === ROOT_ID || n.cross?.id === ROOT_ID; + const pinHomes = this.opts.mode === "pick"; + const relevanceBand = (n: NoteBody): number => { + let band: number; + if (!q) { + band = 0; // empty query → recency only + } else { + const t = n.title.toLowerCase(); + const b = n.body.toLowerCase(); + if (t === q) band = 6; + else if (t.startsWith(q)) band = 5; + else if (t.includes(q)) band = 4; // exact phrase in title + else if (tokens.every((x) => t.includes(x))) band = 3; // all tokens in title + else if (b.includes(q)) band = 2; // exact phrase in body + else band = 1; // token(s) in body only + } + if (pinHomes && isHome(n)) band += 0.5; // destination picker: float homes up + return band; + }; + const matchTier = (tier: NoteBody[]): PickerItem[] => { - const out: PickerItem[] = []; + // 1. Collect the notes that match (+ their per-line clusters for search). + const matched: { n: NoteBody; matchLines: number[] }[] = []; for (const n of tier) { // 0.64.0: structured filters always apply, even when there's no // free text — `in:work` alone should narrow to that folder. if (!passesFilters(n)) continue; if (this.opts.mode === "search") { - if (!q) { out.push(buildItem(n, -1)); continue; } + if (!q) { matched.push({ n, matchLines: [] }); continue; } const titleHit = matchesAll(n.title.toLowerCase()); const lines = n.body.split(/\r?\n/); - // 0.69.12: collect ALL per-line matches, then cluster nearby - // matches together (within 5 lines) and emit one PickerItem - // per cluster — so a long note with multiple distinct - // matches surfaces each as its own result with surrounding - // context. Capped at 5 cluster rows per note to avoid spam. + // 0.69.12: collect ALL per-line matches; clustered into rows below. const matchLines: number[] = []; for (let i = 0; i < lines.length; i++) { if (lineMatchesAll(lines[i])) matchLines.push(i); } const bodyHit = matchLines.length > 0 || matchesAll(n.body.toLowerCase()); if (!titleHit && !bodyHit) continue; - if (matchLines.length === 0) { - // Title-only / body-anywhere hit — no per-line preview. - out.push(buildItem(n, -1)); - } else { - const clusterHeads: number[] = []; - let last = -100; - for (const ln of matchLines) { - if (ln - last > 5) clusterHeads.push(ln); - last = ln; - } - const CAP = 5; - for (const ml of clusterHeads.slice(0, CAP)) out.push(buildItem(n, ml)); - } + matched.push({ n, matchLines }); } else { // pick mode — tokens must all appear in title OR body. if (q && !matchesAll(n.title.toLowerCase()) && !matchesAll(n.body.toLowerCase())) continue; + matched.push({ n, matchLines: [] }); + } + } + // 2. Rank: relevance band desc, then most-recently-edited. Precompute the + // keys (band does substring work) so the comparator stays cheap. Array + // sort is stable, so same-band/same-mtime ties keep tree order. + const scored = matched.map((m) => ({ ...m, band: relevanceBand(m.n), mtime: mtimeFor(m.n) })); + scored.sort((a, b) => (b.band - a.band) || (b.mtime - a.mtime)); + // 3. Emit rows — one per note (title/body hit) or one per match cluster + // (search mode, capped at 5) so a long note surfaces each hit in context. + const out: PickerItem[] = []; + for (const { n, matchLines } of scored) { + if (this.opts.mode === "search" && q && matchLines.length > 0) { + const clusterHeads: number[] = []; + let last = -100; + for (const ln of matchLines) { if (ln - last > 5) clusterHeads.push(ln); last = ln; } + const CAP = 5; + for (const ml of clusterHeads.slice(0, CAP)) out.push(buildItem(n, ml)); + } else { out.push(buildItem(n, -1)); } } diff --git a/src/view.ts b/src/view.ts index 27da607..48b6368 100644 --- a/src/view.ts +++ b/src/view.ts @@ -23,6 +23,7 @@ import { IntegrityWatcher } from "./integrity-watcher"; import { getSettings, getTemplatesFormats, onSettingsChange } from "./settings"; import { StashpadSuggest } from "./note-picker"; import { buildStashpadLink } from "./deep-link"; +import { populateLockedMenu } from "./locked-menu"; import { StashpadCommandPalette } from "./command-palette"; import { setActiveView, clearActiveView } from "./active-view"; import { BreadcrumbLevelsModal, type BreadcrumbLevel, ColorPickerModal, ConfirmDeleteModal, ConfirmModal, DueDatePickerModal, SplitNoteModal } from "./modals"; @@ -1938,135 +1939,21 @@ export class StashpadView extends ItemView { // note menu (openNoteMenu) can't serve them; this is their own small menu. const openLockedMenu = (e: MouseEvent) => { e.preventDefault(); e.stopPropagation(); + // 0.155.0: locked rows present the SAME menu as normal notes (agreed + // design). Built by the shared `populateLockedMenu` builder (locked-menu.ts) + // — one source of truth for this menu + the two aggregate-view locked-row + // menus. `fullParity` renders the full openNoteMenu-mirroring item set + // (actions needing the decrypted note show an "unlock first" notice). const menu = new Menu(); - // 0.152.0: locked rows present the SAME menu as normal notes (agreed - // design). Actions that need the DECRYPTED note show an "unlock first" - // notice instead of doing nothing; the rest act on the ciphertext bundle - // directly. Items mirror openNoteMenu; kept a flat verbatim copy for now — - // DRY-ing into a shared builder is a later cleanup. - const unlockFirst = (verb: string) => new Notice(`Unlock this note first to ${verb}.`); - menu.addItem((i: any) => i.setTitle("Open in new Stashpad tab").setIcon("layout-grid").onClick(() => unlockFirst("open it in a tab"))); - menu.addItem((i: any) => i.setTitle("Open in editor").setIcon("file-text").onClick(() => unlockFirst("open it in the editor"))); - menu.addItem((i: any) => i.setTitle("Focus in Stashpad").setIcon("arrow-right").onClick(() => unlockFirst("focus it"))); - // Copy deep link works without decrypting (the id is known); greyed when - // this bundle has no recorded rootId. - menu.addItem((i: any) => { - i.setTitle("Copy Stashpad link").setIcon("link"); - if (lk.rootId) { - i.onClick(() => { - const link = buildStashpadLink({ vault: this.app.vault.getName(), folder: this.noteFolder, note: lk.rootId!, run: ["reveal"] }); - void navigator.clipboard.writeText(link).then(() => new Notice("Stashpad link copied."), () => new Notice("Couldn't copy the link.")); - }); - } else { - i.setDisabled(true); - } - }); - menu.addSeparator(); - menu.addItem((i: any) => i.setTitle("Split note…").setIcon("split").onClick(() => unlockFirst("split it"))); - menu.addItem((i: any) => i.setTitle("Copy text").setIcon("copy").onClick(() => unlockFirst("copy its text"))); - menu.addItem((i: any) => i.setTitle("Clone (duplicate / copy)").setIcon("files").onClick(() => unlockFirst("clone it"))); - menu.addItem((i: any) => i.setTitle("Fork into a separate note…").setIcon("git-branch").onClick(() => unlockFirst("fork it"))); - // Export the ENCRYPTED bundle as-is — no decryption needed. - menu.addItem((i: any) => i.setTitle("Export to .stash…").setIcon("package").onClick(() => { void this.plugin.exportLockedSubtree(lk.blob); })); - if (this.plugin.settings.okfEnabled) { - menu.addItem((i: any) => i.setTitle("Export as OKF…").setIcon("book-marked").onClick(() => unlockFirst("export it as OKF"))); - } - // Decrypt (in place of the normal menu's "Encrypt" — this is already locked). - menu.addItem((i: any) => i.setTitle("Decrypt (unlock)").setIcon("unlock").onClick(() => void doUnlock(e))); - if (!Platform.isMobile) { - const osManager = Platform.isMacOS ? "Finder" : Platform.isWin ? "File Explorer" : "file manager"; - menu.addItem((i: any) => i.setTitle(`Show in ${osManager}`).setIcon("folder-search").onClick(() => { - try { - const shell = (window as any).require?.("electron")?.shell; - const fullPath = (this.app.vault.adapter as any)?.getFullPath?.(lk.blob); - if (fullPath && shell?.showItemInFolder) shell.showItemInFolder(fullPath); - } catch (err) { console.warn("[Stashpad] showItemInFolder failed", err); } - })); - } - menu.addItem((i: any) => i.setTitle("Copy encrypted file path").setIcon("copy").onClick(() => { - // 0.98.32: full absolute path on desktop (pasteable into Finder/Explorer); - // mobile has no usable filesystem path, so fall back to the vault-relative one. - let path = lk.blob; - if (!Platform.isMobile) { - try { path = (this.app.vault.adapter as any)?.getFullPath?.(lk.blob) || lk.blob; } catch { /* keep relative */ } - } - void navigator.clipboard.writeText(path); - new Notice("Path copied."); - })); - menu.addSeparator(); - menu.addItem((i: any) => i.setTitle("Move to…").setIcon("move").onClick(() => unlockFirst("move it"))); - menu.addItem((i: any) => i.setTitle("Move to Home").setIcon("home").onClick(() => unlockFirst("move it"))); - menu.addItem((i: any) => i.setTitle("Pin to sidebar").setIcon("pin").onClick(() => unlockFirst("pin it"))); - menu.addItem((i: any) => i.setTitle("Pin to top of list").setIcon("arrow-up-to-line").onClick(() => unlockFirst("pin it"))); - menu.addItem((i: any) => i.setTitle("Set color…").setIcon("palette").onClick(() => unlockFirst("set its color"))); - menu.addItem((i: any) => i.setTitle("Task").setIcon("check-circle-2").onClick(() => unlockFirst("change its task state"))); - // Delete the encrypted bundle. Removing the ciphertext needs no password; - // routed through Obsidian's trash so it's recoverable (the password is - // still required to READ it if restored). Confirm first — it may hold - // several notes. - menu.addItem((i: any) => { - i.setTitle(lk.count > 1 ? "Delete encrypted notes…" : "Delete encrypted note…").setIcon("trash-2"); - i.setWarning?.(true); - i.onClick(() => { - new ConfirmModal( - this.app, - lk.count > 1 ? `Delete ${lk.count} encrypted notes?` : "Delete encrypted note?", - "The encrypted file moves to Obsidian's trash (recoverable there). You'll still need your password to read it if you restore it.", - "Delete", - async (ok: boolean) => { - if (!ok) return; - const blobPath = lk.blob; - const metaPath = blobPath.replace(/\.stashenc$/, ".stashmeta"); - const adapter = this.app.vault.adapter; - // Capture everything needed to restore BEFORE removing anything: - // the ciphertext bytes, the sidecar JSON, and the registry entry. - let blobData: ArrayBuffer | null = null; - let metaData: string | null = null; - try { blobData = await adapter.readBinary(blobPath); } catch { blobData = null; } - if (!blobData) { new Notice("Couldn't read the encrypted file to delete it."); return; } - try { if (await adapter.exists(metaPath)) metaData = await adapter.read(metaPath); } catch { metaData = null; } - const prevEntry = (this.plugin.settings.lockedSubtrees ?? []).find((x) => x.blob === blobPath) ?? null; - - // Trash both files (Obsidian trash when the TFile is indexed — - // recoverable there; adapter.remove as a fallback when the index - // lags, e.g. right after a redo-restore). Contents are captured - // above, so the undo entry can restore either way. - const removeBoth = async (): Promise<boolean> => { - const trashByPath = async (path: string) => { - const tf = this.app.vault.getAbstractFileByPath(path); - if (tf) { try { await this.app.fileManager.trashFile(tf); return; } catch { /* fall through */ } } - try { if (await adapter.exists(path)) await adapter.remove(path); } catch { /* non-fatal */ } - }; - await trashByPath(blobPath); - await trashByPath(metaPath); - return true; - }; - const doDelete = async () => { - await removeBoth(); - this.plugin.settings.lockedSubtrees = (this.plugin.settings.lockedSubtrees ?? []).filter((x) => x.blob !== blobPath); - await this.plugin.saveSettings(); - this.render(); - }; - const doRestore = async () => { - await adapter.writeBinary(blobPath, blobData!); - if (metaData != null) { try { await adapter.write(metaPath, metaData); } catch { /* non-fatal */ } } - if (prevEntry && !(this.plugin.settings.lockedSubtrees ?? []).some((x) => x.blob === blobPath)) { - this.plugin.settings.lockedSubtrees = [...(this.plugin.settings.lockedSubtrees ?? []), prevEntry]; - await this.plugin.saveSettings(); - } - this.render(); - }; - - await doDelete(); - this.plugin.getUndoStack(this.noteFolder).push({ - label: lk.count > 1 ? "Delete encrypted notes" : "Delete encrypted note", - undo: doRestore, - redo: doDelete, - }); - new Notice(lk.count > 1 ? "Encrypted notes deleted — undo to restore." : "Encrypted note deleted — undo to restore."); - }, - ).open(); - }); + populateLockedMenu(menu, { + app: this.app, + plugin: this.plugin, + descriptor: { blob: lk.blob, rootId: lk.rootId, count: lk.count, folder: this.noteFolder }, + unlockLabel: "Decrypt (unlock)", + onUnlock: () => void doUnlock(e), + onChange: () => this.render(), + fullParity: true, + confirmDelete: true, }); menu.showAtMouseEvent(e); }; @@ -3441,6 +3328,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())); + // 0.155.1: Share & export ▸ — same submenu as the desktop context menu (the + // ⚡ menu previously had no copy-link/export). Copy-link targets the primary + // selected note; exports act on the whole selection. + this.addShareExportSubmenu(menu, this.getActionTargets()[0] ?? null, { normalizeToNode: false }); if (this.plugin.settings.enableSheetVersions) { menu.addItem((it: any) => it.setTitle("Fork as a version (draft)").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())); @@ -6828,7 +6719,11 @@ export class StashpadView extends ItemView { * keybind counterpart of the context-menu "Encrypt (lock) note + children". * If a parent AND one of its descendants are both selected, only the parent * is locked (its subtree already subsumes the descendant). */ - async cmdLockSelection(): Promise<void> { + /** Lock (encrypt) the selection AND hide each note's filename, regardless of + * the folder's encrypt-filenames pref. Backs the "hide filename" command. */ + cmdLockSelectionHideName(): Promise<void> { return this.cmdLockSelection({ hideName: true }); } + + async cmdLockSelection(opts: { hideName?: boolean } = {}): Promise<void> { if (!this.plugin.encryption?.isConfigured?.()) { new Notice("Set up encryption first (Settings → Stashpad → Encryption)."); return; @@ -6856,7 +6751,7 @@ export class StashpadView extends ItemView { const idx = order.indexOf(t.id); const prevSibling = idx > 0 ? order[idx - 1] : null; // Silent per-item; one summary toast below (a batch shouldn't spam). - const r = await this.plugin.lockNoteSubtree(this.noteFolder, t.id, prevSibling, { silent: true }); + const r = await this.plugin.lockNoteSubtree(this.noteFolder, t.id, prevSibling, { silent: true, hideTitle: opts.hideName }); if (r) { locked++; lockedItems.push({ rootId: t.id, prevSibling, blob: r.blobPath }); await this.log.append({ type: "lock", id: t.id }); } } if (locked > 0) { @@ -6869,7 +6764,7 @@ export class StashpadView extends ItemView { this.plugin.getUndoStack(folder).push({ label: `Lock ${locked} stash${locked === 1 ? "" : "es"}`, undo: async () => { for (const it of lockedItems) { try { await this.plugin.unlockBundleAt(it.blob, { silent: true }); } catch { /* leave the rest */ } } this.render(); }, - redo: async () => { for (const it of lockedItems) { const rr = await this.plugin.lockNoteSubtree(folder, it.rootId, it.prevSibling, { silent: true }); if (rr) it.blob = rr.blobPath; } this.render(); }, + redo: async () => { for (const it of lockedItems) { const rr = await this.plugin.lockNoteSubtree(folder, it.rootId, it.prevSibling, { silent: true, hideTitle: opts.hideName }); if (rr) it.blob = rr.blobPath; } this.render(); }, }); this.plugin.notifications.show({ message: `Locked ${locked} stash${locked === 1 ? "" : "es"} — undo to unlock.`, kind: "success", category: "system", folder: this.noteFolder, actions: [{ label: "All encrypted", onClick: () => void openAggregateView(this.plugin, "encrypted") }] }); } @@ -9441,17 +9336,21 @@ export class StashpadView extends ItemView { * selected note). Paste it anywhere — clicking it lands back on this exact * note. Uses the note's stable frontmatter `id`, so it survives renames. */ async cmdCopyStashpadLink(node?: TreeNode): Promise<void> { - const target = node ?? this.getActionTargets()[0]; - if (!target?.id) { new Notice("No note selected to link to."); return; } - const link = buildStashpadLink({ + // A specific node (right-click) links just that note; otherwise link EVERY + // action target — so a multi-selection (⚡ menu / hotkey) copies one deep + // link per selected note, newline-separated, rather than only the first. + const targets = node ? [node] : this.getActionTargets(); + const valid = targets.filter((t) => !!t?.id); + if (valid.length === 0) { new Notice("No note selected to link to."); return; } + const links = valid.map((t) => buildStashpadLink({ vault: this.app.vault.getName(), folder: this.noteFolder, - note: target.id, + note: t.id, run: ["reveal"], - }); + })); try { - await navigator.clipboard.writeText(link); - new Notice("Stashpad link copied."); + await navigator.clipboard.writeText(links.join("\n")); + new Notice(links.length > 1 ? `${links.length} Stashpad links copied.` : "Stashpad link copied."); } catch { new Notice("Couldn't copy the link to the clipboard."); } @@ -9963,8 +9862,20 @@ export class StashpadView extends ItemView { const knownAuthors = this.plugin.collectKnownAuthors(); const currentAssignees = parseAssignees(curFm ?? {}); new DueDatePickerModal(this.app, current, (result) => { - void this.applyDue(targets, result.iso, result.assignees); - }, { knownAuthors, currentAssignees, title: "Assign / schedule task" }).open(); + void this.applyDue(targets, result.iso, result.assignees, false, { + repeat: result.repeat, autoDoneAfter: result.autoDoneAfter, remindEvery: result.remindEvery, + }); + }, { knownAuthors, currentAssignees, title: "Assign / schedule task", + // 0.155.0: Assign opens the SAME picker as "Set due date" with the full + // control set — the quick +/- adjust row (was silently missing here) plus + // recurrence (single-target only; see cmdSetDue). Unifies the two entry + // points so the modal is identical regardless of how it's opened. + quickAdjusts: this.plugin.settings.dueQuickAdjusts, + showRecurrence: targets.length === 1, + currentRepeat: typeof curFm?.repeat === "string" ? curFm.repeat : "", + currentAutoDoneAfter: typeof curFm?.autoDoneAfter === "string" ? curFm.autoDoneAfter : "", + currentRemindEvery: typeof curFm?.remindEvery === "string" ? curFm.remindEvery : "", + }).open(); } /** 0.76.3: a note is a task when it carries the `task` tag in @@ -11725,6 +11636,40 @@ export class StashpadView extends ItemView { requestAnimationFrame(watchdog); } + /** 0.155.1: shared "Share & export ▸" submenu — used by BOTH the desktop note + * context menu (`openNoteMenu`) and the mobile ⚡ actions menu, so the two + * entry points stay in sync (the ⚡ menu previously had no copy-link/export at + * all). Copy Stashpad link acts on `node` (disabled when null); the exports + * act on `node` (right-click semantics, `normalizeToNode: true`) or on the + * current selection (⚡ menu, `false`). Degrades to the command palette when + * the running Obsidian lacks setSubmenu (never on the 1.13 floor). */ + private addShareExportSubmenu(menu: Menu, node: TreeNode | null, opts: { normalizeToNode: boolean }): void { + const norm = (): void => { + if (opts.normalizeToNode && node && !this.selection.has(node.id)) { + this.selection.clear(); this.selection.add(node.id); this.lastSelected = node.id; + } + }; + const add = (target: { addItem: (cb: (it: any) => unknown) => unknown }): void => { + target.addItem((it: any) => { + it.setTitle("Copy Stashpad link").setIcon("link"); + // Right-click (normalizeToNode) links the clicked note; the ⚡ menu links + // the WHOLE selection (multi-link) via the no-arg selection path. + if (node) it.onClick(() => void this.cmdCopyStashpadLink(opts.normalizeToNode ? node : undefined)); + else it.setDisabled(true); + }); + target.addItem((it: any) => it.setTitle("Export to .stash…").setIcon("package").onClick(() => { norm(); void this.cmdExportStash(); })); + if (this.plugin.settings.okfEnabled) { + target.addItem((it: any) => it.setTitle("Export as OKF…").setIcon("book-marked").onClick(() => { norm(); void this.cmdExportOkf(); })); + } + }; + menu.addItem((it: any) => { + it.setTitle("Share & export").setIcon("share-2"); + const sub = typeof it.setSubmenu === "function" ? it.setSubmenu() : null; + if (sub && typeof sub.addItem === "function") add(sub); + else it.onClick(() => this.openCommandPalette()); + }); + } + private openNoteMenu(evt: MouseEvent, node: TreeNode): void { if (!node.file) return; const file = node.file; @@ -11736,7 +11681,6 @@ export class StashpadView extends ItemView { void this.openFileAtEnd(file); })); menu.addItem((it: any) => it.setTitle("Focus in Stashpad").setIcon("arrow-right").onClick(() => this.navigateTo(node.id))); - menu.addItem((it: any) => it.setTitle("Copy Stashpad link").setIcon("link").onClick(() => void this.cmdCopyStashpadLink(node))); menu.addSeparator(); menu.addItem((it: any) => it.setTitle("Split note…").setIcon("split").onClick(() => void this.cmdSplit(node))); // 0.122.2 (#9): copy the note's text. `focusClicked` (defined below) @@ -11757,20 +11701,12 @@ export class StashpadView extends ItemView { })); // 0.122.2 (#9): "Insert template…" removed from the right-click menu to keep // it compact — still available via command palette + its hotkey. - menu.addItem((it: any) => it.setTitle("Export to .stash").setIcon("package").onClick(() => { - // Multi-select normalisation (matches Clone / Delete / Set color): - // if the right-clicked row isn't in the selection, treat the - // right-click as a single-target action. Otherwise honour the - // full selection. - if (!this.selection.has(node.id)) { this.selection.clear(); this.selection.add(node.id); this.lastSelected = node.id; } - void this.cmdExportStash(); - })); - if (this.plugin.settings.okfEnabled) { - menu.addItem((it: any) => it.setTitle("Export as OKF…").setIcon("book-marked").onClick(() => { - if (!this.selection.has(node.id)) { this.selection.clear(); this.selection.add(node.id); this.lastSelected = node.id; } - void this.cmdExportOkf(); - })); - } + // 0.155.0: Copy Stashpad link + both export flows grouped under a shared + // "Share & export ▸" submenu (mirrors the Task ▸ submenu + the locked-row + // menu) so the top level stays short. Multi-select normalisation matches + // Clone / Delete / Set color. Degrades to the command palette if the running + // Obsidian lacks setSubmenu (never on the 1.13 minAppVersion floor). + this.addShareExportSubmenu(menu, node, { normalizeToNode: true }); // 0.98.1: encrypt (lock) this note + its whole subtree into one .stashenc // bundle, in place. Only shown once a vault encryption password is set up. if (this.plugin.encryption?.isConfigured?.()) {