From 604c2ba312d74c1b1b991f98057ea3703cfe5cbb Mon Sep 17 00:00:00 2001 From: GB <12993901+grub-basket@users.noreply.github.com> Date: Mon, 20 Jul 2026 22:06:32 -0700 Subject: [PATCH] 0.194.0: far more prominent encryption key-loss warnings --- README.md | 20 ++++++++++++++++---- main.js | 6 +++--- manifest.json | 2 +- package.json | 2 +- release-notes/0.194.0.md | 19 +++++++++++++++++++ src/modals.ts | 5 ++++- src/settings.ts | 21 +++++++++++++++++++-- styles.css | 37 ++++++++++++++++++++++++++++++++++--- 8 files changed, 97 insertions(+), 15 deletions(-) create mode 100644 release-notes/0.194.0.md diff --git a/README.md b/README.md index 8400566..07f474c 100644 --- a/README.md +++ b/README.md @@ -119,10 +119,22 @@ and out of the way when you don't: (`.zip` / `.tar.gz` / `.stash`) β€” Google's vendor-neutral Markdown format for handing curated knowledge to LLMs and agents. See [`docs/okf-guide.md`](docs/okf-guide.md). -> πŸ”’ **On encryption:** it was written by an AI assistant and has **not** been -> human-audited or security-tested. Treat it as a way to deter a casual snoop, **not** -> a guarantee β€” don't rely on it for anything sensitive, and keep unencrypted backups. -> It's optional and off by default. +> πŸ”’ **On encryption β€” read before you encrypt anything.** +> +> **Save your folder password in a password manager first.** "Remember on this device +> (keychain)" is a convenience, **not a backup**. An OS or keychain reset, a +> wiped/restored profile, a reinstall, a new machine, or an IT event can erase it at +> any time, without warning. If that was the only copy of your password, everything +> encrypted under it is permanently unreadable β€” by you, by us, by anyone. Setting a +> **Recovery password** as a second way in is strongly recommended. +> +> The encryption was also written by an AI assistant and has **not** been human-audited +> or security-tested. Treat it as a way to deter a casual snoop, **not** a guarantee β€” +> don't rely on it for anything sensitive, and keep unencrypted backups. It's optional +> and off by default. +> +> *Stashpad cannot recover keys or passwords, and is not liable for the loss of keys, +> passwords, or any data encrypted with them.* ## Feedback diff --git a/main.js b/main.js index 36e27e0..9c43c03 100644 --- a/main.js +++ b/main.js @@ -8,9 +8,9 @@ `,Q=d.get(I);if(Q){try{let w=null;await A.fileManager.processFrontMatter(Q,R=>{R.jdPrefix=I,B&&(R.parent=B),(!R.id||typeof R.id!="string")&&(R.id=a.mintNoteId()),R.created||(R.created=new Date().toISOString()),R.attachments||(R.attachments=[]),w=R.id});let D=(await A.vault.read(Q)).match(/^---\r?\n[\s\S]*?\r?\n---\r?\n/),H=D?`${D[0]}${v}`:v;await A.vault.modify(Q,H),w&&p.set(I,w),u++}catch(w){console.error("[stashpad] buildJdIndexNotes: update failed",w),g++}continue}try{let w=a.mintNoteId();p.set(I,w);let k=xe(E,e.slugStopWords),D=Ne(k,w),H=`${t}/${D}`,R=["---",`id: ${w}`,`parent: ${B}`,`created: "${new Date().toISOString()}"`,"attachments: []",`jdPrefix: "${I}"`,"---",""].join(` `);await A.vault.create(H,R+v),f++}catch(w){console.error("[stashpad] buildJdIndexNotes: create failed for",I,w),g++}}return{created:f,updated:u,skipped:g,destFolder:t}}function Ro(A){return(A||"").trim().replace(/^\/+|\/+$/g,"")}function xc(A,a){if((a.jdIndexScope??"vault")==="vault")return A;let e=Ro(a.jdIndexScopeFolder??"");return e?A.filter(t=>{let i=t.parent?.path?.replace(/\/+$/,"")??"";return i===e||i.startsWith(e+"/")}):A}function Nc(A,a,e){if(e==="created"){let t=A.file?.stat?.ctime??0,i=a.file?.stat?.ctime??0;if(t!==i)return t-i}return mr(A.segments,a.segments)}function Ir(A,a){let e=A.match(/^(\d+)-(\d+)$/),t=a.match(/^(\d+)-(\d+)$/),i=e?[e[1]]:A.split("."),s=t?[t[1]]:a.split(".");return mr(i,s)}function mr(A,a){let e=Math.min(A.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 Tc(A,a,e){let t=[],i=s=>"#".repeat(Math.min(s+1,6));if(t.push("# Indexed"),t.push(""),A.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 A)s.set(c.prefix,c);for(let c of A)if(c.prefix.includes("."))for(let d=1;d{let d=s.get(c),h=r.get(c)??0,p=" ".repeat(h),f=i(h),u=d?.folder?` ${d.title} _(folder)_`:(d?.file,"");d?.file?t.push(`${p}- ${f} [[${d.file.basename}|${d.prefix} ${d.title}]]`):d?.folder?t.push(`${p}- ${f} ${d.prefix}${u}`):t.push(`${p}- ${f} ${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 ` ` 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 _s(A,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=A.vault.getAbstractFileByPath(a.previewPath);r instanceof Ee.TFile&&await A.workspace.getLeaf("tab").openFile(r)}n?.hide()},n=new Ee.Notice(e,0),n}var Ee,fr,is,ss=de(()=>{"use strict";Ee=require("obsidian");fi();ce();fr=/^(\d+-\d+|\d+|[A-Za-z0-9]+(?:\.[A-Za-z0-9]+)+)\s+(.+)$/;is=class extends Ee.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 Ee.Setting(e);(i||s)&&l.addButton(c=>{c.setButtonText(this.previewRan?"Re-run preview":"Run preview first"),c.setCta(),c.onClick(async()=>{try{let d=await js(this.app,this.plugin,this.settings);if(d.error==="no-dest"){new Ee.Notice("Set a Designated Stashpad folder for Index first.",5e3),this.close();return}if(d.error==="no-home"){new Ee.Notice(`"${this.settings.jdIndexStashpadFolder}" has no Stashpad home note. Open the folder in Stashpad first.`,7e3),this.close();return}this.previewRan=!0,this.previewPath=d.previewPath,_s(this.app,d),this.contentEl.empty(),this.titleEl.empty(),this.onOpen()}catch(d){new Ee.Notice(`Preview failed: ${d?.message??d}`,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()}}});var tn,mi,Br=de(()=>{"use strict";tn=require("obsidian");ce();mi=class extends tn.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!=="/"&&$s.has(o.name))){o.path!=="/"&&i(o.path)&&s.push(o);for(let r of o.children)r instanceof tn.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,sn,yr=de(()=>{"use strict";Ci=require("obsidian"),sn=class A 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=A.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()}}});function ns(A,a,e){let t=A.vault.getAbstractFileByPath(a);if(!(t instanceof ft.TFile))return[];let i=[{label:"Reveal",keepOpen:!0,onClick:()=>{let s=A.workspace.getLeavesOfType("file-explorer")[0];if(!s)return;A.workspace.revealLeaf(s),s.view?.revealInFolder?.(t)}}];if(!e){let s=ft.Platform.isMacOS?"Finder":ft.Platform.isWin?"File Explorer":"file manager";i.push({label:`Show in ${s}`,keepOpen:!0,onClick:()=>{try{let n=window.require?.("electron")?.shell,r=A.vault.adapter?.getFullPath?.(a);r&&n?.showItemInFolder&&n.showItemInFolder(r)}catch(n){console.warn("[Stashpad] showItemInFolder failed",n)}}})}return i}var ft,Uo,Mc,wr,nn,on=de(()=>{"use strict";ft=require("obsidian"),Uo={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."}},Mc={info:4e3,success:4e3,warning:6e3,error:1e4},wr=5e3,nn=class{constructor(a){this.app=a;this.history=[];this.nextId=1;this.historyLimit=wr;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(r=>r.label)};if(this.pushHistory(i),this.muted.has(t))return null;let s=this.buildContent(a,e),n=a.duration??Mc[e],o=new ft.Notice(s,n);if(a.onBodyClick){let r=a.onBodyClick,l=o.containerEl??o.noticeEl;if(l){l.classList.add("stashpad-notice-clickable"),l.setAttribute("tabindex","0"),l.setAttribute("role","button"),l.setAttribute("aria-label",`${a.message} \u2014 activate to open; use the button to snooze`);let c=()=>{Promise.resolve().then(()=>r()).catch(d=>console.warn("[Stashpad] notification body click failed",d)),o.hide()};l.addEventListener("click",d=>{d.target.closest(".stashpad-notice-action, .stashpad-notice-overlay")||c()}),l.addEventListener("keydown",d=>{d.target===l&&(d.key==="Enter"||d.key===" ")&&(d.preventDefault(),c())})}}return o}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:wr,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(d=>console.warn("[Stashpad] notification action failed",d)),!r.keepOpen){let d=l.closest(".notice");d&&d.parentElement&&d.parentElement.removeChild(d)}}),o.appendChild(l)}i.appendChild(o)}if(a.overlayAction){let o=a.overlayAction;i.classList.add("has-overlay");let r=document.createElement("button");r.className="stashpad-notice-overlay",o.icon&&(0,ft.setIcon)(r,o.icon);let l=document.createElement("span");l.textContent=o.label,r.appendChild(l),r.title=o.title??o.label,r.addEventListener("click",c=>{if(c.stopPropagation(),Promise.resolve().then(()=>o.onClick()).catch(d=>console.warn("[Stashpad] notification overlay action failed",d)),!o.keepOpen){let d=r.closest(".notice");d&&d.parentElement&&d.parentElement.removeChild(d)}}),i.appendChild(r)}return t.appendChild(i),t}}});function Bi(A){if(!A)return"(none)";let a=A.replace(/\bMod\b/g,Lo?"Cmd":"Ctrl");return Lo&&(a=a.replace(/\bAlt\b/g,"Option")),a}function vr(A,a,e={allowSingleKey:!0}){let t=A.placeholder,i=A.value;A.placeholder="Press a key\u2026 (Backspace to cancel)",A.value="",A.classList.add("is-recording");let s=!1,n=()=>{A.placeholder=t,A.classList.remove("is-recording"),s||(A.value=i),A.removeEventListener("keydown",o,!0),A.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 d=[];Lo?(l.metaKey&&d.push("Mod"),l.ctrlKey&&d.push("Ctrl")):l.ctrlKey&&d.push("Mod"),l.altKey&&d.push("Alt"),l.shiftKey&&d.push("Shift");let h=Pc(l.key,l.code);if(!h||d.length===0&&!e.allowSingleKey)return;d.push(h);let p=d.join("+");s=!0,n(),a(p)},r=()=>n();return A.addEventListener("keydown",o,!0),A.addEventListener("blur",r),n}function Pc(A,a){if(!A)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 A.length===1?A.toUpperCase():A}var Er,Lo,Qr=de(()=>{"use strict";Er=require("obsidian"),Lo=Er.Platform.isMacOS});function Wt(A,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(d){n(d)}}function r(c){try{l(t.throw(c))}catch(d){n(d)}}function l(c){c.done?s(c.value):i(c.value).then(o,r)}l((t=t.apply(A,a||[])).next())})}function Hc(){return typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:global}function xr(A,a){return(A&15)+(A>>6|A>>3&8)<<4|(a&15)+(a>>6|a>>3&8)}function Nr(A,a){let e=a.length>>1;for(let t=0;t<e;t++){let i=t<<1;A[t]=xr(a.charCodeAt(i),a.charCodeAt(i+1))}}function Uc(A,a){if(A.length!==a.length*2)return!1;for(let e=0;e<a.length;e++){let t=e<<1;if(a[e]!==xr(A.charCodeAt(t),A.charCodeAt(t+1)))return!1}return!0}function $o(A,a,e){let t=0;for(let i=0;i<e;i++){let s=a[i]>>>4;A[t++]=s>9?s+kr:s+Fr,s=a[i]&15,A[t++]=s>9?s+kr:s+Fr}return String.fromCharCode.apply(null,A)}function Sr(A,a=!0){let e=A.length,t=e%3,i=[],s=e-t;for(let n=0;n<s;n+=3){let o=(A[n]<<16&16711680)+(A[n+1]<<8&65280)+(A[n+2]&255),r=qe.charAt(o>>18&63)+qe.charAt(o>>12&63)+qe.charAt(o>>6&63)+qe.charAt(o&63);i.push(r)}if(t===1){let n=A[e-1],o=qe.charAt(n>>2),r=qe.charAt(n<<4&63);i.push(`${o}${r}`),a&&i.push("==")}else if(t===2){let n=(A[e-2]<<8)+A[e-1],o=qe.charAt(n>>10),r=qe.charAt(n>>4&63),l=qe.charAt(n<<2&63);i.push(`${o}${r}${l}`),a&&i.push("=")}return i.join("")}function Lc(A){let a=Math.floor(A.length*.75),e=A.length;return A[e-1]==="="&&(a-=1,A[e-2]==="="&&(a-=1)),a}function Gc(A){let a=Lc(A),e=A.length,t=new Uint8Array(a),i=0;for(let s=0;s<e;s+=4){let n=as[A.charCodeAt(s)],o=as[A.charCodeAt(s+1)],r=as[A.charCodeAt(s+2)],l=as[A.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}function Tr(A,a){return Wt(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(),Q=e.exports.memory.buffer;t=new Uint8Array(Q,v,y)},l=()=>new DataView(e.exports.memory.buffer).getUint32(e.exports.STATE_SIZE,!0),c=Oc.dispatch(()=>Wt(this,void 0,void 0,function*(){if(!Ko.has(A.name)){let v=Gc(A.data),Q=WebAssembly.compile(v);Ko.set(A.name,Q)}let y=yield Ko.get(A.name);e=yield WebAssembly.instantiate(y,{})})),d=()=>Wt(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,an)}),h=(y=null)=>{i=!0,e.exports.Hash_Init(y)},p=y=>{let v=0;for(;v<y.length;){let Q=y.subarray(v,v+an);v+=Q.length,t.set(Q),e.exports.Hash_Update(Q.length)}},f=y=>{if(!i)throw new Error("update() called before init()");let v=mt(y);p(v)},u=new Uint8Array(a*2),g=(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):$o(u,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(),Q=e.exports.memory.buffer,w=new Uint8Array(Q,y,v),k=new Uint8Array(os+v);return Nr(k,A.hash),k.set(w,os),k},m=y=>{if(!(y instanceof Uint8Array))throw new Error("load() expects an Uint8Array generated by save()");let v=e.exports.Hash_GetState(),Q=l(),w=os+Q,k=e.exports.memory.buffer;if(y.length!==w)throw new Error(`Bad state length (expected ${w} bytes, got ${y.length})`);if(!Uc(A.hash,y.subarray(0,os)))throw new Error("This state was written by an incompatible hash implementation");let D=y.subarray(os);new Uint8Array(k,v,Q).set(D),i=!0},C=y=>typeof y=="string"?y.length<an/4:y.byteLength<an,B=C;switch(A.name){case"argon2":case"scrypt":B=()=>!0;break;case"blake2b":case"blake2s":B=(y,v)=>v<=512&&C(y);break;case"blake3":B=(y,v)=>v===0&&C(y);break;case"xxhash64":case"xxhash3":case"xxhash128":case"crc64":B=()=>!1;break}let E=(y,v=null,Q=null)=>{if(!B(y,v))return h(v),f(y),g("hex",Q);let w=mt(y);return t.set(w),e.exports.Hash_Calculate(w.length,v,Q),$o(u,t,a)};return yield d(),{getMemory:n,writeMemory:s,getExports:o,setMemorySize:r,init:h,update:f,digest:g,save:I,load:m,calculate:E,hashLength:a}})}function br(A){return!Number.isInteger(A)||A<8||A>512||A%8!==0?new Error("Invalid variant! Valid values: 8, 16, ..., 512"):null}function Xc(A,a){return A|a<<16}function Yo(A=512,a=null){if(br(A))return Promise.reject(br(A));let e=null,t=A;if(a!==null){if(e=mt(a),e.length>64)return Promise.reject(new Error("Max key length is 64 bytes"));t=Xc(A,e.length)}let i=A/8;return Tr(Wc,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 Zc(A,a,e){let t=[`m=${a.memorySize}`,`t=${a.iterations}`,`p=${a.parallelism}`].join(",");return`$argon2${a.hashType}$v=19$${t}$${Sr(A,!1)}$${Sr(e,!1)}`}function It(A){return Dr.setInt32(0,A,!0),new Uint8Array(Dr.buffer)}function Jo(A,a,e){return Wt(this,void 0,void 0,function*(){if(e<=64){let r=yield Yo(e*8);return r.update(It(e)),r.update(a),r.digest("binary")}let t=Math.ceil(e/32)-2,i=new Uint8Array(e);A.init(),A.update(It(e)),A.update(a);let s=A.digest("binary");i.set(s.subarray(0,32),0);for(let r=1;r<t;r++)A.init(),A.update(s),s=A.digest("binary"),i.set(s.subarray(0,32),r*32);let n=e-32*t,o;return n===64?(o=A,o.init()):o=yield Yo(n*8),o.update(s),s=o.digest("binary"),i.set(s.subarray(0,n),t*32),i})}function jc(A){switch(A){case"d":return 0;case"i":return 1;default:return 2}}function _c(A){return Wt(this,void 0,void 0,function*(){var a;let{parallelism:e,iterations:t,hashLength:i}=A,s=mt(A.password),n=mt(A.salt),o=19,r=jc(A.hashType),{memorySize:l}=A,c=mt((a=A.secret)!==null&&a!==void 0?a:""),[d,h]=yield Promise.all([Tr($c,1024),Yo(512)]);d.setMemorySize(l*1024+1024);let p=new Uint8Array(24),f=new DataView(p.buffer);f.setInt32(0,e,!0),f.setInt32(4,i,!0),f.setInt32(8,l,!0),f.setInt32(12,t,!0),f.setInt32(16,o,!0),f.setInt32(20,r,!0),d.writeMemory(p,l*1024),h.init(),h.update(p),h.update(It(s.length)),h.update(s),h.update(It(n.length)),h.update(n),h.update(It(c.length)),h.update(c),h.update(It(0));let g=Math.floor(l/(e*4))*4,I=new Uint8Array(72),m=h.digest("binary");I.set(m);for(let E=0;E<e;E++){I.set(It(0),64),I.set(It(E),68);let y=E*g,v=yield Jo(h,I,1024);d.writeMemory(v,y*1024),y+=1,I.set(It(1),64),v=yield Jo(h,I,1024),d.writeMemory(v,y*1024)}let C=new Uint8Array(1024);Nr(C,d.calculate(new Uint8Array([]),l));let B=yield Jo(h,C,i);if(A.outputType==="hex"){let E=new Uint8Array(i*2);return $o(E,B,i)}return A.outputType==="encoded"?Zc(n,A,B):B})}function zo(A){return Wt(this,void 0,void 0,function*(){return ed(A),_c(Object.assign(Object.assign({},A),{hashType:"id"}))})}var le,Go,qo,Oo,Rc,kr,Fr,mt,qe,as,an,os,Oc,Ko,VA,Kc,Jc,qc,$c,Yc,zc,Vc,Wc,WA,Dr,ed,XA,ZA,jA,_A,eh,th,ih,sh,nh,oh,ah,rh,lh,ch,dh,Ah,hh,ph,gh,uh,fh,Ih,mh,Ch,Mr=de(()=>{le=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 Wt(this,void 0,void 0,function*(){let e=yield this.lock();try{return yield Promise.resolve(a())}finally{e()}})}};qo=Hc(),Oo=(Go=qo.Buffer)!==null&&Go!==void 0?Go:null,Rc=qo.TextEncoder?new qo.TextEncoder:null;kr=87,Fr=48;mt=Oo!==null?A=>{if(typeof A=="string"){let a=Oo.from(A,"utf8");return new Uint8Array(a.buffer,a.byteOffset,a.length)}if(Oo.isBuffer(A))return new Uint8Array(A.buffer,A.byteOffset,A.length);if(ArrayBuffer.isView(A))return new Uint8Array(A.buffer,A.byteOffset,A.byteLength);throw new Error("Invalid data type!")}:A=>{if(typeof A=="string")return Rc.encode(A);if(ArrayBuffer.isView(A))return new Uint8Array(A.buffer,A.byteOffset,A.byteLength);throw new Error("Invalid data type!")},qe="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",as=new Uint8Array(256);for(let A=0;A<qe.length;A++)as[qe.charCodeAt(A)]=A;an=16*1024,os=4,Oc=new le,Ko=new Map;VA=new le,Kc="argon2",Jc="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+AhBACACKQNwIAEpA3CFNwOACUEAIAIpA3ggASkDeIU3A4gJQQAgAikDgAEgASkDgAGFNwOQCUEAIAIpA4gBIAEpA4gBhTcDmAlBACACKQOQASABKQOQAYU3A6AJQQAgAikDmAEgASkDmAGFNwOoCUEAIAIpA6ABIAEpA6ABhTcDsAlBACACKQOoASABKQOoAYU3A7gJQQAgAikDsAEgASkDsAGFNwPACUEAIAIpA7gBIAEpA7gBhTcDyAlBACACKQPAASABKQPAAYU3A9AJQQAgAikDyAEgASkD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",qc="e4cdc523",$c={name:Kc,data:Jc,hash:qc},Yc="blake2b",zc="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",Vc="c6f286e6",Wc={name:Yc,data:zc,hash:Vc},WA=new le;Dr=new DataView(new ArrayBuffer(4));ed=A=>{var a;if(!A||typeof A!="object")throw new Error("Invalid options parameter. It requires an object.");if(!A.password)throw new Error("Password must be specified");if(A.password=mt(A.password),A.password.length<1)throw new Error("Password must be specified");if(!A.salt)throw new Error("Salt must be specified");if(A.salt=mt(A.salt),A.salt.length<8)throw new Error("Salt should be at least 8 bytes long");if(A.secret=mt((a=A.secret)!==null&&a!==void 0?a:""),!Number.isInteger(A.iterations)||A.iterations<1)throw new Error("Iterations should be a positive number");if(!Number.isInteger(A.parallelism)||A.parallelism<1)throw new Error("Parallelism should be a positive number");if(!Number.isInteger(A.hashLength)||A.hashLength<4)throw new Error("Hash length should be at least 4 bytes.");if(!Number.isInteger(A.memorySize))throw new Error("Memory size should be specified.");if(A.memorySize<8*A.parallelism)throw new Error("Memory size should be at least 8 * parallelism.");if(A.outputType===void 0&&(A.outputType="hex"),!["hex","binary","encoded"].includes(A.outputType))throw new Error(`Insupported output type ${A.outputType}. Valid values: ['hex', 'binary', 'encoded']`)};XA=new le,ZA=new le,jA=new le,_A=new le,eh=new Uint8Array(8),th=new le,ih=new le,sh=new le,nh=new le,oh=new le,ah=new le,rh=new le,lh=new le,ch=new le,dh=new le,Ah=new le,hh=new Uint8Array(8),ph=new le,gh=new Uint8Array(8),uh=new le,fh=new Uint8Array(8),Ih=new le,mh=new le,Ch=new le});function Ue(A){if(A.length<$e.length+1)return!1;for(let a=0;a<$e.length;a++)if(A[a]!==$e[a])return!1;return!0}function Pr(A,a,e){A[a]=e>>>24&255,A[a+1]=e>>>16&255,A[a+2]=e>>>8&255,A[a+3]=e&255}function Hr(A,a){return A[a]*16777216+(A[a+1]<<16)+(A[a+2]<<8)+A[a+3]}async function Wo(A,a,e){if(e.id===jo)return await zo({password:A,salt:a,parallelism:e.c,iterations:e.b,memorySize:e.a,hashLength:Vo,outputType:"binary"});if(e.id===Zo){let t=await crypto.subtle.importKey("raw",me(new TextEncoder().encode(A)),"PBKDF2",!1,["deriveBits"]),i=await crypto.subtle.deriveBits({name:"PBKDF2",salt:me(a),iterations:e.a,hash:"SHA-256"},t,Vo*8);return new Uint8Array(i)}throw new Error(`Unsupported KDF id (${e.id}).`)}async function rn(A){return crypto.subtle.importKey("raw",me(A),{name:"AES-GCM"},!1,["encrypt","decrypt"])}async function Ct(A,a){let e=crypto.getRandomValues(new Uint8Array(td)),t=crypto.getRandomValues(new Uint8Array(yi)),i,s,n;try{i={id:jo,a:sd,b:nd,c:od},n=await Wo(a,e,i),s="argon2id"}catch(d){console.warn("[Stashpad] Argon2id unavailable \u2014 encrypting with PBKDF2 fallback.",d),i={id:Zo,a:id,b:0,c:0},n=await Wo(a,e,i),s="pbkdf2"}let o=Ur(i,e,t),r=await rn(n),l=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:me(t),additionalData:me(o)},r,me(A))),c=new Uint8Array(o.length+l.length);return c.set(o,0),c.set(l,o.length),{data:c,kdf:s}}async function ls(){if(rs!==null)return rs;try{await zo({password:"x",salt:new Uint8Array(16),parallelism:1,iterations:1,memorySize:8,hashLength:16,outputType:"binary"}),rs=!0}catch{rs=!1}return rs}function Ur(A,a,e){let t=new Uint8Array($e.length+1+1+4+4+1+1+a.length+e.length),i=0;return t.set($e,i),i+=$e.length,t[i++]=Xo,t[i++]=A.id,Pr(t,i,A.a),i+=4,Pr(t,i,A.b),i+=4,t[i++]=A.c,t[i++]=a.length,t.set(a,i),i+=a.length,t.set(e,i),i+=e.length,t}async function wi(A,a){if(!Ue(A))throw new Error("Not an encrypted Stashpad file.");let e=A[$e.length];if(e===1)return ad(A,a);if(e!==Xo)throw new Error(`Unsupported encrypted .stash version (${e}).`);let t=$e.length+1,i={id:A[t++],a:0,b:0,c:0};if(i.a=Hr(A,t),t+=4,i.b=Hr(A,t),t+=4,i.c=A[t++],i.id===jo){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===Zo&&i.a>1e7)throw new Error("Unsupported KDF parameters (file may be corrupted or malicious).");let s=A[t++];if(s<8||s>64)throw new Error("Unsupported KDF parameters (file may be corrupted or malicious).");let n=A.slice(t,t+s);t+=s;let o=A.slice(t,t+yi);t+=yi;let r=A.slice(0,t),l=A.slice(t),c=await Wo(a,n,i),d=await rn(c),h=await crypto.subtle.decrypt({name:"AES-GCM",iv:me(o),additionalData:me(r)},d,me(l));return new Uint8Array(h)}async function ad(A,a){let e=$e.length+1,t=A.slice(e,e+16);e+=16;let i=A.slice(e,e+12);e+=12;let s=A.slice(e),n=await crypto.subtle.importKey("raw",me(new TextEncoder().encode(a)),"PBKDF2",!1,["deriveKey"]),o=await crypto.subtle.deriveKey({name:"PBKDF2",salt:me(t),iterations:21e4,hash:"SHA-256"},n,{name:"AES-GCM",length:256},!1,["decrypt"]),r=await crypto.subtle.decrypt({name:"AES-GCM",iv:me(i)},o,me(s));return new Uint8Array(r)}async function cs(A,a){if(a.length!==Vo)throw new Error("Encryption key must be 32 bytes.");let e=crypto.getRandomValues(new Uint8Array(yi)),i=Ur({id:Rr,a:0,b:0,c:0},new Uint8Array(0),e),s=await rn(a),n=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:me(e),additionalData:me(i)},s,me(A))),o=new Uint8Array(i.length+n.length);return o.set(i,0),o.set(n,i.length),o}async function Ye(A,a){if(!Ue(A))throw new Error("Not an encrypted Stashpad file.");let e=A[$e.length];if(e!==Xo)throw new Error(`Unsupported encrypted version (${e}).`);let t=$e.length+1;if(A[t++]!==Rr)throw new Error("Not a raw-key (.stashenc) envelope.");t+=9;let s=A[t++];t+=s;let n=A.slice(t,t+yi);t+=yi;let o=A.slice(0,t),r=A.slice(t),l=await rn(a),c=await crypto.subtle.decrypt({name:"AES-GCM",iv:me(n),additionalData:me(o)},l,me(r));return new Uint8Array(c)}async function Ei(A,a,e={}){if(!Ue(a))return a;if(e.secretId){let i=A.secretStorage,s=null;try{s=i?.getSecret(e.secretId)??null}catch{s=null}if(s)try{return await wi(a,s)}catch{}}let t;for(;;){let i=await new Promise(s=>{new ds(A,t,!!e.allowLater,s).open()});if(i.kind==="cancel")return null;if(i.kind==="later")return e.onLater?.(),null;try{return await wi(a,i.value)}catch{t="Wrong password or corrupted file. Try again."}}}var $e,Xo,Zo,jo,Rr,td,yi,Vo,id,sd,nd,od,me,_o,rs,Xt=de(()=>{"use strict";Mr();ve();$e=new Uint8Array([83,84,65,83,72,69,78,67]),Xo=2,Zo=1,jo=2,Rr=3,td=32,yi=12,Vo=32,id=6e5,sd=47104,nd=3,od=1,me=A=>A;_o={argon2id:{label:"Argon2id",strong:!0},pbkdf2:{label:"PBKDF2 (fallback)",strong:!1}};rs=null});var Zt,rd,vi,ln,Lr=de(()=>{"use strict";Zt=".stashpad/keys.json",rd=".stashpad",vi="_keys",ln=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(Zt);if(a)return a;try{let t=((await this.a.list(vi)).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(Zt))return!0}catch{}try{return((await this.a.list(vi)).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(rd);let t=`${Zt}.tmp`,i=!1;try{await this.a.write(t,e);try{await this.a.rename(t,Zt)}catch{try{await this.a.remove(Zt)}catch{}await this.a.rename(t,Zt)}i=!0}catch{try{await this.a.exists(t)&&await this.a.remove(t)}catch{}}i||await this.a.write(Zt,e),await this.ensureDir(vi);for(let s=4;s>=1;s--){let n=`${vi}/keys-${s}.json`,o=`${vi}/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(`${vi}/keys-1.json`,e)}catch{}}}});function ea(A){let a="";for(let e=0;e<A.length;e++)a+=String.fromCharCode(A[e]);return btoa(a)}function cd(A){let a=atob(A),e=new Uint8Array(a.length);for(let t=0;t<a.length;t++)e[t]=a.charCodeAt(t);return e}var ld,Gr,cn,dn,Or=de(()=>{"use strict";Xt();pt();ld=".stashkey",Gr=32;cn=()=>new Date().toISOString(),dn=class{constructor(a){this.app=a}get a(){return this.app.vault.adapter}keyPath(a){return`${a.replace(/\/+$/,"")}/${ld}`}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(Gr)),s=await Ct(i,e);return{sk:{v:1,keyId:t??he(8),folderPath:a.replace(/\/+$/,""),slots:[{id:he(8),label:"Folder password",wrapped:ea(s.data),kdf:s.kdf,createdAt:cn()}],createdAt:cn()},dek:i}}async unlock(a,e){for(let t of a.slots)try{let i=await wi(cd(t.wrapped),e);if(i.length!==Gr){i.fill(0);continue}return i}catch{}return null}async changePassword(a,e,t){if(!t)throw new Error("Password required.");let i=await Ct(e,t),s=a.slots.filter(o=>o.recovery),n={id:he(8),label:"Folder password",wrapped:ea(i.data),kdf:i.kdf,createdAt:cn()};return{...a,slots:[n,...s]}}async setRecovery(a,e,t){if(!t)throw new Error("Recovery password required.");let i=await Ct(e,t),s=a.slots.filter(o=>!o.recovery),n={id:he(8),label:"Recovery password",wrapped:ea(i.data),kdf:i.kdf,createdAt:cn(),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)}}});function hn(){return{}}function Ad(A){let a="";for(let e=0;e<A.length;e++)a+=String.fromCharCode(A[e]);return btoa(a)}function hd(A){let a=atob(A),e=new Uint8Array(a.length);for(let t=0;t<a.length;t++)e[t]=a.charCodeAt(t);return e}var dd,An,ta=de(()=>{"use strict";Xt();pt();Lr();Or();dd="stashpad-vault-encryption";An=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 ln(a),this.folderKeystore=new dn(a)}argonProbe(){return ls()}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 wi(hd(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 u=await this.folderKeystore.changePassword(r,o,e);await this.folderKeystore.write(n,u),this.folderKeyFiles.set(n,u);let g=this.folderKcId(n,u.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(u=>!u.label.startsWith("[deprecated]")),c=this.folderKcIdFor(s),d=this.rememberedFolderPassword(c);if(d&&l[0])try{await this.parkThenSet(`${c}-d-${l[0].id}`,d)}catch{}let h=await Ct(o,e),p=s.passwordSlots.map(u=>u.label.startsWith("[deprecated]")?u:{...u,label:`[deprecated] ${u.label}`}),f={...s,kcId:s.kcId??this.folderKcId(s.label,s.keyId),passwordSlots:[{id:he(8),label:"Folder password",wrapped:Ad(h.data),kdf:h.kdf,createdAt:new Date().toISOString()},...p]};this.kf.folderKeys={...this.kf.folderKeys??{},[n]:f},await this.keyfiles.save(this.kf),(t||this.isFolderRemembered(c))&&await this.rememberFolder(this.folderKcIdFor(f),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||`${dd}-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()}}});function gn(A){if(As!==A){As=A;for(let a of pn)a()}}function Bt(){return As}function Kr(A){if(As===A){As=null;for(let a of pn)a()}}function Jr(A){return pn.add(A),()=>pn.delete(A)}var As,pn,un=de(()=>{"use strict";As=null,pn=new Set});function pd(){return P.Platform.isMacOS?"Finder":P.Platform.isWin?"File Explorer":"file manager"}function na(){let A={};for(let a of jt)A[a.id]={primary:a.defaultPrimary,secondary:a.defaultSecondary??"",preferRight:!1,useBoth:!!a.defaultUseBoth};return A}function X(){return qr}function hs(A){qr=A;for(let a of sa)a()}function $r(A){return sa.add(A),()=>sa.delete(A)}function mn(A){try{let a=A.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}}function gd(A,a){return ia||(ia=class extends P.SettingPage{constructor(e,t){super(),this.title=e,this._renderFn=t}display(){this.containerEl.empty(),this._renderFn(this.containerEl)}}),new ia(A,a)}var P,jt,Mt,qr,sa,fn,ia,In,Fi=de(()=>{"use strict";P=require("obsidian");ss();Br();yr();ce();ve();on();Qr();fi();pt();Tt();ta();un();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 Obsidian editor",desc:"Open the cursor row (or focused note) in a regular Obsidian markdown tab.",defaultPrimary:"Mod+Shift+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:"edit",label:"Edit note in Stashpad",desc:"Edit the cursor row (or focused note) in Stashpad's own editor (with a Split toggle) instead of a full Obsidian tab.",defaultPrimary:"E"},{id:"editParent",label:"Edit parent note in Stashpad",desc:"Edit the focused parent note in Stashpad's own editor.",defaultPrimary:"Shift+E"},{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\u2026",desc:"Open the export dialog for the selected subtree(s) \u2014 pick .stash / OKF / plain .zip and full/frontmatter/body content.",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:"openAllTasks",label:"Open all tasks (aggregate view)",desc:"Default: Shift+T \u2014 open the aggregate \u201CAll tasks\u201D view collecting tasks across every Stashpad folder.",defaultPrimary:"Shift+T"},{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"}];Mt={folder:"Stashpad",importDropFolder:"",exportFolder:"_exports",autoImport:!1,inheritObsidianExclusions:!0,folderPanelPinnedFraction:.5,folderPanelPinned:[],folderPanelPinnedAt:{},folderPanelGroupItemOrder:{},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:hn(),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,foldersAlwaysNewTab:!1,importExcludePrefixes:"_",lockedSubtrees:[],searchOpensInNewTab:!0,pinnedNotes:[],hideMobileToolbarInStashpad:!0,slugStopWords:[],searchIncludedFolders:[],searchExcludedFolders:[],shortcuts:{move:"M",pickMove:"O",merge:"&",copy:"C",copyTree:"Y",openEditor:"Mod+Shift+E",openTab:"T",split:"S",edit:"E",editParent:"Shift+E",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:[],splitCheckboxLines:!0,autoNavOnMoveIn:!1,openParentTabOnMoveIn:!0,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:na()},qr=JSON.parse(JSON.stringify(Mt)),sa=new Set;fn=[{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((A,a)=>{let e=t=>t.replace(/^[^\p{L}\p{N}]+/u,"");return e(A.label).localeCompare(e(a.label))}),ia=null;In=class extends P.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 fn){new P.Setting(e).setName(t.label).setHeading();let i=this.itemsForTab(t.id);if(i)for(let s of i){let n=new P.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 fn.map(e=>{let t=this.itemsForTab(e.id);return t?{type:"page",name:e.label,items:t}:{type:"page",name:e.label,page:()=>gd(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 P.Notice("Debug trace is empty \u2014 enable it and reproduce the issue first.");return}try{await navigator.clipboard.writeText(i),new P.Notice("Debug trace copied.")}catch{new P.Notice("Couldn't access clipboard.")}})),e.addButton(t=>t.setButtonText("Clear").onClick(()=>{this.plugin.clearDebugTrace(),new P.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 P.Notice("No log yet \u2014 make some changes first.");return}let n=await i.read(s);new Qi(this.app,n,s).open()})),["log","history","diagnostics"])]}notificationsItems(){let e=new Set(this.plugin.settings.mutedNotificationCategories??[]),t=Object.keys(Uo);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=Uo[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 ps(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 P.Notice("No log yet \u2014 make some changes first.");return}let l=await o.read(r);new Qi(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 P.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 Le(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 P.Notice("Folder password set \u2014 share it securely."),this.update?.(),this.pfeRerender?.(),null}}).open()}promptChangeFolderPassword(e){new Le(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 P.Notice("Folder password changed."),this.update?.(),this.pfeRerender?.(),null}}).open()}promptSetFolderRecovery(e){let t=e.split("/").pop()||e;new Le(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 P.Notice("Recovery password set \u2014 keep it somewhere safe."),this.update?.(),this.pfeRerender?.(),null}}).open()}promptRemoveFolderRecovery(e){let t=e.split("/").pop()||e;new j(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 P.Notice(s.message);return}new P.Notice("Recovery password removed."),this.update?.(),this.pfeRerender?.()}}).open()}promptUnlockFolder(e){new Le(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 P.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 P.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",d=new P.Setting(e).setName("Password").setDesc(c);if(o?d.addButton(u=>u.setButtonText("Manage on parent folder").onClick(()=>{this.pfeSelected=n,this.update?.(),this.pfeRerender?.()})):s?r?d.addButton(u=>u.setButtonText("Change password\u2026").onClick(()=>this.promptChangeFolderPassword(t))):d.addButton(u=>u.setButtonText("Unlock\u2026").setCta().onClick(()=>this.promptUnlockFolder(t))):d.addButton(u=>u.setButtonText("Set folder password\u2026").setCta().onClick(()=>this.promptSetFolderPassword(t))),s&&r){let u=this.plugin.encryption.folderHasRecovery(t),g=new P.Setting(e).setName("Recovery password").setDesc(u?"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(u?"Change recovery\u2026":"Add recovery\u2026").onClick(()=>this.promptSetFolderRecovery(t))),u&&g.addButton(I=>{I.setButtonText("Remove recovery").onClick(()=>this.promptRemoveFolderRecovery(t)),I.buttonEl.addClass("mod-warning")})}let h=async u=>{this.plugin.settings.folderEncPrefs={...this.plugin.settings.folderEncPrefs??{},[t]:{...(this.plugin.settings.folderEncPrefs??{})[t]??{},...u}},await this.plugin.saveSettings()};new P.Setting(e).setName("Trash handling").setDesc("Where notes deleted from this folder go.").addDropdown(u=>u.addOption("","Stashpad trash (default)").addOption("obsidian","Obsidian native trash").setValue(l.trashHandling==="obsidian"?"obsidian":"").onChange(g=>h({trashHandling:g||void 0})));let p=(u,g,I,m,C=!1)=>{new P.Setting(e).setName(u).addToggle(B=>B.setValue(!!l[g]).onChange(async E=>{if(E&&C){if(!this.plugin.encryption.hasFolderKey(t)){new P.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]=E,E||(y[I]=!1),await h(y),m&&await m(E),this.pfeRerender?.()})),new P.Setting(e).setName(`\u21B3 ${u} \u2014 hide filenames`).setClass("stashpad-subsetting").addToggle(B=>{B.setValue(!!l[I]),B.setDisabled(!l[g]),B.onChange(async E=>{let y={};y[I]=E,await h(y),this.pfeRerender?.()})})};p("Encrypt this folder's notes","encryptContent","encryptFilenames",async u=>{u?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 u=>{if(!u)return;let g=this.plugin.archivedPlainNotesIn(`${t}/archive`).length;g!==0&&new j(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 P.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 P.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(u=>{u.setPlaceholder("global"),u.setValue(l.reEncryptAfterMin==null?"":String(l.reEncryptAfterMin)),u.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)}):u.setValue(l.reEncryptAfterMin==null?"":String(l.reEncryptAfterMin))}})});let f=this.plugin.discoverStashpadFolders().filter(u=>u!==t&&u.startsWith(t+"/")).sort();if(f.length){new P.Setting(e).setName("Subfolders").setDesc(`${f.length} subfolder${f.length===1?"":"s"} \u2014 they use \u201C${t.split("/").pop()}\u201D's password. Encrypt each individually.`).setHeading();for(let u of f){let g=(this.plugin.settings.folderEncPrefs??{})[u]??{},I=async B=>{this.plugin.settings.folderEncPrefs={...this.plugin.settings.folderEncPrefs??{},[u]:{...(this.plugin.settings.folderEncPrefs??{})[u]??{},...B}},await this.plugin.saveSettings()},m=(this.plugin.settings.lockedSubtrees??[]).some(B=>(B.folder||"").replace(/\/+$/,"")===u),C=u.slice(t.length+1);new P.Setting(e).setName(C).addToggle(B=>B.setValue(m).onChange(async E=>{E?await this.plugin.lockFolder(u):await this.plugin.unlockFolder(u);let y=(this.plugin.settings.lockedSubtrees??[]).some(v=>(v.folder||"").replace(/\/+$/,"")===u);await I({encryptContent:y,...y?{}:{encryptFilenames:!1}}),this.update?.(),this.pfeRerender?.()})),new P.Setting(e).setName(`\u21B3 ${C} \u2014 hide filenames`).setClass("stashpad-subsetting").addToggle(B=>{B.setValue(!!g.encryptFilenames),B.setDisabled(!m),B.onChange(E=>void I({encryptFilenames:E}))})}}}buildGeneralCategories(){let e=async()=>this.plugin.saveSettings(),t=(s,n,o,r,l)=>this.renderDef(s,n,c=>c.addToggle(d=>d.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 mi(this.app,n.inputEl),n.setValue(this.plugin.settings.folder).setPlaceholder("Stashpad");let o=async()=>{let r=(n.getValue()||"").trim().replace(/^\/+|\/+$/g,"")||Mt.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(d=>(d??"").trim().replace(/^\/+|\/+$/g,"")).filter(Boolean));if(l.some(d=>c.has(d))){new P.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 d=c.trim();d&&(0,P.setIcon)(r,d)};s.addDropdown(c=>{for(let d of n)c.addOption(d,d.split("/").pop()||d);c.setValue(this.iconPickFolder),c.onChange(d=>{this.iconPickFolder=d;let h=this.plugin.getFolderIcon(d)??"";o?.setValue(h),l(h)})}),s.addText(c=>{o=c,c.setPlaceholder("type to search\u2026 (e.g. rocket)"),new sn(this.app,c.inputEl),c.setValue(this.plugin.getFolderIcon(this.iconPickFolder)??""),c.onChange(async d=>{l(d),await this.plugin.setFolderIcon(this.iconPickFolder,d.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,"")||Mt.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: ${it(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=mn(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(d=>d.trim()).filter(d=>/^\d+\s*[mhdw]$/i.test(d)).map(d=>d.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.composerCopy.push(t("Split a pasted checklist into separate tasks",'When every line of what you submit is a checkbox \u2014 "- [ ] milk", "[x] eggs" \u2014 create one task per line instead of a single note. Applies even when "split on newlines" is off. On by default.',()=>this.plugin.settings.splitCheckboxLines,s=>{this.plugin.settings.splitCheckboxLines=s},["checkbox","task","split","paste","checklist"])),i.movingNotes.push(t("Open the new parent in a background tab after moving a note IN","When you nest a note into another note, open that parent in a background Stashpad tab so its new home is one click away \u2014 without stealing focus from what you're doing. Skipped when the destination is Home or already open in a tab. On by default.",()=>this.plugin.settings.openParentTabOnMoveIn,s=>{this.plugin.settings.openParentTabOnMoveIn=s},["background","tab","move","in","parent"])),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 P.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 P.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 P.Notice("Enter a folder name first.");return}try{await this.plugin.createNewStashpad(l),new P.Notice(`Created Stashpad "${l}".`),o&&(o.value=""),await this.plugin.waitForStashpadFolder(l,2e3),this.update?.()}catch(c){new P.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 P.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:st).join(` +`}function _s(A,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=A.vault.getAbstractFileByPath(a.previewPath);r instanceof Ee.TFile&&await A.workspace.getLeaf("tab").openFile(r)}n?.hide()},n=new Ee.Notice(e,0),n}var Ee,fr,is,ss=de(()=>{"use strict";Ee=require("obsidian");fi();ce();fr=/^(\d+-\d+|\d+|[A-Za-z0-9]+(?:\.[A-Za-z0-9]+)+)\s+(.+)$/;is=class extends Ee.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 Ee.Setting(e);(i||s)&&l.addButton(c=>{c.setButtonText(this.previewRan?"Re-run preview":"Run preview first"),c.setCta(),c.onClick(async()=>{try{let d=await js(this.app,this.plugin,this.settings);if(d.error==="no-dest"){new Ee.Notice("Set a Designated Stashpad folder for Index first.",5e3),this.close();return}if(d.error==="no-home"){new Ee.Notice(`"${this.settings.jdIndexStashpadFolder}" has no Stashpad home note. Open the folder in Stashpad first.`,7e3),this.close();return}this.previewRan=!0,this.previewPath=d.previewPath,_s(this.app,d),this.contentEl.empty(),this.titleEl.empty(),this.onOpen()}catch(d){new Ee.Notice(`Preview failed: ${d?.message??d}`,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()}}});var tn,mi,Br=de(()=>{"use strict";tn=require("obsidian");ce();mi=class extends tn.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!=="/"&&$s.has(o.name))){o.path!=="/"&&i(o.path)&&s.push(o);for(let r of o.children)r instanceof tn.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,sn,yr=de(()=>{"use strict";Ci=require("obsidian"),sn=class A 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=A.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()}}});function ns(A,a,e){let t=A.vault.getAbstractFileByPath(a);if(!(t instanceof ft.TFile))return[];let i=[{label:"Reveal",keepOpen:!0,onClick:()=>{let s=A.workspace.getLeavesOfType("file-explorer")[0];if(!s)return;A.workspace.revealLeaf(s),s.view?.revealInFolder?.(t)}}];if(!e){let s=ft.Platform.isMacOS?"Finder":ft.Platform.isWin?"File Explorer":"file manager";i.push({label:`Show in ${s}`,keepOpen:!0,onClick:()=>{try{let n=window.require?.("electron")?.shell,r=A.vault.adapter?.getFullPath?.(a);r&&n?.showItemInFolder&&n.showItemInFolder(r)}catch(n){console.warn("[Stashpad] showItemInFolder failed",n)}}})}return i}var ft,Uo,Mc,wr,nn,on=de(()=>{"use strict";ft=require("obsidian"),Uo={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."}},Mc={info:4e3,success:4e3,warning:6e3,error:1e4},wr=5e3,nn=class{constructor(a){this.app=a;this.history=[];this.nextId=1;this.historyLimit=wr;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(r=>r.label)};if(this.pushHistory(i),this.muted.has(t))return null;let s=this.buildContent(a,e),n=a.duration??Mc[e],o=new ft.Notice(s,n);if(a.onBodyClick){let r=a.onBodyClick,l=o.containerEl??o.noticeEl;if(l){l.classList.add("stashpad-notice-clickable"),l.setAttribute("tabindex","0"),l.setAttribute("role","button"),l.setAttribute("aria-label",`${a.message} \u2014 activate to open; use the button to snooze`);let c=()=>{Promise.resolve().then(()=>r()).catch(d=>console.warn("[Stashpad] notification body click failed",d)),o.hide()};l.addEventListener("click",d=>{d.target.closest(".stashpad-notice-action, .stashpad-notice-overlay")||c()}),l.addEventListener("keydown",d=>{d.target===l&&(d.key==="Enter"||d.key===" ")&&(d.preventDefault(),c())})}}return o}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:wr,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(d=>console.warn("[Stashpad] notification action failed",d)),!r.keepOpen){let d=l.closest(".notice");d&&d.parentElement&&d.parentElement.removeChild(d)}}),o.appendChild(l)}i.appendChild(o)}if(a.overlayAction){let o=a.overlayAction;i.classList.add("has-overlay");let r=document.createElement("button");r.className="stashpad-notice-overlay",o.icon&&(0,ft.setIcon)(r,o.icon);let l=document.createElement("span");l.textContent=o.label,r.appendChild(l),r.title=o.title??o.label,r.addEventListener("click",c=>{if(c.stopPropagation(),Promise.resolve().then(()=>o.onClick()).catch(d=>console.warn("[Stashpad] notification overlay action failed",d)),!o.keepOpen){let d=r.closest(".notice");d&&d.parentElement&&d.parentElement.removeChild(d)}}),i.appendChild(r)}return t.appendChild(i),t}}});function Bi(A){if(!A)return"(none)";let a=A.replace(/\bMod\b/g,Lo?"Cmd":"Ctrl");return Lo&&(a=a.replace(/\bAlt\b/g,"Option")),a}function vr(A,a,e={allowSingleKey:!0}){let t=A.placeholder,i=A.value;A.placeholder="Press a key\u2026 (Backspace to cancel)",A.value="",A.classList.add("is-recording");let s=!1,n=()=>{A.placeholder=t,A.classList.remove("is-recording"),s||(A.value=i),A.removeEventListener("keydown",o,!0),A.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 d=[];Lo?(l.metaKey&&d.push("Mod"),l.ctrlKey&&d.push("Ctrl")):l.ctrlKey&&d.push("Mod"),l.altKey&&d.push("Alt"),l.shiftKey&&d.push("Shift");let h=Pc(l.key,l.code);if(!h||d.length===0&&!e.allowSingleKey)return;d.push(h);let p=d.join("+");s=!0,n(),a(p)},r=()=>n();return A.addEventListener("keydown",o,!0),A.addEventListener("blur",r),n}function Pc(A,a){if(!A)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 A.length===1?A.toUpperCase():A}var Er,Lo,Qr=de(()=>{"use strict";Er=require("obsidian"),Lo=Er.Platform.isMacOS});function Wt(A,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(d){n(d)}}function r(c){try{l(t.throw(c))}catch(d){n(d)}}function l(c){c.done?s(c.value):i(c.value).then(o,r)}l((t=t.apply(A,a||[])).next())})}function Hc(){return typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:global}function xr(A,a){return(A&15)+(A>>6|A>>3&8)<<4|(a&15)+(a>>6|a>>3&8)}function Nr(A,a){let e=a.length>>1;for(let t=0;t<e;t++){let i=t<<1;A[t]=xr(a.charCodeAt(i),a.charCodeAt(i+1))}}function Uc(A,a){if(A.length!==a.length*2)return!1;for(let e=0;e<a.length;e++){let t=e<<1;if(a[e]!==xr(A.charCodeAt(t),A.charCodeAt(t+1)))return!1}return!0}function $o(A,a,e){let t=0;for(let i=0;i<e;i++){let s=a[i]>>>4;A[t++]=s>9?s+kr:s+Fr,s=a[i]&15,A[t++]=s>9?s+kr:s+Fr}return String.fromCharCode.apply(null,A)}function Sr(A,a=!0){let e=A.length,t=e%3,i=[],s=e-t;for(let n=0;n<s;n+=3){let o=(A[n]<<16&16711680)+(A[n+1]<<8&65280)+(A[n+2]&255),r=qe.charAt(o>>18&63)+qe.charAt(o>>12&63)+qe.charAt(o>>6&63)+qe.charAt(o&63);i.push(r)}if(t===1){let n=A[e-1],o=qe.charAt(n>>2),r=qe.charAt(n<<4&63);i.push(`${o}${r}`),a&&i.push("==")}else if(t===2){let n=(A[e-2]<<8)+A[e-1],o=qe.charAt(n>>10),r=qe.charAt(n>>4&63),l=qe.charAt(n<<2&63);i.push(`${o}${r}${l}`),a&&i.push("=")}return i.join("")}function Lc(A){let a=Math.floor(A.length*.75),e=A.length;return A[e-1]==="="&&(a-=1,A[e-2]==="="&&(a-=1)),a}function Gc(A){let a=Lc(A),e=A.length,t=new Uint8Array(a),i=0;for(let s=0;s<e;s+=4){let n=as[A.charCodeAt(s)],o=as[A.charCodeAt(s+1)],r=as[A.charCodeAt(s+2)],l=as[A.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}function Tr(A,a){return Wt(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(),Q=e.exports.memory.buffer;t=new Uint8Array(Q,v,y)},l=()=>new DataView(e.exports.memory.buffer).getUint32(e.exports.STATE_SIZE,!0),c=Oc.dispatch(()=>Wt(this,void 0,void 0,function*(){if(!Ko.has(A.name)){let v=Gc(A.data),Q=WebAssembly.compile(v);Ko.set(A.name,Q)}let y=yield Ko.get(A.name);e=yield WebAssembly.instantiate(y,{})})),d=()=>Wt(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,an)}),h=(y=null)=>{i=!0,e.exports.Hash_Init(y)},p=y=>{let v=0;for(;v<y.length;){let Q=y.subarray(v,v+an);v+=Q.length,t.set(Q),e.exports.Hash_Update(Q.length)}},f=y=>{if(!i)throw new Error("update() called before init()");let v=mt(y);p(v)},u=new Uint8Array(a*2),g=(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):$o(u,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(),Q=e.exports.memory.buffer,w=new Uint8Array(Q,y,v),k=new Uint8Array(os+v);return Nr(k,A.hash),k.set(w,os),k},m=y=>{if(!(y instanceof Uint8Array))throw new Error("load() expects an Uint8Array generated by save()");let v=e.exports.Hash_GetState(),Q=l(),w=os+Q,k=e.exports.memory.buffer;if(y.length!==w)throw new Error(`Bad state length (expected ${w} bytes, got ${y.length})`);if(!Uc(A.hash,y.subarray(0,os)))throw new Error("This state was written by an incompatible hash implementation");let D=y.subarray(os);new Uint8Array(k,v,Q).set(D),i=!0},C=y=>typeof y=="string"?y.length<an/4:y.byteLength<an,B=C;switch(A.name){case"argon2":case"scrypt":B=()=>!0;break;case"blake2b":case"blake2s":B=(y,v)=>v<=512&&C(y);break;case"blake3":B=(y,v)=>v===0&&C(y);break;case"xxhash64":case"xxhash3":case"xxhash128":case"crc64":B=()=>!1;break}let E=(y,v=null,Q=null)=>{if(!B(y,v))return h(v),f(y),g("hex",Q);let w=mt(y);return t.set(w),e.exports.Hash_Calculate(w.length,v,Q),$o(u,t,a)};return yield d(),{getMemory:n,writeMemory:s,getExports:o,setMemorySize:r,init:h,update:f,digest:g,save:I,load:m,calculate:E,hashLength:a}})}function br(A){return!Number.isInteger(A)||A<8||A>512||A%8!==0?new Error("Invalid variant! Valid values: 8, 16, ..., 512"):null}function Xc(A,a){return A|a<<16}function Yo(A=512,a=null){if(br(A))return Promise.reject(br(A));let e=null,t=A;if(a!==null){if(e=mt(a),e.length>64)return Promise.reject(new Error("Max key length is 64 bytes"));t=Xc(A,e.length)}let i=A/8;return Tr(Wc,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 Zc(A,a,e){let t=[`m=${a.memorySize}`,`t=${a.iterations}`,`p=${a.parallelism}`].join(",");return`$argon2${a.hashType}$v=19$${t}$${Sr(A,!1)}$${Sr(e,!1)}`}function It(A){return Dr.setInt32(0,A,!0),new Uint8Array(Dr.buffer)}function Jo(A,a,e){return Wt(this,void 0,void 0,function*(){if(e<=64){let r=yield Yo(e*8);return r.update(It(e)),r.update(a),r.digest("binary")}let t=Math.ceil(e/32)-2,i=new Uint8Array(e);A.init(),A.update(It(e)),A.update(a);let s=A.digest("binary");i.set(s.subarray(0,32),0);for(let r=1;r<t;r++)A.init(),A.update(s),s=A.digest("binary"),i.set(s.subarray(0,32),r*32);let n=e-32*t,o;return n===64?(o=A,o.init()):o=yield Yo(n*8),o.update(s),s=o.digest("binary"),i.set(s.subarray(0,n),t*32),i})}function jc(A){switch(A){case"d":return 0;case"i":return 1;default:return 2}}function _c(A){return Wt(this,void 0,void 0,function*(){var a;let{parallelism:e,iterations:t,hashLength:i}=A,s=mt(A.password),n=mt(A.salt),o=19,r=jc(A.hashType),{memorySize:l}=A,c=mt((a=A.secret)!==null&&a!==void 0?a:""),[d,h]=yield Promise.all([Tr($c,1024),Yo(512)]);d.setMemorySize(l*1024+1024);let p=new Uint8Array(24),f=new DataView(p.buffer);f.setInt32(0,e,!0),f.setInt32(4,i,!0),f.setInt32(8,l,!0),f.setInt32(12,t,!0),f.setInt32(16,o,!0),f.setInt32(20,r,!0),d.writeMemory(p,l*1024),h.init(),h.update(p),h.update(It(s.length)),h.update(s),h.update(It(n.length)),h.update(n),h.update(It(c.length)),h.update(c),h.update(It(0));let g=Math.floor(l/(e*4))*4,I=new Uint8Array(72),m=h.digest("binary");I.set(m);for(let E=0;E<e;E++){I.set(It(0),64),I.set(It(E),68);let y=E*g,v=yield Jo(h,I,1024);d.writeMemory(v,y*1024),y+=1,I.set(It(1),64),v=yield Jo(h,I,1024),d.writeMemory(v,y*1024)}let C=new Uint8Array(1024);Nr(C,d.calculate(new Uint8Array([]),l));let B=yield Jo(h,C,i);if(A.outputType==="hex"){let E=new Uint8Array(i*2);return $o(E,B,i)}return A.outputType==="encoded"?Zc(n,A,B):B})}function zo(A){return Wt(this,void 0,void 0,function*(){return ed(A),_c(Object.assign(Object.assign({},A),{hashType:"id"}))})}var le,Go,qo,Oo,Rc,kr,Fr,mt,qe,as,an,os,Oc,Ko,VA,Kc,Jc,qc,$c,Yc,zc,Vc,Wc,WA,Dr,ed,XA,ZA,jA,_A,eh,th,ih,sh,nh,oh,ah,rh,lh,ch,dh,Ah,hh,ph,gh,uh,fh,Ih,mh,Ch,Mr=de(()=>{le=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 Wt(this,void 0,void 0,function*(){let e=yield this.lock();try{return yield Promise.resolve(a())}finally{e()}})}};qo=Hc(),Oo=(Go=qo.Buffer)!==null&&Go!==void 0?Go:null,Rc=qo.TextEncoder?new qo.TextEncoder:null;kr=87,Fr=48;mt=Oo!==null?A=>{if(typeof A=="string"){let a=Oo.from(A,"utf8");return new Uint8Array(a.buffer,a.byteOffset,a.length)}if(Oo.isBuffer(A))return new Uint8Array(A.buffer,A.byteOffset,A.length);if(ArrayBuffer.isView(A))return new Uint8Array(A.buffer,A.byteOffset,A.byteLength);throw new Error("Invalid data type!")}:A=>{if(typeof A=="string")return Rc.encode(A);if(ArrayBuffer.isView(A))return new Uint8Array(A.buffer,A.byteOffset,A.byteLength);throw new Error("Invalid data type!")},qe="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",as=new Uint8Array(256);for(let A=0;A<qe.length;A++)as[qe.charCodeAt(A)]=A;an=16*1024,os=4,Oc=new le,Ko=new Map;VA=new le,Kc="argon2",Jc="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+AhBACACKQNwIAEpA3CFNwOACUEAIAIpA3ggASkDeIU3A4gJQQAgAikDgAEgASkDgAGFNwOQCUEAIAIpA4gBIAEpA4gBhTcDmAlBACACKQOQASABKQOQAYU3A6AJQQAgAikDmAEgASkDmAGFNwOoCUEAIAIpA6ABIAEpA6ABhTcDsAlBACACKQOoASABKQOoAYU3A7gJQQAgAikDsAEgASkDsAGFNwPACUEAIAIpA7gBIAEpA7gBhTcDyAlBACACKQPAASABKQPAAYU3A9AJQQAgAikDyAEgASkD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",qc="e4cdc523",$c={name:Kc,data:Jc,hash:qc},Yc="blake2b",zc="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",Vc="c6f286e6",Wc={name:Yc,data:zc,hash:Vc},WA=new le;Dr=new DataView(new ArrayBuffer(4));ed=A=>{var a;if(!A||typeof A!="object")throw new Error("Invalid options parameter. It requires an object.");if(!A.password)throw new Error("Password must be specified");if(A.password=mt(A.password),A.password.length<1)throw new Error("Password must be specified");if(!A.salt)throw new Error("Salt must be specified");if(A.salt=mt(A.salt),A.salt.length<8)throw new Error("Salt should be at least 8 bytes long");if(A.secret=mt((a=A.secret)!==null&&a!==void 0?a:""),!Number.isInteger(A.iterations)||A.iterations<1)throw new Error("Iterations should be a positive number");if(!Number.isInteger(A.parallelism)||A.parallelism<1)throw new Error("Parallelism should be a positive number");if(!Number.isInteger(A.hashLength)||A.hashLength<4)throw new Error("Hash length should be at least 4 bytes.");if(!Number.isInteger(A.memorySize))throw new Error("Memory size should be specified.");if(A.memorySize<8*A.parallelism)throw new Error("Memory size should be at least 8 * parallelism.");if(A.outputType===void 0&&(A.outputType="hex"),!["hex","binary","encoded"].includes(A.outputType))throw new Error(`Insupported output type ${A.outputType}. Valid values: ['hex', 'binary', 'encoded']`)};XA=new le,ZA=new le,jA=new le,_A=new le,eh=new Uint8Array(8),th=new le,ih=new le,sh=new le,nh=new le,oh=new le,ah=new le,rh=new le,lh=new le,ch=new le,dh=new le,Ah=new le,hh=new Uint8Array(8),ph=new le,gh=new Uint8Array(8),uh=new le,fh=new Uint8Array(8),Ih=new le,mh=new le,Ch=new le});function Ue(A){if(A.length<$e.length+1)return!1;for(let a=0;a<$e.length;a++)if(A[a]!==$e[a])return!1;return!0}function Pr(A,a,e){A[a]=e>>>24&255,A[a+1]=e>>>16&255,A[a+2]=e>>>8&255,A[a+3]=e&255}function Hr(A,a){return A[a]*16777216+(A[a+1]<<16)+(A[a+2]<<8)+A[a+3]}async function Wo(A,a,e){if(e.id===jo)return await zo({password:A,salt:a,parallelism:e.c,iterations:e.b,memorySize:e.a,hashLength:Vo,outputType:"binary"});if(e.id===Zo){let t=await crypto.subtle.importKey("raw",me(new TextEncoder().encode(A)),"PBKDF2",!1,["deriveBits"]),i=await crypto.subtle.deriveBits({name:"PBKDF2",salt:me(a),iterations:e.a,hash:"SHA-256"},t,Vo*8);return new Uint8Array(i)}throw new Error(`Unsupported KDF id (${e.id}).`)}async function rn(A){return crypto.subtle.importKey("raw",me(A),{name:"AES-GCM"},!1,["encrypt","decrypt"])}async function Ct(A,a){let e=crypto.getRandomValues(new Uint8Array(td)),t=crypto.getRandomValues(new Uint8Array(yi)),i,s,n;try{i={id:jo,a:sd,b:nd,c:od},n=await Wo(a,e,i),s="argon2id"}catch(d){console.warn("[Stashpad] Argon2id unavailable \u2014 encrypting with PBKDF2 fallback.",d),i={id:Zo,a:id,b:0,c:0},n=await Wo(a,e,i),s="pbkdf2"}let o=Ur(i,e,t),r=await rn(n),l=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:me(t),additionalData:me(o)},r,me(A))),c=new Uint8Array(o.length+l.length);return c.set(o,0),c.set(l,o.length),{data:c,kdf:s}}async function ls(){if(rs!==null)return rs;try{await zo({password:"x",salt:new Uint8Array(16),parallelism:1,iterations:1,memorySize:8,hashLength:16,outputType:"binary"}),rs=!0}catch{rs=!1}return rs}function Ur(A,a,e){let t=new Uint8Array($e.length+1+1+4+4+1+1+a.length+e.length),i=0;return t.set($e,i),i+=$e.length,t[i++]=Xo,t[i++]=A.id,Pr(t,i,A.a),i+=4,Pr(t,i,A.b),i+=4,t[i++]=A.c,t[i++]=a.length,t.set(a,i),i+=a.length,t.set(e,i),i+=e.length,t}async function wi(A,a){if(!Ue(A))throw new Error("Not an encrypted Stashpad file.");let e=A[$e.length];if(e===1)return ad(A,a);if(e!==Xo)throw new Error(`Unsupported encrypted .stash version (${e}).`);let t=$e.length+1,i={id:A[t++],a:0,b:0,c:0};if(i.a=Hr(A,t),t+=4,i.b=Hr(A,t),t+=4,i.c=A[t++],i.id===jo){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===Zo&&i.a>1e7)throw new Error("Unsupported KDF parameters (file may be corrupted or malicious).");let s=A[t++];if(s<8||s>64)throw new Error("Unsupported KDF parameters (file may be corrupted or malicious).");let n=A.slice(t,t+s);t+=s;let o=A.slice(t,t+yi);t+=yi;let r=A.slice(0,t),l=A.slice(t),c=await Wo(a,n,i),d=await rn(c),h=await crypto.subtle.decrypt({name:"AES-GCM",iv:me(o),additionalData:me(r)},d,me(l));return new Uint8Array(h)}async function ad(A,a){let e=$e.length+1,t=A.slice(e,e+16);e+=16;let i=A.slice(e,e+12);e+=12;let s=A.slice(e),n=await crypto.subtle.importKey("raw",me(new TextEncoder().encode(a)),"PBKDF2",!1,["deriveKey"]),o=await crypto.subtle.deriveKey({name:"PBKDF2",salt:me(t),iterations:21e4,hash:"SHA-256"},n,{name:"AES-GCM",length:256},!1,["decrypt"]),r=await crypto.subtle.decrypt({name:"AES-GCM",iv:me(i)},o,me(s));return new Uint8Array(r)}async function cs(A,a){if(a.length!==Vo)throw new Error("Encryption key must be 32 bytes.");let e=crypto.getRandomValues(new Uint8Array(yi)),i=Ur({id:Rr,a:0,b:0,c:0},new Uint8Array(0),e),s=await rn(a),n=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:me(e),additionalData:me(i)},s,me(A))),o=new Uint8Array(i.length+n.length);return o.set(i,0),o.set(n,i.length),o}async function Ye(A,a){if(!Ue(A))throw new Error("Not an encrypted Stashpad file.");let e=A[$e.length];if(e!==Xo)throw new Error(`Unsupported encrypted version (${e}).`);let t=$e.length+1;if(A[t++]!==Rr)throw new Error("Not a raw-key (.stashenc) envelope.");t+=9;let s=A[t++];t+=s;let n=A.slice(t,t+yi);t+=yi;let o=A.slice(0,t),r=A.slice(t),l=await rn(a),c=await crypto.subtle.decrypt({name:"AES-GCM",iv:me(n),additionalData:me(o)},l,me(r));return new Uint8Array(c)}async function Ei(A,a,e={}){if(!Ue(a))return a;if(e.secretId){let i=A.secretStorage,s=null;try{s=i?.getSecret(e.secretId)??null}catch{s=null}if(s)try{return await wi(a,s)}catch{}}let t;for(;;){let i=await new Promise(s=>{new ds(A,t,!!e.allowLater,s).open()});if(i.kind==="cancel")return null;if(i.kind==="later")return e.onLater?.(),null;try{return await wi(a,i.value)}catch{t="Wrong password or corrupted file. Try again."}}}var $e,Xo,Zo,jo,Rr,td,yi,Vo,id,sd,nd,od,me,_o,rs,Xt=de(()=>{"use strict";Mr();ve();$e=new Uint8Array([83,84,65,83,72,69,78,67]),Xo=2,Zo=1,jo=2,Rr=3,td=32,yi=12,Vo=32,id=6e5,sd=47104,nd=3,od=1,me=A=>A;_o={argon2id:{label:"Argon2id",strong:!0},pbkdf2:{label:"PBKDF2 (fallback)",strong:!1}};rs=null});var Zt,rd,vi,ln,Lr=de(()=>{"use strict";Zt=".stashpad/keys.json",rd=".stashpad",vi="_keys",ln=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(Zt);if(a)return a;try{let t=((await this.a.list(vi)).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(Zt))return!0}catch{}try{return((await this.a.list(vi)).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(rd);let t=`${Zt}.tmp`,i=!1;try{await this.a.write(t,e);try{await this.a.rename(t,Zt)}catch{try{await this.a.remove(Zt)}catch{}await this.a.rename(t,Zt)}i=!0}catch{try{await this.a.exists(t)&&await this.a.remove(t)}catch{}}i||await this.a.write(Zt,e),await this.ensureDir(vi);for(let s=4;s>=1;s--){let n=`${vi}/keys-${s}.json`,o=`${vi}/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(`${vi}/keys-1.json`,e)}catch{}}}});function ea(A){let a="";for(let e=0;e<A.length;e++)a+=String.fromCharCode(A[e]);return btoa(a)}function cd(A){let a=atob(A),e=new Uint8Array(a.length);for(let t=0;t<a.length;t++)e[t]=a.charCodeAt(t);return e}var ld,Gr,cn,dn,Or=de(()=>{"use strict";Xt();pt();ld=".stashkey",Gr=32;cn=()=>new Date().toISOString(),dn=class{constructor(a){this.app=a}get a(){return this.app.vault.adapter}keyPath(a){return`${a.replace(/\/+$/,"")}/${ld}`}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(Gr)),s=await Ct(i,e);return{sk:{v:1,keyId:t??he(8),folderPath:a.replace(/\/+$/,""),slots:[{id:he(8),label:"Folder password",wrapped:ea(s.data),kdf:s.kdf,createdAt:cn()}],createdAt:cn()},dek:i}}async unlock(a,e){for(let t of a.slots)try{let i=await wi(cd(t.wrapped),e);if(i.length!==Gr){i.fill(0);continue}return i}catch{}return null}async changePassword(a,e,t){if(!t)throw new Error("Password required.");let i=await Ct(e,t),s=a.slots.filter(o=>o.recovery),n={id:he(8),label:"Folder password",wrapped:ea(i.data),kdf:i.kdf,createdAt:cn()};return{...a,slots:[n,...s]}}async setRecovery(a,e,t){if(!t)throw new Error("Recovery password required.");let i=await Ct(e,t),s=a.slots.filter(o=>!o.recovery),n={id:he(8),label:"Recovery password",wrapped:ea(i.data),kdf:i.kdf,createdAt:cn(),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)}}});function hn(){return{}}function Ad(A){let a="";for(let e=0;e<A.length;e++)a+=String.fromCharCode(A[e]);return btoa(a)}function hd(A){let a=atob(A),e=new Uint8Array(a.length);for(let t=0;t<a.length;t++)e[t]=a.charCodeAt(t);return e}var dd,An,ta=de(()=>{"use strict";Xt();pt();Lr();Or();dd="stashpad-vault-encryption";An=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 ln(a),this.folderKeystore=new dn(a)}argonProbe(){return ls()}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 wi(hd(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 u=await this.folderKeystore.changePassword(r,o,e);await this.folderKeystore.write(n,u),this.folderKeyFiles.set(n,u);let g=this.folderKcId(n,u.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(u=>!u.label.startsWith("[deprecated]")),c=this.folderKcIdFor(s),d=this.rememberedFolderPassword(c);if(d&&l[0])try{await this.parkThenSet(`${c}-d-${l[0].id}`,d)}catch{}let h=await Ct(o,e),p=s.passwordSlots.map(u=>u.label.startsWith("[deprecated]")?u:{...u,label:`[deprecated] ${u.label}`}),f={...s,kcId:s.kcId??this.folderKcId(s.label,s.keyId),passwordSlots:[{id:he(8),label:"Folder password",wrapped:Ad(h.data),kdf:h.kdf,createdAt:new Date().toISOString()},...p]};this.kf.folderKeys={...this.kf.folderKeys??{},[n]:f},await this.keyfiles.save(this.kf),(t||this.isFolderRemembered(c))&&await this.rememberFolder(this.folderKcIdFor(f),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||`${dd}-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()}}});function gn(A){if(As!==A){As=A;for(let a of pn)a()}}function Bt(){return As}function Kr(A){if(As===A){As=null;for(let a of pn)a()}}function Jr(A){return pn.add(A),()=>pn.delete(A)}var As,pn,un=de(()=>{"use strict";As=null,pn=new Set});function pd(){return P.Platform.isMacOS?"Finder":P.Platform.isWin?"File Explorer":"file manager"}function na(){let A={};for(let a of jt)A[a.id]={primary:a.defaultPrimary,secondary:a.defaultSecondary??"",preferRight:!1,useBoth:!!a.defaultUseBoth};return A}function X(){return qr}function hs(A){qr=A;for(let a of sa)a()}function $r(A){return sa.add(A),()=>sa.delete(A)}function mn(A){try{let a=A.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}}function gd(A,a){return ia||(ia=class extends P.SettingPage{constructor(e,t){super(),this.title=e,this._renderFn=t}display(){this.containerEl.empty(),this._renderFn(this.containerEl)}}),new ia(A,a)}var P,jt,Mt,qr,sa,fn,ia,In,Fi=de(()=>{"use strict";P=require("obsidian");ss();Br();yr();ce();ve();on();Qr();fi();pt();Tt();ta();un();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 Obsidian editor",desc:"Open the cursor row (or focused note) in a regular Obsidian markdown tab.",defaultPrimary:"Mod+Shift+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:"edit",label:"Edit note in Stashpad",desc:"Edit the cursor row (or focused note) in Stashpad's own editor (with a Split toggle) instead of a full Obsidian tab.",defaultPrimary:"E"},{id:"editParent",label:"Edit parent note in Stashpad",desc:"Edit the focused parent note in Stashpad's own editor.",defaultPrimary:"Shift+E"},{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\u2026",desc:"Open the export dialog for the selected subtree(s) \u2014 pick .stash / OKF / plain .zip and full/frontmatter/body content.",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:"openAllTasks",label:"Open all tasks (aggregate view)",desc:"Default: Shift+T \u2014 open the aggregate \u201CAll tasks\u201D view collecting tasks across every Stashpad folder.",defaultPrimary:"Shift+T"},{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"}];Mt={folder:"Stashpad",importDropFolder:"",exportFolder:"_exports",autoImport:!1,inheritObsidianExclusions:!0,folderPanelPinnedFraction:.5,folderPanelPinned:[],folderPanelPinnedAt:{},folderPanelGroupItemOrder:{},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:hn(),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,foldersAlwaysNewTab:!1,importExcludePrefixes:"_",lockedSubtrees:[],searchOpensInNewTab:!0,pinnedNotes:[],hideMobileToolbarInStashpad:!0,slugStopWords:[],searchIncludedFolders:[],searchExcludedFolders:[],shortcuts:{move:"M",pickMove:"O",merge:"&",copy:"C",copyTree:"Y",openEditor:"Mod+Shift+E",openTab:"T",split:"S",edit:"E",editParent:"Shift+E",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:[],splitCheckboxLines:!0,autoNavOnMoveIn:!1,openParentTabOnMoveIn:!0,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:na()},qr=JSON.parse(JSON.stringify(Mt)),sa=new Set;fn=[{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((A,a)=>{let e=t=>t.replace(/^[^\p{L}\p{N}]+/u,"");return e(A.label).localeCompare(e(a.label))}),ia=null;In=class extends P.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 fn){new P.Setting(e).setName(t.label).setHeading();let i=this.itemsForTab(t.id);if(i)for(let s of i){let n=new P.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 fn.map(e=>{let t=this.itemsForTab(e.id);return t?{type:"page",name:e.label,items:t}:{type:"page",name:e.label,page:()=>gd(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 P.Notice("Debug trace is empty \u2014 enable it and reproduce the issue first.");return}try{await navigator.clipboard.writeText(i),new P.Notice("Debug trace copied.")}catch{new P.Notice("Couldn't access clipboard.")}})),e.addButton(t=>t.setButtonText("Clear").onClick(()=>{this.plugin.clearDebugTrace(),new P.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 P.Notice("No log yet \u2014 make some changes first.");return}let n=await i.read(s);new Qi(this.app,n,s).open()})),["log","history","diagnostics"])]}notificationsItems(){let e=new Set(this.plugin.settings.mutedNotificationCategories??[]),t=Object.keys(Uo);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=Uo[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 ps(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 P.Notice("No log yet \u2014 make some changes first.");return}let l=await o.read(r);new Qi(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 P.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 Le(this.app,{mode:"setup",offerKeychain:!0,title:`Set password for \u201C${e.split("/").pop()}\u201D`,intro:"A separate password just for this folder. Save it in a password manager BEFORE you continue \u2014 the device keychain is a convenience that can be wiped at any time, not a backup. There is NO recovery if it's lost: Stashpad cannot recover it, and everything encrypted under it becomes permanently unreadable.",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 P.Notice("Folder password set \u2014 share it securely."),this.update?.(),this.pfeRerender?.(),null}}).open()}promptChangeFolderPassword(e){new Le(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 P.Notice("Folder password changed."),this.update?.(),this.pfeRerender?.(),null}}).open()}promptSetFolderRecovery(e){let t=e.split("/").pop()||e;new Le(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 P.Notice("Recovery password set \u2014 keep it somewhere safe."),this.update?.(),this.pfeRerender?.(),null}}).open()}promptRemoveFolderRecovery(e){let t=e.split("/").pop()||e;new j(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 P.Notice(s.message);return}new P.Notice("Recovery password removed."),this.update?.(),this.pfeRerender?.()}}).open()}promptUnlockFolder(e){new Le(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 P.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 P.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",d=new P.Setting(e).setName("Password").setDesc(c);if(o?d.addButton(u=>u.setButtonText("Manage on parent folder").onClick(()=>{this.pfeSelected=n,this.update?.(),this.pfeRerender?.()})):s?r?d.addButton(u=>u.setButtonText("Change password\u2026").onClick(()=>this.promptChangeFolderPassword(t))):d.addButton(u=>u.setButtonText("Unlock\u2026").setCta().onClick(()=>this.promptUnlockFolder(t))):d.addButton(u=>u.setButtonText("Set folder password\u2026").setCta().onClick(()=>this.promptSetFolderPassword(t))),s&&r){let u=this.plugin.encryption.folderHasRecovery(t),g=new P.Setting(e).setName("Recovery password").setDesc(u?"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(u?"Change recovery\u2026":"Add recovery\u2026").onClick(()=>this.promptSetFolderRecovery(t))),u&&g.addButton(I=>{I.setButtonText("Remove recovery").onClick(()=>this.promptRemoveFolderRecovery(t)),I.buttonEl.addClass("mod-warning")})}let h=async u=>{this.plugin.settings.folderEncPrefs={...this.plugin.settings.folderEncPrefs??{},[t]:{...(this.plugin.settings.folderEncPrefs??{})[t]??{},...u}},await this.plugin.saveSettings()};new P.Setting(e).setName("Trash handling").setDesc("Where notes deleted from this folder go.").addDropdown(u=>u.addOption("","Stashpad trash (default)").addOption("obsidian","Obsidian native trash").setValue(l.trashHandling==="obsidian"?"obsidian":"").onChange(g=>h({trashHandling:g||void 0})));let p=(u,g,I,m,C=!1)=>{new P.Setting(e).setName(u).addToggle(B=>B.setValue(!!l[g]).onChange(async E=>{if(E&&C){if(!this.plugin.encryption.hasFolderKey(t)){new P.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]=E,E||(y[I]=!1),await h(y),m&&await m(E),this.pfeRerender?.()})),new P.Setting(e).setName(`\u21B3 ${u} \u2014 hide filenames`).setClass("stashpad-subsetting").addToggle(B=>{B.setValue(!!l[I]),B.setDisabled(!l[g]),B.onChange(async E=>{let y={};y[I]=E,await h(y),this.pfeRerender?.()})})};p("Encrypt this folder's notes","encryptContent","encryptFilenames",async u=>{u?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 u=>{if(!u)return;let g=this.plugin.archivedPlainNotesIn(`${t}/archive`).length;g!==0&&new j(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 P.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 P.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(u=>{u.setPlaceholder("global"),u.setValue(l.reEncryptAfterMin==null?"":String(l.reEncryptAfterMin)),u.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)}):u.setValue(l.reEncryptAfterMin==null?"":String(l.reEncryptAfterMin))}})});let f=this.plugin.discoverStashpadFolders().filter(u=>u!==t&&u.startsWith(t+"/")).sort();if(f.length){new P.Setting(e).setName("Subfolders").setDesc(`${f.length} subfolder${f.length===1?"":"s"} \u2014 they use \u201C${t.split("/").pop()}\u201D's password. Encrypt each individually.`).setHeading();for(let u of f){let g=(this.plugin.settings.folderEncPrefs??{})[u]??{},I=async B=>{this.plugin.settings.folderEncPrefs={...this.plugin.settings.folderEncPrefs??{},[u]:{...(this.plugin.settings.folderEncPrefs??{})[u]??{},...B}},await this.plugin.saveSettings()},m=(this.plugin.settings.lockedSubtrees??[]).some(B=>(B.folder||"").replace(/\/+$/,"")===u),C=u.slice(t.length+1);new P.Setting(e).setName(C).addToggle(B=>B.setValue(m).onChange(async E=>{E?await this.plugin.lockFolder(u):await this.plugin.unlockFolder(u);let y=(this.plugin.settings.lockedSubtrees??[]).some(v=>(v.folder||"").replace(/\/+$/,"")===u);await I({encryptContent:y,...y?{}:{encryptFilenames:!1}}),this.update?.(),this.pfeRerender?.()})),new P.Setting(e).setName(`\u21B3 ${C} \u2014 hide filenames`).setClass("stashpad-subsetting").addToggle(B=>{B.setValue(!!g.encryptFilenames),B.setDisabled(!m),B.onChange(E=>void I({encryptFilenames:E}))})}}}buildGeneralCategories(){let e=async()=>this.plugin.saveSettings(),t=(s,n,o,r,l)=>this.renderDef(s,n,c=>c.addToggle(d=>d.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 mi(this.app,n.inputEl),n.setValue(this.plugin.settings.folder).setPlaceholder("Stashpad");let o=async()=>{let r=(n.getValue()||"").trim().replace(/^\/+|\/+$/g,"")||Mt.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(d=>(d??"").trim().replace(/^\/+|\/+$/g,"")).filter(Boolean));if(l.some(d=>c.has(d))){new P.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 d=c.trim();d&&(0,P.setIcon)(r,d)};s.addDropdown(c=>{for(let d of n)c.addOption(d,d.split("/").pop()||d);c.setValue(this.iconPickFolder),c.onChange(d=>{this.iconPickFolder=d;let h=this.plugin.getFolderIcon(d)??"";o?.setValue(h),l(h)})}),s.addText(c=>{o=c,c.setPlaceholder("type to search\u2026 (e.g. rocket)"),new sn(this.app,c.inputEl),c.setValue(this.plugin.getFolderIcon(this.iconPickFolder)??""),c.onChange(async d=>{l(d),await this.plugin.setFolderIcon(this.iconPickFolder,d.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,"")||Mt.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: ${it(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=mn(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(d=>d.trim()).filter(d=>/^\d+\s*[mhdw]$/i.test(d)).map(d=>d.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.composerCopy.push(t("Split a pasted checklist into separate tasks",'When every line of what you submit is a checkbox \u2014 "- [ ] milk", "[x] eggs" \u2014 create one task per line instead of a single note. Applies even when "split on newlines" is off. On by default.',()=>this.plugin.settings.splitCheckboxLines,s=>{this.plugin.settings.splitCheckboxLines=s},["checkbox","task","split","paste","checklist"])),i.movingNotes.push(t("Open the new parent in a background tab after moving a note IN","When you nest a note into another note, open that parent in a background Stashpad tab so its new home is one click away \u2014 without stealing focus from what you're doing. Skipped when the destination is Home or already open in a tab. On by default.",()=>this.plugin.settings.openParentTabOnMoveIn,s=>{this.plugin.settings.openParentTabOnMoveIn=s},["background","tab","move","in","parent"])),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 P.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 P.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 P.Notice("Enter a folder name first.");return}try{await this.plugin.createNewStashpad(l),new P.Notice(`Created Stashpad "${l}".`),o&&(o.value=""),await this.plugin.waitForStashpadFolder(l,2e3),this.update?.()}catch(c){new P.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 P.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:st).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=[...st],n&&(n.value=st.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.windowsTabs.push(t("Folders always open in a new tab","When you open a folder (folders panel, folder switcher, or the file-explorer \u201COpen folder in Stashpad\u201D), always open a NEW tab at the home note instead of reusing an already-open tab. The folder switcher also drops its \u201CReveal <folder> tab\u201D option. Off by default (reuses an existing tab when there is one).",()=>this.plugin.settings.foldersAlwaysNewTab,s=>{this.plugin.settings.foldersAlwaysNewTab=s},["folder","new tab","reveal","open","panel"])),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,d)=>{let h=o.createEl("p",{cls:"stashpad-enc-info-item"});h.createEl("strong",{text:`${c} \u2014 `}),h.appendText(d)};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 P.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 d=async()=>{let p=await this.plugin.encryptionStateStrict();if(p.live){let u=()=>{new j(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 P.Notice(`Deleted ${m} locked item${m===1?"":"s"}.`),d()},"Cancel",!0).open()},g=async()=>{if(await this.plugin.unlockAllInVault(),(await this.plugin.encryptionStateStrict()).live){new P.Notice("Some notes are still locked (decryption was cancelled or failed) \u2014 removal cancelled.",1e4);return}d()};new j(this.app,"Encrypted notes are still locked",`Some notes or folders are still encrypted (locked) and have no plaintext copy. Before removing encryption: +`)),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.windowsTabs.push(t("Folders always open in a new tab","When you open a folder (folders panel, folder switcher, or the file-explorer \u201COpen folder in Stashpad\u201D), always open a NEW tab at the home note instead of reusing an already-open tab. The folder switcher also drops its \u201CReveal <folder> tab\u201D option. Off by default (reuses an existing tab when there is one).",()=>this.plugin.settings.foldersAlwaysNewTab,s=>{this.plugin.settings.foldersAlwaysNewTab=s},["folder","new tab","reveal","open","panel"])),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","Encrypt notes per folder with a password you choose. Keep that password in a password manager \u2014 there is no recovery if it is lost.",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",{cls:"stashpad-enc-lead"}).setText("\u26A0\uFE0F Write your password down somewhere outside this computer \u2014 a password manager \u2014 BEFORE you encrypt anything."),n.createEl("p").setText("\u201CRemember on this device (keychain)\u201D is a convenience, NOT a backup. An OS or keychain reset, a wiped/restored profile, a reinstall, a new machine, or an IT/server event can erase it at any time, without warning and without asking you. If the only copy of your password was in the keychain, everything encrypted under it is permanently unreadable \u2014 by you, by us, by anyone."),n.createEl("p").setText("Store the password in a password manager (1Password, Bitwarden, KeePass\u2026), and set a Recovery password as a second way in. Both are stored outside the keychain, so they survive the events above."),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."),n.createEl("p",{cls:"stashpad-enc-liability"}).setText("Stashpad cannot recover keys or passwords, and is not liable for the loss of keys, passwords, or any data encrypted with them. Backing them up is yours to do.");let o=i.createEl("details",{cls:"stashpad-enc-info"});o.createEl("summary",{text:"\u2139\uFE0F How Stashpad encryption works (concepts)"});let r=(c,d)=>{let h=o.createEl("p",{cls:"stashpad-enc-info-item"});h.createEl("strong",{text:`${c} \u2014 `}),h.appendText(d)};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 P.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 d=async()=>{let p=await this.plugin.encryptionStateStrict();if(p.live){let u=()=>{new j(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 P.Notice(`Deleted ${m} locked item${m===1?"":"s"}.`),d()},"Cancel",!0).open()},g=async()=>{if(await this.plugin.unlockAllInVault(),(await this.plugin.encryptionStateStrict()).live){new P.Notice("Some notes are still locked (decryption was cancelled or failed) \u2014 removal cancelled.",1e4);return}d()};new j(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?g():u()},"Delete locked content").open();return}let f=(u,g)=>{new ki(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.${u} 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 P.Notice("Locked notes appeared while this dialog was open \u2014 removal cancelled. Decrypt everything first.",1e4);return}if(I.trash&&!g){new P.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 C of m)await this.plugin.purgeDeletedAt(C.blob);await e.clear(),new P.Notice("Encryption removed."),this.update?.()}}).open()};if(p.trash){let u=async()=>{let I=await this.plugin.restoreAllTrash();if((await this.plugin.encryptionStateStrict()).trash){new P.Notice("Some encrypted-trash items couldn't be decrypted \u2014 removal cancelled. Check the trash tab and try again.",1e4);return}f(I>0?` (${I} trash item${I===1?"":"s"} were decrypted back to their folders.)`:"",!0)},g=()=>{new j(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&&f(" \u26A0\uFE0F The encrypted trash is being permanently discarded.",!0)},"Cancel",!0).open()};new j(this.app,"Encrypted notes in the trash",`There are encrypted, deleted notes in the trash. Removing encryption makes them PERMANENTLY unreadable. @@ -22,7 +22,7 @@ `:"")+f)}if(!s)return;let n=a.selectionStart,o=a.selectionEnd,r=a.value.slice(0,n),l=a.value.slice(o),d=(r&&!r.endsWith(` `)?` `:"")+s+` -`;a.value=r+d+l,this.cursorText=a.value;let h=r.length+d.length;a.setSelectionRange(h,h),a.dispatchEvent(new Event("input")),a.focus()};a.addEventListener("paste",i=>{let s=i.clipboardData;if(!s)return;let n=[];for(let o of Array.from(s.files??[]))n.push(o);if(n.length===0){for(let o of Array.from(s.items??[]))if(o.kind==="file"){let r=o.getAsFile();r&&n.push(r)}}n.length!==0&&(i.preventDefault(),i.stopPropagation(),t(n))}),a.addEventListener("dragover",i=>{if(!(!i.dataTransfer||!Array.from(i.dataTransfer.types).includes("Files"))){i.preventDefault(),i.stopPropagation();try{i.dataTransfer.dropEffect="copy"}catch{}}}),a.addEventListener("drop",i=>{let s=Array.from(i.dataTransfer?.files??[]);s.length!==0&&(i.preventDefault(),i.stopPropagation(),t(s))})}destroy(){this.autocomplete?.detach(),this.autocomplete=null}async commit(){if(this.surface==="edit"){await this.saveEdit();return}this.mode==="line"?await this.commitLine():this.mode==="cursor"?await this.commitCursor():await this.commitPreset()}async saveEdit(){let a=this.cursorTextarea;a&&(await this.cb.onSave(a.value),this.cb.onDone())}isDirty(){return(this.cursorTextarea?.value??this.cursorText)!==this.body}setSurface(a){this.surface!==a&&(this.surface=a,this.render())}moveDivider(a){return this.mode!=="line"?!1:(this.lineCursorIdx=Math.max(1,Math.min(this.lines.length-1,this.lineCursorIdx+a)),this.render(),!0)}async commitLine(){await this.cb.onSplitAtLine(this.lineCursorIdx,this.nest),this.cb.onDone()}async commitCursor(){let a=this.cursorTextarea;if(!a)return;let e=a.selectionStart;if(e<=0||e>=a.value.length){new G.Notice("Move the cursor inside the text \u2014 neither end can be empty.");return}await this.cb.onSplitAtChar(a.value,e,this.nest),this.cb.onDone()}async commitPreset(){let a=Yt(this.body,this.presetMode);if(a.length<2){new G.Notice("That delimiter wouldn't split this note.");return}await this.cb.onSplitMany(a,this.nest),this.cb.onDone()}render(){if(this.autocomplete?.detach(),this.autocomplete=null,this.host.empty(),this.host.toggleClass("stashpad-edit-surface",this.surface==="edit"),this.cb.onTitle?.(this.surface==="edit"?"Edit note":"Split note"),this.renderSurfaceToggle(),this.surface==="edit"){this.renderEditSurface();return}this.renderSplitSurface()}renderSurfaceToggle(){let a=this.host.createDiv({cls:"stashpad-split-surface"}),e=G.Platform.isMacOS?"\u2318":"Ctrl+",t=(i,s,n,o)=>{let r=a.createEl("button",{cls:"stashpad-split-surface-btn"});(0,G.setIcon)(r.createSpan({cls:"stashpad-split-btn-icon"}),n),r.createSpan({text:i}),r.createSpan({cls:"stashpad-split-kbd-hint",text:`${e}${o}`}),r.toggleClass("is-active",this.surface===s),r.onmousedown=l=>l.preventDefault(),r.onclick=()=>this.setSurface(s)};t("Edit","edit","pencil-line","E"),t("Split","split","split","S")}renderPopOut(a){if(!this.cb.popOut)return;let e=a.createEl("button",{cls:"stashpad-split-popout-btn"});(0,G.setIcon)(e.createSpan({cls:"stashpad-split-popout-icon"}),"maximize-2"),e.createSpan({text:G.Platform.isMobile?"Pop-out":"Open in a tab"}),e.setAttr("aria-label","Open in a full tab"),e.onmousedown=t=>t.preventDefault(),e.onclick=()=>this.cb.popOut(this.getState())}renderOpenExternal(a){if(!this.cb.onOpenExternal)return;let e=a.createEl("button",{cls:"stashpad-split-popout-btn"});(0,G.setIcon)(e.createSpan({cls:"stashpad-split-popout-icon"}),"pencil"),e.createSpan({text:G.Platform.isMobile?"Advanced":"Obsidian editor"}),e.setAttr("aria-label","Open in a full Obsidian editor tab"),e.onmousedown=t=>t.preventDefault(),e.onclick=()=>{this.cb.onOpenExternal(),this.cb.close()}}renderEditSurface(){this.renderEditorSections();let a=this.host.createDiv({cls:"stashpad-split-edit-tools"}),e=a.createSpan({cls:"stashpad-split-count"}),t=()=>{let c=this.cursorTextarea?.value??"",d=(c.trim().match(/\S+/g)||[]).length;e.setText(`${d} word${d===1?"":"s"} \xB7 ${c.length} char${c.length===1?"":"s"}`)},i=a.createEl("button",{cls:"stashpad-split-case-btn"});(0,G.setIcon)(i.createSpan({cls:"stashpad-split-btn-icon"}),"case-sensitive"),i.createSpan({text:"Case"}),i.setAttr("aria-label","Cycle case of the selection (or all text): lower \u2192 UPPER \u2192 Title \u2192 Sentence"),i.onmousedown=c=>c.preventDefault(),i.onclick=()=>this.cycleCase(t),this.cursorTextarea?.addEventListener("input",t),t();let s=this.host.createDiv({cls:"stashpad-split-help"});G.Platform.isPhone||s.setText("Edit the note, then Save. \xB7 \u2318/Ctrl+Enter or Save to write \xB7 \u2318/Ctrl+S \u2192 Split \xB7 Esc discards.");let n=this.host.createDiv({cls:"stashpad-split-actions"}),o=n.createEl("button",{cls:"stashpad-split-cancel-btn"});(0,G.setIcon)(o.createSpan({cls:"stashpad-split-btn-icon"}),"x"),o.createSpan({text:"Cancel"}),o.createSpan({cls:"stashpad-split-esc-hint",text:" (Esc)"}),o.onmousedown=c=>c.preventDefault(),o.onclick=()=>this.cb.close(),this.renderPopOut(n),this.renderOpenExternal(n);let l=n.createDiv({cls:"stashpad-split-actions-right"}).createEl("button",{cls:"stashpad-split-confirm-btn mod-cta"});(0,G.setIcon)(l.createSpan({cls:"stashpad-split-btn-icon"}),"save"),l.createSpan({text:"Save"}),l.onmousedown=c=>c.preventDefault(),l.onclick=()=>void this.commit()}cycleCase(a){let e=this.cursorTextarea;if(!e)return;let t=e.selectionStart!==e.selectionEnd,i=t?e.selectionStart:0,s=t?e.selectionEnd:e.value.length,n=e.value.slice(i,s),o=["lower","upper","title","sentence"],r=o[this.caseCycleIndex%o.length];this.caseCycleIndex+=1;let l=fd(n,r);e.value=e.value.slice(0,i)+l+e.value.slice(s),e.setSelectionRange(i,i+l.length),this.cursorText=e.value,e.dispatchEvent(new Event("input")),a(),e.focus()}renderSplitSurface(){let a=this.host.createDiv({cls:"stashpad-split-modes"}),e=(p,f,u,g,I=!1)=>{let m=a.createEl("button",{cls:"stashpad-split-mode-btn"});(0,G.setIcon)(m.createSpan({cls:"stashpad-split-btn-icon"}),g),m.createSpan({text:p}),m.toggleClass("is-active",f),m.disabled=I,m.onmousedown=C=>C.preventDefault(),I||(m.onclick=u)};this.lines.length>=2&&e("Line",this.mode==="line",()=>{this.mode="line",this.render()},"separator-horizontal"),e("Cursor",this.mode==="cursor",()=>{this.mode="cursor",this.render()},"text-cursor-input");let t={lines:"list",paragraphs:"pilcrow",headings:"heading"};["lines","paragraphs","headings"].forEach(p=>{let f=Yt(this.body,p).length,u=f<2,g=p==="paragraphs"?"Blank line(s)":gi[p],I=u?g:`${g} (${f})`;e(I,this.mode==="preset"&&this.presetMode===p,()=>{this.mode="preset",this.presetMode=p,this.render()},t[p],u)}),this.mode==="line"?this.renderLineMode():this.mode==="cursor"?this.renderEditorSections():this.renderPresetMode();let i=this.host.createDiv({cls:"stashpad-split-help"}),s=()=>{if(G.Platform.isPhone){i.setCssStyles({display:"none"});return}i.setCssStyles({display:""});let p=this.nest?"New part nested under the original.":"New part added as a sibling.",f=this.nest?"New parts nested under the original.":"New parts added as siblings.",u="\u2318/Ctrl+Enter or Split to confirm";i.setText(this.mode==="line"?`\u2191/\u2193 or click to pick the split line \xB7 ${u} \xB7 ${p}`:this.mode==="cursor"?`Click or arrow to position the cursor \xB7 ${u} \xB7 ${p}`:`Preview of the resulting parts \xB7 ${u} \xB7 ${f}`)};s();let n=this.host.createDiv({cls:"stashpad-split-actions"}),o=n.createEl("button",{cls:"stashpad-split-cancel-btn"});(0,G.setIcon)(o.createSpan({cls:"stashpad-split-btn-icon"}),"x"),o.createSpan({text:"Cancel"}),o.createSpan({cls:"stashpad-split-esc-hint",text:" (Esc)"}),o.onmousedown=p=>p.preventDefault(),o.onclick=()=>this.cb.close(),this.renderPopOut(n),this.renderOpenExternal(n);let r=n.createDiv({cls:"stashpad-split-actions-right"}),l=r.createEl("label",{cls:"stashpad-split-nest"}),c=l.createEl("input",{type:"checkbox"});c.checked=this.nest,l.createSpan({text:"Nest under original"}),c.onchange=()=>{this.nest=c.checked,s()};let d=this.mode==="preset"?Yt(this.body,this.presetMode).length:0,h=r.createEl("button",{cls:"stashpad-split-confirm-btn mod-cta"});(0,G.setIcon)(h.createSpan({cls:"stashpad-split-btn-icon"}),"split"),h.createSpan({text:this.mode==="preset"&&d>=2?`Split into ${d}`:"Split"}),h.onmousedown=p=>p.preventDefault(),h.onclick=()=>this.commit()}renderPresetMode(){let a=Yt(this.body,this.presetMode),e=this.host.createDiv({cls:"stashpad-split-preset-list"});if(a.length<2){e.createDiv({cls:"stashpad-split-empty",text:"This delimiter wouldn't split the note into more than one part."});return}a.forEach((t,i)=>{let s=e.createDiv({cls:"stashpad-split-part-card"}),n=s.createDiv({cls:"stashpad-split-part-num"});n.createSpan({cls:"stashpad-split-part-title",text:`Part ${i+1}`}),n.appendChild(this.makeCopyButton(()=>t,`Copy part ${i+1}`)),s.createDiv({cls:"stashpad-split-part-body",text:t})})}renderLineMode(){let a=this.host.createDiv({cls:"stashpad-split-list"}),e=null;for(let t=0;t<this.lines.length;t++){t===this.lineCursorIdx&&(e=a.createDiv({cls:"stashpad-split-divider",text:"\u2500\u2500 split here \u2500\u2500"}));let i=a.createDiv({cls:"stashpad-split-line"});i.createSpan({cls:"stashpad-split-lineno",text:String(t+1)}),i.createSpan({cls:"stashpad-split-text",text:this.lines[t]||" "}),i.onclick=()=>{let s=Math.max(1,Math.min(this.lines.length-1,t+1));s!==this.lineCursorIdx&&(this.lineCursorIdx=s,this.render())}}e&&window.requestAnimationFrame(()=>e.scrollIntoView({block:"center"}))}buildSplitSection(a,e,t){let i=a.createDiv({cls:`stashpad-split-section stashpad-split-${e}`}),s=i.createEl("button",{cls:"stashpad-split-section-header"});s.setAttr("type","button");let n=s.createSpan({cls:"stashpad-split-chevron"});(0,G.setIcon)(n,"chevron-down"),s.createSpan({cls:"stashpad-split-section-title",text:t});let o=i.createDiv({cls:"stashpad-split-section-body"}),r=()=>{i.toggleClass("is-collapsed",this.collapsed[e]),s.setAttr("aria-expanded",String(!this.collapsed[e]))};return s.onmousedown=l=>l.preventDefault(),s.onclick=l=>{l.preventDefault(),this.collapsed[e]=!this.collapsed[e],r()},r(),{section:i,body:o}}makeCopyButton(a,e,t="stashpad-split-copy-btn"){let i=createEl("button",{cls:t});return(0,G.setIcon)(i,"copy"),i.setAttr("aria-label",e),i.onmousedown=s=>s.preventDefault(),i.onclick=s=>{s.preventDefault(),s.stopPropagation();let n=a();navigator.clipboard?.writeText(n).then(()=>new G.Notice("Copied to clipboard."),()=>new G.Notice("Couldn't access the clipboard."))},i}renderEditorSections(){if(G.Platform.isMobile){this.renderEditorTabbed();return}let a=this.buildSplitSection(this.host,"orig","Original \u2014 will be replaced");a.body.createDiv({cls:"stashpad-split-panel-body",text:this.body}),a.section.appendChild(this.makeCopyButton(()=>this.body,"Copy the original text","stashpad-split-copy-btn stashpad-split-section-copy"));let e=this.buildSplitSection(this.host,"changes","Changes"),t=e.body.createDiv({cls:"stashpad-split-panel-body stashpad-split-diff-body"}),s=this.buildSplitSection(this.host,"edit",this.surface==="edit"?"Your edit":"Your edit \u2014 the split uses this").body.createEl("textarea",{cls:"stashpad-split-cursor-ta"});s.value=this.cursorText,s.readOnly=!1,this.cursorTextarea=s,this.enhanceTextarea(s);let n=()=>{t.empty();for(let h of zr(this.body,s.value)){let p=h.t==="ins"?"stashpad-diff-ins":h.t==="del"?"stashpad-diff-del":"stashpad-diff-eq";t.createSpan({cls:p,text:h.s})}},o=()=>{let h=s.value!==this.body;a.section.setCssStyles({display:h?"":"none"}),e.section.setCssStyles({display:h?"":"none"}),h&&n()},r=parseFloat(getComputedStyle(s).lineHeight)||22,l=this.surface==="edit"?G.Platform.isMobile?10:40:G.Platform.isMobile?3:12,c=2,d=()=>{s.setCssStyles({height:"auto"});let h=Math.min(r*l+16,Math.round(window.innerHeight*.5)),p=Math.min(s.scrollHeight,h);s.setCssStyles({height:`${Math.max(p,r*c+16)}px`,overflowY:"auto"})};o(),requestAnimationFrame(()=>{d(),s.focus();let h=this.surface==="edit"?s.value.length:Math.floor(s.value.length/2);s.setSelectionRange(h,h)}),s.addEventListener("input",()=>{this.cursorText=s.value,d(),o()})}renderEditorTabbed(){let a=this.host.createDiv({cls:"stashpad-split-tabs"}),e=a.createDiv({cls:"stashpad-split-tabbar"}),t=a.createDiv({cls:"stashpad-split-tabbody"}),i=t.createDiv({cls:"stashpad-split-tabpanel stashpad-split-tabpanel-edit"}),s=i.createEl("textarea",{cls:"stashpad-split-cursor-ta"});s.value=this.cursorText,s.readOnly=!1,this.cursorTextarea=s,this.enhanceTextarea(s);let n=t.createDiv({cls:"stashpad-split-tabpanel"});n.createDiv({cls:"stashpad-split-tab-copybar"}).appendChild(this.makeCopyButton(()=>this.body,"Copy the original text","stashpad-split-copy-btn stashpad-split-tab-copy")),n.createDiv({cls:"stashpad-split-panel-body",text:this.body});let r=t.createDiv({cls:"stashpad-split-tabpanel"}),l=r.createDiv({cls:"stashpad-split-panel-body stashpad-split-diff-body"}),c=[{key:"edit",label:this.surface==="edit"?"Your edit":"Edit",panel:i},{key:"orig",label:"Original",panel:n},{key:"changes",label:"Changes",panel:r}],d={},h="edit",p=g=>{h=g;for(let I of c)I.panel.toggleClass("is-active",I.key===g),d[I.key]?.toggleClass("is-active",I.key===g);g==="edit"&&s.focus()};for(let g of c){let I=e.createEl("button",{cls:"stashpad-split-tab",text:g.label});I.onmousedown=m=>m.preventDefault(),I.onclick=()=>p(g.key),d[g.key]=I}let f=()=>{l.empty();for(let g of zr(this.body,s.value)){let I=g.t==="ins"?"stashpad-diff-ins":g.t==="del"?"stashpad-diff-del":"stashpad-diff-eq";l.createSpan({cls:I,text:g.s})}},u=()=>{let g=s.value!==this.body;d.orig.toggleClass("is-hidden",!g),d.changes.toggleClass("is-hidden",!g),g&&f(),!g&&(h==="orig"||h==="changes")&&p("edit")};s.setCssStyles({overflowY:"auto"}),u(),p("edit"),requestAnimationFrame(()=>{s.focus();let g=this.surface==="edit"?s.value.length:Math.floor(s.value.length/2);s.setSelectionRange(g,g)}),s.addEventListener("input",()=>{this.cursorText=s.value,u()})}},Bs="stashpad-split-view",bi=class extends G.Modal{constructor(e,t,i,s={}){super(e);this.body=t;this.cbs=i;this.init=s;this.ui=null;this.committing=!1}onOpen(){this.modalEl.addClass("stashpad-split-modal"),this.ui=new us(this.app,this.contentEl,this.body,this.init,{onSplitAtLine:this.cbs.onSplitAtLine,onSplitAtChar:this.cbs.onSplitAtChar,onSplitMany:this.cbs.onSplitMany,onSave:this.cbs.onSave,onOpenExternal:this.cbs.onOpenExternal,onImportFile:this.cbs.onImportFile,close:()=>this.close(),onDone:()=>{this.committing=!0,this.close()},onTitle:e=>this.titleEl.setText(e),popOut:this.cbs.popOut?e=>{this.committing=!0,this.close(),this.cbs.popOut(e)}:void 0}),this.scope.register(["Mod"],"Enter",e=>{e.preventDefault(),this.ui?.commit()}),this.scope.register([],"ArrowUp",e=>{this.ui?.moveDivider(-1)&&e.preventDefault()}),this.scope.register([],"ArrowDown",e=>{this.ui?.moveDivider(1)&&e.preventDefault()}),this.scope.register(["Mod"],"e",e=>{e.preventDefault(),this.ui?.setSurface("edit")}),this.scope.register(["Mod"],"s",e=>{e.preventDefault(),this.ui?.setSurface("split")}),this.scope.register(["Mod","Shift"],"e",e=>{e.preventDefault(),this.cbs.onOpenExternal&&(this.cbs.onOpenExternal(),this.close())})}close(){if(this.committing||!this.ui?.isDirty()){super.close();return}new j(this.app,"Discard unsaved edits?","You've edited this note but haven't saved. Close and discard your changes?","Discard",e=>{e&&(this.committing=!0,this.close())},"Keep editing",!0).open()}onClose(){this.ui?.destroy(),this.ui=null,this.contentEl.empty()}},Di=class extends G.ItemView{constructor(e){super(e);this.ui=null;this.ctx=null;this.prevLeaf=null;this.autoCloseTimer=null;this.expiredGrace=null;this.title="Note";this.viewIcon="pencil-line";this.closingIntentionally=!1}getViewType(){return Bs}getDisplayText(){return this.title}getIcon(){return this.viewIcon}setHeader(e,t){this.title=e,this.viewIcon=t,this.leaf.updateHeader?.()}setContext(e){this.expiredGrace!=null&&(window.clearTimeout(this.expiredGrace),this.expiredGrace=null),this.ctx=e,this.prevLeaf=e.prevLeaf??null;let t=e.init.surface==="edit";this.setHeader(t?"Edit note":"Split note",t?"pencil-line":"split"),this.renderUI()}async onOpen(){this.contentEl.addClass("stashpad-split-modal","stashpad-split-view"),this.ctx||(this.expiredGrace=window.setTimeout(()=>{this.expiredGrace=null,this.ctx||this.renderExpired()},800))}renderUI(){let e=this.contentEl;e.empty(),e.addClass("stashpad-split-modal","stashpad-split-view"),this.ctx&&(this.ui=new us(this.app,e,this.ctx.body,this.ctx.init,{onSplitAtLine:this.ctx.cbs.onSplitAtLine,onSplitAtChar:this.ctx.cbs.onSplitAtChar,onSplitMany:this.ctx.cbs.onSplitMany,onSave:this.ctx.cbs.onSave,onOpenExternal:this.ctx.cbs.onOpenExternal,onImportFile:this.ctx.cbs.onImportFile,close:()=>this.guardedDetach(),onDone:()=>this.startClosePanel("\u2713 Done.",null,!0),onTitle:t=>this.setHeader(t,t.startsWith("Edit")?"pencil-line":"split")}),this.registerDomEvent(e,"keydown",t=>{let i=t.metaKey||t.ctrlKey;i&&t.shiftKey&&(t.key==="e"||t.key==="E")?(t.preventDefault(),this.ctx?.cbs.onOpenExternal?.(),this.guardedDetach()):i&&t.key==="Enter"?(t.preventDefault(),this.ui?.commit()):i&&!t.shiftKey&&(t.key==="e"||t.key==="E")?(t.preventDefault(),this.ui?.setSurface("edit")):i&&(t.key==="s"||t.key==="S")?(t.preventDefault(),this.ui?.setSurface("split")):t.key==="ArrowUp"?this.ui?.moveDivider(-1)&&t.preventDefault():t.key==="ArrowDown"&&this.ui?.moveDivider(1)&&t.preventDefault()}))}renderExpired(){this.setHeader("Expired","clock"),this.startClosePanel("This session has expired.","It can't be restored \u2014 closing this tab\u2026",!1)}startClosePanel(e,t,i){let s=this.contentEl;s.empty(),this.ui?.destroy(),this.ui=null;let n=s.createDiv({cls:"stashpad-split-done"});n.createDiv({cls:"stashpad-split-done-title",text:e}),t&&n.createDiv({cls:"stashpad-split-countdown",text:t});let o=n.createDiv({cls:"stashpad-split-countdown"}),r=n.createDiv({cls:"stashpad-split-done-btns"}),l=r.createEl("button",{cls:"mod-cta",text:"Close now"}),c=r.createEl("button",{text:"Keep tab open"}),d=4,h=()=>o.setText(`Closing this tab in ${d}\u2026`),p=()=>{this.autoCloseTimer!=null&&(window.clearInterval(this.autoCloseTimer),this.autoCloseTimer=null)},f=()=>{p(),i?this.closeAndRefocus():this.leaf.detach()};h(),this.autoCloseTimer=window.setInterval(()=>{d-=1,d<=0?f():h()},1e3),l.onclick=f,c.onclick=()=>{p(),o.setText("Close this tab whenever you're ready."),c.remove(),l.setText("Close tab")}}guardedDetach(){if(!this.ui?.isDirty()){this.closingIntentionally=!0,this.leaf.detach();return}new j(this.app,"Discard unsaved edits?","You've edited this note but haven't saved. Close this tab and discard your changes?","Discard",e=>{e&&(this.closingIntentionally=!0,this.leaf.detach())},"Keep editing",!0).open()}leafStillOpen(e){let t=!1;return this.app.workspace.iterateAllLeaves(i=>{i===e&&(t=!0)}),t}closeAndRefocus(){let e=this.prevLeaf;this.closingIntentionally=!0,this.leaf.detach(),e&&this.leafStillOpen(e)&&this.app.workspace.setActiveLeaf(e,{focus:!0})}async onClose(){!this.closingIntentionally&&this.ui?.isDirty()&&new G.Notice("Closed the Stashpad editor with unsaved changes \u2014 they were discarded. Use Save (\u2318/Ctrl+Enter) next time.",7e3),this.autoCloseTimer!=null&&(window.clearInterval(this.autoCloseTimer),this.autoCloseTimer=null),this.expiredGrace!=null&&(window.clearTimeout(this.expiredGrace),this.expiredGrace=null),this.ui?.destroy(),this.ui=null,this.contentEl.empty()}};xi=class extends G.Modal{constructor(e,t,i,s,n={}){super(e);this.defaultBaseName=t;this.noteCount=i;this.onConfirm=s;this.opts=n;this.delivered=!1}onOpen(){this.contentEl.empty();let e=!!this.opts.locked;this.titleEl.setText(e?"Export encrypted bundle":"Export"),this.modalEl.addClass("stashpad-export-modal"),this.contentEl.createEl("p",{cls:"stashpad-export-desc",text:e?`Re-export this locked bundle (${this.noteCount} note${this.noteCount===1?"":"s"}) as a shareable .stash.`:`Export ${this.noteCount} note${this.noteCount===1?"":"s"}.`});let t=this.contentEl.createDiv({cls:"stashpad-export-field"});t.createEl("label",{cls:"stashpad-export-label",text:"File name"});let i=t.createEl("input",{type:"text"});i.addClass("stashpad-export-name"),i.value=this.defaultBaseName;let s=this.contentEl.createEl("div",{cls:"stashpad-export-preview"}),n="full",o=()=>{},r=this.contentEl.createDiv();Id(r,Y=>{n=Y,o()}),e&&r.setCssStyles({display:"none"});let l="stash",c=this.contentEl.createDiv({cls:"stashpad-export-format"});c.createEl("label",{cls:"stashpad-export-label",text:"Format"});let d=c.createDiv({cls:"stashpad-export-content-seg"}),h=[{id:"stash",label:"Stashpad .stash"},...this.opts.okfEnabled?[{id:"okf",label:"OKF bundle"}]:[],{id:"zip",label:"Plain .zip"}],p=new Map;for(let Y of h){let be=d.createEl("button",{cls:"stashpad-export-content-opt",text:Y.label});be.toggleClass("is-active",Y.id===l),be.onclick=Be=>{Be.preventDefault(),l=Y.id,p.forEach((Pe,Ze)=>Pe.toggleClass("is-active",Ze===l)),o()},p.set(Y.id,be)}let f=this.contentEl.createDiv({cls:"stashpad-okf-formats"}),u=(Y,be)=>{let Be=f.createDiv({cls:"stashpad-okf-fmt"}),Pe=Be.createEl("input",{type:"checkbox"});return Pe.checked=be,Be.createEl("label",{text:Y}),Pe.onchange=()=>o(),Pe},g=u(".zip \u2014 OKF bundle (portable)",!0),I=u(".tar.gz \u2014 OKF bundle (tarball)",!1),m=f.createDiv({cls:"stashpad-export-pw-hint is-error"});m.setText("Pick at least one OKF format."),m.setCssStyles({display:"none"}),e&&c.setCssStyles({display:"none"});let C=this.contentEl.createDiv({cls:"stashpad-export-zipwarn"});C.setText("Frontmatter-only / body-only exports save as a plain .zip of the selected markdown (with referenced attachments) \u2014 not a re-importable .stash."),C.setCssStyles({display:"none"});let B=this.contentEl.createDiv({cls:"stashpad-export-encrypt"}),E=B.createDiv({cls:"stashpad-export-toggle"}),y=E.createEl("input",{type:"checkbox"});y.id="stashpad-export-encrypt-cb";let v=E.createEl("label",{text:"Encrypt with a password"});v.htmlFor=y.id;let Q=B.createDiv({cls:"stashpad-export-pw-area"});Q.setCssStyles({display:"none"});let w=[],k=Y=>{let be=Q.createDiv({cls:"stashpad-export-pw-row"}),Be=be.createEl("input",{type:"password"});Be.addClass("stashpad-export-name"),Be.placeholder=Y;let Pe=be.createEl("button",{cls:"stashpad-export-copy"}),Ze=()=>{let Ft=Be.value.length===0;Pe.setText(Ft?"Paste":"Copy"),Pe.toggleClass("is-paste",Ft),Pe.setAttr("aria-label",`${Ft?"Paste into":"Copy"} ${Y.toLowerCase()}`)};return Pe.onclick=async Ft=>{if(Ft.preventDefault(),Be.value.length===0)try{let Js=(await navigator.clipboard?.readText())?.trim();if(!Js){new G.Notice("Clipboard is empty.");return}Be.value=Js,Be.dispatchEvent(new Event("input")),new G.Notice("Pasted from clipboard.")}catch{new G.Notice("Couldn't read the clipboard.")}else navigator.clipboard?.writeText(Be.value).then(()=>new G.Notice("Passphrase copied to clipboard."),()=>new G.Notice("Couldn't access the clipboard."))},Ze(),w.push(Ze),Be},D=k("Password"),H=k("Confirm password"),R=Q.createDiv({cls:"stashpad-export-strength"}),L=R.createDiv({cls:"stashpad-strength-bar"}),x=[0,1,2,3].map(()=>L.createDiv({cls:"stashpad-strength-seg"})),U=R.createEl("span",{cls:"stashpad-strength-label"}),T=Q.createDiv({cls:"stashpad-export-genrow"}),b=T.createEl("button",{cls:"stashpad-export-gen",text:"Generate strong passphrase"}),M=T.createEl("button",{cls:"stashpad-export-show",text:"Show"}),O=Q.createEl("div",{cls:"stashpad-export-pw-hint"}),K=Q.createEl("div",{cls:"stashpad-export-pw-suite"});K.setText("Encryption: AES-256-GCM. Checking key-derivation suite for this device\u2026"),this.opts.kdfProbe?this.opts.kdfProbe().then(Y=>{K.toggleClass("is-weak",!Y),K.setText(Y?"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(()=>{K.setText("Encryption: AES-256-GCM with a password-derived key.")}):K.setText("Encryption: Argon2id + AES-256-GCM (falls back to PBKDF2 if Argon2 can't run here).");let z=this.app.secretStorage,V=Q.createDiv({cls:"stashpad-export-remember"}),W=V.createEl("input",{type:"checkbox"});W.checked=!0,W.id="stashpad-export-remember-cb";let q=V.createEl("label",{text:"Remember in this vault (this device) \u2014 skips the prompt when you re-import here."});q.htmlFor=W.id;let ee=Q.createDiv({cls:"stashpad-export-remember-note"});ee.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."),ee.setCssStyles({display:W.checked?"":"none"}),W.onchange=()=>{ee.setCssStyles({display:W.checked?"":"none"})},z||V.setCssStyles({display:"none"});let ue=()=>e?"stash":n!=="full"?"zip":l,oe=()=>{let Y=i.value.trim()||this.defaultBaseName;return!e&&n!=="full"?`${Y}-${n}`:ue()==="stash"&&y.checked?`${Y}-encrypted`:Y},ie=()=>{let Y=ue();if(Y==="stash"){s.setText(`Saves as: ${oe()}-<timestamp>.stash`);return}if(Y==="okf"){s.setText(`Saves as: ${oe()}-<timestamp>.zip / .tar.gz (OKF bundle)`);return}s.setText(`Saves as: ${oe()}-<timestamp>.zip (plain archive \u2014 not re-importable)`)};i.oninput=ie;let te=this.contentEl.createDiv({cls:"stashpad-export-footer"}),fe=te.createEl("button",{text:"Cancel"});fe.onclick=()=>this.close();let we=te.createEl("button",{cls:"mod-cta",text:"Export"}),se=()=>{let Y=Mo(D.value);R.style.visibility=D.value?"visible":"hidden",x.forEach((be,Be)=>be.toggleClass("is-on",D.value!==""&&Be<=Y.level)),L.dataset.level=String(Y.level),U.setText(Y.label)},Ae=()=>{let Y=!e&&n!=="full",be=ue();c.setCssStyles({display:!e&&!Y?"":"none"}),f.setCssStyles({display:!e&&!Y&&l==="okf"?"":"none"}),C.setCssStyles({display:Y?"":"none"});let Be=be==="stash";B.setCssStyles({display:Be?"":"none"});let Pe=Be&&y.checked;Q.setCssStyles({display:Pe?"":"none"});let Ze=!0;Pe&&(D.value?D.value!==H.value?(O.setText("Passwords don't match."),O.addClass("is-error"),Ze=!1):(O.setText("\u26A0\uFE0F If you lose this password, the export can't be recovered."),O.removeClass("is-error")):(O.setText("Enter a password to encrypt this export."),O.removeClass("is-error"),Ze=!1));let Ft=!e&&!Y&&l==="okf"&&!g.checked&&!I.checked;m.setCssStyles({display:Ft?"":"none"}),Ft&&(Ze=!1),se(),w.forEach(Js=>Js()),we.disabled=!Ze,we.toggleClass("is-disabled",!Ze),ie()},Xe=!1,li=Y=>{Xe=Y,D.type=H.type=Y?"text":"password",M.setText(Y?"Hide":"Show")};M.onclick=Y=>{Y.preventDefault(),li(!Xe)},b.onclick=Y=>{Y.preventDefault(),D.value=H.value=To(),li(!1),new G.Notice("Passphrase generated (hidden) \u2014 Show to view, or Copy to save it."),Ae()},y.onchange=Ae,D.oninput=Ae,H.oninput=Ae,o=Ae,Ae();let Ks=()=>{let Y=ue(),be=Y==="stash"&&y.checked?D.value:null;this.commit({baseName:oe(),content:n,format:Y,okf:{zip:g.checked,targz:I.checked},password:be,remember:!!be&&W.checked})};we.onclick=Ks,this.scope.register([],"Enter",Y=>{Y.preventDefault(),we.disabled||Ks()}),requestAnimationFrame(()=>{i.focus(),i.select()})}commit(e){let t=e.baseName.trim()||this.defaultBaseName,i=e.password&&e.password.length?e.password:null;this.delivered=!0,this.close(),this.onConfirm({...e,baseName:t,password:i,remember:!!i&&e.remember})}onClose(){this.contentEl.empty()}},ds=class extends G.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()}},Le=class extends G.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 C=I.createEl("button",{cls:"stashpad-export-copy"}),B=()=>{let E=m.value.length===0;C.setText(E?"Paste":"Copy"),C.toggleClass("is-paste",E),C.setAttr("aria-label",`${E?"Paste into":"Copy"} ${g.toLowerCase()}`)};return C.onclick=async E=>{if(E.preventDefault(),m.value.length===0)try{let y=(await navigator.clipboard?.readText())?.trim();if(!y){new G.Notice("Clipboard is empty.");return}m.value=y,m.dispatchEvent(new Event("input")),new G.Notice("Pasted from clipboard.")}catch{new G.Notice("Couldn't read the clipboard.")}else navigator.clipboard?.writeText(m.value).then(()=>new G.Notice("Copied to clipboard."),()=>new G.Notice("Couldn't access the clipboard."))},m.addEventListener("input",B),B(),t.push(B),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"})),C=g.createEl("span",{cls:"stashpad-strength-label"}),B=this.contentEl.createDiv({cls:"stashpad-encryption-counter"}),E=()=>{let w=n.value,k=Mo(w);m.forEach((D,H)=>D.toggleClass("is-on",H<k.level)),C.setText(w?k.label:""),B.setText(`${w.length} character${w.length===1?"":"s"}${w.length>0&&w.length<6?" \u2014 use at least 6":""}`),B.toggleClass("is-weak",w.length>0&&w.length<6)};n.addEventListener("input",E),E();let y=this.contentEl.createDiv({cls:"stashpad-export-genrow"});y.createEl("button",{cls:"stashpad-export-gen",text:"Generate strong passphrase"}).onclick=w=>{w.preventDefault();let k=To(5);n.value=k,o&&(o.value=k),E(),t.forEach(D=>D()),new G.Notice("Generated \u2014 copy it somewhere safe; there's no recovery."),navigator.clipboard?.writeText(k).catch(()=>{})};let v=y.createEl("button",{cls:"stashpad-export-show",text:"Show"});v.onclick=w=>{w.preventDefault();let k=n.type==="password";n.type=k?"text":"password",o&&(o.type=k?"text":"password"),v.setText(k?"Hide":"Show")};let Q=this.contentEl.createEl("div",{cls:"stashpad-export-pw-suite"});Q.setText("Encryption: AES-256-GCM. Checking key-derivation suite\u2026"),this.opts.kdfProbe?this.opts.kdfProbe().then(w=>{Q.toggleClass("is-weak",!w),Q.setText(w?"Encryption: Argon2id + AES-256-GCM \u2014 the strongest suite (used on this device).":"\u26A0\uFE0F Argon2id can't run here, so this will use the weaker PBKDF2 (600k) + AES-256-GCM fallback.")}).catch(()=>Q.setText("Encryption: AES-256-GCM with a password-derived key.")):Q.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 d=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"}),f=!1,u=async()=>{if(f)return;let g=s?.value??void 0,I=n?.value??void 0;if((e==="unlock"||e==="change")&&!g){d("Enter your current password.");return}if(e==="setup"||e==="change"){if(!I){d("Enter a password.");return}if(I.length<6){d("Use at least 6 characters.");return}if(I!==o?.value){d("Passwords don't match.");return}}f=!0,p.disabled=!0,c.setCssStyles({display:"none"});let m=p.textContent;p.setText("Working\u2026");try{let C=await this.opts.onSubmit({current:g,next:I,remember:!!r?.checked});if(C){d(C),f=!1,p.disabled=!1,p.setText(m??"OK");return}this.succeeded=!0,this.close()}catch(C){d(`Failed: ${C.message}`),f=!1,p.disabled=!1,p.setText(m??"OK")}};p.onclick=()=>void u(),this.scope.register([],"Enter",g=>{g.preventDefault(),u()}),requestAnimationFrame(()=>(s??n)?.focus())}onClose(){this.contentEl.empty(),this.succeeded||this.opts.onCancel?.()}},ki=class extends G.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",d=>{d.preventDefault(),c()}),requestAnimationFrame(()=>(e??t).focus())}onClose(){this.contentEl.empty()}},fs=class extends G.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,G.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 l=(await navigator.clipboard?.readText?.())?.trim();l&&(i.value=l,s.hide()),i.focus()}catch{new G.Notice("Couldn't read the clipboard \u2014 paste manually.")}},i.addEventListener("input",()=>s.hide());let s=this.contentEl.createEl("div",{cls:"stashpad-open-link-autohint"});(0,G.setIcon)(s.createSpan({cls:"stashpad-open-link-autohint-icon"}),"clipboard-check"),s.createSpan({text:"Link automatically pasted from your clipboard."}),s.hide();let n=this.contentEl.createDiv({cls:"stashpad-export-footer"});n.createEl("button",{text:"Cancel"}).onclick=()=>this.close();let o=n.createEl("button",{cls:"mod-cta",text:"Open"}),r=()=>{let l=i.value.trim();l&&(this.close(),this.onSubmit(l))};o.onclick=()=>r(),this.scope.register([],"Enter",l=>{l.preventDefault(),r()}),requestAnimationFrame(()=>{i.focus(),navigator.clipboard?.readText?.().then(l=>{!i.value&&l&&/obsidian:\/\/stashpad\?/i.test(l.trim())&&(i.value=l.trim(),i.select(),s.show())}).catch(()=>{})})}onClose(){this.contentEl.empty()}},Bn=class extends G.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=d=>{let h=d.startsWith("#")?d:"#"+d;/^#[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",d=>{d.preventDefault(),this.commit({addToPalette:!1})}),this.scope.register(["Mod"],"Enter",d=>{d.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()}},gs=class gs extends G.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=[...gs.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=!gs.DEFAULT_PALETTE.some(h=>h.toLowerCase()===r.toLowerCase()),d=this.items.length;if(l.onclick=()=>this.activate(d),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 Bn(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()}};gs.DEFAULT_PALETTE=["#E07A78","#E08A47","#E0A744","#B0CC6E","#6BC07A","#5BA9CE","#9B82C9","#C57AB5","#D75AA8"];_t=gs,j=class extends G.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(` +`;a.value=r+d+l,this.cursorText=a.value;let h=r.length+d.length;a.setSelectionRange(h,h),a.dispatchEvent(new Event("input")),a.focus()};a.addEventListener("paste",i=>{let s=i.clipboardData;if(!s)return;let n=[];for(let o of Array.from(s.files??[]))n.push(o);if(n.length===0){for(let o of Array.from(s.items??[]))if(o.kind==="file"){let r=o.getAsFile();r&&n.push(r)}}n.length!==0&&(i.preventDefault(),i.stopPropagation(),t(n))}),a.addEventListener("dragover",i=>{if(!(!i.dataTransfer||!Array.from(i.dataTransfer.types).includes("Files"))){i.preventDefault(),i.stopPropagation();try{i.dataTransfer.dropEffect="copy"}catch{}}}),a.addEventListener("drop",i=>{let s=Array.from(i.dataTransfer?.files??[]);s.length!==0&&(i.preventDefault(),i.stopPropagation(),t(s))})}destroy(){this.autocomplete?.detach(),this.autocomplete=null}async commit(){if(this.surface==="edit"){await this.saveEdit();return}this.mode==="line"?await this.commitLine():this.mode==="cursor"?await this.commitCursor():await this.commitPreset()}async saveEdit(){let a=this.cursorTextarea;a&&(await this.cb.onSave(a.value),this.cb.onDone())}isDirty(){return(this.cursorTextarea?.value??this.cursorText)!==this.body}setSurface(a){this.surface!==a&&(this.surface=a,this.render())}moveDivider(a){return this.mode!=="line"?!1:(this.lineCursorIdx=Math.max(1,Math.min(this.lines.length-1,this.lineCursorIdx+a)),this.render(),!0)}async commitLine(){await this.cb.onSplitAtLine(this.lineCursorIdx,this.nest),this.cb.onDone()}async commitCursor(){let a=this.cursorTextarea;if(!a)return;let e=a.selectionStart;if(e<=0||e>=a.value.length){new G.Notice("Move the cursor inside the text \u2014 neither end can be empty.");return}await this.cb.onSplitAtChar(a.value,e,this.nest),this.cb.onDone()}async commitPreset(){let a=Yt(this.body,this.presetMode);if(a.length<2){new G.Notice("That delimiter wouldn't split this note.");return}await this.cb.onSplitMany(a,this.nest),this.cb.onDone()}render(){if(this.autocomplete?.detach(),this.autocomplete=null,this.host.empty(),this.host.toggleClass("stashpad-edit-surface",this.surface==="edit"),this.cb.onTitle?.(this.surface==="edit"?"Edit note":"Split note"),this.renderSurfaceToggle(),this.surface==="edit"){this.renderEditSurface();return}this.renderSplitSurface()}renderSurfaceToggle(){let a=this.host.createDiv({cls:"stashpad-split-surface"}),e=G.Platform.isMacOS?"\u2318":"Ctrl+",t=(i,s,n,o)=>{let r=a.createEl("button",{cls:"stashpad-split-surface-btn"});(0,G.setIcon)(r.createSpan({cls:"stashpad-split-btn-icon"}),n),r.createSpan({text:i}),r.createSpan({cls:"stashpad-split-kbd-hint",text:`${e}${o}`}),r.toggleClass("is-active",this.surface===s),r.onmousedown=l=>l.preventDefault(),r.onclick=()=>this.setSurface(s)};t("Edit","edit","pencil-line","E"),t("Split","split","split","S")}renderPopOut(a){if(!this.cb.popOut)return;let e=a.createEl("button",{cls:"stashpad-split-popout-btn"});(0,G.setIcon)(e.createSpan({cls:"stashpad-split-popout-icon"}),"maximize-2"),e.createSpan({text:G.Platform.isMobile?"Pop-out":"Open in a tab"}),e.setAttr("aria-label","Open in a full tab"),e.onmousedown=t=>t.preventDefault(),e.onclick=()=>this.cb.popOut(this.getState())}renderOpenExternal(a){if(!this.cb.onOpenExternal)return;let e=a.createEl("button",{cls:"stashpad-split-popout-btn"});(0,G.setIcon)(e.createSpan({cls:"stashpad-split-popout-icon"}),"pencil"),e.createSpan({text:G.Platform.isMobile?"Advanced":"Obsidian editor"}),e.setAttr("aria-label","Open in a full Obsidian editor tab"),e.onmousedown=t=>t.preventDefault(),e.onclick=()=>{this.cb.onOpenExternal(),this.cb.close()}}renderEditSurface(){this.renderEditorSections();let a=this.host.createDiv({cls:"stashpad-split-edit-tools"}),e=a.createSpan({cls:"stashpad-split-count"}),t=()=>{let c=this.cursorTextarea?.value??"",d=(c.trim().match(/\S+/g)||[]).length;e.setText(`${d} word${d===1?"":"s"} \xB7 ${c.length} char${c.length===1?"":"s"}`)},i=a.createEl("button",{cls:"stashpad-split-case-btn"});(0,G.setIcon)(i.createSpan({cls:"stashpad-split-btn-icon"}),"case-sensitive"),i.createSpan({text:"Case"}),i.setAttr("aria-label","Cycle case of the selection (or all text): lower \u2192 UPPER \u2192 Title \u2192 Sentence"),i.onmousedown=c=>c.preventDefault(),i.onclick=()=>this.cycleCase(t),this.cursorTextarea?.addEventListener("input",t),t();let s=this.host.createDiv({cls:"stashpad-split-help"});G.Platform.isPhone||s.setText("Edit the note, then Save. \xB7 \u2318/Ctrl+Enter or Save to write \xB7 \u2318/Ctrl+S \u2192 Split \xB7 Esc discards.");let n=this.host.createDiv({cls:"stashpad-split-actions"}),o=n.createEl("button",{cls:"stashpad-split-cancel-btn"});(0,G.setIcon)(o.createSpan({cls:"stashpad-split-btn-icon"}),"x"),o.createSpan({text:"Cancel"}),o.createSpan({cls:"stashpad-split-esc-hint",text:" (Esc)"}),o.onmousedown=c=>c.preventDefault(),o.onclick=()=>this.cb.close(),this.renderPopOut(n),this.renderOpenExternal(n);let l=n.createDiv({cls:"stashpad-split-actions-right"}).createEl("button",{cls:"stashpad-split-confirm-btn mod-cta"});(0,G.setIcon)(l.createSpan({cls:"stashpad-split-btn-icon"}),"save"),l.createSpan({text:"Save"}),l.onmousedown=c=>c.preventDefault(),l.onclick=()=>void this.commit()}cycleCase(a){let e=this.cursorTextarea;if(!e)return;let t=e.selectionStart!==e.selectionEnd,i=t?e.selectionStart:0,s=t?e.selectionEnd:e.value.length,n=e.value.slice(i,s),o=["lower","upper","title","sentence"],r=o[this.caseCycleIndex%o.length];this.caseCycleIndex+=1;let l=fd(n,r);e.value=e.value.slice(0,i)+l+e.value.slice(s),e.setSelectionRange(i,i+l.length),this.cursorText=e.value,e.dispatchEvent(new Event("input")),a(),e.focus()}renderSplitSurface(){let a=this.host.createDiv({cls:"stashpad-split-modes"}),e=(p,f,u,g,I=!1)=>{let m=a.createEl("button",{cls:"stashpad-split-mode-btn"});(0,G.setIcon)(m.createSpan({cls:"stashpad-split-btn-icon"}),g),m.createSpan({text:p}),m.toggleClass("is-active",f),m.disabled=I,m.onmousedown=C=>C.preventDefault(),I||(m.onclick=u)};this.lines.length>=2&&e("Line",this.mode==="line",()=>{this.mode="line",this.render()},"separator-horizontal"),e("Cursor",this.mode==="cursor",()=>{this.mode="cursor",this.render()},"text-cursor-input");let t={lines:"list",paragraphs:"pilcrow",headings:"heading"};["lines","paragraphs","headings"].forEach(p=>{let f=Yt(this.body,p).length,u=f<2,g=p==="paragraphs"?"Blank line(s)":gi[p],I=u?g:`${g} (${f})`;e(I,this.mode==="preset"&&this.presetMode===p,()=>{this.mode="preset",this.presetMode=p,this.render()},t[p],u)}),this.mode==="line"?this.renderLineMode():this.mode==="cursor"?this.renderEditorSections():this.renderPresetMode();let i=this.host.createDiv({cls:"stashpad-split-help"}),s=()=>{if(G.Platform.isPhone){i.setCssStyles({display:"none"});return}i.setCssStyles({display:""});let p=this.nest?"New part nested under the original.":"New part added as a sibling.",f=this.nest?"New parts nested under the original.":"New parts added as siblings.",u="\u2318/Ctrl+Enter or Split to confirm";i.setText(this.mode==="line"?`\u2191/\u2193 or click to pick the split line \xB7 ${u} \xB7 ${p}`:this.mode==="cursor"?`Click or arrow to position the cursor \xB7 ${u} \xB7 ${p}`:`Preview of the resulting parts \xB7 ${u} \xB7 ${f}`)};s();let n=this.host.createDiv({cls:"stashpad-split-actions"}),o=n.createEl("button",{cls:"stashpad-split-cancel-btn"});(0,G.setIcon)(o.createSpan({cls:"stashpad-split-btn-icon"}),"x"),o.createSpan({text:"Cancel"}),o.createSpan({cls:"stashpad-split-esc-hint",text:" (Esc)"}),o.onmousedown=p=>p.preventDefault(),o.onclick=()=>this.cb.close(),this.renderPopOut(n),this.renderOpenExternal(n);let r=n.createDiv({cls:"stashpad-split-actions-right"}),l=r.createEl("label",{cls:"stashpad-split-nest"}),c=l.createEl("input",{type:"checkbox"});c.checked=this.nest,l.createSpan({text:"Nest under original"}),c.onchange=()=>{this.nest=c.checked,s()};let d=this.mode==="preset"?Yt(this.body,this.presetMode).length:0,h=r.createEl("button",{cls:"stashpad-split-confirm-btn mod-cta"});(0,G.setIcon)(h.createSpan({cls:"stashpad-split-btn-icon"}),"split"),h.createSpan({text:this.mode==="preset"&&d>=2?`Split into ${d}`:"Split"}),h.onmousedown=p=>p.preventDefault(),h.onclick=()=>this.commit()}renderPresetMode(){let a=Yt(this.body,this.presetMode),e=this.host.createDiv({cls:"stashpad-split-preset-list"});if(a.length<2){e.createDiv({cls:"stashpad-split-empty",text:"This delimiter wouldn't split the note into more than one part."});return}a.forEach((t,i)=>{let s=e.createDiv({cls:"stashpad-split-part-card"}),n=s.createDiv({cls:"stashpad-split-part-num"});n.createSpan({cls:"stashpad-split-part-title",text:`Part ${i+1}`}),n.appendChild(this.makeCopyButton(()=>t,`Copy part ${i+1}`)),s.createDiv({cls:"stashpad-split-part-body",text:t})})}renderLineMode(){let a=this.host.createDiv({cls:"stashpad-split-list"}),e=null;for(let t=0;t<this.lines.length;t++){t===this.lineCursorIdx&&(e=a.createDiv({cls:"stashpad-split-divider",text:"\u2500\u2500 split here \u2500\u2500"}));let i=a.createDiv({cls:"stashpad-split-line"});i.createSpan({cls:"stashpad-split-lineno",text:String(t+1)}),i.createSpan({cls:"stashpad-split-text",text:this.lines[t]||" "}),i.onclick=()=>{let s=Math.max(1,Math.min(this.lines.length-1,t+1));s!==this.lineCursorIdx&&(this.lineCursorIdx=s,this.render())}}e&&window.requestAnimationFrame(()=>e.scrollIntoView({block:"center"}))}buildSplitSection(a,e,t){let i=a.createDiv({cls:`stashpad-split-section stashpad-split-${e}`}),s=i.createEl("button",{cls:"stashpad-split-section-header"});s.setAttr("type","button");let n=s.createSpan({cls:"stashpad-split-chevron"});(0,G.setIcon)(n,"chevron-down"),s.createSpan({cls:"stashpad-split-section-title",text:t});let o=i.createDiv({cls:"stashpad-split-section-body"}),r=()=>{i.toggleClass("is-collapsed",this.collapsed[e]),s.setAttr("aria-expanded",String(!this.collapsed[e]))};return s.onmousedown=l=>l.preventDefault(),s.onclick=l=>{l.preventDefault(),this.collapsed[e]=!this.collapsed[e],r()},r(),{section:i,body:o}}makeCopyButton(a,e,t="stashpad-split-copy-btn"){let i=createEl("button",{cls:t});return(0,G.setIcon)(i,"copy"),i.setAttr("aria-label",e),i.onmousedown=s=>s.preventDefault(),i.onclick=s=>{s.preventDefault(),s.stopPropagation();let n=a();navigator.clipboard?.writeText(n).then(()=>new G.Notice("Copied to clipboard."),()=>new G.Notice("Couldn't access the clipboard."))},i}renderEditorSections(){if(G.Platform.isMobile){this.renderEditorTabbed();return}let a=this.buildSplitSection(this.host,"orig","Original \u2014 will be replaced");a.body.createDiv({cls:"stashpad-split-panel-body",text:this.body}),a.section.appendChild(this.makeCopyButton(()=>this.body,"Copy the original text","stashpad-split-copy-btn stashpad-split-section-copy"));let e=this.buildSplitSection(this.host,"changes","Changes"),t=e.body.createDiv({cls:"stashpad-split-panel-body stashpad-split-diff-body"}),s=this.buildSplitSection(this.host,"edit",this.surface==="edit"?"Your edit":"Your edit \u2014 the split uses this").body.createEl("textarea",{cls:"stashpad-split-cursor-ta"});s.value=this.cursorText,s.readOnly=!1,this.cursorTextarea=s,this.enhanceTextarea(s);let n=()=>{t.empty();for(let h of zr(this.body,s.value)){let p=h.t==="ins"?"stashpad-diff-ins":h.t==="del"?"stashpad-diff-del":"stashpad-diff-eq";t.createSpan({cls:p,text:h.s})}},o=()=>{let h=s.value!==this.body;a.section.setCssStyles({display:h?"":"none"}),e.section.setCssStyles({display:h?"":"none"}),h&&n()},r=parseFloat(getComputedStyle(s).lineHeight)||22,l=this.surface==="edit"?G.Platform.isMobile?10:40:G.Platform.isMobile?3:12,c=2,d=()=>{s.setCssStyles({height:"auto"});let h=Math.min(r*l+16,Math.round(window.innerHeight*.5)),p=Math.min(s.scrollHeight,h);s.setCssStyles({height:`${Math.max(p,r*c+16)}px`,overflowY:"auto"})};o(),requestAnimationFrame(()=>{d(),s.focus();let h=this.surface==="edit"?s.value.length:Math.floor(s.value.length/2);s.setSelectionRange(h,h)}),s.addEventListener("input",()=>{this.cursorText=s.value,d(),o()})}renderEditorTabbed(){let a=this.host.createDiv({cls:"stashpad-split-tabs"}),e=a.createDiv({cls:"stashpad-split-tabbar"}),t=a.createDiv({cls:"stashpad-split-tabbody"}),i=t.createDiv({cls:"stashpad-split-tabpanel stashpad-split-tabpanel-edit"}),s=i.createEl("textarea",{cls:"stashpad-split-cursor-ta"});s.value=this.cursorText,s.readOnly=!1,this.cursorTextarea=s,this.enhanceTextarea(s);let n=t.createDiv({cls:"stashpad-split-tabpanel"});n.createDiv({cls:"stashpad-split-tab-copybar"}).appendChild(this.makeCopyButton(()=>this.body,"Copy the original text","stashpad-split-copy-btn stashpad-split-tab-copy")),n.createDiv({cls:"stashpad-split-panel-body",text:this.body});let r=t.createDiv({cls:"stashpad-split-tabpanel"}),l=r.createDiv({cls:"stashpad-split-panel-body stashpad-split-diff-body"}),c=[{key:"edit",label:this.surface==="edit"?"Your edit":"Edit",panel:i},{key:"orig",label:"Original",panel:n},{key:"changes",label:"Changes",panel:r}],d={},h="edit",p=g=>{h=g;for(let I of c)I.panel.toggleClass("is-active",I.key===g),d[I.key]?.toggleClass("is-active",I.key===g);g==="edit"&&s.focus()};for(let g of c){let I=e.createEl("button",{cls:"stashpad-split-tab",text:g.label});I.onmousedown=m=>m.preventDefault(),I.onclick=()=>p(g.key),d[g.key]=I}let f=()=>{l.empty();for(let g of zr(this.body,s.value)){let I=g.t==="ins"?"stashpad-diff-ins":g.t==="del"?"stashpad-diff-del":"stashpad-diff-eq";l.createSpan({cls:I,text:g.s})}},u=()=>{let g=s.value!==this.body;d.orig.toggleClass("is-hidden",!g),d.changes.toggleClass("is-hidden",!g),g&&f(),!g&&(h==="orig"||h==="changes")&&p("edit")};s.setCssStyles({overflowY:"auto"}),u(),p("edit"),requestAnimationFrame(()=>{s.focus();let g=this.surface==="edit"?s.value.length:Math.floor(s.value.length/2);s.setSelectionRange(g,g)}),s.addEventListener("input",()=>{this.cursorText=s.value,u()})}},Bs="stashpad-split-view",bi=class extends G.Modal{constructor(e,t,i,s={}){super(e);this.body=t;this.cbs=i;this.init=s;this.ui=null;this.committing=!1}onOpen(){this.modalEl.addClass("stashpad-split-modal"),this.ui=new us(this.app,this.contentEl,this.body,this.init,{onSplitAtLine:this.cbs.onSplitAtLine,onSplitAtChar:this.cbs.onSplitAtChar,onSplitMany:this.cbs.onSplitMany,onSave:this.cbs.onSave,onOpenExternal:this.cbs.onOpenExternal,onImportFile:this.cbs.onImportFile,close:()=>this.close(),onDone:()=>{this.committing=!0,this.close()},onTitle:e=>this.titleEl.setText(e),popOut:this.cbs.popOut?e=>{this.committing=!0,this.close(),this.cbs.popOut(e)}:void 0}),this.scope.register(["Mod"],"Enter",e=>{e.preventDefault(),this.ui?.commit()}),this.scope.register([],"ArrowUp",e=>{this.ui?.moveDivider(-1)&&e.preventDefault()}),this.scope.register([],"ArrowDown",e=>{this.ui?.moveDivider(1)&&e.preventDefault()}),this.scope.register(["Mod"],"e",e=>{e.preventDefault(),this.ui?.setSurface("edit")}),this.scope.register(["Mod"],"s",e=>{e.preventDefault(),this.ui?.setSurface("split")}),this.scope.register(["Mod","Shift"],"e",e=>{e.preventDefault(),this.cbs.onOpenExternal&&(this.cbs.onOpenExternal(),this.close())})}close(){if(this.committing||!this.ui?.isDirty()){super.close();return}new j(this.app,"Discard unsaved edits?","You've edited this note but haven't saved. Close and discard your changes?","Discard",e=>{e&&(this.committing=!0,this.close())},"Keep editing",!0).open()}onClose(){this.ui?.destroy(),this.ui=null,this.contentEl.empty()}},Di=class extends G.ItemView{constructor(e){super(e);this.ui=null;this.ctx=null;this.prevLeaf=null;this.autoCloseTimer=null;this.expiredGrace=null;this.title="Note";this.viewIcon="pencil-line";this.closingIntentionally=!1}getViewType(){return Bs}getDisplayText(){return this.title}getIcon(){return this.viewIcon}setHeader(e,t){this.title=e,this.viewIcon=t,this.leaf.updateHeader?.()}setContext(e){this.expiredGrace!=null&&(window.clearTimeout(this.expiredGrace),this.expiredGrace=null),this.ctx=e,this.prevLeaf=e.prevLeaf??null;let t=e.init.surface==="edit";this.setHeader(t?"Edit note":"Split note",t?"pencil-line":"split"),this.renderUI()}async onOpen(){this.contentEl.addClass("stashpad-split-modal","stashpad-split-view"),this.ctx||(this.expiredGrace=window.setTimeout(()=>{this.expiredGrace=null,this.ctx||this.renderExpired()},800))}renderUI(){let e=this.contentEl;e.empty(),e.addClass("stashpad-split-modal","stashpad-split-view"),this.ctx&&(this.ui=new us(this.app,e,this.ctx.body,this.ctx.init,{onSplitAtLine:this.ctx.cbs.onSplitAtLine,onSplitAtChar:this.ctx.cbs.onSplitAtChar,onSplitMany:this.ctx.cbs.onSplitMany,onSave:this.ctx.cbs.onSave,onOpenExternal:this.ctx.cbs.onOpenExternal,onImportFile:this.ctx.cbs.onImportFile,close:()=>this.guardedDetach(),onDone:()=>this.startClosePanel("\u2713 Done.",null,!0),onTitle:t=>this.setHeader(t,t.startsWith("Edit")?"pencil-line":"split")}),this.registerDomEvent(e,"keydown",t=>{let i=t.metaKey||t.ctrlKey;i&&t.shiftKey&&(t.key==="e"||t.key==="E")?(t.preventDefault(),this.ctx?.cbs.onOpenExternal?.(),this.guardedDetach()):i&&t.key==="Enter"?(t.preventDefault(),this.ui?.commit()):i&&!t.shiftKey&&(t.key==="e"||t.key==="E")?(t.preventDefault(),this.ui?.setSurface("edit")):i&&(t.key==="s"||t.key==="S")?(t.preventDefault(),this.ui?.setSurface("split")):t.key==="ArrowUp"?this.ui?.moveDivider(-1)&&t.preventDefault():t.key==="ArrowDown"&&this.ui?.moveDivider(1)&&t.preventDefault()}))}renderExpired(){this.setHeader("Expired","clock"),this.startClosePanel("This session has expired.","It can't be restored \u2014 closing this tab\u2026",!1)}startClosePanel(e,t,i){let s=this.contentEl;s.empty(),this.ui?.destroy(),this.ui=null;let n=s.createDiv({cls:"stashpad-split-done"});n.createDiv({cls:"stashpad-split-done-title",text:e}),t&&n.createDiv({cls:"stashpad-split-countdown",text:t});let o=n.createDiv({cls:"stashpad-split-countdown"}),r=n.createDiv({cls:"stashpad-split-done-btns"}),l=r.createEl("button",{cls:"mod-cta",text:"Close now"}),c=r.createEl("button",{text:"Keep tab open"}),d=4,h=()=>o.setText(`Closing this tab in ${d}\u2026`),p=()=>{this.autoCloseTimer!=null&&(window.clearInterval(this.autoCloseTimer),this.autoCloseTimer=null)},f=()=>{p(),i?this.closeAndRefocus():this.leaf.detach()};h(),this.autoCloseTimer=window.setInterval(()=>{d-=1,d<=0?f():h()},1e3),l.onclick=f,c.onclick=()=>{p(),o.setText("Close this tab whenever you're ready."),c.remove(),l.setText("Close tab")}}guardedDetach(){if(!this.ui?.isDirty()){this.closingIntentionally=!0,this.leaf.detach();return}new j(this.app,"Discard unsaved edits?","You've edited this note but haven't saved. Close this tab and discard your changes?","Discard",e=>{e&&(this.closingIntentionally=!0,this.leaf.detach())},"Keep editing",!0).open()}leafStillOpen(e){let t=!1;return this.app.workspace.iterateAllLeaves(i=>{i===e&&(t=!0)}),t}closeAndRefocus(){let e=this.prevLeaf;this.closingIntentionally=!0,this.leaf.detach(),e&&this.leafStillOpen(e)&&this.app.workspace.setActiveLeaf(e,{focus:!0})}async onClose(){!this.closingIntentionally&&this.ui?.isDirty()&&new G.Notice("Closed the Stashpad editor with unsaved changes \u2014 they were discarded. Use Save (\u2318/Ctrl+Enter) next time.",7e3),this.autoCloseTimer!=null&&(window.clearInterval(this.autoCloseTimer),this.autoCloseTimer=null),this.expiredGrace!=null&&(window.clearTimeout(this.expiredGrace),this.expiredGrace=null),this.ui?.destroy(),this.ui=null,this.contentEl.empty()}};xi=class extends G.Modal{constructor(e,t,i,s,n={}){super(e);this.defaultBaseName=t;this.noteCount=i;this.onConfirm=s;this.opts=n;this.delivered=!1}onOpen(){this.contentEl.empty();let e=!!this.opts.locked;this.titleEl.setText(e?"Export encrypted bundle":"Export"),this.modalEl.addClass("stashpad-export-modal"),this.contentEl.createEl("p",{cls:"stashpad-export-desc",text:e?`Re-export this locked bundle (${this.noteCount} note${this.noteCount===1?"":"s"}) as a shareable .stash.`:`Export ${this.noteCount} note${this.noteCount===1?"":"s"}.`});let t=this.contentEl.createDiv({cls:"stashpad-export-field"});t.createEl("label",{cls:"stashpad-export-label",text:"File name"});let i=t.createEl("input",{type:"text"});i.addClass("stashpad-export-name"),i.value=this.defaultBaseName;let s=this.contentEl.createEl("div",{cls:"stashpad-export-preview"}),n="full",o=()=>{},r=this.contentEl.createDiv();Id(r,Y=>{n=Y,o()}),e&&r.setCssStyles({display:"none"});let l="stash",c=this.contentEl.createDiv({cls:"stashpad-export-format"});c.createEl("label",{cls:"stashpad-export-label",text:"Format"});let d=c.createDiv({cls:"stashpad-export-content-seg"}),h=[{id:"stash",label:"Stashpad .stash"},...this.opts.okfEnabled?[{id:"okf",label:"OKF bundle"}]:[],{id:"zip",label:"Plain .zip"}],p=new Map;for(let Y of h){let be=d.createEl("button",{cls:"stashpad-export-content-opt",text:Y.label});be.toggleClass("is-active",Y.id===l),be.onclick=Be=>{Be.preventDefault(),l=Y.id,p.forEach((Pe,Ze)=>Pe.toggleClass("is-active",Ze===l)),o()},p.set(Y.id,be)}let f=this.contentEl.createDiv({cls:"stashpad-okf-formats"}),u=(Y,be)=>{let Be=f.createDiv({cls:"stashpad-okf-fmt"}),Pe=Be.createEl("input",{type:"checkbox"});return Pe.checked=be,Be.createEl("label",{text:Y}),Pe.onchange=()=>o(),Pe},g=u(".zip \u2014 OKF bundle (portable)",!0),I=u(".tar.gz \u2014 OKF bundle (tarball)",!1),m=f.createDiv({cls:"stashpad-export-pw-hint is-error"});m.setText("Pick at least one OKF format."),m.setCssStyles({display:"none"}),e&&c.setCssStyles({display:"none"});let C=this.contentEl.createDiv({cls:"stashpad-export-zipwarn"});C.setText("Frontmatter-only / body-only exports save as a plain .zip of the selected markdown (with referenced attachments) \u2014 not a re-importable .stash."),C.setCssStyles({display:"none"});let B=this.contentEl.createDiv({cls:"stashpad-export-encrypt"}),E=B.createDiv({cls:"stashpad-export-toggle"}),y=E.createEl("input",{type:"checkbox"});y.id="stashpad-export-encrypt-cb";let v=E.createEl("label",{text:"Encrypt with a password"});v.htmlFor=y.id;let Q=B.createDiv({cls:"stashpad-export-pw-area"});Q.setCssStyles({display:"none"});let w=[],k=Y=>{let be=Q.createDiv({cls:"stashpad-export-pw-row"}),Be=be.createEl("input",{type:"password"});Be.addClass("stashpad-export-name"),Be.placeholder=Y;let Pe=be.createEl("button",{cls:"stashpad-export-copy"}),Ze=()=>{let Ft=Be.value.length===0;Pe.setText(Ft?"Paste":"Copy"),Pe.toggleClass("is-paste",Ft),Pe.setAttr("aria-label",`${Ft?"Paste into":"Copy"} ${Y.toLowerCase()}`)};return Pe.onclick=async Ft=>{if(Ft.preventDefault(),Be.value.length===0)try{let Js=(await navigator.clipboard?.readText())?.trim();if(!Js){new G.Notice("Clipboard is empty.");return}Be.value=Js,Be.dispatchEvent(new Event("input")),new G.Notice("Pasted from clipboard.")}catch{new G.Notice("Couldn't read the clipboard.")}else navigator.clipboard?.writeText(Be.value).then(()=>new G.Notice("Passphrase copied to clipboard."),()=>new G.Notice("Couldn't access the clipboard."))},Ze(),w.push(Ze),Be},D=k("Password"),H=k("Confirm password"),R=Q.createDiv({cls:"stashpad-export-strength"}),L=R.createDiv({cls:"stashpad-strength-bar"}),x=[0,1,2,3].map(()=>L.createDiv({cls:"stashpad-strength-seg"})),U=R.createEl("span",{cls:"stashpad-strength-label"}),T=Q.createDiv({cls:"stashpad-export-genrow"}),b=T.createEl("button",{cls:"stashpad-export-gen",text:"Generate strong passphrase"}),M=T.createEl("button",{cls:"stashpad-export-show",text:"Show"}),O=Q.createEl("div",{cls:"stashpad-export-pw-hint"}),K=Q.createEl("div",{cls:"stashpad-export-pw-suite"});K.setText("Encryption: AES-256-GCM. Checking key-derivation suite for this device\u2026"),this.opts.kdfProbe?this.opts.kdfProbe().then(Y=>{K.toggleClass("is-weak",!Y),K.setText(Y?"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(()=>{K.setText("Encryption: AES-256-GCM with a password-derived key.")}):K.setText("Encryption: Argon2id + AES-256-GCM (falls back to PBKDF2 if Argon2 can't run here).");let z=this.app.secretStorage,V=Q.createDiv({cls:"stashpad-export-remember"}),W=V.createEl("input",{type:"checkbox"});W.checked=!0,W.id="stashpad-export-remember-cb";let q=V.createEl("label",{text:"Remember in this vault (this device) \u2014 skips the prompt when you re-import here."});q.htmlFor=W.id;let ee=Q.createDiv({cls:"stashpad-export-remember-note"});ee.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."),ee.setCssStyles({display:W.checked?"":"none"}),W.onchange=()=>{ee.setCssStyles({display:W.checked?"":"none"})},z||V.setCssStyles({display:"none"});let ue=()=>e?"stash":n!=="full"?"zip":l,oe=()=>{let Y=i.value.trim()||this.defaultBaseName;return!e&&n!=="full"?`${Y}-${n}`:ue()==="stash"&&y.checked?`${Y}-encrypted`:Y},ie=()=>{let Y=ue();if(Y==="stash"){s.setText(`Saves as: ${oe()}-<timestamp>.stash`);return}if(Y==="okf"){s.setText(`Saves as: ${oe()}-<timestamp>.zip / .tar.gz (OKF bundle)`);return}s.setText(`Saves as: ${oe()}-<timestamp>.zip (plain archive \u2014 not re-importable)`)};i.oninput=ie;let te=this.contentEl.createDiv({cls:"stashpad-export-footer"}),fe=te.createEl("button",{text:"Cancel"});fe.onclick=()=>this.close();let we=te.createEl("button",{cls:"mod-cta",text:"Export"}),se=()=>{let Y=Mo(D.value);R.style.visibility=D.value?"visible":"hidden",x.forEach((be,Be)=>be.toggleClass("is-on",D.value!==""&&Be<=Y.level)),L.dataset.level=String(Y.level),U.setText(Y.label)},Ae=()=>{let Y=!e&&n!=="full",be=ue();c.setCssStyles({display:!e&&!Y?"":"none"}),f.setCssStyles({display:!e&&!Y&&l==="okf"?"":"none"}),C.setCssStyles({display:Y?"":"none"});let Be=be==="stash";B.setCssStyles({display:Be?"":"none"});let Pe=Be&&y.checked;Q.setCssStyles({display:Pe?"":"none"});let Ze=!0;Pe&&(D.value?D.value!==H.value?(O.setText("Passwords don't match."),O.addClass("is-error"),Ze=!1):(O.setText("\u26A0\uFE0F If you lose this password, the export can't be recovered."),O.removeClass("is-error")):(O.setText("Enter a password to encrypt this export."),O.removeClass("is-error"),Ze=!1));let Ft=!e&&!Y&&l==="okf"&&!g.checked&&!I.checked;m.setCssStyles({display:Ft?"":"none"}),Ft&&(Ze=!1),se(),w.forEach(Js=>Js()),we.disabled=!Ze,we.toggleClass("is-disabled",!Ze),ie()},Xe=!1,li=Y=>{Xe=Y,D.type=H.type=Y?"text":"password",M.setText(Y?"Hide":"Show")};M.onclick=Y=>{Y.preventDefault(),li(!Xe)},b.onclick=Y=>{Y.preventDefault(),D.value=H.value=To(),li(!1),new G.Notice("Passphrase generated (hidden) \u2014 Show to view, or Copy to save it."),Ae()},y.onchange=Ae,D.oninput=Ae,H.oninput=Ae,o=Ae,Ae();let Ks=()=>{let Y=ue(),be=Y==="stash"&&y.checked?D.value:null;this.commit({baseName:oe(),content:n,format:Y,okf:{zip:g.checked,targz:I.checked},password:be,remember:!!be&&W.checked})};we.onclick=Ks,this.scope.register([],"Enter",Y=>{Y.preventDefault(),we.disabled||Ks()}),requestAnimationFrame(()=>{i.focus(),i.select()})}commit(e){let t=e.baseName.trim()||this.defaultBaseName,i=e.password&&e.password.length?e.password:null;this.delivered=!0,this.close(),this.onConfirm({...e,baseName:t,password:i,remember:!!i&&e.remember})}onClose(){this.contentEl.empty()}},ds=class extends G.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()}},Le=class extends G.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 C=I.createEl("button",{cls:"stashpad-export-copy"}),B=()=>{let E=m.value.length===0;C.setText(E?"Paste":"Copy"),C.toggleClass("is-paste",E),C.setAttr("aria-label",`${E?"Paste into":"Copy"} ${g.toLowerCase()}`)};return C.onclick=async E=>{if(E.preventDefault(),m.value.length===0)try{let y=(await navigator.clipboard?.readText())?.trim();if(!y){new G.Notice("Clipboard is empty.");return}m.value=y,m.dispatchEvent(new Event("input")),new G.Notice("Pasted from clipboard.")}catch{new G.Notice("Couldn't read the clipboard.")}else navigator.clipboard?.writeText(m.value).then(()=>new G.Notice("Copied to clipboard."),()=>new G.Notice("Couldn't access the clipboard."))},m.addEventListener("input",B),B(),t.push(B),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"})),C=g.createEl("span",{cls:"stashpad-strength-label"}),B=this.contentEl.createDiv({cls:"stashpad-encryption-counter"}),E=()=>{let w=n.value,k=Mo(w);m.forEach((D,H)=>D.toggleClass("is-on",H<k.level)),C.setText(w?k.label:""),B.setText(`${w.length} character${w.length===1?"":"s"}${w.length>0&&w.length<6?" \u2014 use at least 6":""}`),B.toggleClass("is-weak",w.length>0&&w.length<6)};n.addEventListener("input",E),E();let y=this.contentEl.createDiv({cls:"stashpad-export-genrow"});y.createEl("button",{cls:"stashpad-export-gen",text:"Generate strong passphrase"}).onclick=w=>{w.preventDefault();let k=To(5);n.value=k,o&&(o.value=k),E(),t.forEach(D=>D()),new G.Notice("Generated \u2014 copy it somewhere safe; there's no recovery."),navigator.clipboard?.writeText(k).catch(()=>{})};let v=y.createEl("button",{cls:"stashpad-export-show",text:"Show"});v.onclick=w=>{w.preventDefault();let k=n.type==="password";n.type=k?"text":"password",o&&(o.type=k?"text":"password"),v.setText(k?"Hide":"Show")};let Q=this.contentEl.createEl("div",{cls:"stashpad-export-pw-suite"});Q.setText("Encryption: AES-256-GCM. Checking key-derivation suite\u2026"),this.opts.kdfProbe?this.opts.kdfProbe().then(w=>{Q.toggleClass("is-weak",!w),Q.setText(w?"Encryption: Argon2id + AES-256-GCM \u2014 the strongest suite (used on this device).":"\u26A0\uFE0F Argon2id can't run here, so this will use the weaker PBKDF2 (600k) + AES-256-GCM fallback.")}).catch(()=>Q.setText("Encryption: AES-256-GCM with a password-derived key.")):Q.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 it doesn't sync, and anyone with access to this unlocked device could decrypt. This is a convenience, NOT a backup: an OS/keychain reset, a restored profile, a reinstall or a new machine can erase it without warning. Keep the password in a password manager too, or you will lose access to everything encrypted under it."),m.addClass("stashpad-keychain-note"),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 d=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"}),f=!1,u=async()=>{if(f)return;let g=s?.value??void 0,I=n?.value??void 0;if((e==="unlock"||e==="change")&&!g){d("Enter your current password.");return}if(e==="setup"||e==="change"){if(!I){d("Enter a password.");return}if(I.length<6){d("Use at least 6 characters.");return}if(I!==o?.value){d("Passwords don't match.");return}}f=!0,p.disabled=!0,c.setCssStyles({display:"none"});let m=p.textContent;p.setText("Working\u2026");try{let C=await this.opts.onSubmit({current:g,next:I,remember:!!r?.checked});if(C){d(C),f=!1,p.disabled=!1,p.setText(m??"OK");return}this.succeeded=!0,this.close()}catch(C){d(`Failed: ${C.message}`),f=!1,p.disabled=!1,p.setText(m??"OK")}};p.onclick=()=>void u(),this.scope.register([],"Enter",g=>{g.preventDefault(),u()}),requestAnimationFrame(()=>(s??n)?.focus())}onClose(){this.contentEl.empty(),this.succeeded||this.opts.onCancel?.()}},ki=class extends G.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",d=>{d.preventDefault(),c()}),requestAnimationFrame(()=>(e??t).focus())}onClose(){this.contentEl.empty()}},fs=class extends G.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,G.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 l=(await navigator.clipboard?.readText?.())?.trim();l&&(i.value=l,s.hide()),i.focus()}catch{new G.Notice("Couldn't read the clipboard \u2014 paste manually.")}},i.addEventListener("input",()=>s.hide());let s=this.contentEl.createEl("div",{cls:"stashpad-open-link-autohint"});(0,G.setIcon)(s.createSpan({cls:"stashpad-open-link-autohint-icon"}),"clipboard-check"),s.createSpan({text:"Link automatically pasted from your clipboard."}),s.hide();let n=this.contentEl.createDiv({cls:"stashpad-export-footer"});n.createEl("button",{text:"Cancel"}).onclick=()=>this.close();let o=n.createEl("button",{cls:"mod-cta",text:"Open"}),r=()=>{let l=i.value.trim();l&&(this.close(),this.onSubmit(l))};o.onclick=()=>r(),this.scope.register([],"Enter",l=>{l.preventDefault(),r()}),requestAnimationFrame(()=>{i.focus(),navigator.clipboard?.readText?.().then(l=>{!i.value&&l&&/obsidian:\/\/stashpad\?/i.test(l.trim())&&(i.value=l.trim(),i.select(),s.show())}).catch(()=>{})})}onClose(){this.contentEl.empty()}},Bn=class extends G.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=d=>{let h=d.startsWith("#")?d:"#"+d;/^#[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",d=>{d.preventDefault(),this.commit({addToPalette:!1})}),this.scope.register(["Mod"],"Enter",d=>{d.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()}},gs=class gs extends G.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=[...gs.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=!gs.DEFAULT_PALETTE.some(h=>h.toLowerCase()===r.toLowerCase()),d=this.items.length;if(l.onclick=()=>this.activate(d),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 Bn(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()}};gs.DEFAULT_PALETTE=["#E07A78","#E08A47","#E0A744","#B0CC6E","#6BC07A","#5BA9CE","#9B82C9","#C57AB5","#D75AA8"];_t=gs,j=class extends G.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))}},Is=class extends G.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()}};ze=class extends G.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 Q=Date.parse(this.current);Number.isNaN(Q)||(e=new Date(Q))}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,G.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,G.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,G.setIcon)(c,"clock");let d=l.createEl("input",{type:"time",cls:"stashpad-due-time"}),h=l.createSpan({cls:"stashpad-due-clear",attr:{"aria-label":"Clear time"}});(0,G.setIcon)(h,"x"),h.onclick=()=>{d.value="",d.focus()},n.onclick=()=>{try{o.showPicker?.()}catch{}},c.onclick=()=>this.openTimeNumpad(c,d),e&&(o.value=this.toDateValue(e),d.value=this.toTimeValue(e));let p=(this.opts.quickAdjusts??Vr).map(Q=>({raw:Q,min:Wr(Q)})).filter(Q=>Q.min!=null);if(p.length>0){let Q=1,w=t.createDiv({cls:"stashpad-due-quickadjust"}),k=w.createEl("button",{cls:"stashpad-due-adjust-flip",attr:{type:"button"}}),D=()=>{k.setText(Q>0?"+":"\u2212"),k.toggleClass("is-minus",Q<0),k.title=Q>0?"Adding time (click to subtract)":"Subtracting time (click to add)"};D(),k.onclick=()=>{Q=-Q,D()};let H=R=>{let L=new Date,x,U,T;if(o.value){let[K,z,V]=o.value.split("-").map(W=>parseInt(W,10));x=K,U=z-1,T=V}else x=L.getFullYear(),U=L.getMonth(),T=L.getDate();let b,M;if(d.value){let[K,z]=d.value.split(":").map(V=>parseInt(V,10));b=K,M=z}else b=L.getHours(),M=L.getMinutes();let O=new Date(x,U,T,b,M,0,0);O.setMinutes(O.getMinutes()+Q*R),o.value=this.toDateValue(O),d.value=this.toTimeValue(O)};for(let R of p){let L=w.createEl("button",{cls:"stashpad-due-adjust-btn",text:R.raw,attr:{type:"button"}});L.onclick=()=>H(R.min)}}this.opts.hideAssignees||this.renderAssignSection(t);let f=t.createDiv({cls:"stashpad-due-grid"}),u=(Q,w)=>{let k=f.createEl("button",{cls:"stashpad-due-btn stashpad-due-preset",text:Q});k.onclick=()=>{let D=w();o.value=this.toDateValue(D),d.value||(d.value=this.toTimeValue(D))}},g=Q=>(Q.setHours(9,0,0,0),Q);u("Today",()=>g(this.startOfTodayLocal())),u("Tomorrow",()=>{let Q=this.startOfTodayLocal();return Q.setDate(Q.getDate()+1),g(Q)}),u("Next week",()=>{let Q=this.startOfTodayLocal();return Q.setDate(Q.getDate()+7),g(Q)});let I=f.createEl("button",{cls:"stashpad-due-btn",text:"Clear"});I.onclick=()=>{o.value="",d.value="",o.focus()};let m=null,C=null,B=null;if(this.opts.showRecurrence){let Q=t.createEl("details",{cls:"stashpad-due-recur"});(this.opts.currentRepeat||this.opts.currentAutoDoneAfter||this.opts.currentRemindEvery)&&(Q.open=!0),Q.createEl("summary",{text:"\u{1F501} Repeat & reminders"});let w=(k,D,H)=>{let R=Q.createDiv({cls:"stashpad-due-recur-row"});R.createEl("label",{text:k});let L=R.createEl("input",{type:"text",attr:{placeholder:D}});return H&&(L.value=H),L};m=w("Repeat",'e.g. "every weekday", "every 30 days when done"',this.opts.currentRepeat),C=w("Auto-complete after",'e.g. "1d" \u2014 mark done once this overdue',this.opts.currentAutoDoneAfter),B=w("Remind every",'e.g. "2h" \u2014 re-notify until done',this.opts.currentRemindEvery)}let E=()=>this.opts.showRecurrence?{repeat:m.value.trim(),autoDoneAfter:C.value.trim(),remindEvery:B.value.trim()}:{},y=f.createEl("button",{cls:"stashpad-due-btn",text:"Cancel"});y.onclick=()=>{this.didChoose=!0,this.close()};let v=f.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,...E()});return}let[Q,w,k]=o.value.split("-").map(L=>parseInt(L,10)),D=9,H=0;if(d.value){let[L,x]=d.value.split(":").map(U=>parseInt(U,10));D=L,H=x}let R=new Date(Q,w-1,k,D,H,0,0);this.didChoose=!0,this.close(),this.onPick({iso:R.toISOString(),assignees:this.assignees,...E()})},requestAnimationFrame(()=>o.focus())}onClose(){this.tinyClosePopover?.(),this.contentEl.empty(),this.didChoose}renderAssignSection(e){Xr(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(C=>parseInt(C,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,d=(this.modalEl??i.body).createDiv({cls:"stashpad-when-popover stashpad-due-time-pop"});d.setCssStyles({position:"fixed",zIndex:"9999"});let h=null,p=()=>{d.remove(),i.removeEventListener("mousedown",f,!0),i.removeEventListener("keydown",u,!0),this.tinyClosePopover===p&&(this.tinyClosePopover=null)},f=I=>{!d.contains(I.target)&&I.target!==e&&!e.contains(I.target)&&p()},u=I=>{I.key==="Escape"?(I.preventDefault(),I.stopPropagation(),p()):I.key==="Enter"&&h&&(I.preventDefault(),I.stopPropagation(),h())};this.tinyClosePopover=p,Ws(d,{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();d.setCssStyles({left:`${Math.max(8,Math.min(g.left,s.innerWidth-220))}px`,top:`${g.bottom+4}px`}),setTimeout(()=>{i.addEventListener("mousedown",f,!0),i.addEventListener("keydown",u,!0),d.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}`}},ti=class ti extends G.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 j(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(ti.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=ud(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 d of t.actionLabels){let h=c.createSpan({cls:"stashpad-notif-action-chip"});h.setText(d),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(ti.PAGE,e)} more`});if(t.onclick=()=>{this.appendMore(ti.PAGE),this.renderFooter()},e>ti.PAGE){let i=this.footerEl.createEl("button",{text:`Load all (${e})`});i.onclick=()=>{this.appendMore(e),this.renderFooter()}}}};ti.PAGE=100;ps=ti,oa=class extends G.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,G.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()}},ms=class extends G.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()}},Cs=class extends G.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 qd(A,a){return Jd(A,a||{},0,0)}function $d(A,a){return Ud(A,{i:2},a&&a.out,a&&a.dictionary)}function Yn(A,a){if(a){for(var e=new pe(A.length),t=0;t<A.length;++t)e[t]=A.charCodeAt(t);return e}if(vl)return vl.encode(A);for(var i=A.length,s=new pe(A.length+(A.length>>1)),n=0,o=function(c){s[n++]=c},t=0;t<i;++t){if(n+5>s.length){var r=new pe(n+8+(i-t<<1));r.set(s),s=r}var l=A.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)|A.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 Ds(s,0,n)}function ba(A,a){if(a){for(var e="",t=0;t<A.length;t+=16384)e+=String.fromCharCode.apply(null,A.subarray(t,t+16384));return e}else{if(Qa)return Qa.decode(A);var i=zd(A),s=i.s,e=i.r;return e.length&&Se(8),s}}function Ml(A,a){a||(a={});var e={},t=[];Tl(A,"",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,d=Yn(n),h=d.length,p=l.comment,f=p&&Yn(p),u=f&&f.length,g=ka(l.extra);h>65535&&Se(11);var I=c?qd(r,l):r,m=I.length,C=Kd();C.p(r),t.push(Nl(l,{size:r.length,crc:C.d(),c:I,f:d,m:f,u:h!=n.length||f&&p.length!=u,o:i,compression:c})),i+=30+h+g+m,s+=76+2*(h+g)+(u||0)+m}for(var B=new pe(s+22),E=i,y=s-i,v=0;v<t.length;++v){var d=t[v];Ql(B,d.o,d,d.f,d.u,d.c.length);var Q=30+d.f.length+ka(d.extra);B.set(d.c,d.o+Q),Ql(B,i,d,d.f,d.u,d.c.length,d.o,d.m),i+=16+Q+(d.m?d.m.length:0)}return Zd(B,i,t.length,y,E),B}function Pl(A,a){for(var e={},t=A.length-22;Ke(A,t)!=101010256;--t)(!t||A.length-t>65558)&&Se(13);var i=rt(A,t+8);if(!i)return{};var s=Ke(A,t+16),n=Ke(A,t-20)==117853008;if(n){var o=Ke(A,t-12);n=Ke(A,o)==101075792,n&&(i=Ke(A,o+32),s=Ke(A,o+48))}for(var r=a&&a.filter,l=0;l<i;++l){var c=Wd(A,s,n),d=c[0],h=c[1],p=c[2],f=c[3],u=c[4],g=c[5],I=Vd(A,g);s=u,(!r||r({name:f,size:h,originalSize:p,compression:d}))&&(d?d==8?e[f]=$d(A.subarray(I,I+h),{out:new pe(p)}):Se(14,"unknown compression type "+d):e[f]=Ds(A,I,I+h))}return e}var pe,Re,Fa,zn,Vn,ya,kl,Fl,Sl,wa,bl,Nd,yl,Ea,wt,_,lt,Ot,_,_,_,_,bs,_,Td,Md,Pd,Hd,Ia,Ve,ma,Sa,Ds,Rd,Se,Ud,Et,Fs,Ca,va,wl,Ss,Dl,El,Ld,xl,Gd,Od,Kd,Jd,Nl,rt,Ke,Ba,ke,Tl,vl,Qa,Yd,zd,Vd,Wd,Xd,ka,Ql,Zd,Hl=de(()=>{pe=Uint8Array,Re=Uint16Array,Fa=Int32Array,zn=new pe([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]),Vn=new pe([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]),ya=new pe([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),kl=function(A,a){for(var e=new Re(31),t=0;t<31;++t)e[t]=a+=1<<A[t-1];for(var i=new Fa(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}},Fl=kl(zn,2),Sl=Fl.b,wa=Fl.r;Sl[28]=258,wa[258]=28;bl=kl(Vn,0),Nd=bl.b,yl=bl.r,Ea=new Re(32768);for(_=0;_<32768;++_)wt=(_&43690)>>1|(_&21845)<<1,wt=(wt&52428)>>2|(wt&13107)<<2,wt=(wt&61680)>>4|(wt&3855)<<4,Ea[_]=((wt&65280)>>8|(wt&255)<<8)>>1;lt=function(A,a,e){for(var t=A.length,i=0,s=new Re(a);i<t;++i)A[i]&&++s[A[i]-1];var n=new Re(a);for(i=1;i<a;++i)n[i]=n[i-1]+s[i-1]<<1;var o;if(e){o=new Re(1<<a);var r=15-a;for(i=0;i<t;++i)if(A[i])for(var l=i<<4|A[i],c=a-A[i],d=n[A[i]-1]++<<c,h=d|(1<<c)-1;d<=h;++d)o[Ea[d]>>r]=l}else for(o=new Re(t),i=0;i<t;++i)A[i]&&(o[i]=Ea[n[A[i]-1]++]>>15-A[i]);return o},Ot=new pe(288);for(_=0;_<144;++_)Ot[_]=8;for(_=144;_<256;++_)Ot[_]=9;for(_=256;_<280;++_)Ot[_]=7;for(_=280;_<288;++_)Ot[_]=8;bs=new pe(32);for(_=0;_<32;++_)bs[_]=5;Td=lt(Ot,9,0),Md=lt(Ot,9,1),Pd=lt(bs,5,0),Hd=lt(bs,5,1),Ia=function(A){for(var a=A[0],e=1;e<A.length;++e)A[e]>a&&(a=A[e]);return a},Ve=function(A,a,e){var t=a/8|0;return(A[t]|A[t+1]<<8)>>(a&7)&e},ma=function(A,a){var e=a/8|0;return(A[e]|A[e+1]<<8|A[e+2]<<16)>>(a&7)},Sa=function(A){return(A+7)/8|0},Ds=function(A,a,e){return(a==null||a<0)&&(a=0),(e==null||e>A.length)&&(e=A.length),new pe(A.subarray(a,e))},Rd=["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"],Se=function(A,a,e){var t=new Error(a||Rd[A]);if(t.code=A,Error.captureStackTrace&&Error.captureStackTrace(t,Se),!e)throw t;return t},Ud=function(A,a,e,t){var i=A.length,s=t?t.length:0;if(!i||a.f&&!a.l)return e||new pe(0);var n=!e,o=n||a.i!=2,r=a.i;n&&(e=new pe(i*3));var l=function(fe){var we=e.length;if(fe>we){var se=new pe(Math.max(we*2,fe));se.set(e),e=se}},c=a.f||0,d=a.p||0,h=a.b||0,p=a.l,f=a.d,u=a.m,g=a.n,I=i*8;do{if(!p){c=Ve(A,d,1);var m=Ve(A,d+1,3);if(d+=3,m)if(m==1)p=Md,f=Hd,u=9,g=5;else if(m==2){var y=Ve(A,d,31)+257,v=Ve(A,d+10,15)+4,Q=y+Ve(A,d+5,31)+1;d+=14;for(var w=new pe(Q),k=new pe(19),D=0;D<v;++D)k[ya[D]]=Ve(A,d+D*3,7);d+=v*3;for(var H=Ia(k),R=(1<<H)-1,L=lt(k,H,1),D=0;D<Q;){var x=L[Ve(A,d,R)];d+=x&15;var C=x>>4;if(C<16)w[D++]=C;else{var U=0,T=0;for(C==16?(T=3+Ve(A,d,3),d+=2,U=w[D-1]):C==17?(T=3+Ve(A,d,7),d+=3):C==18&&(T=11+Ve(A,d,127),d+=7);T--;)w[D++]=U}}var b=w.subarray(0,y),M=w.subarray(y);u=Ia(b),g=Ia(M),p=lt(b,u,1),f=lt(M,g,1)}else Se(1);else{var C=Sa(d)+4,B=A[C-4]|A[C-3]<<8,E=C+B;if(E>i){r&&Se(0);break}o&&l(h+B),e.set(A.subarray(C,E),h),a.b=h+=B,a.p=d=E*8,a.f=c;continue}if(d>I){r&&Se(0);break}}o&&l(h+131072);for(var O=(1<<u)-1,K=(1<<g)-1,z=d;;z=d){var U=p[ma(A,d)&O],V=U>>4;if(d+=U&15,d>I){r&&Se(0);break}if(U||Se(2),V<256)e[h++]=V;else if(V==256){z=d,p=null;break}else{var W=V-254;if(V>264){var D=V-257,q=zn[D];W=Ve(A,d,(1<<q)-1)+Sl[D],d+=q}var ee=f[ma(A,d)&K],ue=ee>>4;ee||Se(3),d+=ee&15;var M=Nd[ue];if(ue>3){var q=Vn[ue];M+=ma(A,d)&(1<<q)-1,d+=q}if(d>I){r&&Se(0);break}o&&l(h+131072);var oe=h+W;if(h<M){var ie=s-M,te=Math.min(M,oe);for(ie+h<0&&Se(3);h<te;++h)e[h]=t[ie+h]}for(;h<oe;++h)e[h]=e[h-M]}}a.l=p,a.p=z,a.b=h,a.f=c,p&&(c=1,a.m=u,a.d=f,a.n=g)}while(!c);return h!=e.length&&n?Ds(e,0,h):e.subarray(0,h)},Et=function(A,a,e){e<<=a&7;var t=a/8|0;A[t]|=e,A[t+1]|=e>>8},Fs=function(A,a,e){e<<=a&7;var t=a/8|0;A[t]|=e,A[t+1]|=e>>8,A[t+2]|=e>>16},Ca=function(A,a){for(var e=[],t=0;t<A.length;++t)A[t]&&e.push({s:t,f:A[t]});var i=e.length,s=e.slice();if(!i)return{t:xl,l:0};if(i==1){var n=new pe(e[0].s+1);return n[e[0].s]=1,{t:n,l:1}}e.sort(function(E,y){return E.f-y.f}),e.push({s:-1,f:25001});var o=e[0],r=e[1],l=0,c=1,d=2;for(e[0]={s:-1,f:o.f+r.f,l:o,r};c!=i-1;)o=e[e[l].f<e[d].f?l++:d++],r=e[l!=c&&e[l].f<e[d].f?l++:d++],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 Re(h+1),f=va(e[c-1],p,0);if(f>a){var t=0,u=0,g=f-a,I=1<<g;for(s.sort(function(y,v){return p[v.s]-p[y.s]||y.f-v.f});t<i;++t){var m=s[t].s;if(p[m]>a)u+=I-(1<<f-p[m]),p[m]=a;else break}for(u>>=g;u>0;){var C=s[t].s;p[C]<a?u-=1<<a-p[C]++-1:++t}for(;t>=0&&u;--t){var B=s[t].s;p[B]==a&&(--p[B],++u)}f=a}return{t:new pe(p),l:f}},va=function(A,a,e){return A.s==-1?Math.max(va(A.l,a,e+1),va(A.r,a,e+1)):a[A.s]=e},wl=function(A){for(var a=A.length;a&&!A[--a];);for(var e=new Re(++a),t=0,i=A[0],s=1,n=function(r){e[t++]=r},o=1;o<=a;++o)if(A[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=A[o]}return{c:e.subarray(0,t),n:a}},Ss=function(A,a){for(var e=0,t=0;t<a.length;++t)e+=A[t]*a[t];return e},Dl=function(A,a,e){var t=e.length,i=Sa(a+2);A[i]=t&255,A[i+1]=t>>8,A[i+2]=A[i]^255,A[i+3]=A[i+1]^255;for(var s=0;s<t;++s)A[i+s+4]=e[s];return(i+4+t)*8},El=function(A,a,e,t,i,s,n,o,r,l,c){Et(a,c++,e),++i[256];for(var d=Ca(i,15),h=d.t,p=d.l,f=Ca(s,15),u=f.t,g=f.l,I=wl(h),m=I.c,C=I.n,B=wl(u),E=B.c,y=B.n,v=new Re(19),Q=0;Q<m.length;++Q)++v[m[Q]&31];for(var Q=0;Q<E.length;++Q)++v[E[Q]&31];for(var w=Ca(v,7),k=w.t,D=w.l,H=19;H>4&&!k[ya[H-1]];--H);var R=l+5<<3,L=Ss(i,Ot)+Ss(s,bs)+n,x=Ss(i,h)+Ss(s,u)+n+14+3*H+Ss(v,k)+2*v[16]+3*v[17]+7*v[18];if(r>=0&&R<=L&&R<=x)return Dl(a,c,A.subarray(r,r+l));var U,T,b,M;if(Et(a,c,1+(x<L)),c+=2,x<L){U=lt(h,p,0),T=h,b=lt(u,g,0),M=u;var O=lt(k,D,0);Et(a,c,C-257),Et(a,c+5,y-1),Et(a,c+10,H-4),c+=14;for(var Q=0;Q<H;++Q)Et(a,c+3*Q,k[ya[Q]]);c+=3*H;for(var K=[m,E],z=0;z<2;++z)for(var V=K[z],Q=0;Q<V.length;++Q){var W=V[Q]&31;Et(a,c,O[W]),c+=k[W],W>15&&(Et(a,c,V[Q]>>5&127),c+=V[Q]>>12)}}else U=Td,T=Ot,b=Pd,M=bs;for(var Q=0;Q<o;++Q){var q=t[Q];if(q>255){var W=q>>18&31;Fs(a,c,U[W+257]),c+=T[W+257],W>7&&(Et(a,c,q>>23&31),c+=zn[W]);var ee=q&31;Fs(a,c,b[ee]),c+=M[ee],ee>3&&(Fs(a,c,q>>5&8191),c+=Vn[ee])}else Fs(a,c,U[q]),c+=T[q]}return Fs(a,c,U[256]),c+T[256]},Ld=new Fa([65540,131080,131088,131104,262176,1048704,1048832,2114560,2117632]),xl=new pe(0),Gd=function(A,a,e,t,i,s){var n=s.z||A.length,o=new pe(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 d=Ld[a-1],h=d>>13,p=d&8191,f=(1<<e)-1,u=s.p||new Re(32768),g=s.h||new Re(f+1),I=Math.ceil(e/3),m=2*I,C=function(Ae){return(A[Ae]^A[Ae+1]<<I^A[Ae+2]<<m)&f},B=new Fa(25e3),E=new Re(288),y=new Re(32),v=0,Q=0,w=s.i||0,k=0,D=s.w||0,H=0;w+2<n;++w){var R=C(w),L=w&32767,x=g[R];if(u[L]=x,g[R]=L,D<=w){var U=n-w;if((v>7e3||k>24576)&&(U>423||!l)){c=El(A,r,0,B,E,y,Q,k,H,w-H,c),k=v=Q=0,H=w;for(var T=0;T<286;++T)E[T]=0;for(var T=0;T<30;++T)y[T]=0}var b=2,M=0,O=p,K=L-x&32767;if(U>2&&R==C(w-K))for(var z=Math.min(h,U)-1,V=Math.min(32767,w),W=Math.min(258,U);K<=V&&--O&&L!=x;){if(A[w+b]==A[w+b-K]){for(var q=0;q<W&&A[w+q]==A[w+q-K];++q);if(q>b){if(b=q,M=K,q>z)break;for(var ee=Math.min(K,q-2),ue=0,T=0;T<ee;++T){var oe=w-K+T&32767,ie=u[oe],te=oe-ie&32767;te>ue&&(ue=te,x=oe)}}}L=x,x=u[L],K+=L-x&32767}if(M){B[k++]=268435456|wa[b]<<18|yl[M];var fe=wa[b]&31,we=yl[M]&31;Q+=zn[fe]+Vn[we],++E[257+fe],++y[we],D=w+b,++v}else B[k++]=A[w],++E[A[w]]}}for(w=Math.max(w,D);w<n;++w)B[k++]=A[w],++E[A[w]];c=El(A,r,l,B,E,y,Q,k,H,w-H,c),l||(s.r=c&7|r[c/8|0]<<3,c-=7,s.h=g,s.p=u,s.i=w,s.w=D)}else{for(var w=s.w||0;w<n+l;w+=65535){var se=w+65535;se>=n&&(r[c/8|0]=l,se=n),c=Dl(r,c+1,A.subarray(w,se))}s.i=n}return Ds(o,0,t+Sa(c)+i)},Od=function(){for(var A=new Int32Array(256),a=0;a<256;++a){for(var e=a,t=9;--t;)e=(e&1&&-306674912)^e>>>1;A[a]=e}return A}(),Kd=function(){var A=-1;return{p:function(a){for(var e=A,t=0;t<a.length;++t)e=Od[e&255^a[t]]^e>>>8;A=e},d:function(){return~A}}},Jd=function(A,a,e,t,i){if(!i&&(i={l:1},a.dictionary)){var s=a.dictionary.subarray(-32768),n=new pe(s.length+A.length);n.set(s),n.set(A,s.length),A=n,i.w=s.length}return Gd(A,a.level==null?6:a.level,a.mem==null?i.l?Math.ceil(Math.max(8,Math.min(13,Math.log(A.length)))*1.5):20:12+a.mem,e,t,i)},Nl=function(A,a){var e={};for(var t in A)e[t]=A[t];for(var t in a)e[t]=a[t];return e},rt=function(A,a){return A[a]|A[a+1]<<8},Ke=function(A,a){return(A[a]|A[a+1]<<8|A[a+2]<<16|A[a+3]<<24)>>>0},Ba=function(A,a){return Ke(A,a)+Ke(A,a+4)*4294967296},ke=function(A,a,e){for(;e;++a)A[a]=e,e>>>=8};Tl=function(A,a,e,t){for(var i in A){var s=A[i],n=a+i,o=t;Array.isArray(s)&&(o=Nl(t,s[1]),s=s[0]),ArrayBuffer.isView(s)?e[n]=[s,o]:(e[n+="/"]=[new pe(0),o],Tl(s,n,e,t))}},vl=typeof TextEncoder<"u"&&new TextEncoder,Qa=typeof TextDecoder<"u"&&new TextDecoder,Yd=0;try{Qa.decode(xl,{stream:!0}),Yd=1}catch{}zd=function(A){for(var a="",e=0;;){var t=A[e++],i=(t>127)+(t>223)+(t>239);if(e+i>A.length)return{s:a,r:Ds(A,e-1)};i?i==3?(t=((t&15)<<18|(A[e++]&63)<<12|(A[e++]&63)<<6|A[e++]&63)-65536,a+=String.fromCharCode(55296|t>>10,56320|t&1023)):i&1?a+=String.fromCharCode((t&31)<<6|A[e++]&63):a+=String.fromCharCode((t&15)<<12|(A[e++]&63)<<6|A[e++]&63):a+=String.fromCharCode(t)}};Vd=function(A,a){return a+30+rt(A,a+26)+rt(A,a+28)},Wd=function(A,a,e){var t=rt(A,a+28),i=rt(A,a+30),s=ba(A.subarray(a+46,a+46+t),!(rt(A,a+8)&2048)),n=a+46+t,o=Xd(A,n,i,e,Ke(A,a+20),Ke(A,a+24),Ke(A,a+42)),r=o[0],l=o[1],c=o[2];return[rt(A,a+10),r,l,s,n+i+rt(A,a+32),c]},Xd=function(A,a,e,t,i,s,n){var o=i==4294967295,r=s==4294967295,l=n==4294967295,c=a+e,d=o+r+l;if(t&&d){for(;a+4<c;a+=4+rt(A,a+2))if(rt(A,a)==1)return[o?Ba(A,a+4+8*r):i,r?Ba(A,a+4):s,l?Ba(A,a+4+8*(r+o)):n,1];t<2&&Se(13)}return[i,s,n,0]},ka=function(A){var a=0;if(A)for(var e in A){var t=A[e].length;t>65535&&Se(9),a+=t+4}return a},Ql=function(A,a,e,t,i,s,n,o){var r=t.length,l=e.extra,c=o&&o.length,d=ka(l);ke(A,a,n!=null?33639248:67324752),a+=4,n!=null&&(A[a++]=20,A[a++]=e.os),A[a]=20,a+=2,A[a++]=e.flag<<1|(s<0&&8),A[a++]=i&&8,A[a++]=e.compression&255,A[a++]=e.compression>>8;var h=new Date(e.mtime==null?Date.now():e.mtime),p=h.getFullYear()-1980;if((p<0||p>119)&&Se(10),ke(A,a,p<<25|h.getMonth()+1<<21|h.getDate()<<16|h.getHours()<<11|h.getMinutes()<<5|h.getSeconds()>>1),a+=4,s!=-1&&(ke(A,a,e.crc),ke(A,a+4,s<0?-s-2:s),ke(A,a+8,e.size)),ke(A,a+12,r),ke(A,a+14,d),a+=16,n!=null&&(ke(A,a,c),ke(A,a+6,e.attrs),ke(A,a+10,n),a+=14),A.set(t,a),a+=r,d)for(var f in l){var u=l[f],g=u.length;ke(A,a,+f),ke(A,a+2,g),A.set(u,a+4),a+=4+g}return c&&(A.set(o,a),a+=c),a},Zd=function(A,a,e,t,i){ke(A,a,101010256),ke(A,a+8,e),ke(A,a+10,e),ke(A,a+12,t),ke(A,a+16,i)}});var Ll={};zi(Ll,{bytesToStr:()=>Wn,unzipFiles:()=>Oi,zipFiles:()=>Gi});function _d(A){return typeof A=="string"?Yn(A):A instanceof Uint8Array?A:new Uint8Array(A)}function Gi(A,a=6){let e={};for(let t of A)e[t.name]=[_d(t.data),{level:a}];return Promise.resolve(Ml(e,{level:a}))}function Wn(A){return ba(A)}function Oi(A){let a=A instanceof Uint8Array?A:new Uint8Array(A),e=0,t=0,i=s=>{if(t+=1,t>Ul)throw new Error(`Refusing to unzip: too many entries (>${Ul}) \u2014 possible zip bomb.`);if(s.originalSize>jd)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>Rl)throw new Error(`Refusing to unzip: total size >${Math.round(Rl/1048576)} MiB \u2014 possible zip bomb.`);return!0};return Promise.resolve(Pl(a,{filter:i}))}var Rl,jd,Ul,Xn=de(()=>{"use strict";Hl();Rl=512*1024*1024,jd=256*1024*1024,Ul=2e4});var bA={};zi(bA,{default:()=>Bo});module.exports=wc(bA);var N=require("obsidian");var Vi="sheet-group",ht="sheet-order",ci="sheet-final",za="sheet-label",Wi="sheet-origin",Xi="forked-from",je="fork-siblings",Eo="forked-at",vo=[Vi,ht,ci,za,Wi,Xi,je,Eo];function _e(A){if(!A)return null;let a=A[Vi];return typeof a=="string"&&a.trim()?a:null}function wo(A){let a=A?.[ht];return typeof a=="number"?a:null}function Zi(A){return _e(A)!==null&&wo(A)!==null}function ji(A){return A?.[ci]===!0}function Va(A){return A?.[Wi]===!0}function Ec(A){let a=A?.[Xi];return typeof a=="string"&&a.trim()?a:null}function qs(A){return typeof A!="string"?null:A.replace(/^\[\[/,"").replace(/\]\]$/,"").split("|")[0].split("#")[0].trim()||null}function Wa(A){return qs(Ec(A))}function vc(A){let a=A?.[za];return typeof a=="string"&&a.trim()?a:null}function Xa(){let A=Date.now().toString(36),a=Math.floor(Math.random()*1e6).toString(36);return`s-${A}-${a}`}function Fe(A,a){return a.file?A.metadataCache.getFileCache(a.file)?.frontmatter:null}function Qo(A,a){return a.slice().sort((e,t)=>{let i=wo(Fe(A,e)),s=wo(Fe(A,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 Za(A,a){if(a.length===0)return null;let e=Qo(A,a);return e.find(t=>ji(Fe(A,t)))??e[0]}function ja(A,a,e){let t=vc(Fe(A,a));return t||e}pt();ce();var Qe=require("obsidian");var re=require("obsidian");ce();Tt();ve();ce();function aa(A,a){let e=A.basename;return a&&e.endsWith(`-${a}`)?e=e.slice(0,-(a.length+1)):a||(e=e.replace(/-[abcdefghijkmnpqrstuvwxyz23456789]{6}$/,"")),e.replace(/-/g," ").trim()||A.basename}function yn(A,a){let e=new Set(a.discoverStashpadFolders()),t=[];for(let i of A.vault.getMarkdownFiles()){let s=i.parent?.path?.replace(/\/+$/,"")??"";if(!e.has(s))continue;let n=A.metadataCache.getFileCache(i)?.frontmatter??{},o=typeof n.id=="string"?n.id:null;if(!o||o===S)continue;let r=n.completed===!0,l=hi(n,"task")||n.task===!0||n.completed!==void 0,c=typeof n.due=="string"||typeof n.due=="number"?String(n.due):null,d=null;if(typeof n.due=="number")Number.isFinite(n.due)&&n.due>=1e11&&(d=n.due);else if(c){let h=Date.parse(c);Number.isNaN(h)||(d=h)}!l&&!r&&d==null&&!c||t.push({file:i,folder:s,id:o,title:aa(i,o),task:l,completed:r,due:d,dueRaw:c,color:typeof n.color=="string"?n.color:null,assignedTo:xt(n),assignedBy:gt(n.assignedBy),author:gt(n.author)})}return t}var Zr=require("obsidian");var ot=require("obsidian");ve();Tt();var md=0,ra=[{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 wn(){return{assign:"all",person:"",folder:"all",status:"all"}}function ws(A,a,e,t,i){let s=()=>ws(A,a,e,t,i);A.empty(),A.addClass("stashpad-task-triage");let n=yn(a,e),o=(e.settings.authorId??"").trim(),r=b=>!!o&&b.assignedTo.some(M=>M.id===o),l=b=>{switch(t.assign){case"mine":return r(b);case"others":return b.assignedTo.length>0&&!r(b);case"byme":return!!o&&b.assignedBy?.id===o;case"unassigned":return b.assignedTo.length===0;default:return!0}},c=b=>!t.person||b.assignedTo.some(M=>M.id===t.person)||b.author?.id===t.person||b.assignedBy?.id===t.person,d=new Map;for(let b of n){for(let M of b.assignedTo)d.set(M.id,M.name);b.assignedBy&&d.set(b.assignedBy.id,b.assignedBy.name),b.author&&d.set(b.author.id,b.author.name)}let h=[...d.entries()].map(([b,M])=>({id:b,name:M})).sort((b,M)=>b.name.localeCompare(M.name)),p=[...new Set(n.map(b=>b.folder))].sort((b,M)=>b.localeCompare(M));t.folder!=="all"&&!p.includes(t.folder)&&(t.folder="all");let f=b=>t.folder==="all"||b.folder===t.folder,u=A.createDiv({cls:"stashpad-triage-filters"}),g=u.createEl("button",{cls:"stashpad-triage-reset",attr:{"aria-label":"Reset filters"}});(0,ot.setIcon)(g,"rotate-ccw"),g.onclick=()=>{t.assign="all",t.person="",t.folder="all",s()};let I=u.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 b of["all","mine","others","byme","unassigned"]){let M=I.createEl("option",{text:m[b],value:b});t.assign===b&&(M.selected=!0)}I.onchange=()=>{t.assign=I.value,s()};let C=u.createEl("select",{cls:"stashpad-triage-select"}),B=C.createEl("option",{text:"All folders",value:"all"});t.folder==="all"&&(B.selected=!0);for(let b of p){let M=C.createEl("option",{text:b.split("/").pop()||b,value:b});t.folder===b&&(M.selected=!0)}if(C.onchange=()=>{t.folder=C.value,s()},h.length>0){let b=new Map;for(let q of h)b.has(q.name)||b.set(q.name,q.id);let M=`stashpad-task-authors-${++md}`,O=u.createDiv({cls:"stashpad-triage-authorwrap"}),K=O.createEl("input",{cls:"stashpad-triage-authorsearch",attr:{type:"text",list:M,placeholder:"Any person\u2026",spellcheck:"false"}}),z=O.createEl("button",{cls:"stashpad-triage-authorclear",attr:{"aria-label":"Clear person filter"}});(0,ot.setIcon)(z,"x"),z.onclick=()=>{K.value="",t.person?(t.person="",s()):K.focus()};let V=O.createEl("datalist");V.id=M;for(let q of h)V.createEl("option",{value:q.name});t.person&&(K.value=d.get(t.person)??"");let W=()=>{let q=K.value.trim();if(q===""){t.person&&(t.person="",s());return}let ee=b.get(q);ee&&t.person!==ee&&(t.person=ee,s())};K.onchange=W,K.addEventListener("keydown",q=>{q.key==="Enter"&&W()})}let E=Date.now(),y=new Date;y.setHours(0,0,0,0);let v=y.getTime(),Q=v+864e5,w=n.filter(b=>l(b)&&c(b)&&f(b)),k={overdue:[],today:[],upcoming:[],nodate:[],completed:[]};for(let b of w){if(b.completed){k.completed.push(b);continue}if(b.due==null){k.nodate.push(b);continue}b.due<v?k.overdue.push(b):b.due<Q?k.today.push(b):k.upcoming.push(b)}let D=(b,M)=>b.due==null&&M.due==null?b.title.localeCompare(M.title):b.due==null?1:M.due==null?-1:b.due-M.due,H=A.createDiv({cls:"stashpad-triage-chips"}),R=(b,M,O)=>{let K=H.createEl("button",{cls:"stashpad-triage-chip"});t.status===b&&K.addClass("is-active"),K.createSpan({text:M}),K.createSpan({cls:"stashpad-triage-chip-count",text:String(O)}),K.onclick=()=>{t.status=b,s()}};R("all","All",w.length);for(let b of ra)R(b.key,b.label,k[b.key].length);if(w.length===0){A.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 L=async b=>{try{await a.fileManager.processFrontMatter(b.file,M=>{M.completed=M.completed!==!0})}catch(M){new ot.Notice(`Couldn't update task: ${M.message}`);return}s()},x=b=>{let M=b.dueRaw??(b.due!=null?new Date(b.due).toISOString():null);new ze(a,M,O=>{a.fileManager.processFrontMatter(b.file,K=>{O.iso===null?delete K.due:(K.due=O.iso,K.task=!0)}).then(s).catch(K=>new ot.Notice(`Couldn't snooze: ${K.message}`))},{title:"Snooze \u2014 reschedule",hideAssignees:!0,quickAdjusts:e.settings.dueQuickAdjusts}).open()},U=t.status==="all"?ra:ra.filter(b=>b.key===t.status),T=!1;for(let b of U){let M=k[b.key];if(M.length===0)continue;if(T=!0,M.sort(b.key==="completed"?(K,z)=>D(z,K):D),t.status==="all"){let K=A.createDiv({cls:`stashpad-review-section is-${b.key}`});(0,ot.setIcon)(K.createSpan({cls:"stashpad-review-section-icon"}),b.icon),K.createSpan({cls:"stashpad-review-section-name",text:b.label}),K.createSpan({cls:"stashpad-review-section-count",text:String(M.length)})}let O=A.createDiv({cls:"stashpad-review-list"});for(let K of M)Cd(O,K,E,e,{toggleCompleted:L,snooze:x,onOpen:i.onOpen})}T||A.createDiv({cls:"stashpad-tasks-empty"}).setText("Nothing in this view.")}function Cd(A,a,e,t,i){let s=A.createDiv({cls:"stashpad-review-row"});a.completed&&s.addClass("is-completed");let n=s.createSpan({cls:"stashpad-review-check"});(0,ot.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,f=new Date(e);f.setHours(0,0,0,0);let u=f.getTime(),g=a.due>=u&&a.due<u+864e5,I=l.createSpan({cls:"stashpad-review-due",text:g?pi(a.due,t.settings):Nt(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"}),d=c.createEl("button",{cls:"stashpad-review-btn"});(0,ot.setIcon)(d,"alarm-clock"),d.title="Snooze \u2014 reschedule",d.onclick=()=>i.snooze(a);let h=c.createEl("button",{cls:"stashpad-review-btn"});(0,ot.setIcon)(h,"arrow-right"),h.title="Open note",h.onclick=()=>i.onOpen(a.folder,a.id)}var Ni=class extends Zr.Modal{constructor(e,t){super(e);this.plugin=t;this.state=wn()}onOpen(){this.modalEl.addClass("stashpad-task-review-modal"),this.titleEl.setText("Daily task review"),ws(this.contentEl,this.app,this.plugin,this.state,{onOpen:(e,t)=>{this.plugin.revealNoteByRef(e,t),this.close()}})}onClose(){this.contentEl.empty()}};function Ht(A,a,e){let t=A.createSpan({cls:"stashpad-count-badge"});e&&t.addClass("is-expanded"),t.setText(a>99?"99+":String(a))}var Es={pinned:{label:"Pinned",icon:"pin"},shared:{label:"Shared",icon:"users"},tasks:{label:"Tasks",icon:"check-circle-2"}},En=class extends re.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 St}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()===$&&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,re.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,re.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,re.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,re.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 d of Object.keys(Es)){let h=Es[d],p=l.createEl("button",{cls:"stashpad-panels-bar-btn"});(0,re.setIcon)(p.createSpan({cls:"stashpad-panels-bar-btn-icon"}),h.icon),p.createSpan({cls:"stashpad-panels-bar-btn-text",text:h.label}),this.activePanel===d&&p.addClass("is-active"),p.onclick=()=>{this.activePanel!==d&&(this.activePanel=d,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 re.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,re.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,re.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,f)=>this.renderPinnedRow(t,p,f));return}let c=new Map;r.forEach((p,f)=>{let u=c.get(p.folder);u||(u=[],c.set(p.folder,u)),u.push({pin:p,idx:f})});let d=this.plugin.lastActiveStashpadLeaf?.view?.noteFolder,h=Array.from(c.keys());d&&c.has(d)&&(h.splice(h.indexOf(d),1),h.unshift(d));for(let p of h){let f=p.split("/").pop()||p,u=t.createDiv({cls:"stashpad-pinned-group-header"});p===d&&u.addClass("is-active-folder"),u.createSpan({cls:"stashpad-pinned-group-name",text:f});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,d=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 C=p.getBoundingClientRect(),B=m.clientY-C.top<C.height/2;p.toggleClass("drop-before",B),p.toggleClass("drop-after",!B)}),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 C=parseInt(m.dataTransfer?.getData("text/plain")??"",10);if(!Number.isFinite(C)||C===i)return;let B=p.getBoundingClientRect(),E=m.clientY-B.top<B.height/2;this.reorderPin(C,E?i:i+1)});let f=p.createSpan({cls:"stashpad-pinned-toggle"});d&&(Ht(f,c,h),f.onclick=m=>{m.stopPropagation();let C=`${t.folder}|${t.id}`;this.expanded.has(C)?this.expanded.delete(C):this.expanded.add(C),this.render()});let u=p.createSpan({cls:"stashpad-pinned-icon"});(0,re.setIcon)(u,d?"folder-tree":"file-text"),r&&(u.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 C=new re.Menu;C.addItem(B=>B.setTitle("Unpin from sidebar").setIcon("pin-off").onClick(()=>{this.plugin.unpinNote(t)})),C.showAtMouseEvent(m)},d&&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((d,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,d=>{d.pinnedAt=c})}catch(d){console.warn("[Stashpad] pin reorder failed",d)}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,d=r.completed===!0,h=this.childrenOf(t,l).length,p=h>0,f=this.expanded.has(`${t}|${l}`),u=e.createDiv({cls:"stashpad-pinned-subrow"});d&&u.addClass("is-completed"),u.style.paddingLeft=`${s*16}px`;let g=u.createSpan({cls:"stashpad-pinned-toggle"});p&&(Ht(g,h,f),g.onclick=C=>{C.stopPropagation();let B=`${t}|${l}`;this.expanded.has(B)?this.expanded.delete(B):this.expanded.add(B),this.render()});let I=u.createSpan({cls:"stashpad-pinned-icon"});(0,re.setIcon)(I,"file-text"),c&&(I.style.color=c);let m=u.createSpan({cls:"stashpad-pinned-label",text:this.titleFromFile(o)});m.onclick=()=>this.openPinFromPanel({folder:t,id:l}),p&&f&&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 aa(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 re.Notice("No log yet \u2014 make some changes first.");return}let i=await e.read(t),{LogModal:s}=await Promise.resolve().then(()=>(ve(),ys));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()===$)return this.app.workspace.revealLeaf(e),e.view;let t=this.findActiveStashpad();if(t)return t;let i=this.app.workspace.getLeavesOfType($);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()===$?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 d of s){let h=d.authorId;h&&!n.has(h)&&n.set(h,d.authorDisplay||h)}let o=t.createDiv({cls:"stashpad-shared-filters"}),r=(d,h,p)=>{let f=o.createEl("button",{cls:"stashpad-shared-chip",text:d});return h&&f.addClass("is-active"),f.onclick=p,f};if(r("All",this.sharedAuthorFilter==="all",()=>{this.sharedAuthorFilter="all",this.render()}),r("Mine",this.sharedAuthorFilter==="mine",()=>{this.sharedAuthorFilter="mine",this.render()}),r("Others",this.sharedAuthorFilter==="others",()=>{this.sharedAuthorFilter="others",this.render()}),n.size>1){let d=o.createEl("select",{cls:"stashpad-shared-author-select"}),h=d.createEl("option",{text:"Any author"});h.value="__any__";for(let[f,u]of n){let g=d.createEl("option",{text:u});g.value=f}let p=["all","mine","others"].includes(this.sharedAuthorFilter)?"__any__":this.sharedAuthorFilter;d.value=p,d.onchange=()=>{let f=d.value;f==="__any__"?this.sharedAuthorFilter="all":this.sharedAuthorFilter=f,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(d=>{if(this.sharedContribOnly&&d.contributorCount===0)return!1;switch(this.sharedAuthorFilter){case"all":return!0;case"mine":return d.authorId===i;case"others":return d.authorId!==i;default:return d.authorId===this.sharedAuthorFilter}});if(c.length===0){t.createDiv({cls:"stashpad-shared-empty"}).setText("No shared notes match the current filters.");return}for(let d of c){let h=t.createDiv({cls:"stashpad-pinned-row stashpad-shared-row"}),p=h.createSpan({cls:"stashpad-pinned-icon"});(0,re.setIcon)(p,"users"),d.color&&(p.style.color=d.color);let f=h.createSpan({cls:"stashpad-pinned-label",text:d.title});f.onclick=()=>this.openSharedFromPanel(d.folder,d.id);let u=d.folder.split("/").pop()||d.folder;h.createSpan({cls:"stashpad-pinned-folder",text:u}),d.authorDisplay&&h.createSpan({cls:"stashpad-shared-meta"}).setText(d.authorId===i?`you \xB7 ${d.contributorCount} contributor${d.contributorCount===1?"":"s"}`:`by ${d.authorDisplay}${d.contributorCount>0?` \xB7 ${d.contributorCount} contributor${d.contributorCount===1?"":"s"}`:""}`)}}collectSharedNotes(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),d=Array.isArray(l.contributors)?l.contributors.filter(C=>typeof C=="string"):[],h=s.get(r)??null;if(!(d.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:d.length})}return n.sort((o,r)=>{let l=this.app.metadataCache.getFileCache(o.file)?.frontmatter??{},c=this.app.metadataCache.getFileCache(r.file)?.frontmatter??{},d=l.modified??l.created??"";return(c.modified??c.created??"").localeCompare(d)}),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,re.setIcon)(s.createSpan({cls:"stashpad-btn-icon"}),"maximize-2"),s.createSpan({text:"Daily review"}),s.onclick=()=>new Ni(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=T=>!!o&&T.assignedTo.some(b=>b.id===o),l=T=>{let b=this.taskAssignFilter;if(b.startsWith("person:")){let M=b.slice(7);return T.assignedTo.some(O=>O.id===M)}switch(b){case"mine":return r(T);case"others":return T.assignedTo.length>0&&!r(T);case"byme":return!!o&&T.assignedBy?.id===o;case"unassigned":return T.assignedTo.length===0;default:return!0}},c=new Map;for(let T of n){for(let b of T.assignedTo)b.id!==o&&c.set(b.id,b.name);T.assignedBy&&T.assignedBy.id!==o&&c.set(T.assignedBy.id,T.assignedBy.name)}let d=[...c.entries()].map(([T,b])=>({id:T,name:b})).sort((T,b)=>T.name.localeCompare(b.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"}),f=T=>{let b={all:"Everyone",mine:"Assigned to me",others:"Assigned to others",byme:"Assigned by me",unassigned:"Unassigned"};return T.startsWith("person:")?c.get(T.slice(7))??"Person":b[T]??T},u=T=>{let b=p.createEl("option",{text:f(T),value:T});this.taskAssignFilter===T&&(b.selected=!0)};for(let T of["all","mine","others","byme","unassigned"])u(T);if(d.length>0){let T=p.createEl("optgroup");T.setAttr("label","By person");for(let b of d){let M=T.createEl("option",{text:b.name,value:`person:${b.id}`});this.taskAssignFilter===`person:${b.id}`&&(M.selected=!0)}}p.onchange=()=>{this.taskAssignFilter=p.value,this.render()};let g=[...new Set(n.map(T=>T.folder))].sort((T,b)=>T.localeCompare(b));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"}),C=m.createEl("option",{text:"All folders",value:"all"});this.taskFolderFilter==="all"&&(C.selected=!0);for(let T of g){let b=m.createEl("option",{text:T.split("/").pop()||T,value:T});this.taskFolderFilter===T&&(b.selected=!0)}m.onchange=()=>{this.taskFolderFilter=m.value,this.render()};let B=T=>this.taskFolderFilter==="all"||T.folder===this.taskFolderFilter,E=n.filter(T=>l(T)&&B(T));if(E.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(),Q=v+24*60*60*1e3,w={overdue:[],today:[],upcoming:[],nodate:[],completed:[]};for(let T of E){if(T.completed){w.completed.push(T);continue}if(T.due==null){w.nodate.push(T);continue}T.due<v?w.overdue.push(T):T.due<Q?w.today.push(T):w.upcoming.push(T)}let k=(T,b)=>T.due==null&&b.due==null?T.title.localeCompare(b.title):T.due==null?1:b.due==null?-1:T.due-b.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"}),R=E.length,L=(T,b,M)=>{let O=H.createEl("button",{cls:"stashpad-task-filter"});this.taskFilter===T&&O.addClass("is-active"),O.createSpan({cls:"stashpad-task-filter-label",text:b}),O.createSpan({cls:"stashpad-task-filter-count",text:String(M)}),O.onclick=()=>{this.taskFilter=T,this.render()}};L("all","All",R),L("overdue","Overdue",w.overdue.length),L("today","Today",w.today.length),L("upcoming","Upcoming",w.upcoming.length),L("nodate","No date",w.nodate.length),L("completed","Done",w.completed.length);let x=this.taskFilter==="all"?D:D.filter(T=>T.key===this.taskFilter),U=!1;for(let T of x){let b=w[T.key];if(b.length!==0){if(U=!0,b.sort(T.key==="completed"?(M,O)=>k(O,M):k),this.taskFilter==="all"){let M=t.createDiv({cls:`stashpad-task-section-header is-${T.key}`});(0,re.setIcon)(M.createSpan({cls:"stashpad-task-section-icon"}),T.icon),M.createSpan({cls:"stashpad-task-section-name",text:T.label}),M.createSpan({cls:"stashpad-task-section-count",text:String(b.length)})}for(let M of b)this.renderTaskRow(t,M,T.key==="today")}}if(!U&&this.taskFilter!=="all"){t.createDiv({cls:"stashpad-tasks-empty"}).setText(`Nothing in "${x[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,re.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 d of t.assignedTo){let h=c.createSpan({cls:"stashpad-task-assignee"});l&&d.id===l&&h.addClass("is-me"),h.setText(this.initials(d.name)),h.title=l&&d.id===l?`${d.name} (you)`:d.name}}let r=s.createEl("button",{cls:"stashpad-task-snooze"});(0,re.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 re.Menu;c.addItem(d=>d.setTitle("Open").setIcon("arrow-right").onClick(()=>{this.openTaskFromPanel(t.folder,t.id)})),c.addItem(d=>d.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 ze(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 re.Notice(`Couldn't snooze: ${s.message}`))},{title:"Snooze \u2014 reschedule",hideAssignees:!0,quickAdjusts:this.plugin.settings.dueQuickAdjusts}).open()}formatDueShort(e,t){return t?pi(e,this.plugin.settings):Nt(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 re.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 yn(this.app,this.plugin)}};async function vn(A){let a=A.workspace.getLeavesOfType(St);if(a.length>0){A.workspace.revealLeaf(a[0]);return}let e=A.workspace.getLeftLeaf(!1);if(!e){new re.Notice("Stashpad: couldn't open the panels view.");return}await e.setViewState({type:St,active:!0}),A.workspace.revealLeaf(e)}Cn();Tt();ce();function jr(A){return/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(A)}var Qn=class extends Qe.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 Jt}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?.()===$&&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?.()===$&&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?.()===$&&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,Qe.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"}),d=c.createDiv({cls:"stashpad-detail-titlerow"});d.createDiv({cls:"stashpad-detail-title",text:this.titleFor(o)});let h=d.createEl("button",{cls:"stashpad-detail-open-btn",attr:{"aria-label":"Open in Stashpad tab"}});(0,Qe.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"&&jr(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):it(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 f=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 Qe.Component;this.addChild(m),this.bodyComponent=m,await Qe.MarkdownRenderer.render(this.app,I,f,o.path,m)}catch(g){f.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 u=this.composerInputEl;if(i&&u&&(u.focus(),s!=null)){let g=Math.min(s,u.value.length);try{u.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,Qe.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 Pt(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?.()!==$||typeof i.createNoteUnder!="function"){new Qe.Notice("Open a Stashpad view to add notes.");return}try{await i.createNoteUnder(t,e.id)}catch(s){new Qe.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?.()!==$)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"&&jr(l.color)?l.color:null,d=l.completed===!0,h=i.getChildren(n.id),p=h.length>0,f=`${s}|${n.id}`,u=this.expanded.has(f),g=e.createDiv({cls:"stashpad-detail-child-row"});d&&g.addClass("is-completed"),o>0&&(g.style.paddingLeft=`${o*16}px`),g.draggable=!0,g.dataset.id=n.id,g.addEventListener("dragstart",E=>{E.dataTransfer?.setData("text/plain",n.id),E.dataTransfer&&(E.dataTransfer.effectAllowed="move"),g.addClass("is-dragging")}),g.addEventListener("dragend",()=>g.removeClass("is-dragging")),g.addEventListener("dragover",E=>{E.preventDefault(),E.dataTransfer&&(E.dataTransfer.dropEffect="move");let y=g.getBoundingClientRect(),v=E.clientY-y.top<y.height/2;g.toggleClass("drop-before",v),g.toggleClass("drop-after",!v)}),g.addEventListener("dragleave",()=>{g.removeClass("drop-before"),g.removeClass("drop-after")}),g.addEventListener("drop",E=>{E.preventDefault(),g.removeClass("drop-before"),g.removeClass("drop-after");let y=E.dataTransfer?.getData("text/plain");if(!y||y===n.id)return;let v=g.getBoundingClientRect(),Q=E.clientY-v.top<v.height/2;typeof t.reorderToTarget=="function"&&t.reorderToTarget([y],n.id,Q?"before":"after")}),g.oncontextmenu=E=>{E.preventDefault();let y=i.get(n.id);y&&typeof t.openNoteMenu=="function"&&t.openNoteMenu(E,y)};let I=g.createSpan({cls:"stashpad-detail-child-toggle"});if(p&&(Ht(I,h.length,u),I.onclick=E=>{E.stopPropagation(),this.expanded.has(f)?this.expanded.delete(f):this.expanded.add(f),this.render()}),hi(l,"task")||l.task===!0||l.completed!==void 0){let E=g.createSpan({cls:"stashpad-detail-child-checkbox"});(0,Qe.setIcon)(E,d?"check-square":"square"),E.title=d?"Mark not done":"Mark done",E.addEventListener("mousedown",y=>y.stopPropagation()),E.addEventListener("dblclick",y=>{y.preventDefault(),y.stopPropagation()}),E.onclick=y=>{y.preventDefault(),y.stopPropagation();let v=i.get(n.id);v&&typeof t.toggleCompletedForNode=="function"&&t.toggleCompletedForNode(v)}}let C=g.createSpan({cls:"stashpad-detail-child-icon"});(0,Qe.setIcon)(C,p?"folder-tree":"file-text"),c&&(C.style.color=c);let B=g.createSpan({cls:"stashpad-detail-child-title",text:this.titleFor(n.file)});if(B.onclick=()=>{t?.navigateTo&&t.navigateTo(n.id)},p&&u){let E=new Set(r).add(n.id);for(let y of h)this.renderDetailChildRow(e,t,i,s,y,o+1,E)}}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)?it(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 Qe.Notice(`Couldn't open: ${i.message}`)}}};async function kn(A){let a=A.workspace.getLeavesOfType(Jt);if(a.length>0){A.workspace.revealLeaf(a[0]);return}let e=A.workspace.getRightLeaf(!1);if(!e){new Qe.Notice("Stashpad: couldn't open the detail panel.");return}await e.setViewState({type:Jt,active:!0}),A.workspace.revealLeaf(e)}var F=require("obsidian");ce();var Rt=require("obsidian");ce();function Bd(A,a){let e=A.vault.getAbstractFileByPath(a);if(!(e instanceof Rt.TFolder))return[];let t=[],i=[e];for(;i.length;){let s=i.pop();for(let n of s.children)n instanceof Rt.TFile?n.extension==="md"&&t.push(n):n instanceof Rt.TFolder&&(tr(n.name)||i.push(n))}return t}var Fn=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?Bd(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),d=c?i.get(c):void 0,h=this.synthetic.get(n.path),p=d??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===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 d=r.has(l)?r.get(l):1/0,h=r.has(c)?r.get(c):1/0;return d===h?0:d-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 Rt.TFile&&e(l.path)&&l.extension==="md"&&(this.applyChange(l),i())},n=l=>{l instanceof Rt.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 Rt.TFile))return;let d=typeof c=="string"?c:null;!e(l.path)&&!e(d)||this.applyRename(l,d??"")&&i()};return this.app.metadataCache.on("changed",s),this.app.vault.on("create",n),this.app.vault.on("delete",o),this.app.vault.on("rename",r),()=>{this.app.metadataCache.off("changed",s),this.app.vault.off("create",n),this.app.vault.off("delete",o),this.app.vault.off("rename",r),this.coalesceTimer!=null&&(window.clearTimeout(this.coalesceTimer),this.coalesceTimer=null)}}applyChange(a){if(qt(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),d=e?.created??"",h=!1;return c.file!==a&&(c.file=a,h=!0),c.created!==d&&(c.created=d,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(qt(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 la=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(` diff --git a/manifest.json b/manifest.json index 0788dc1..fa338b7 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "stashpad", "name": "Stashpad", - "version": "0.193.0", + "version": "0.194.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 2cbc4fb..7ba5ec7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "stashpad-obsidian", - "version": "0.193.0", + "version": "0.194.0", "private": true, "scripts": { "dev": "node esbuild.config.mjs", diff --git a/release-notes/0.194.0.md b/release-notes/0.194.0.md new file mode 100644 index 0000000..6b693de --- /dev/null +++ b/release-notes/0.194.0.md @@ -0,0 +1,19 @@ +# 0.194.0 + +## Encryption warnings + +Prompted by a real loss: a server/profile reset wiped a machine's OS keychain and took +the only copy of a folder password with it. + +- **The keychain is called out as a convenience, not a backup.** "Remember on this + device (keychain)" now says so at the moment you tick it: an OS or keychain reset, a + wiped or restored profile, a reinstall, a new machine, or an IT event can erase it at + any time, without warning β€” and if that was the only copy of your password, + everything encrypted under it is permanently unreadable. +- **"Save it in a password manager first" leads the warning**, in larger, bolder type, + ahead of everything else β€” along with a nudge to set a **Recovery password** as a + second way in. Both live outside the keychain, so they survive the events above. +- The encryption warning callout is **larger and more prominent** overall, and the same + warning now appears in the README and in the password-setup dialog. +- Added plainly: **Stashpad cannot recover keys or passwords, and is not liable for the + loss of keys, passwords, or any data encrypted with them.** diff --git a/src/modals.ts b/src/modals.ts index 10e65f2..9f1d18e 100644 --- a/src/modals.ts +++ b/src/modals.ts @@ -1972,7 +1972,10 @@ export class EncryptionPasswordModal extends Modal { const lbl = row.createEl("label", { text: "Remember on this device (keychain) β€” auto-unlock here without re-typing." }); lbl.htmlFor = rememberCb.id; const note = this.contentEl.createDiv({ cls: "stashpad-export-remember-note" }); - note.setText("Stored only in this device's keychain β€” doesn't sync to your other devices. Anyone with access to this unlocked device + keychain could decrypt."); + // 0.194.0: this checkbox is where people accidentally make the keychain the + // ONLY copy of their password. Say so here, at the moment of the decision. + note.setText("Stored only in this device's keychain β€” it doesn't sync, and anyone with access to this unlocked device could decrypt. This is a convenience, NOT a backup: an OS/keychain reset, a restored profile, a reinstall or a new machine can erase it without warning. Keep the password in a password manager too, or you will lose access to everything encrypted under it."); + note.addClass("stashpad-keychain-note"); note.setCssStyles({ display: rememberCb.checked ? "" : "none" }); rememberCb.onchange = () => { note.setCssStyles({ display: rememberCb!.checked ? "" : "none" }); }; } diff --git a/src/settings.ts b/src/settings.ts index 380ae36..654da0a 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -1108,7 +1108,7 @@ export class StashpadSettingTab extends PluginSettingTab { } private promptSetFolderPassword(folder: string): void { new EncryptionPasswordModal(this.app, { mode: "setup", offerKeychain: true, title: `Set password for β€œ${folder.split("/").pop()}”`, - 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.", + intro: "A separate password just for this folder. Save it in a password manager BEFORE you continue β€” the device keychain is a convenience that can be wiped at any time, not a backup. There is NO recovery if it's lost: Stashpad cannot recover it, and everything encrypted under it becomes permanently unreadable.", onSubmit: async ({ next, remember }) => { if (!next) return "Enter a password."; try { await this.plugin.encryption.setupFolderKey(folder, next, this.folderKeyLabel(folder), remember); } catch (e) { return (e as Error).message; } new Notice("Folder password set β€” share it securely."); this.update?.(); this.pfeRerender?.(); return null; } }).open(); } private promptChangeFolderPassword(folder: string): void { @@ -1656,7 +1656,7 @@ export class StashpadSettingTab extends PluginSettingTab { const enc = this.plugin.encryption; const items: SettingDefinitionItem[] = []; - items.push(this.sectionDef("Vault Encryption", "Set one password to encrypt content in this vault. Stored only on this device β€” there is no recovery if you lose it.", (host) => { + items.push(this.sectionDef("Vault Encryption", "Encrypt notes per folder with a password you choose. Keep that password in a password manager β€” there is no recovery if it is lost.", (host) => { host.addClass("stashpad-encryption-section"); const betaRow = host.createDiv({ cls: "stashpad-beta-row" }); betaRow.createEl("span", { cls: "stashpad-beta-badge", text: "BETA" }); @@ -1665,6 +1665,20 @@ export class StashpadSettingTab extends PluginSettingTab { // a ⚠️ description paragraph here, and a "no recovery" callout at the top // of the per-folder section). Same .stashpad-enc-warning callout style. const warn = host.createEl("div", { cls: "stashpad-enc-warning" }); + // 0.194.0: keychain loss leads, because it's the failure that actually happens. + // (Real incident: a server/profile reset wiped the OS keychain and took the only + // copy of a folder password with it.) The key itself lives in the folder's + // `.stashkey`; the keychain only ever held a CONVENIENCE copy of the password β€” + // so if that copy was the only one, the content is gone. + warn.createEl("p", { cls: "stashpad-enc-lead" }).setText( + "⚠️ Write your password down somewhere outside this computer β€” a password manager β€” BEFORE you encrypt anything.", + ); + warn.createEl("p").setText( + "β€œRemember on this device (keychain)” is a convenience, NOT a backup. An OS or keychain reset, a wiped/restored profile, a reinstall, a new machine, or an IT/server event can erase it at any time, without warning and without asking you. If the only copy of your password was in the keychain, everything encrypted under it is permanently unreadable β€” by you, by us, by anyone.", + ); + warn.createEl("p").setText( + "Store the password in a password manager (1Password, Bitwarden, KeePass…), and set a Recovery password as a second way in. Both are stored outside the keychain, so they survive the events above.", + ); warn.createEl("p").setText( "⚠️ AI-built, NOT human-audited. This encryption was written by an AI assistant β€” not reviewed or security-audited by a human. Treat it as best-effort protection against a casual snoop, not a guarantee β€” and always keep your own unencrypted backups of anything important.", ); @@ -1674,6 +1688,9 @@ export class StashpadSettingTab extends PluginSettingTab { warn.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 β€” it can corrupt files.", ); + warn.createEl("p", { cls: "stashpad-enc-liability" }).setText( + "Stashpad cannot recover keys or passwords, and is not liable for the loss of keys, passwords, or any data encrypted with them. Backing them up is yours to do.", + ); // 0.137.4: ONE collapsible, toggle-free "how it works" reference block, so // the individual setting rows below can stay one-liners instead of each diff --git a/styles.css b/styles.css index 55ea848..bd287b4 100644 --- a/styles.css +++ b/styles.css @@ -6090,11 +6090,30 @@ body.stashpad-folderpanel-resizing { cursor: row-resize; user-select: none; } Vault Encryption section (was three separate warnings) β€” inset 14px to line up with the section's setting rows. */ margin: 4px 14px 18px; - font-size: 13px; - line-height: 1.5; + /* 0.194.0: bumped 13px -> 14px and the rule 3px -> 4px. A user lost an encryption + key to a keychain wipe; this callout is the last thing standing between someone + and permanent data loss, so it gets read-me-first weight. */ + font-size: 14px; + line-height: 1.55; } .stashpad-enc-warning p { margin: 0; } -.stashpad-enc-warning p + p { margin-top: 8px; } +.stashpad-enc-warning p + p { margin-top: 9px; } +/* The single most important sentence in the plugin β€” larger and bolder than the + paragraphs beneath it. */ +.stashpad-enc-warning .stashpad-enc-lead { + font-size: 15px; + font-weight: 600; + line-height: 1.45; +} +.stashpad-enc-warning strong { color: var(--text-normal); font-weight: 700; } +/* Liability line: quieter than the warnings, but unmissable. */ +.stashpad-enc-warning .stashpad-enc-liability { + margin-top: 11px; + padding-top: 9px; + border-top: 1px solid rgba(var(--color-red-rgb, 224, 49, 49), 0.35); + font-size: 13px; + font-style: italic; +} /* 0.137.4: collapsible "how encryption works" concepts block β€” one toggle-free reference so the individual setting rows can stay one-liners. Collapsed by default (details), neutral (not a warning). */ @@ -6229,3 +6248,15 @@ button.stashpad-btn-loading::after { .stashpad-import-view .stashpad-import-preview { max-height: none; } .stashpad-import-popicon { display: inline-flex; margin-left: 4px; vertical-align: -2px; } .stashpad-import-popicon svg { width: 14px; height: 14px; } + +/* 0.194.0 β€” the keychain opt-in note carries a real data-loss warning now, so it + gets warning colour instead of reading as neutral fine print. */ +.stashpad-keychain-note { + color: var(--text-normal); + border-left: 3px solid var(--color-red, #e03131); + background: rgba(var(--color-red-rgb, 224, 49, 49), 0.10); + padding: 8px 10px; + border-radius: 4px; + margin-top: 6px; + line-height: 1.5; +}