diff --git a/main.js b/main.js index a030865..c0d85b7 100644 --- a/main.js +++ b/main.js @@ -6,7 +6,7 @@ `).trim()),e.filter(Boolean)}function Ft(A,r,t){A.empty();try{(0,ia.setIcon)(A,r)}catch{}let e=A.querySelector("svg");e&&e.querySelector("path, line, circle, rect, polyline, polygon, ellipse")||(A.empty(),A.createSpan({cls:"stashpad-icon-fallback",text:t}))}function sa(A){if(A instanceof Element&&A.closest(".modal, .modal-container, .suggestion-container, .menu, .prompt"))return!0;let r=new Set([document]);A instanceof Element&&A.ownerDocument&&r.add(A.ownerDocument);for(let t of r)if(t.body?.querySelector(".modal-bg")||t.body?.querySelector(".modal-container .modal")||t.body?.querySelector(".suggestion-container")||t.body?.querySelector(".menu.mod-active"))return!0;return!1}function na(A){let r=[],t=/^([ \t]*)(`{3,})[ \t]*([^\n`]*)\n([\s\S]*?)\n\1\2[ \t]*$/gm,e;for(;(e=t.exec(A))!=null;)r.push({lang:e[3].trim(),code:e[4]});return r}function Fi(A){return A.split("/").map(r=>r.split(" ").map(t=>t&&/^[a-z]/.test(t)?t[0].toUpperCase()+t.slice(1):t).join(" ")).join("/")}function oa(A,r,t){let e=new Set(r),i=A.filter(n=>!e.has(n)),s=A.findIndex(n=>e.has(n));if(s<0)return A.slice();switch(t){case"top":return[...r,...i];case"bottom":return[...i,...r];case"up":{let n=Math.max(0,s-1),o=i.slice();return o.splice(n,0,...r),o}case"down":{let n=(()=>{let c=-1;return A.forEach((d,h)=>{e.has(d)&&(c=h)}),c})(),o=0;for(let c=0;c0){let n=e[i-1];return(!/[a-z0-9]/.test(n)?600:500)-Math.min(i,99)}let s=0;for(let n=0;n({t:e,s:dl(t,e.raw)})).filter(e=>e.s>=0).sort((e,i)=>i.s-e.s||i.t.count-e.t.count||e.t.label.localeCompare(i.t.label)).map(e=>e.t):r}var ia,Ei,xe,Ne,ki=Jt(()=>{"use strict";ia=require("obsidian"),Ei={lines:"Each line",paragraphs:"Paragraphs (blank line)",headings:"Headings"};xe="__stashpad:tagged__",Ne="__stashpad:untagged__"});function hl(A,r){return A>12?A>=24?0:A:r==="am"?A===12?0:A:A===12?12:A+12}function As(A,r){A.addClass("stashpad-when-pop-time");let t=r.seedPeriod,e=A.createDiv({cls:"stashpad-when-time-display"}),i=e.createEl("input",{cls:"stashpad-when-time-field",attr:{type:"text",inputmode:"numeric",maxlength:"2"}});i.value=String(r.seedH),e.createSpan({cls:"stashpad-when-time-colon",text:":"});let s=e.createEl("input",{cls:"stashpad-when-time-field",attr:{type:"text",inputmode:"numeric",maxlength:"2"}});s.value=String(r.seedM).padStart(2,"0");let n=e.createDiv({cls:"stashpad-when-time-period"}),o=n.createEl("button",{cls:"stashpad-when-time-ampm",text:"AM"});o.type="button";let a=n.createEl("button",{cls:"stashpad-when-time-ampm",text:"PM"});a.type="button";let l=()=>{o.toggleClass("is-active",t==="am"),a.toggleClass("is-active",t==="pm")};l(),o.addEventListener("mousedown",B=>B.preventDefault()),a.addEventListener("mousedown",B=>B.preventDefault()),o.addEventListener("click",B=>{B.preventDefault(),t="am",l()}),a.addEventListener("click",B=>{B.preventDefault(),t="pm",l()});let c=i;i.addEventListener("focus",()=>{c=i,i.select()}),s.addEventListener("focus",()=>{c=s,s.select()});let d=()=>{let w=(parseInt(i.value||"0",10)||0)>12;o.toggleClass("is-disabled",w),a.toggleClass("is-disabled",w),o.disabled=w,a.disabled=w},h=B=>{let w=B.value.replace(/\D/g,"").slice(0,2);if(B.value=w,w===""){B===i&&d();return}let y=parseInt(w,10),Q=B===i?24:59;y>Q&&(B.value=String(Q)),B===i&&d()};for(let B of[i,s])B.addEventListener("input",()=>h(B));d();let g=()=>{let B=parseInt(i.value||"12",10)||12,w=parseInt(s.value||"0",10)||0,y=B>12;r.onFinalize({hours24:hl(B,t),minutes:w,raw:{hh:B,mm:w,period:t,is24:y}}),r.close()};r.setOnEnter?.(g);let u=[i,s,o,a],p=(B,w)=>{let y=u.indexOf(B);if(y===-1)return;let Q=(y+w+u.length)%u.length;u[Q].focus()},f=B=>{B.addEventListener("keydown",w=>{w.key==="Enter"?(w.preventDefault(),w.stopPropagation(),g()):w.key==="Escape"?(w.preventDefault(),w.stopPropagation(),r.close()):w.key==="Tab"&&(w.preventDefault(),w.stopPropagation(),p(B,w.shiftKey?-1:1))})},I=A.createDiv({cls:"stashpad-when-time-pad"}),m=["1","2","3","4","5","6","7","8","9","backspace","0","insert"],C=null;for(let B of m){let w=I.createEl("button",{cls:"stashpad-when-time-padbtn"});w.type="button",B==="backspace"?(0,ra.setIcon)(w,"delete"):B==="insert"?(w.setText("OK"),C=w):w.setText(B),B==="insert"&&w.addClass("is-go"),w.addEventListener("mousedown",y=>y.preventDefault()),w.addEventListener("click",y=>{if(y.preventDefault(),B==="insert"){g();return}if(B==="backspace"){c.value=c.value.slice(0,-1),h(c),c.focus();return}let Q=c.selectionStart===0&&c.selectionEnd===c.value.length&&c.value.length>0,v=2,E=Q||c.value.length>=v?B:c.value+B;c.value=E,h(c),c.focus(),c.setSelectionRange(c.value.length,c.value.length),c===i&&c.value.length>=v&&(s.focus(),s.select())})}C&&u.push(C);for(let B of u)f(B);i.focus(),i.select()}function la(A){let{hh:r,mm:t,period:e,is24:i}=A.raw;return i?`${r}:${String(t).padStart(2,"0")}`:`${r}:${String(t).padStart(2,"0")}${e}`}var ra,Tn=Jt(()=>{"use strict";ra=require("obsidian")});function Aa(A){let r=Math.floor(4294967296/A)*A,t=new Uint32Array(1),e;do crypto.getRandomValues(t),e=t[0];while(e>=r);return e%A}function Pn(A=5){let r=[];for(let t=0;t=1&&s.every(a=>/^[a-zA-Z]+$/.test(a))&&(i=Math.min(i,s.length*11)),pl.has(A.toLowerCase())&&(i=Math.min(i,12));let n=i<36?0:i<56?1:i<76?2:3,o=["Weak \u2014 easily guessed","Fair","Good","Strong"][n];return{bits:i,level:n,label:o}}function gl(A){let r=2166136261;for(let t=0;t>>0).toString(16).padStart(8,"0")}function Ve(A){let r="stashpad-",t=gl(A),e=64-r.length-1-t.length,i=A.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,Math.max(0,e)).replace(/-+$/g,"");return`${r}${i}-${t}`}var ca,pl,ds=Jt(()=>{"use strict";ca="able acid acorn actor adept agile alarm album alert algae amber amble anchor angle ankle apple april arbor arc arctic arena armor arrow ascot aspen atlas atom attic auburn audio autumn award axis bacon badge bagel baker balmy bamboo banjo barge basil basin batch beach beam bean bear beaver begin belt bench berry birch bison black blade blaze bliss bloom blue board boat bold bolt bonus boost booth borax bother bottle boulder bounce bovine bowl brave bread breeze brick bridge brisk broad bronze brook broom brown brush bubble bucket bug bulb bundle burst cabin cable cacao cactus camel cameo candle canoe canvas canyon cargo carol carrot castle catch cedar cello chalk charm chart cheese cherry chess chime chirp cider cinder circle citrus clamp clay clever cliff cloak clock cloud clover coast cobra cocoa comet coral cosmos cotton couch cougar crane crater cream crest cricket crisp crown crumb crystal cube cumin curio dagger daisy dapper dawn deck deer delta denim depot desert dial diamond dingo ditch dock dodge dolphin domino donut draft dragon drift drum dune dusk eagle early earth easel ebony echo eclipse edge eel eagle elbow elder ember emboss emerald ember emu engine ermine ether ever fable falcon fancy farm fawn feather felt fennel fern ferry fiber fiddle field fig finch flame flask flax fleet flint float flock flora flute focus foam forest fossil fox frame frost fudge garden gecko ginger glacier glade glass glide globe glory glove gnat goat golden gopher gourd grape grass gravel grove guava gull hammer hamlet harbor hatch hazel heron hickory hippo honey hornet hostel ivory ivy jade jaguar jasmine jelly jetty jewel jolly jungle juniper kayak kelp kettle kiwi koala ladle lagoon lamp lantern larch lark lasso lava ledge lemon lentil leopard lever lilac lime linen lizard llama lobby locket lodge lotus lunar lupine lynx maple marble marsh meadow medal melon mellow mentor mesa metro mimic mint mirror mocha morsel moss mottle mural muslin nacho nectar nest noble nomad noodle nougat nutmeg oasis oat ocean ochre olive onyx opal orbit orca otter oval owl oxide oyster pace paddle palm panda pantry papaya parka parsley pasta pearl pebble pelican pepper pewter phantom piano picnic pigeon pilot pine pixel plank plaza plum pocket pollen pond poplar poppy portal potato pottery prairie prism puffin pumice quail quartz quill quilt quince rabbit radish raft rapid raven reed reef relish ribbon ridge rind ripple river robin rocket rope rover ruby rudder rust saffron sage salmon sandal sash satin sauce scout sedge sequin shadow shale shark shell shore shrub silk silo silver siren sketch slate sleet slope sloth smoke snail sonar sorrel spark sparrow spice spire sprig spruce squid stable stamp starling steam stem stilt stone stork storm stove straw stream stucco summit sundae sunset swan sweater syrup tabby talon tango tapir tassel tawny teal tempo thicket thimble thistle thorn thunder tidal tiger timber toffee token topaz torch totem trail tulip tundra turtle tusk twig umber unicorn valley vanilla velvet vermil violet viper vista vivid vortex waffle walnut warbler wasp water weasel wharf wheat whisk willow window winter wisp wombat wonder woven yam yarn yeast yew yodel yonder zebra zenith zephyr zigzag zinc zircon".split(/\s+/).filter(Boolean).filter((A,r,t)=>t.indexOf(A)===r);pl=new Set(["password","passw0rd","password1","123456","12345678","123456789","qwerty","abc123","letmein","welcome","admin","iloveyou","monkey","dragon","sunshine","princess","football","baseball","trustno1","000000","111111","secret"])});var hs={};Ii(hs,{newId:()=>W});function W(A=6){let r="",t=new Uint8Array(A);crypto.getRandomValues(t);for(let e=0;e{"use strict";da="abcdefghijkmnpqrstuvwxyz23456789"});var Hi={};Ii(Hi,{BreadcrumbLevelsModal:()=>Ni,ColorPickerModal:()=>Pe,ConfirmDeleteModal:()=>We,ConfirmModal:()=>et,CustomColorModal:()=>ps,DueDatePickerModal:()=>Ze,EncryptionPasswordModal:()=>At,ExportStashModal:()=>Xe,ImportDupChoiceModal:()=>Ti,ImportLogModal:()=>Un,LogModal:()=>ze,NotificationHistoryModal:()=>Mi,OkfExportModal:()=>Pi,SplitNoteModal:()=>bi,StashPasswordModal:()=>Di,TypeToConfirmModal:()=>xi,buildAssigneePicker:()=>ha});function ha(A,r){let t=[...r.initial],e=r.knownAuthors,i=A.createDiv({cls:"stashpad-assign"});i.createDiv({cls:"stashpad-assign-label",text:"Assign to"});let s=i.createDiv({cls:"stashpad-assign-chips"}),n=i.createDiv({cls:"stashpad-assign-input-wrap"}),o=n.createEl("input",{type:"text",cls:"stashpad-assign-input",attr:{placeholder:"Add a person \u2014 type a name\u2026"}}),a=n.createDiv({cls:"stashpad-assign-suggest"});a.setCssStyles({display:"none"});let l=()=>r.onChange([...t]),c=()=>{s.empty(),t.length===0&&s.createSpan({cls:"stashpad-assign-empty",text:"No one yet"});for(let g of t){let u=s.createSpan({cls:"stashpad-assign-chip"});u.createSpan({cls:"stashpad-assign-chip-name",text:g.name});let p=u.createSpan({cls:"stashpad-assign-chip-x",text:"\xD7"});p.title=`Remove ${g.name}`,p.onclick=()=>{t=t.filter(f=>f.id!==g.id),l(),c()}}},d=g=>{g.name.trim()&&(t.some(u=>u.id===g.id)||t.push(g),o.value="",a.setCssStyles({display:"none"}),l(),c(),o.focus())},h=()=>{let g=o.value.trim();a.empty();let u=new Set(t.map(I=>I.id)),f=e.filter(I=>!u.has(I.id)&&as(g,I.name)).slice(0,6).map(I=>({label:I.name,onPick:()=>d(I)}));if(g&&!e.some(I=>I.name.toLowerCase()===g.toLowerCase())&&f.push({label:`Create \u201C${g}\u201D`,onPick:()=>d({id:W(6),name:g})}),f.length===0){a.setCssStyles({display:"none"});return}a.setCssStyles({display:""});for(let I of f){let m=a.createDiv({cls:"stashpad-assign-suggest-item",text:I.label});m.onmousedown=C=>{C.preventDefault(),I.onPick()}}};o.addEventListener("input",h),o.addEventListener("focus",h),o.addEventListener("keydown",g=>{if(g.key==="Enter"){g.preventDefault();let u=a.querySelector(".stashpad-assign-suggest-item");u&&u.dispatchEvent(new MouseEvent("mousedown"))}else g.key==="Escape"&&a.style.display!=="none"&&(g.stopPropagation(),a.setCssStyles({display:"none"}))}),o.addEventListener("blur",()=>{window.setTimeout(()=>{a.setCssStyles({display:"none"})},120)}),c()}var K,ul,Me,ze,We,bi,Xe,Di,At,xi,ps,Si,Pe,et,Ni,Ze,Te,Mi,Un,Ti,Pi,kt=Jt(()=>{"use strict";K=require("obsidian");ki();Tn();rt();ds();Gt();ul=K.moment,Me=class Me extends K.Modal{constructor(t,e,i){super(t);this.text=e;this.jsonlPath=i;this.events=[];this.visible=[];this.shownCount=0;this.typeFilter=null;this.listEl=null;this.footerEl=null;this.countEl=null;this.filterSelEl=null}onOpen(){this.contentEl.empty(),this.titleEl.setText("Stashpad log"),this.modalEl.addClass("stashpad-log-modal"),this.events=[];for(let l of this.text.trim().split(/\r?\n/))if(l)try{this.events.push(JSON.parse(l))}catch{}this.events.reverse();let t=this.contentEl.createDiv({cls:"stashpad-log-toolbar"});this.countEl=t.createSpan({cls:"stashpad-log-count"}),this.updateCount(),this.filterSelEl=t.createEl("select",{cls:"stashpad-log-type-filter"}),this.filterSelEl.onchange=()=>this.setTypeFilter(this.filterSelEl.value||null),this.refreshTypeFilter();let e=t.createEl("button",{text:"Reveal JSONL"});e.onclick=()=>this.shellAct("reveal");let i=t.createEl("button",{text:"Open in default app"});i.onclick=()=>this.shellAct("open");let s=t.createEl("button",{text:"Copy raw JSONL"}),n=null;s.onclick=async()=>{await navigator.clipboard.writeText(this.text),s.setText("Copied"),n!=null&&window.clearTimeout(n),n=window.setTimeout(()=>{s.setText("Copy raw JSONL"),n=null},1500)};let o=t.createEl("button",{text:"Export copy"});o.onclick=()=>this.exportCopy();let a=t.createEl("button",{cls:"mod-warning",text:"Clear log"});a.onclick=()=>this.clearLog(),this.listEl=this.contentEl.createDiv({cls:"stashpad-log-list"}),this.refreshList(),this.footerEl=this.contentEl.createDiv({cls:"stashpad-log-footer"}),this.renderFooter()}refreshList(){if(this.listEl){if(this.visible=this.typeFilter?this.events.filter(t=>t.type===this.typeFilter):this.events.slice(),this.shownCount=0,this.listEl.empty(),!this.visible.length){this.listEl.createDiv({cls:"stashpad-log-empty",text:this.typeFilter?`No "${this.typeFilter}" events.`:"No events yet."}),this.updateCount();return}this.appendMore(Me.PAGE)}}setTypeFilter(t){(this.typeFilter??null)!==(t??null)&&(this.typeFilter=t,this.refreshList(),this.renderFooter())}refreshTypeFilter(){if(!this.filterSelEl)return;let t=this.filterSelEl;t.empty();let e=new Map;for(let n of this.events)e.set(n.type,(e.get(n.type)??0)+1);let i=[...e.entries()].sort((n,o)=>o[1]-n[1]||n[0].localeCompare(o[0])),s=t.createEl("option",{text:`All types (${this.events.length})`});s.value="";for(let[n,o]of i){let a=t.createEl("option",{text:`${n} (${o})`});a.value=n}this.typeFilter&&!e.has(this.typeFilter)&&(this.typeFilter=null),t.value=this.typeFilter??""}updateCount(){if(!this.countEl)return;let t=this.visible.length,e=this.typeFilter?`${t} ${this.typeFilter} event${t===1?"":"s"}`:`${t} event${t===1?"":"s"}`;this.shownCount===0||this.shownCount>=t?this.countEl.setText(e):this.countEl.setText(`Showing ${this.shownCount} of ${e}`)}appendMore(t){if(!this.listEl)return;let e=Math.min(this.visible.length,this.shownCount+t);for(let i=this.shownCount;i{this.appendMore(Me.PAGE),this.renderFooter()},t>Me.PAGE){let i=this.footerEl.createEl("button",{text:`Load all (${t})`});i.onclick=()=>{this.appendMore(t),this.renderFooter()}}}shellAct(t){try{let e=this.app.vault.adapter.getFullPath?.(this.jsonlPath);if(!e)throw new Error("no full path");let{shell:i}=window.require("electron");t==="reveal"?i.showItemInFolder(e):i.openPath(e)}catch(e){new K.Notice(`Couldn't ${t}: ${e.message}`)}}async exportCopy(){try{let t=(0,K.moment)().format("YYYY-MM-DD_HHmmss"),e=this.jsonlPath.replace(/\/[^/]+$/,"")||"",i=e?`${e}/${t}-log.jsonl`:`${t}-log.jsonl`;return await this.app.vault.adapter.write(i,this.text),new K.Notice(`Exported log \u2192 ${i}`),i}catch(t){return new K.Notice(`Export failed: ${t.message}`),null}}clearLog(){new et(this.app,"Clear log?","A timestamped copy will be saved alongside the active log before it's truncated.","Export & clear",async t=>{if(!(!t||!await this.exportCopy())){try{await this.app.vault.adapter.write(this.jsonlPath,"")}catch(i){new K.Notice(`Clear failed: ${i.message}`);return}this.text="",this.events=[],this.typeFilter=null,this.shownCount=0,this.refreshTypeFilter(),this.refreshList(),this.footerEl&&this.footerEl.empty(),new K.Notice("Log cleared.")}}).open()}renderEvent(t){let e=document.createElement("div");e.className=`stashpad-log-row stashpad-log-${t.type}`;let i=(0,K.moment)(t.ts).isValid()?(0,K.moment)(t.ts).format("YYYY-MM-DD HH:mm:ss"):t.ts,s=document.createElement("span");s.className="stashpad-log-ts",s.textContent=i,e.appendChild(s);let n=document.createElement("span");n.className="stashpad-log-type",n.textContent=t.type,e.appendChild(n);let o=document.createElement("span");o.className="stashpad-log-author",o.textContent=t.author?t.author:"\u2014",t.author||o.classList.add("is-empty"),e.appendChild(o);let a=document.createElement("span");return a.className="stashpad-log-msg",a.textContent=this.describe(t),e.appendChild(a),e}describe(t){let e=t.payload??{};switch(t.type){case"create":return`Created "${e.path??t.id}" under ${e.parent??"?"}`;case"delete":{let i=Array.isArray(e.attachmentsRemoved)?e.attachmentsRemoved.length:0,s=e.mergedInto?` (merged into ${e.mergedInto})`:"";return`Deleted ${t.id}${s}${i?` \u2014 also removed ${i} attachment${i===1?"":"s"}`:""}`}case"missing":return`Missing: ${e.lastPath??t.id}`;case"parent_change":{let i=e.reason?` (${e.reason})`:"";return`Moved ${t.id} from ${e.from??"null"} \u2192 ${e.to??"null"}${i}`}case"rename":return`Renamed ${e.from??"?"} \u2192 ${e.to??"?"}`;case"reorder":{let i=e.count??1,s=e.dir??"?",n=e.parent??t.id??"?";return`Reordered ${i} note${i===1?"":"s"} (${s}) under ${n}`}case"complete":{let i=e.count??1,s=e.undo?" (undo)":e.redo?" (redo)":"";return`Marked ${i} note${i===1?"":"s"} complete${s}`}case"uncomplete":{let i=e.count??1,s=e.undo?" (undo)":e.redo?" (redo)":"";return`Unmarked ${i} note${i===1?"":"s"}${s}`}case"stash_export":{let i=e.noteCount??"?";return`Exported ${i} note${i===1?"":"s"} \u2192 ${e.path??"?"}`}case"stash_import":{let i=e.noteCount??"?",s=[];e.attachmentsWritten&&s.push(`${e.attachmentsWritten} attachment${e.attachmentsWritten===1?"":"s"}`),e.collisionsRenamed&&s.push(`${e.collisionsRenamed} renamed`);let n=s.length?` (${s.join(", ")})`:"";return`Imported ${i} note${i===1?"":"s"} from ${e.from??"?"} \u2192 ${e.into??"?"}${n}`}case"attachment_add":return`Added attachment ${e.path??t.id}`;case"attachment_remove":return`Removed attachment ${e.path??t.id}`;case"palette_color_add":return`Added palette color ${e.color??t.id}`;case"palette_color_remove":return`Removed palette color ${e.color??t.id}`;default:return JSON.stringify(e)}}onClose(){this.contentEl.empty()}};Me.PAGE=100;ze=Me,We=class extends K.Modal{constructor(t,e,i,s,n,o){super(t);this.noteTitle=e;this.descendantCount=i;this.attachmentCount=s;this.offerAttachmentDelete=n;this.onChoose=o}onOpen(){this.modalEl?.addClass("stashpad-compact-modal"),this.contentEl.empty(),this.titleEl.setText(`Delete "${this.noteTitle}"?`);let t=[];this.descendantCount>0&&t.push(`${this.descendantCount} descendant note${this.descendantCount===1?"":"s"} will also be deleted.`),this.attachmentCount>0&&t.push(`${this.attachmentCount} attachment${this.attachmentCount===1?"":"s"} found across these notes.`),this.contentEl.createEl("p",{text:t.join(" ")});let e=this.offerAttachmentDelete&&this.attachmentCount>0;if(this.offerAttachmentDelete&&this.attachmentCount>0){let o=this.contentEl.createEl("label",{cls:"stashpad-modal-check"}),a=o.createEl("input",{type:"checkbox"});a.checked=e,a.onchange=()=>{e=a.checked},o.createSpan({text:" Also delete attachments"})}let i=this.contentEl.createDiv({cls:"stashpad-modal-btns"}),s=i.createEl("button",{text:"Cancel"});s.onclick=()=>this.close();let n=i.createEl("button",{cls:"mod-warning",text:"Delete"});n.onclick=()=>{this.close(),this.onChoose(e)}}onClose(){this.contentEl.empty()}},bi=class extends K.Modal{constructor(t,e,i,s,n){super(t);this.body=e;this.onSplitAtLine=i;this.onSplitAtChar=s;this.onSplitMany=n;this.mode="line";this.cursorTextarea=null;this.lines=e.replace(/\r\n/g,` `).split(` `),this.lineCursorIdx=Math.max(1,Math.min(this.lines.length-1,Math.floor(this.lines.length/2))),this.lines.length<2&&(this.mode="cursor")}onOpen(){this.titleEl.setText("Split note"),this.modalEl.addClass("stashpad-split-modal"),this.render(),this.scope.register([],"Tab",t=>{this.lines.length<2||(t.preventDefault(),this.mode=this.mode==="line"?"cursor":"line",this.render())}),this.scope.register([],"Enter",t=>{this.mode==="line"&&(t.preventDefault(),this.commitLine())}),this.scope.register(["Mod"],"Enter",t=>{this.mode==="cursor"&&(t.preventDefault(),this.commitCursor())}),this.scope.register([],"ArrowUp",t=>{this.mode==="line"&&(t.preventDefault(),this.lineCursorIdx=Math.max(1,this.lineCursorIdx-1),this.render())}),this.scope.register([],"ArrowDown",t=>{this.mode==="line"&&(t.preventDefault(),this.lineCursorIdx=Math.min(this.lines.length-1,this.lineCursorIdx+1),this.render())})}commitLine(){let t=this.lineCursorIdx;this.close(),this.onSplitAtLine(t)}commitCursor(){let t=this.cursorTextarea;if(!t)return;let e=t.selectionStart;if(e<=0||e>=t.value.length){new K.Notice("Move the cursor inside the text \u2014 neither end can be empty.");return}this.close(),this.onSplitAtChar(e)}render(){this.contentEl.empty();let t=this.contentEl.createDiv({cls:"stashpad-split-quick"});t.createSpan({cls:"stashpad-split-quick-label",text:"Split by:"}),["lines","paragraphs","headings"].forEach(o=>{let a=vi(this.body,o),l=t.createEl("button",{cls:"stashpad-split-quick-btn",text:`${Ei[o]} (${a.length})`});l.disabled=a.length<2,l.onmousedown=c=>c.preventDefault(),l.onclick=()=>{let c=vi(this.body,o);if(c.length<2){new K.Notice("That delimiter wouldn't split this note.");return}this.close(),this.onSplitMany(c)}});let e=this.contentEl.createDiv({cls:"stashpad-split-toggle-bar"});if(this.lines.length>=2){let o=e.createEl("button",{text:"Line split",cls:"stashpad-split-mode-btn"});this.mode==="line"&&o.addClass("is-active"),o.onclick=()=>{this.mode="line",this.render()}}let i=e.createEl("button",{text:"Cursor split",cls:"stashpad-split-mode-btn"});this.mode==="cursor"&&i.addClass("is-active"),i.onclick=()=>{this.mode="cursor",this.render()};let s=e.createEl("button",{text:"Split",cls:"stashpad-split-confirm-btn mod-cta"});s.onmousedown=o=>o.preventDefault(),s.onclick=()=>{this.mode==="line"?this.commitLine():this.commitCursor()},this.mode==="line"?this.renderLineMode():this.renderCursorMode();let n=this.contentEl.createDiv({cls:"stashpad-split-help"});K.Platform.isMobile?n.setText(this.mode==="line"?"Tap a line to position the divider, then Split.":"Tap inside the text to position the cursor, then Split."):n.setText(this.mode==="line"?"\u2191/\u2193 pick split line \xB7 Enter or Split confirm \xB7 Tab \u2192 cursor mode \xB7 Esc cancel \xB7 Children stay with the first part":"Click or arrow to position cursor \xB7 Mod+Enter or Split confirm \xB7 Tab \u2192 line mode \xB7 Esc cancel \xB7 Children stay with the first part")}renderLineMode(){let t=this.contentEl.createDiv({cls:"stashpad-split-list"}),e=null;for(let i=0;i{let n=Math.max(1,Math.min(this.lines.length-1,i+1));n!==this.lineCursorIdx&&(this.lineCursorIdx=n,this.render())}}e&&window.requestAnimationFrame(()=>e.scrollIntoView({block:"center"}))}renderCursorMode(){let e=this.contentEl.createDiv({cls:"stashpad-split-cursor-wrap"}).createEl("textarea",{cls:"stashpad-split-cursor-ta"});e.value=this.body,e.readOnly=!1,this.cursorTextarea=e;let i=parseFloat(getComputedStyle(e).lineHeight)||22,s=K.Platform.isMobile?3:12,n=2,o=()=>{e.setCssStyles({height:"auto"});let a=Math.min(e.scrollHeight,i*s+16);e.setCssStyles({height:`${Math.max(a,i*n+16)}px`})};requestAnimationFrame(()=>{o();let a=Math.floor(e.value.length/2);e.focus(),e.setSelectionRange(a,a)}),e.addEventListener("input",o)}onClose(){this.cursorTextarea=null,this.contentEl.empty()}},Xe=class extends K.Modal{constructor(t,e,i,s,n){super(t);this.defaultBaseName=e;this.noteCount=i;this.onConfirm=s;this.kdfProbe=n;this.delivered=!1}onOpen(){this.contentEl.empty(),this.titleEl.setText("Export to .stash"),this.modalEl.addClass("stashpad-export-modal"),this.contentEl.createEl("p",{cls:"stashpad-export-desc",text:`${this.noteCount} note${this.noteCount===1?"":"s"} will be bundled into a single .stash file.`});let t=this.contentEl.createDiv({cls:"stashpad-export-field"});t.createEl("label",{cls:"stashpad-export-label",text:"File name"});let e=t.createEl("input",{type:"text"});e.addClass("stashpad-export-name"),e.value=this.defaultBaseName;let i=this.contentEl.createEl("div",{cls:"stashpad-export-preview"}),s=this.contentEl.createDiv({cls:"stashpad-export-encrypt"}),n=s.createDiv({cls:"stashpad-export-toggle"}),o=n.createEl("input",{type:"checkbox"});o.id="stashpad-export-encrypt-cb";let a=n.createEl("label",{text:"Encrypt with a password"});a.htmlFor=o.id;let l=s.createDiv({cls:"stashpad-export-pw-area"});l.setCssStyles({display:"none"});let c=[],d=L=>{let z=l.createDiv({cls:"stashpad-export-pw-row"}),O=z.createEl("input",{type:"password"});O.addClass("stashpad-export-name"),O.placeholder=L;let J=z.createEl("button",{cls:"stashpad-export-copy"}),nt=()=>{let ct=O.value.length===0;J.setText(ct?"Paste":"Copy"),J.toggleClass("is-paste",ct),J.setAttr("aria-label",`${ct?"Paste into":"Copy"} ${L.toLowerCase()}`)};return J.onclick=async ct=>{if(ct.preventDefault(),O.value.length===0)try{let ot=(await navigator.clipboard?.readText())?.trim();if(!ot){new K.Notice("Clipboard is empty.");return}O.value=ot,O.dispatchEvent(new Event("input")),new K.Notice("Pasted from clipboard.")}catch{new K.Notice("Couldn't read the clipboard.")}else navigator.clipboard?.writeText(O.value).then(()=>new K.Notice("Passphrase copied to clipboard."),()=>new K.Notice("Couldn't access the clipboard."))},nt(),c.push(nt),O},h=d("Password"),g=d("Confirm password"),u=l.createDiv({cls:"stashpad-export-strength"}),p=u.createDiv({cls:"stashpad-strength-bar"}),f=[0,1,2,3].map(()=>p.createDiv({cls:"stashpad-strength-seg"})),I=u.createEl("span",{cls:"stashpad-strength-label"}),m=l.createDiv({cls:"stashpad-export-genrow"}),C=m.createEl("button",{cls:"stashpad-export-gen",text:"Generate strong passphrase"}),B=m.createEl("button",{cls:"stashpad-export-show",text:"Show"}),w=l.createEl("div",{cls:"stashpad-export-pw-hint"}),y=l.createEl("div",{cls:"stashpad-export-pw-suite"});y.setText("Encryption: AES-256-GCM. Checking key-derivation suite for this device\u2026"),this.kdfProbe?this.kdfProbe().then(L=>{y.toggleClass("is-weak",!L),y.setText(L?"Encryption: Argon2id + AES-256-GCM \u2014 the strongest suite (used on this device).":"\u26A0\uFE0F Argon2id can't run on this device, so this export will use the weaker PBKDF2 (600k) + AES-256-GCM fallback.")}).catch(()=>{y.setText("Encryption: AES-256-GCM with a password-derived key.")}):y.setText("Encryption: Argon2id + AES-256-GCM (falls back to PBKDF2 if Argon2 can't run here).");let Q=this.app.secretStorage,v=l.createDiv({cls:"stashpad-export-remember"}),E=v.createEl("input",{type:"checkbox"});E.id="stashpad-export-remember-cb";let S=v.createEl("label",{text:"Remember in this vault (this device) \u2014 skips the prompt when you re-import here."});S.htmlFor=E.id;let D=l.createDiv({cls:"stashpad-export-remember-note"});D.setText("Saved only in this device's keychain \u2014 it doesn't sync to your other devices and isn't shared with anyone you send this file to. Keep the passphrase somewhere safe if you'll open this export elsewhere."),D.setCssStyles({display:"none"}),E.onchange=()=>{D.setCssStyles({display:E.checked?"":"none"})},Q||v.setCssStyles({display:"none"});let H=()=>{let L=e.value.trim()||this.defaultBaseName;return o.checked?`${L}-encrypted`:L},U=()=>i.setText(`Saves as: ${H()}-.stash`);e.oninput=U;let N=this.contentEl.createDiv({cls:"stashpad-export-footer"}),b=N.createEl("button",{text:"Cancel"});b.onclick=()=>this.close();let T=N.createEl("button",{cls:"mod-cta",text:"Export"}),P=()=>{let L=Hn(h.value);u.style.visibility=h.value?"visible":"hidden",f.forEach((z,O)=>z.toggleClass("is-on",h.value!==""&&O<=L.level)),p.dataset.level=String(L.level),I.setText(L.label)},R=()=>{let L=o.checked;l.setCssStyles({display:L?"":"none"});let z=!0;L&&(h.value?h.value!==g.value?(w.setText("Passwords don't match."),w.addClass("is-error"),z=!1):(w.setText("\u26A0\uFE0F If you lose this password, the export can't be recovered."),w.removeClass("is-error")):(w.setText("Enter a password to encrypt this export."),w.removeClass("is-error"),z=!1)),P(),c.forEach(O=>O()),T.disabled=!z,T.toggleClass("is-disabled",!z),U()},Z=!1,$=L=>{Z=L,h.type=g.type=L?"text":"password",B.setText(L?"Hide":"Show")};B.onclick=L=>{L.preventDefault(),$(!Z)},C.onclick=L=>{L.preventDefault(),h.value=g.value=Pn(),$(!1),new K.Notice("Passphrase generated (hidden) \u2014 Show to view, or Copy to save it."),R()},o.onchange=R,h.oninput=R,g.oninput=R,R();let V=()=>this.commit(H(),o.checked?h.value:null,o.checked&&E.checked);T.onclick=V,this.scope.register([],"Enter",L=>{L.preventDefault(),T.disabled||V()}),requestAnimationFrame(()=>{e.focus(),e.select()})}commit(t,e,i){let s=t.trim()||this.defaultBaseName,n=e&&e.length?e:null;this.delivered=!0,this.close(),this.onConfirm(s,n,!!n&&i)}onClose(){this.contentEl.empty()}},Di=class extends K.Modal{constructor(t,e,i,s){super(t);this.errorMsg=e;this.allowLater=i;this.onResult=s;this.delivered=!1}onOpen(){this.contentEl.empty(),this.titleEl.setText("Encrypted .stash"),this.modalEl.addClass("stashpad-export-modal"),this.contentEl.createEl("p",{cls:"stashpad-export-desc",text:"This export is password-protected. Enter its password to import it."}),this.errorMsg&&this.contentEl.createEl("div",{cls:"stashpad-export-error",text:this.errorMsg});let t=this.contentEl.createEl("input",{type:"password"});t.addClass("stashpad-export-name"),t.placeholder="Password";let e=this.contentEl.createDiv({cls:"stashpad-export-footer"});if(e.createEl("button",{text:"Cancel"}).onclick=()=>this.close(),this.allowLater){let s=e.createEl("button",{text:"Remind me later"});s.title="Don't import now \u2014 surface the reminder again later.",s.onclick=()=>this.finish({kind:"later"})}let i=e.createEl("button",{cls:"mod-cta",text:"Decrypt & import"});i.onclick=()=>this.submit(t.value),this.scope.register([],"Enter",s=>{s.preventDefault(),this.submit(t.value)}),requestAnimationFrame(()=>t.focus())}submit(t){t&&this.finish({kind:"password",value:t})}finish(t){this.delivered=!0,this.close(),this.onResult(t)}onClose(){this.delivered||(this.delivered=!0,this.onResult({kind:"cancel"})),this.contentEl.empty()}},At=class extends K.Modal{constructor(t,e){super(t);this.opts=e;this.succeeded=!1}onOpen(){let{mode:t}=this.opts;this.contentEl.empty(),this.modalEl.addClass("stashpad-export-modal","stashpad-encryption-modal"),this.titleEl.setText(this.opts.title??(t==="setup"?"Set up encryption password":t==="change"?"Change encryption password":"Unlock encryption")),this.contentEl.createDiv({cls:"stashpad-beta-row"}).createEl("span",{cls:"stashpad-beta-badge",text:"BETA"}),this.opts.intro?this.contentEl.createEl("p",{cls:"stashpad-export-desc",text:this.opts.intro}):t==="setup"&&this.contentEl.createEl("p",{cls:"stashpad-export-desc",text:"This single password protects everything you encrypt in this vault. It is stored only on this device. There is NO recovery \u2014 if you lose it, anything you've encrypted is gone for good."});let e=[],i=f=>{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=f;let C=I.createEl("button",{cls:"stashpad-export-copy"}),B=()=>{let w=m.value.length===0;C.setText(w?"Paste":"Copy"),C.toggleClass("is-paste",w),C.setAttr("aria-label",`${w?"Paste into":"Copy"} ${f.toLowerCase()}`)};return C.onclick=async w=>{if(w.preventDefault(),m.value.length===0)try{let y=(await navigator.clipboard?.readText())?.trim();if(!y){new K.Notice("Clipboard is empty.");return}m.value=y,m.dispatchEvent(new Event("input")),new K.Notice("Pasted from clipboard.")}catch{new K.Notice("Couldn't read the clipboard.")}else navigator.clipboard?.writeText(m.value).then(()=>new K.Notice("Copied to clipboard."),()=>new K.Notice("Couldn't access the clipboard."))},m.addEventListener("input",B),B(),e.push(B),m},s=null,n=null,o=null;if((t==="unlock"||t==="change")&&(s=i("Current password")),(t==="setup"||t==="change")&&(n=i(t==="change"?"New password":"Password"),o=i("Confirm password")),n){let f=this.contentEl.createDiv({cls:"stashpad-export-strength"}),I=f.createDiv({cls:"stashpad-strength-bar"}),m=[0,1,2,3].map(()=>I.createDiv({cls:"stashpad-strength-seg"})),C=f.createEl("span",{cls:"stashpad-strength-label"}),B=this.contentEl.createDiv({cls:"stashpad-encryption-counter"}),w=()=>{let E=n.value,S=Hn(E);m.forEach((D,H)=>D.toggleClass("is-on",H0&&E.length<6?" \u2014 use at least 6":""}`),B.toggleClass("is-weak",E.length>0&&E.length<6)};n.addEventListener("input",w),w();let y=this.contentEl.createDiv({cls:"stashpad-export-genrow"});y.createEl("button",{cls:"stashpad-export-gen",text:"Generate strong passphrase"}).onclick=E=>{E.preventDefault();let S=Pn(5);n.value=S,o&&(o.value=S),w(),e.forEach(D=>D()),new K.Notice("Generated \u2014 copy it somewhere safe; there's no recovery."),navigator.clipboard?.writeText(S).catch(()=>{})};let Q=y.createEl("button",{cls:"stashpad-export-show",text:"Show"});Q.onclick=E=>{E.preventDefault();let S=n.type==="password";n.type=S?"text":"password",o&&(o.type=S?"text":"password"),Q.setText(S?"Hide":"Show")};let v=this.contentEl.createEl("div",{cls:"stashpad-export-pw-suite"});v.setText("Encryption: AES-256-GCM. Checking key-derivation suite\u2026"),this.opts.kdfProbe?this.opts.kdfProbe().then(E=>{v.toggleClass("is-weak",!E),v.setText(E?"Encryption: Argon2id + AES-256-GCM \u2014 the strongest suite (used on this device).":"\u26A0\uFE0F Argon2id can't run here, so this will use the weaker PBKDF2 (600k) + AES-256-GCM fallback.")}).catch(()=>v.setText("Encryption: AES-256-GCM with a password-derived key.")):v.setText("Encryption: Argon2id + AES-256-GCM (PBKDF2 fallback if Argon2 can't run here).")}let a=null,l=this.app.secretStorage;if(this.opts.offerKeychain&&l){let f=this.contentEl.createDiv({cls:"stashpad-export-remember"});a=f.createEl("input",{type:"checkbox"}),a.id="stashpad-enc-remember";let I=f.createEl("label",{text:"Remember on this device (keychain) \u2014 auto-unlock here without re-typing."});I.htmlFor=a.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:"none"}),a.onchange=()=>{m.setCssStyles({display:a.checked?"":"none"})}}let c=this.contentEl.createEl("div",{cls:"stashpad-export-error"});c.setCssStyles({display:"none"});let d=f=>{c.setText(f),c.setCssStyles({display:""})},h=this.contentEl.createDiv({cls:"stashpad-export-footer"});h.createEl("button",{text:"Cancel"}).onclick=()=>this.close();let g=h.createEl("button",{cls:"mod-cta",text:t==="setup"?"Set up":t==="change"?"Change":"Unlock"}),u=!1,p=async()=>{if(u)return;let f=s?.value??void 0,I=n?.value??void 0;if((t==="unlock"||t==="change")&&!f){d("Enter your current password.");return}if(t==="setup"||t==="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}}u=!0,g.disabled=!0,c.setCssStyles({display:"none"});let m=g.textContent;g.setText("Working\u2026");try{let C=await this.opts.onSubmit({current:f,next:I,remember:!!a?.checked});if(C){d(C),u=!1,g.disabled=!1,g.setText(m??"OK");return}this.succeeded=!0,this.close()}catch(C){d(`Failed: ${C.message}`),u=!1,g.disabled=!1,g.setText(m??"OK")}};g.onclick=()=>void p(),this.scope.register([],"Enter",f=>{f.preventDefault(),p()}),requestAnimationFrame(()=>(s??n)?.focus())}onClose(){this.contentEl.empty(),this.succeeded||this.opts.onCancel?.()}},xi=class extends K.Modal{constructor(t,e){super(t);this.opts=e}onOpen(){this.contentEl.empty(),this.modalEl.addClass("stashpad-export-modal","stashpad-encryption-modal"),this.titleEl.setText(this.opts.title),this.contentEl.createEl("p",{cls:"stashpad-export-desc",text:this.opts.body});let t=null;this.opts.requirePassword&&(this.contentEl.createEl("p",{cls:"stashpad-export-desc"}).setText("Enter your encryption password:"),t=this.contentEl.createEl("input",{type:"password"}),t.addClass("stashpad-export-name","stashpad-encryption-field"),t.placeholder="Password"),this.contentEl.createEl("p",{cls:"stashpad-export-desc"}).setText(`Type "${this.opts.phrase}" to confirm.`);let e=this.contentEl.createEl("input",{type:"text"});e.addClass("stashpad-export-name","stashpad-encryption-field"),e.placeholder=this.opts.phrase;let i=this.contentEl.createEl("div",{cls:"stashpad-export-error"});i.setCssStyles({display:"none"});let s=this.contentEl.createDiv({cls:"stashpad-export-footer"});s.createEl("button",{text:"Cancel"}).onclick=()=>this.close();let n=s.createEl("button",{cls:"mod-cta mod-warning",text:this.opts.confirmText}),o=()=>e.value.trim().toLowerCase()===this.opts.phrase.trim().toLowerCase(),a=()=>{n.disabled=!o()||!!this.opts.requirePassword&&!t?.value};e.addEventListener("input",a),t?.addEventListener("input",a),a();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(t.value))){i.setText("Wrong password."),i.setCssStyles({display:""}),l=!1,a();return}this.close(),await this.opts.onConfirm()}};n.onclick=()=>void c(),this.scope.register([],"Enter",d=>{d.preventDefault(),c()}),requestAnimationFrame(()=>(t??e).focus())}onClose(){this.contentEl.empty()}},ps=class extends K.Modal{constructor(t,e,i){super(t);this.onResult=i;this.delivered=!1;this.value=e&&/^#[0-9a-f]{6}$/i.test(e)?e:"#888888"}onOpen(){this.contentEl.empty(),this.titleEl.setText("Custom color"),this.modalEl.addClass("stashpad-custom-color-modal");let t=this.contentEl.createDiv({cls:"stashpad-custom-color-row"}),e=t.createDiv({cls:"stashpad-custom-color-preview"});e.style.background=this.value;let i=t.createEl("input",{type:"color"});i.value=this.value,i.addClass("stashpad-custom-color-wheel"),e.onclick=()=>i.click();let s=t.createEl("input",{type:"text"});s.addClass("stashpad-custom-color-hex"),s.placeholder="#RRGGBB",s.value=this.value,s.maxLength=7;let n=d=>{let h=d.startsWith("#")?d:"#"+d;/^#[0-9a-f]{6}$/i.test(h)&&(this.value=h,e.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"}),a=o.createEl("button",{text:"Cancel"});a.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(t){this.delivered=!0,this.close(),this.onResult(this.value,t)}onClose(){this.delivered||(this.delivered=!0,this.onResult(this.value,{addToPalette:!1})),this.contentEl.empty()}},Si=class Si extends K.Modal{constructor(t,e,i,s,n){super(t);this.currentColor=e;this.customPalette=i;this.onPick=s;this.onDeleteCustom=n;this.focusIdx=-1;this.items=[]}onOpen(){this.contentEl.empty(),this.titleEl.setText("Pick a color"),this.modalEl.addClass("stashpad-color-modal");let t=this.contentEl.createDiv({cls:"stashpad-color-grid"});this.items=[];let e=t.createDiv({cls:"stashpad-color-tile stashpad-color-none"});e.title="No color",e.onclick=()=>this.activate(0),this.items.push({kind:"none",color:null,el:e});let i=[...Si.DEFAULT_PALETTE,...this.customPalette];for(let a of i){let l=t.createDiv({cls:"stashpad-color-tile"});l.style.background=a,l.title=a;let c=!Si.DEFAULT_PALETTE.some(h=>h.toLowerCase()===a.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=g=>{g.stopPropagation(),this.handleDelete(a)}}this.items.push({kind:c?"custom":"preset",color:a,el:l})}let s=t.createDiv({cls:"stashpad-color-tile stashpad-color-add"});s.title="Custom color\u2026";let n=this.items.length;s.onclick=()=>this.activate(n),this.items.push({kind:"add",color:null,el:s});let o=this.items.findIndex(a=>this.currentColor===null?a.kind==="none":this.currentColor?a.color!==null&&a.color.toLowerCase()===this.currentColor.toLowerCase():!1);this.focusIdx=o>=0?o:0,this.refreshActive(),this.scope.register([],"ArrowRight",a=>{a.preventDefault(),this.moveFocus(1)}),this.scope.register([],"ArrowLeft",a=>{a.preventDefault(),this.moveFocus(-1)}),this.scope.register([],"ArrowDown",a=>{a.preventDefault(),this.moveFocus(this.columns())}),this.scope.register([],"ArrowUp",a=>{a.preventDefault(),this.moveFocus(-this.columns())}),this.scope.register([],"Enter",a=>{a.preventDefault(),this.activate(this.focusIdx)}),requestAnimationFrame(()=>this.modalEl.focus())}activate(t){if(t<0||t>=this.items.length)return;this.focusIdx=t,this.refreshActive();let e=this.items[t];if(e.kind==="add"){this.close(),new ps(this.app,this.currentColor,(i,s)=>{this.onPick(i,s)}).open();return}this.close(),this.onPick(e.color,{addToPalette:!1})}columns(){if(!this.items.length)return 1;let t=this.items[0].el.parentElement;if(!t)return 1;let e=t.getBoundingClientRect(),i=this.items[0].el.getBoundingClientRect();if(i.width<=0)return 1;let s=i.top,n=0;for(let o of this.items){let a=o.el.getBoundingClientRect();if(Math.abs(a.top-s)<1)n++;else break}return Math.max(1,n)}async handleDelete(t){if(this.onDeleteCustom)try{let e=await this.onDeleteCustom(t);this.customPalette=Array.isArray(e)?e:this.customPalette.filter(i=>i.toLowerCase()!==t.toLowerCase()),this.onOpen()}catch(e){console.warn("Stashpad: palette delete failed",e)}}moveFocus(t){if(!this.items.length)return;let e=Math.max(0,Math.min(this.items.length-1,this.focusIdx+t));this.focusIdx=e,this.refreshActive()}refreshActive(){for(let t=0;t{this.didChoose=!0,this.close(),this.onChoose(!1)};let s=e.createEl("button",{cls:"mod-cta",text:this.confirmText});s.onclick=()=>{this.didChoose=!0,this.close(),this.onChoose(!0)},requestAnimationFrame(()=>s.focus())}onClose(){this.contentEl.empty(),this.didChoose||(this.didChoose=!0,this.onChoose(!1))}},Ni=class extends K.Modal{constructor(t,e,i,s={}){super(t);this.levels=e;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 t=this.contentEl.createDiv({cls:"stashpad-bc-levels"});for(let e of this.levels){let i=t.createDiv({cls:"stashpad-bc-level-row"});if(e.isCurrent&&i.addClass("is-current"),i.createSpan({cls:"stashpad-bc-level-num",text:String(e.level)}),i.createSpan({cls:"stashpad-bc-level-label",text:e.label}),!e.isCurrent){i.setAttribute("role","button"),i.setAttribute("tabindex","0");let s=()=>{this.close(),this.onPick(e.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(e.id,s,i,()=>this.close())},this.opts.attachLongPress?.(i,()=>this.opts.onContext(e.id,null,i,()=>this.close())))}}onClose(){this.contentEl.empty()}};Ze=class extends K.Modal{constructor(t,e,i,s={}){super(t);this.current=e;this.onPick=i;this.opts=s;this.didChoose=!1;this.assignees=[];this.tinyClosePopover=null;this.assignees=[...s.currentAssignees??[]]}onOpen(){this.modalEl?.addClass("stashpad-compact-modal"),this.contentEl.empty(),this.titleEl.setText(this.opts.title??"Set due date");let t=null;if(this.current){let C=Date.parse(this.current);Number.isNaN(C)||(t=new Date(C))}let e=this.contentEl.createDiv({cls:"stashpad-due-picker"}),i=e.createDiv({cls:"stashpad-due-fields"}),s=i.createDiv({cls:"stashpad-due-field"}),n=s.createSpan({cls:"stashpad-due-field-icon"});(0,K.setIcon)(n,"calendar");let o=s.createEl("input",{type:"date",cls:"stashpad-due-date"}),a=s.createSpan({cls:"stashpad-due-clear",attr:{"aria-label":"Clear date"}});(0,K.setIcon)(a,"x"),a.onclick=()=>{o.value="",o.focus()};let l=i.createDiv({cls:"stashpad-due-field"}),c=l.createSpan({cls:"stashpad-due-field-icon"});(0,K.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,K.setIcon)(h,"x"),h.onclick=()=>{d.value="",d.focus()},n.onclick=()=>{try{o.showPicker?.()}catch{}},c.onclick=()=>this.openTimeNumpad(c,d),t&&(o.value=this.toDateValue(t),d.value=this.toTimeValue(t)),this.renderAssignSection(e);let g=e.createDiv({cls:"stashpad-due-grid"}),u=(C,B)=>{let w=g.createEl("button",{cls:"stashpad-due-btn stashpad-due-preset",text:C});w.onclick=()=>{let y=B();o.value=this.toDateValue(y),d.value||(d.value=this.toTimeValue(y))}},p=C=>(C.setHours(9,0,0,0),C);u("Today",()=>p(this.startOfTodayLocal())),u("Tomorrow",()=>{let C=this.startOfTodayLocal();return C.setDate(C.getDate()+1),p(C)}),u("Next week",()=>{let C=this.startOfTodayLocal();return C.setDate(C.getDate()+7),p(C)});let f=g.createEl("button",{cls:"stashpad-due-btn",text:"Clear"});f.onclick=()=>{o.value="",d.value="",o.focus()};let I=g.createEl("button",{cls:"stashpad-due-btn",text:"Cancel"});I.onclick=()=>{this.didChoose=!0,this.close()};let m=g.createEl("button",{cls:"stashpad-due-btn mod-cta",text:"Set"});m.onclick=()=>{if(!o.value){this.didChoose=!0,this.close(),this.onPick({iso:null,assignees:this.assignees});return}let[C,B,w]=o.value.split("-").map(E=>parseInt(E,10)),y=9,Q=0;if(d.value){let[E,S]=d.value.split(":").map(D=>parseInt(D,10));y=E,Q=S}let v=new Date(C,B-1,w,y,Q,0,0);this.didChoose=!0,this.close(),this.onPick({iso:v.toISOString(),assignees:this.assignees})},requestAnimationFrame(()=>o.focus())}onClose(){this.tinyClosePopover?.(),this.contentEl.empty(),this.didChoose}renderAssignSection(t){ha(t,{knownAuthors:this.opts.knownAuthors??[],initial:this.assignees,onChange:e=>{this.assignees=e}})}openTimeNumpad(t,e){this.tinyClosePopover?.();let i=t.ownerDocument??document,s=i.defaultView??window,n=9,o=0;if(e.value){let[f,I]=e.value.split(":").map(m=>parseInt(m,10));Number.isFinite(f)&&(n=f),Number.isFinite(I)&&(o=I)}else{let f=new Date;n=f.getHours(),o=f.getMinutes()}let a=n>=12?"pm":"am",l=n===0?12:n>12?n-12:n,c=i.body.createDiv({cls:"stashpad-when-popover stashpad-due-time-pop"});c.setCssStyles({position:"fixed",zIndex:"9999"});let d=null,h=()=>{c.remove(),i.removeEventListener("mousedown",g,!0),i.removeEventListener("keydown",u,!0),this.tinyClosePopover===h&&(this.tinyClosePopover=null)},g=f=>{!c.contains(f.target)&&f.target!==t&&!t.contains(f.target)&&h()},u=f=>{f.key==="Escape"?(f.preventDefault(),f.stopPropagation(),h()):f.key==="Enter"&&d&&(f.preventDefault(),f.stopPropagation(),d())};this.tinyClosePopover=h,As(c,{seedH:l,seedM:o,seedPeriod:a,close:h,setOnEnter:f=>{d=f},onFinalize:f=>{e.value=`${String(f.hours24).padStart(2,"0")}:${String(f.minutes).padStart(2,"0")}`}});let p=t.getBoundingClientRect();c.setCssStyles({left:`${Math.max(8,Math.min(p.left,s.innerWidth-220))}px`,top:`${p.bottom+4}px`}),setTimeout(()=>{i.addEventListener("mousedown",g,!0),i.addEventListener("keydown",u,!0)},0)}startOfTodayLocal(){let t=new Date;return t.setHours(0,0,0,0),t}toDateValue(t){let e=t.getFullYear(),i=String(t.getMonth()+1).padStart(2,"0"),s=String(t.getDate()).padStart(2,"0");return`${e}-${i}-${s}`}toTimeValue(t){let e=String(t.getHours()).padStart(2,"0"),i=String(t.getMinutes()).padStart(2,"0");return`${e}:${i}`}},Te=class Te extends K.Modal{constructor(t,e,i,s=null,n){super(t);this.service=e;this.openLog=i;this.currentAuthorId=s;this.getNoteAuthorIds=n;this.records=[];this.visible=[];this.shownCount=0;this.categoryFilter=null;this.listEl=null;this.footerEl=null;this.countEl=null;this.filterSelEl=null;this.unsubscribe=null;this.authorFilter="all";this.authorSelEl=null}onOpen(){this.contentEl.empty(),this.titleEl.setText("Stashpad notification history"),this.modalEl.addClass("stashpad-log-modal"),this.modalEl.addClass("stashpad-notif-history-modal"),this.records=this.service.recent();let t=this.contentEl.createDiv({cls:"stashpad-log-toolbar"});if(this.countEl=t.createSpan({cls:"stashpad-log-count"}),this.updateCount(),this.filterSelEl=t.createEl("select",{cls:"stashpad-log-type-filter"}),this.filterSelEl.onchange=()=>this.setCategoryFilter(this.filterSelEl.value||null),this.refreshCategoryFilter(),this.authorSelEl=t.createEl("select",{cls:"stashpad-log-type-filter stashpad-notif-author-filter"}),this.authorSelEl.onchange=()=>this.setAuthorFilter(this.authorSelEl.value||"all"),this.refreshAuthorFilter(),this.openLog){let i=t.createEl("button",{text:"Open log"});i.title="Open the per-folder Stashpad log for the most recent notification's folder.",i.onclick=()=>{let s=this.records.find(n=>!!n.folder);this.openLog?.(s?.folder)}}let e=t.createEl("button",{cls:"mod-warning",text:"Clear history"});e.onclick=()=>{new et(this.app,"Clear notification history?",`This will permanently remove all ${this.records.length} stored notifications from the history. The current toasts on screen are unaffected. This can't be undone.`,"Clear history",i=>{i&&this.service.clearHistory()}).open()},this.listEl=this.contentEl.createDiv({cls:"stashpad-log-list"}),this.refreshList(),this.footerEl=this.contentEl.createDiv({cls:"stashpad-log-footer"}),this.renderFooter(),this.unsubscribe=this.service.onChange(()=>{this.records=this.service.recent(),this.refreshCategoryFilter(),this.refreshAuthorFilter(),this.refreshList(),this.renderFooter()})}setAuthorFilter(t){this.authorFilter!==t&&(this.authorFilter=t,this.refreshList(),this.renderFooter())}refreshAuthorFilter(){if(!this.authorSelEl)return;let t=this.authorSelEl;t.empty(),t.createEl("option",{text:"All authors"}).value="all",this.currentAuthorId&&(t.createEl("option",{text:"Me"}).value="me"),t.createEl("option",{text:"Cross-author"}).value="cross";let e=new Set;for(let s of this.records)s.authorId&&s.authorId!==this.currentAuthorId&&e.add(s.authorId);if(e.size>0){let s=t.createEl("option",{text:"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"});s.disabled=!0;for(let n of[...e].sort())t.createEl("option",{text:n}).value=n}new Set(["all","cross",...this.currentAuthorId?["me"]:[],...e]).has(this.authorFilter)||(this.authorFilter="all"),t.value=this.authorFilter}isCrossAuthor(t){let e=t.authorId??null;if(!e)return!1;for(let i of t.affectedAuthorIds??[])if(i&&i!==e)return!0;if(!this.getNoteAuthorIds)return!1;for(let i of t.affectedIds){let s=this.getNoteAuthorIds(i);for(let n of s)if(n&&n!==e)return!0}return!1}onClose(){this.unsubscribe?.(),this.unsubscribe=null,this.contentEl.empty()}setCategoryFilter(t){(this.categoryFilter??null)!==(t??null)&&(this.categoryFilter=t,this.refreshList(),this.renderFooter())}refreshCategoryFilter(){if(!this.filterSelEl)return;let t=this.filterSelEl;t.empty();let e=new Map;for(let n of this.records)e.set(n.category,(e.get(n.category)??0)+1);let i=[...e.entries()].sort((n,o)=>o[1]-n[1]||n[0].localeCompare(o[0])),s=t.createEl("option",{text:`All categories (${this.records.length})`});s.value="";for(let[n,o]of i){let a=t.createEl("option",{text:`${n} (${o})`});a.value=n}this.categoryFilter&&!e.has(this.categoryFilter)&&(this.categoryFilter=null),t.value=this.categoryFilter??""}refreshList(){if(this.listEl){if(this.visible=this.records.filter(t=>{if(this.categoryFilter&&t.category!==this.categoryFilter)return!1;switch(this.authorFilter){case"all":return!0;case"me":return!!this.currentAuthorId&&t.authorId===this.currentAuthorId;case"cross":return this.isCrossAuthor(t);default:return t.authorId===this.authorFilter}}),this.shownCount=0,this.listEl.empty(),!this.visible.length){this.listEl.createDiv({cls:"stashpad-log-empty",text:this.categoryFilter?`No "${this.categoryFilter}" notifications.`:"No notifications yet."}),this.updateCount();return}this.appendMore(Te.PAGE)}}appendMore(t){if(!this.listEl)return;let e=Math.min(this.visible.length,this.shownCount+t);for(let i=this.shownCount;i0){let c=i.createDiv({cls:"stashpad-notif-actions-snapshot"});for(let d of e.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 t=this.visible.length,e=this.categoryFilter?`${t} ${this.categoryFilter} notification${t===1?"":"s"}`:`${t} notification${t===1?"":"s"}`;this.shownCount===0||this.shownCount>=t?this.countEl.setText(e):this.countEl.setText(`Showing ${this.shownCount} of ${e}`)}renderFooter(){if(!this.footerEl)return;this.footerEl.empty();let t=this.visible.length-this.shownCount;if(t<=0)return;let e=this.footerEl.createEl("button",{text:`Load ${Math.min(Te.PAGE,t)} more`});if(e.onclick=()=>{this.appendMore(Te.PAGE),this.renderFooter()},t>Te.PAGE){let i=this.footerEl.createEl("button",{text:`Load all (${t})`});i.onclick=()=>{this.appendMore(t),this.renderFooter()}}}};Te.PAGE=100;Mi=Te,Un=class extends K.Modal{constructor(t,e){super(t);this.entries=e}onOpen(){if(this.contentEl.empty(),this.titleEl.setText("Stashpad import log"),this.entries.length===0){this.contentEl.createDiv({cls:"stashpad-log-empty",text:"Nothing imported yet."});return}let t=this.contentEl.createDiv({cls:"stashpad-import-log-list"});for(let e of this.entries){let i=t.createDiv({cls:"stashpad-import-log-row"}),s=(0,K.moment)(e.ts).format("YYYY-MM-DD HH:mm");i.createSpan({cls:"stashpad-import-log-when",text:s});let n=e.kind==="folder"?"folder":e.kind==="md"?"note":"file";i.createSpan({cls:`stashpad-import-log-kind is-${e.kind}`,text:n}),i.createSpan({cls:"stashpad-import-log-name",text:e.originalName});let o=[e.folder.split("/").pop()||e.folder];e.notePaths.length>1&&o.push(`${e.notePaths.length} notes`),i.createSpan({cls:"stashpad-import-log-meta",text:o.join(" \xB7 ")})}}onClose(){this.contentEl.empty()}},Ti=class extends K.Modal{constructor(t,e,i){super(t);this.message=e;this.onChoose=i;this.chose=!1}onOpen(){this.modalEl?.addClass("stashpad-compact-modal"),this.contentEl.empty(),this.titleEl.setText("Possible duplicate import");let t=this.contentEl.createDiv({cls:"stashpad-confirm-body"});for(let o of this.message.split(` +`))t.createDiv({cls:"stashpad-confirm-line",text:n});let e=this.contentEl.createDiv({cls:"stashpad-modal-btns"}),i=e.createEl("button",{text:this.cancelText});i.onclick=()=>{this.didChoose=!0,this.close(),this.onChoose(!1)};let s=e.createEl("button",{cls:"mod-cta",text:this.confirmText});s.onclick=()=>{this.didChoose=!0,this.close(),this.onChoose(!0)},requestAnimationFrame(()=>s.focus())}onClose(){this.contentEl.empty(),this.didChoose||(this.didChoose=!0,this.onChoose(!1))}},Ni=class extends K.Modal{constructor(t,e,i,s={}){super(t);this.levels=e;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 t=this.contentEl.createDiv({cls:"stashpad-bc-levels"});for(let e of this.levels){let i=t.createDiv({cls:"stashpad-bc-level-row"});if(e.isCurrent&&i.addClass("is-current"),i.createSpan({cls:"stashpad-bc-level-num",text:String(e.level)}),i.createSpan({cls:"stashpad-bc-level-label",text:e.label}),!e.isCurrent){i.setAttribute("role","button"),i.setAttribute("tabindex","0");let s=()=>{this.close(),this.onPick(e.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(e.id,s,i,()=>this.close())},this.opts.attachLongPress?.(i,()=>this.opts.onContext(e.id,null,i,()=>this.close())))}}onClose(){this.contentEl.empty()}};Ze=class extends K.Modal{constructor(t,e,i,s={}){super(t);this.current=e;this.onPick=i;this.opts=s;this.didChoose=!1;this.assignees=[];this.tinyClosePopover=null;this.assignees=[...s.currentAssignees??[]]}onOpen(){this.modalEl?.addClass("stashpad-compact-modal"),this.contentEl.empty(),this.titleEl.setText(this.opts.title??"Set due date");let t=null;if(this.current){let C=Date.parse(this.current);Number.isNaN(C)||(t=new Date(C))}let e=this.contentEl.createDiv({cls:"stashpad-due-picker"}),i=e.createDiv({cls:"stashpad-due-fields"}),s=i.createDiv({cls:"stashpad-due-field"}),n=s.createSpan({cls:"stashpad-due-field-icon"});(0,K.setIcon)(n,"calendar");let o=s.createEl("input",{type:"date",cls:"stashpad-due-date"}),a=s.createSpan({cls:"stashpad-due-clear",attr:{"aria-label":"Clear date"}});(0,K.setIcon)(a,"x"),a.onclick=()=>{o.value="",o.focus()};let l=i.createDiv({cls:"stashpad-due-field"}),c=l.createSpan({cls:"stashpad-due-field-icon"});(0,K.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,K.setIcon)(h,"x"),h.onclick=()=>{d.value="",d.focus()},n.onclick=()=>{try{o.showPicker?.()}catch{}},c.onclick=()=>this.openTimeNumpad(c,d),t&&(o.value=this.toDateValue(t),d.value=this.toTimeValue(t)),this.renderAssignSection(e);let g=e.createDiv({cls:"stashpad-due-grid"}),u=(C,B)=>{let w=g.createEl("button",{cls:"stashpad-due-btn stashpad-due-preset",text:C});w.onclick=()=>{let y=B();o.value=this.toDateValue(y),d.value||(d.value=this.toTimeValue(y))}},p=C=>(C.setHours(9,0,0,0),C);u("Today",()=>p(this.startOfTodayLocal())),u("Tomorrow",()=>{let C=this.startOfTodayLocal();return C.setDate(C.getDate()+1),p(C)}),u("Next week",()=>{let C=this.startOfTodayLocal();return C.setDate(C.getDate()+7),p(C)});let f=g.createEl("button",{cls:"stashpad-due-btn",text:"Clear"});f.onclick=()=>{o.value="",d.value="",o.focus()};let I=g.createEl("button",{cls:"stashpad-due-btn",text:"Cancel"});I.onclick=()=>{this.didChoose=!0,this.close()};let m=g.createEl("button",{cls:"stashpad-due-btn mod-cta",text:"Set"});m.onclick=()=>{if(!o.value){this.didChoose=!0,this.close(),this.onPick({iso:null,assignees:this.assignees});return}let[C,B,w]=o.value.split("-").map(E=>parseInt(E,10)),y=9,Q=0;if(d.value){let[E,S]=d.value.split(":").map(D=>parseInt(D,10));y=E,Q=S}let v=new Date(C,B-1,w,y,Q,0,0);this.didChoose=!0,this.close(),this.onPick({iso:v.toISOString(),assignees:this.assignees})},requestAnimationFrame(()=>o.focus())}onClose(){this.tinyClosePopover?.(),this.contentEl.empty(),this.didChoose}renderAssignSection(t){ha(t,{knownAuthors:this.opts.knownAuthors??[],initial:this.assignees,onChange:e=>{this.assignees=e}})}openTimeNumpad(t,e){this.tinyClosePopover?.();let i=t.ownerDocument??document,s=i.defaultView??window,n=9,o=0;if(e.value){let[I,m]=e.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 a=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,g=()=>{d.remove(),i.removeEventListener("mousedown",u,!0),i.removeEventListener("keydown",p,!0),this.tinyClosePopover===g&&(this.tinyClosePopover=null)},u=I=>{!d.contains(I.target)&&I.target!==t&&!t.contains(I.target)&&g()},p=I=>{I.key==="Escape"?(I.preventDefault(),I.stopPropagation(),g()):I.key==="Enter"&&h&&(I.preventDefault(),I.stopPropagation(),h())};this.tinyClosePopover=g,As(d,{seedH:l,seedM:o,seedPeriod:a,close:g,setOnEnter:I=>{h=I},onFinalize:I=>{e.value=`${String(I.hours24).padStart(2,"0")}:${String(I.minutes).padStart(2,"0")}`}});let f=t.getBoundingClientRect();d.setCssStyles({left:`${Math.max(8,Math.min(f.left,s.innerWidth-220))}px`,top:`${f.bottom+4}px`}),setTimeout(()=>{i.addEventListener("mousedown",u,!0),i.addEventListener("keydown",p,!0),d.querySelector(".stashpad-when-time-field")?.focus()},0)}startOfTodayLocal(){let t=new Date;return t.setHours(0,0,0,0),t}toDateValue(t){let e=t.getFullYear(),i=String(t.getMonth()+1).padStart(2,"0"),s=String(t.getDate()).padStart(2,"0");return`${e}-${i}-${s}`}toTimeValue(t){let e=String(t.getHours()).padStart(2,"0"),i=String(t.getMinutes()).padStart(2,"0");return`${e}:${i}`}},Te=class Te extends K.Modal{constructor(t,e,i,s=null,n){super(t);this.service=e;this.openLog=i;this.currentAuthorId=s;this.getNoteAuthorIds=n;this.records=[];this.visible=[];this.shownCount=0;this.categoryFilter=null;this.listEl=null;this.footerEl=null;this.countEl=null;this.filterSelEl=null;this.unsubscribe=null;this.authorFilter="all";this.authorSelEl=null}onOpen(){this.contentEl.empty(),this.titleEl.setText("Stashpad notification history"),this.modalEl.addClass("stashpad-log-modal"),this.modalEl.addClass("stashpad-notif-history-modal"),this.records=this.service.recent();let t=this.contentEl.createDiv({cls:"stashpad-log-toolbar"});if(this.countEl=t.createSpan({cls:"stashpad-log-count"}),this.updateCount(),this.filterSelEl=t.createEl("select",{cls:"stashpad-log-type-filter"}),this.filterSelEl.onchange=()=>this.setCategoryFilter(this.filterSelEl.value||null),this.refreshCategoryFilter(),this.authorSelEl=t.createEl("select",{cls:"stashpad-log-type-filter stashpad-notif-author-filter"}),this.authorSelEl.onchange=()=>this.setAuthorFilter(this.authorSelEl.value||"all"),this.refreshAuthorFilter(),this.openLog){let i=t.createEl("button",{text:"Open log"});i.title="Open the per-folder Stashpad log for the most recent notification's folder.",i.onclick=()=>{let s=this.records.find(n=>!!n.folder);this.openLog?.(s?.folder)}}let e=t.createEl("button",{cls:"mod-warning",text:"Clear history"});e.onclick=()=>{new et(this.app,"Clear notification history?",`This will permanently remove all ${this.records.length} stored notifications from the history. The current toasts on screen are unaffected. This can't be undone.`,"Clear history",i=>{i&&this.service.clearHistory()}).open()},this.listEl=this.contentEl.createDiv({cls:"stashpad-log-list"}),this.refreshList(),this.footerEl=this.contentEl.createDiv({cls:"stashpad-log-footer"}),this.renderFooter(),this.unsubscribe=this.service.onChange(()=>{this.records=this.service.recent(),this.refreshCategoryFilter(),this.refreshAuthorFilter(),this.refreshList(),this.renderFooter()})}setAuthorFilter(t){this.authorFilter!==t&&(this.authorFilter=t,this.refreshList(),this.renderFooter())}refreshAuthorFilter(){if(!this.authorSelEl)return;let t=this.authorSelEl;t.empty(),t.createEl("option",{text:"All authors"}).value="all",this.currentAuthorId&&(t.createEl("option",{text:"Me"}).value="me"),t.createEl("option",{text:"Cross-author"}).value="cross";let e=new Set;for(let s of this.records)s.authorId&&s.authorId!==this.currentAuthorId&&e.add(s.authorId);if(e.size>0){let s=t.createEl("option",{text:"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"});s.disabled=!0;for(let n of[...e].sort())t.createEl("option",{text:n}).value=n}new Set(["all","cross",...this.currentAuthorId?["me"]:[],...e]).has(this.authorFilter)||(this.authorFilter="all"),t.value=this.authorFilter}isCrossAuthor(t){let e=t.authorId??null;if(!e)return!1;for(let i of t.affectedAuthorIds??[])if(i&&i!==e)return!0;if(!this.getNoteAuthorIds)return!1;for(let i of t.affectedIds){let s=this.getNoteAuthorIds(i);for(let n of s)if(n&&n!==e)return!0}return!1}onClose(){this.unsubscribe?.(),this.unsubscribe=null,this.contentEl.empty()}setCategoryFilter(t){(this.categoryFilter??null)!==(t??null)&&(this.categoryFilter=t,this.refreshList(),this.renderFooter())}refreshCategoryFilter(){if(!this.filterSelEl)return;let t=this.filterSelEl;t.empty();let e=new Map;for(let n of this.records)e.set(n.category,(e.get(n.category)??0)+1);let i=[...e.entries()].sort((n,o)=>o[1]-n[1]||n[0].localeCompare(o[0])),s=t.createEl("option",{text:`All categories (${this.records.length})`});s.value="";for(let[n,o]of i){let a=t.createEl("option",{text:`${n} (${o})`});a.value=n}this.categoryFilter&&!e.has(this.categoryFilter)&&(this.categoryFilter=null),t.value=this.categoryFilter??""}refreshList(){if(this.listEl){if(this.visible=this.records.filter(t=>{if(this.categoryFilter&&t.category!==this.categoryFilter)return!1;switch(this.authorFilter){case"all":return!0;case"me":return!!this.currentAuthorId&&t.authorId===this.currentAuthorId;case"cross":return this.isCrossAuthor(t);default:return t.authorId===this.authorFilter}}),this.shownCount=0,this.listEl.empty(),!this.visible.length){this.listEl.createDiv({cls:"stashpad-log-empty",text:this.categoryFilter?`No "${this.categoryFilter}" notifications.`:"No notifications yet."}),this.updateCount();return}this.appendMore(Te.PAGE)}}appendMore(t){if(!this.listEl)return;let e=Math.min(this.visible.length,this.shownCount+t);for(let i=this.shownCount;i0){let c=i.createDiv({cls:"stashpad-notif-actions-snapshot"});for(let d of e.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 t=this.visible.length,e=this.categoryFilter?`${t} ${this.categoryFilter} notification${t===1?"":"s"}`:`${t} notification${t===1?"":"s"}`;this.shownCount===0||this.shownCount>=t?this.countEl.setText(e):this.countEl.setText(`Showing ${this.shownCount} of ${e}`)}renderFooter(){if(!this.footerEl)return;this.footerEl.empty();let t=this.visible.length-this.shownCount;if(t<=0)return;let e=this.footerEl.createEl("button",{text:`Load ${Math.min(Te.PAGE,t)} more`});if(e.onclick=()=>{this.appendMore(Te.PAGE),this.renderFooter()},t>Te.PAGE){let i=this.footerEl.createEl("button",{text:`Load all (${t})`});i.onclick=()=>{this.appendMore(t),this.renderFooter()}}}};Te.PAGE=100;Mi=Te,Un=class extends K.Modal{constructor(t,e){super(t);this.entries=e}onOpen(){if(this.contentEl.empty(),this.titleEl.setText("Stashpad import log"),this.entries.length===0){this.contentEl.createDiv({cls:"stashpad-log-empty",text:"Nothing imported yet."});return}let t=this.contentEl.createDiv({cls:"stashpad-import-log-list"});for(let e of this.entries){let i=t.createDiv({cls:"stashpad-import-log-row"}),s=(0,K.moment)(e.ts).format("YYYY-MM-DD HH:mm");i.createSpan({cls:"stashpad-import-log-when",text:s});let n=e.kind==="folder"?"folder":e.kind==="md"?"note":"file";i.createSpan({cls:`stashpad-import-log-kind is-${e.kind}`,text:n}),i.createSpan({cls:"stashpad-import-log-name",text:e.originalName});let o=[e.folder.split("/").pop()||e.folder];e.notePaths.length>1&&o.push(`${e.notePaths.length} notes`),i.createSpan({cls:"stashpad-import-log-meta",text:o.join(" \xB7 ")})}}onClose(){this.contentEl.empty()}},Ti=class extends K.Modal{constructor(t,e,i){super(t);this.message=e;this.onChoose=i;this.chose=!1}onOpen(){this.modalEl?.addClass("stashpad-compact-modal"),this.contentEl.empty(),this.titleEl.setText("Possible duplicate import");let t=this.contentEl.createDiv({cls:"stashpad-confirm-body"});for(let o of this.message.split(` `))t.createDiv({cls:"stashpad-confirm-line",text:o});let e=this.contentEl.createDiv({cls:"stashpad-modal-btns"}),i=e.createEl("button",{text:"Skip duplicates"});i.onclick=()=>{this.chose=!0,this.close(),this.onChoose("skip")};let s=e.createEl("button",{text:"Replace existing"});s.onclick=()=>{this.chose=!0,this.close(),this.onChoose("replace")};let n=e.createEl("button",{cls:"mod-cta",text:"Import anyway"});n.onclick=()=>{this.chose=!0,this.close(),this.onChoose("anyway")}}onClose(){this.chose||this.onChoose("skip"),this.contentEl.empty()}},Pi=class extends K.Modal{constructor(t,e,i,s){super(t);this.noteCount=i;this.onConfirm=s;this.base=e}onOpen(){this.contentEl.empty(),this.modalEl.addClass("stashpad-export-modal"),this.titleEl.setText("Export as OKF"),this.contentEl.createEl("p",{cls:"stashpad-export-desc",text:`Export ${this.noteCount} note${this.noteCount===1?"":"s"} as an Open Knowledge Format bundle. Pick one or more formats.`});let t=this.contentEl.createEl("input",{type:"text"});t.addClass("stashpad-export-name"),t.value=this.base,t.placeholder="Export name";let e=(l,c)=>{let d=this.contentEl.createDiv({cls:"stashpad-okf-fmt"}),h=d.createEl("input",{type:"checkbox"});return h.checked=c,d.createEl("label",{text:l}),h},i=e(".zip \u2014 OKF bundle (portable)",!0),s=e(".tar.gz \u2014 OKF bundle (tarball)",!1),n=e(".stash \u2014 Stashpad format (re-importable)",!1),o=this.contentEl.createDiv({cls:"stashpad-export-footer"});o.createEl("button",{text:"Cancel"}).onclick=()=>this.close();let a=o.createEl("button",{cls:"mod-cta",text:"Export"});a.onclick=()=>{if(!i.checked&&!s.checked&&!n.checked){new K.Notice("Pick at least one format.");return}this.close(),this.onConfirm(t.value.trim()||this.base,{zip:i.checked,targz:s.checked,stash:n.checked})},requestAnimationFrame(()=>t.focus())}onClose(){this.contentEl.empty()}}});function St(A,r=Vt){let t=r instanceof Set?r:new Set(r.map(o=>o.toLowerCase())),e=(A.split(/\r?\n/).find(o=>o.trim().length>0)??"").trim();if(!e)return"Untitled";let s=e.replace(/['‘-‛ʼ]/g,"").replace(/[^A-Za-z0-9\s]+/g," ").split(/\s+/).filter(o=>o&&!t.has(o.toLowerCase())).map(o=>o.length>=2&&/^[A-Z0-9]+$/.test(o)?o:o.charAt(0).toUpperCase()+o.slice(1).toLowerCase()),n="";for(let o of s){let a=n?`${n}-${o}`:o;if(a.length>50)break;n=a}return n||"Untitled"}function bt(A,r){return`${A}-${r}.md`}function me(A){let r=A.match(/-([a-z0-9]{4,12})$/);return r?r[1]:null}function fs(A,r){let t=A.lastIndexOf(".");return t>0?`${A.slice(0,t)}-${r}${A.slice(t)}`:`${A}-${r}`}function pa(A){let r=A.match(/^([0-9a-z]{7,9})-(.+)$/);if(!r)return null;let t=parseInt(r[1],36);return!Number.isFinite(t)||t<142e10||t>Date.now()+864e5?null:{stamp:r[1],rest:r[2]}}var Vt,je=Jt(()=>{"use strict";Vt=["a","an","the","and","or","but","if","then","else","of","in","on","at","to","for","with","by","from","as","is","are","was","were","be","been","being","i","you","he","she","it","we","they","this","that","these","those","my","your","our","their","do","does","did","so","just","very","really","im"]});var Cs={};Ii(Cs,{JdBuildConfirmModal:()=>Ri,buildJdIndexNotes:()=>Gn,buildJdIndexPreview:()=>Is,buildJdPreviewNotice:()=>ms,scanForJdNotes:()=>_e});function Rn(A,r){if(/^\d+-\d+$/.test(A))return null;if(A.includes(".")){let e=A.split(".").slice(0,-1).join(".");return r.has(e)?e:Rn(e,r)}if(/^\d+$/.test(A)){let t=parseInt(A,10);for(let e of r){let i=e.match(/^(\d+)-(\d+)$/);if(!i)continue;let s=parseInt(i[1],10),n=parseInt(i[2],10);if(t>=s&&t<=n)return e}return null}return null}function _e(A,r,t){let e=A.vault.getMarkdownFiles(),i=Il(e,t),s=t.jdIndexIncludeStashpadFolders===!0,n=s?new Set:new Set(r.discoverStashpadFolders()),o=u=>s?!1:Array.from(n).some(p=>u===p||u.startsWith(p+"/")),a=[],l=[],c=[];for(let u of i){let p=u.parent?.path?.replace(/\/+$/,"")??"";if(o(p)){c.push(u);continue}let f=u.basename.match(ga);f?a.push({prefix:f[1],segments:f[1].split("."),title:f[2],file:u,folder:null}):l.push(u)}let d=(t.jdIndexScope??"vault")==="folder"?(t.jdIndexScopeFolder??"").trim().replace(/^\/+|\/+$/g,""):"",h=u=>{let p=u.path.replace(/\/+$/,"");if(!(d&&p&&p!==d&&!p.startsWith(d+"/"))){if(p&&!o(p)){let f=u.name.match(ga);f&&a.push({prefix:f[1],segments:f[1].split("."),title:f[2],file:null,folder:u})}}for(let f of u.children)f instanceof ft.TFolder&&h(f)};h(A.vault.getRoot());let g=t.jdIndexSort??"natural";return a.sort((u,p)=>ml(u,p,g)),{indexed:a,nonIndex:l,skippedStashpadNotes:c}}async function Is(A,r,t){let e=Ln(t.jdIndexStashpadFolder??"");if(!e)return{..._e(A,r,t),previewPath:null,error:"no-dest"};let i=_e(A,r,t),s=fl(A,e);if(!s)return{...i,previewPath:null,error:"no-home"};let n=Cl(i.indexed,i.nonIndex,i.skippedStashpadNotes),a=(await A.vault.read(s)).match(/^---\r?\n[\s\S]*?\r?\n---\r?\n/),l=a?`${a[0]}${n}`:n;return await A.vault.modify(s,l),{...i,previewPath:s.path}}function fl(A,r){let t=A.vault.getAbstractFileByPath(r);if(!(t instanceof ft.TFolder))return null;for(let e of t.children){if(!(e instanceof ft.TFile)||e.extension!=="md")continue;if((A.metadataCache.getFileCache(e)?.frontmatter??{}).id===k)return e}return null}async function Gn(A,r,t){let e=Ln(t.jdIndexStashpadFolder??"");if(!e)return{created:0,updated:0,skipped:0,destFolder:"",error:"no-dest"};if(!new Set(r.discoverStashpadFolders()).has(e))return{created:0,updated:0,skipped:0,destFolder:e,error:"dest-not-stashpad"};let s=_e(A,r,t),n=new Map;for(let I of s.indexed)n.set(I.prefix,I);for(let I of s.indexed)if(I.prefix.includes("."))for(let m=1;m{l.push(I);for(let m of a.get(I)??[])c(m)};for(let I of o)c(I);let d=new Map,h=A.vault.getAbstractFileByPath(e);if(h instanceof ft.TFolder)for(let I of h.children){if(!(I instanceof ft.TFile)||I.extension!=="md")continue;let m=A.metadataCache.getFileCache(I)?.frontmatter??{};typeof m.jdPrefix=="string"&&d.set(m.jdPrefix,I)}let g=new Map,u=0,p=0,f=0;for(let I of l){let m=n.get(I)??null,C=Rn(I,new Set(n.keys())),B=C?g.get(C)??k:k,w=m?`${I} ${m.title}`:I,y=m?.file?`[[${m.file.basename}]]`:"",Q=y?`${y} `:`${w} `,v=d.get(I);if(v){try{let E=null;await A.fileManager.processFrontMatter(v,U=>{U.jdPrefix=I,B&&(U.parent=B),(!U.id||typeof U.id!="string")&&(U.id=W()),U.created||(U.created=new Date().toISOString()),U.attachments||(U.attachments=[]),E=U.id});let D=(await A.vault.read(v)).match(/^---\r?\n[\s\S]*?\r?\n---\r?\n/),H=D?`${D[0]}${Q}`:Q;await A.vault.modify(v,H),E&&g.set(I,E),p++}catch(E){console.error("[stashpad] buildJdIndexNotes: update failed",E),f++}continue}try{let E=W();g.set(I,E);let S=St(w,t.slugStopWords),D=bt(S,E),H=`${e}/${D}`,U=["---",`id: ${E}`,`parent: ${B}`,`created: "${new Date().toISOString()}"`,"attachments: []",`jdPrefix: "${I}"`,"---",""].join(` @@ -90,7 +90,7 @@ ${B}`):t=B}catch(C){console.warn("[Stashpad] template read failed",C)}}}let l=St `);this.plugin.importService.suppress(d,6e4),await vt.timeAsync("write.createNote.file",()=>this.app.vault.create(d,I)),i.collectInto?.push({path:d,content:I});try{let m=this.app.vault.getAbstractFileByPath(d);if(m&&m.extension==="md"){if(!n)this.tree.insertSynthetic({id:o,parent:h,children:[],file:m,created:g}),i.deferRender||this.render(),this.fmSync.scheduleParentChange(o,null,h);else{i.deferRender||this.render();let C=s.split("/").pop()||s,B=(t.split(` `).find(w=>w.trim())??"note").trim().slice(0,60);i.deferUndo||this.plugin.notifications.show({message:`"${B}" landed in \`${C}\``,kind:"success",category:"create",duration:0,folder:s,affectedIds:[o],actions:[{label:"Jump to note",onClick:()=>{this.switchToFolderAndFocus(s,o)}}]})}if(a)try{await this.app.fileManager.processFrontMatter(m,C=>{for(let[B,w]of Object.entries(a))ue.includes(B)||Sn.includes(B)||C[B]===void 0&&(C[B]=w)})}catch(C){console.warn("[Stashpad] template fm overlay failed",C)}}}catch{}if(await this.log.append({type:"create",id:o,payload:{path:d,parent:h}}),i.record!==!1&&!i.deferUndo){let m=t;this.plugin.getUndoStack(s).push({label:n?"Send note":"Create note",undo:async()=>{let C=this.app.vault.getAbstractFileByPath(d);if(C)try{await this.app.fileManager.trashFile(C)}catch{}if(this.composerDraft=m,this.saveDraft(m),this.recordLastSubmitted(""),this.composerInputEl){this.composerInputEl.value=m;let B=m.length;this.composerInputEl.setSelectionRange(B,B),this.composerInputEl.focus()}n||this.tree.rebuild(this.noteFolder),this.render()},redo:async()=>{await this.app.vault.adapter.exists(d)||await this.app.vault.create(d,I),this.composerDraft="",this.saveDraft(""),this.recordLastSubmitted(m),this.composerInputEl&&(this.composerInputEl.value=""),n||this.tree.rebuild(this.noteFolder),this.render()}})}return o}catch(I){return new F.Notice(`Stashpad: failed to create note (${I.message})`),null}}async createNotesBatch(t,e,i,s,n){let o=t.length,a=[],l=!!i?.targetFolder&&i.targetFolder!==this.noteFolder,c=8,d=null;if(o>=c){let h=new F.Notice("",0),g=h.messageEl;g.empty(),g.createDiv({cls:"stashpad-split-progress-title",text:`Splitting into ${o} notes\u2026`});let p=g.createDiv({cls:"stashpad-split-progress-bar"}).createDiv({cls:"stashpad-split-progress-fill"}),f=g.createDiv({cls:"stashpad-split-progress-label",text:`0 / ${o}`});d={notice:h,fill:p,label:f}}this.beginBulkRender();try{for(let h=0;hwindow.setTimeout(u,0))}}finally{d?.notice.hide();try{await this.fmSync.flush()}catch{}this.endBulkRender()}if(a.length){let h=a.slice();this.plugin.getUndoStack(n).push({label:`Create ${h.length} notes`,undo:async()=>{for(let{path:g}of h){let u=this.app.vault.getAbstractFileByPath(g);if(u)try{await this.app.fileManager.trashFile(u)}catch{}}if(this.composerDraft=s,this.saveDraft(s),this.recordLastSubmitted(""),this.composerInputEl){this.composerInputEl.value=s;let g=s.length;this.composerInputEl.setSelectionRange(g,g),this.composerInputEl.focus()}l||this.tree.rebuild(this.noteFolder),this.render()},redo:async()=>{for(let{path:g,content:u}of h)await this.app.vault.adapter.exists(g)||await this.app.vault.create(g,u);this.composerDraft="",this.saveDraft(""),this.composerInputEl&&(this.composerInputEl.value=""),l||this.tree.rebuild(this.noteFolder),this.render()}})}o>=c&&this.plugin.notifications.show({message:`Created ${a.length} notes${l?` in \`${n.split("/").pop()}\``:""}.`,kind:"success",category:"create"})}extractAttachments(t){let e=[],i=/!\[\[([^\]\|]+)(?:\|[^\]]+)?\]\]/g,s;for(;(s=i.exec(t))!==null;)e.push(s[1]);return e}async ensureFolder(t){if(await this.app.vault.adapter.exists(t)){let e=this.app.vault.getAbstractFileByPath(t);if(e&&!(e instanceof F.TFolder))throw new Error(`${t} exists and is not a folder`);return}try{await this.app.vault.createFolder(t)}catch(e){let i=e?.message??"";if(!/already exists/i.test(i))throw e}}async importAttachment(t){try{let e=await t.arrayBuffer(),i=`${this.noteFolder}/_attachments`;await this.ensureFolder(i);let s=t.name.replace(/[^\w.\-]+/g,"_"),n=Date.now().toString(36),o=`${i}/${fs(s,n)}`;return await this.app.vault.createBinary(o,e),await this.log.append({type:"attachment_add",id:k,payload:{path:o,name:t.name,size:t.size}}),this.plugin.notifications.show({message:`Attached ${t.name}`,kind:"success",category:"attachment",affectedPaths:[o],folder:this.noteFolder}),`![[${o}]]`}catch(e){return new F.Notice(`Stashpad: attachment failed (${e.message})`),null}}claimSelectedAsAuthor(){this.authorship.claimSelectedAsAuthor()}claimFolderAsAuthor(){this.authorship.claimFolderAsAuthor()}claimSelectedWithContributor(){this.authorship.claimSelectedWithContributor()}claimFolderWithContributor(){this.authorship.claimFolderWithContributor()}renderAuthorshipFooter(t,e){if(!e.file)return;let i=this.plugin.settings;if(!i.showAuthor&&!i.showContributors&&!i.showLastEdit)return;let s=this.app.metadataCache.getFileCache(e.file)?.frontmatter??{},n=typeof s.author=="string"?s.author:"",o=Array.isArray(s.contributors)?s.contributors.filter(p=>typeof p=="string"&&p.trim()!==""):[],a=typeof s.modified=="string"?s.modified:typeof s.created=="string"?s.created:"",l=i.showAuthor&&!!n,c=i.showContributors&&o.length>0,d=i.showLastEdit&&!!a;if(!l&&!c&&!d)return;let h=t.createDiv({cls:"stashpad-note-authorship"}),g=(p,f)=>{let I=f.replace(/^\[\[/,"").replace(/\]\]$/,""),m=I.indexOf("|"),C=m>=0?I.slice(0,m):I,B=m>=0?I.slice(m+1):I.split("/").pop()??I,w=p.createEl("a",{cls:"internal-link",text:B});w.setAttribute("data-href",C),w.setAttribute("href",C)},u=[];l&&u.push(p=>{p.createSpan({cls:"stashpad-authorship-label",text:"by "}),g(p,n)}),c&&u.push(p=>{p.createSpan({cls:"stashpad-authorship-label",text:"with "}),o.forEach((f,I)=>{I>0&&p.createSpan({text:", "}),g(p,f)})}),d&&u.push(p=>{p.createSpan({cls:"stashpad-authorship-label",text:"edited "}),p.createSpan({text:this.formatTimeInline(a)})}),u.forEach((p,f)=>{f>0&&h.createSpan({cls:"stashpad-authorship-sep",text:"\xB7"});let I=h.createSpan({cls:"stashpad-authorship-piece"});p(I)}),h.addEventListener("click",p=>this.handleRenderedClick(p,e))}activeStopwords(){return this.plugin.settings.slugStopWords??Vt}scheduleSlugRename(t){let e=this.slugDebouncers.get(t.path);e&&e.cancel(),e=(0,F.debounce)(()=>void this.maybeRenameForSlug(t),3e4),this.slugDebouncers.set(t.path,e),e()}async maybeRenameForSlug(t){let e=me(t.basename);if(!e||e===k)return;let i=await this.app.vault.cachedRead(t),s=this.stripFrontmatter(i),n=St(s,this.activeStopwords()),o=bt(n,e);if(t.name===o)return;let a=t.parent?`${t.parent.path}/${o}`:o;if(this.app.vault.getAbstractFileByPath(a))return;let l=t.path;try{await this.app.fileManager.renameFile(t,a),await this.log.append({type:"rename",id:e,payload:{from:l,to:a}})}catch{}}scheduleAttachmentSync(t){let e=this.attachmentDebouncers.get(t.path);e&&e.cancel(),e=(0,F.debounce)(()=>void this.syncAttachmentsFrontmatter(t),1500),this.attachmentDebouncers.set(t.path,e),e()}async syncAttachmentsFrontmatter(t){let e=await this.app.vault.cachedRead(t),i=this.stripFrontmatter(e),s=this.extractAttachments(i),n=this.app.metadataCache.getFileCache(t)?.frontmatter,a=(Array.isArray(n?.attachments)?n.attachments:[]).filter(d=>typeof d=="string").map(d=>be(d));if(a.length===s.length&&a.every((d,h)=>d===s[h]))return;let c=s.map(d=>$t(d));await this.app.fileManager.processFrontMatter(t,d=>{d.attachments=c})}stripFrontmatter(t){let e=t.replace(/^\uFEFF/,""),i=e.match(/^\s*---\s*\r?\n[\s\S]*?\r?\n---\s*(?:\r?\n|$)/);return i?e.slice(i[0].length):e}formatTime(t){if(!t)return"";let e=(0,F.moment)(t);if(!e.isValid())return"";let i=X();if(i.useTemplatesFormat){let n=Ts(this.app);if(n)return`${e.format(n.dateFormat)} ${e.format(n.timeFormat)}`}let s=e.valueOf();return`${ls(s,i)} -${cs(s,i)}`}formatTimeInline(t){if(!t)return"";let e=(0,F.moment)(t);if(!e.isValid())return"";if(X().useTemplatesFormat){let s=Ts(this.app);if(s){let n=/:ss/.test(s.timeFormat)?s.timeFormat:s.timeFormat.replace(/(:mm)/,"$1:ss");return`${e.format(s.dateFormat)} ${e.format(n)}`}}return`${e.format("YYYY.MM.DD")} ${e.format("HH:mm:ss A")}`}scrollListToBottom(){let t=this.listEl;if(!t)return;if(this.stickToListBottom=!0,t.scrollTop=t.scrollHeight,F.Platform.isMobile){let a=0,l=()=>{!this.stickToListBottom||a>=8||(a++,Date.now()>=this.keyboardTransitionUntil&&(t.scrollTop=t.scrollHeight),window.setTimeout(l,120))};window.setTimeout(l,60);return}this.stickyRowObserver?.disconnect();let e=()=>{if(!this.stickToListBottom){this.stickyRowObserver?.disconnect(),this.stickyRowObserver=null;return}t.scrollTop=t.scrollHeight},i=new ResizeObserver(e);for(let a of Array.from(t.children))a instanceof HTMLElement&&i.observe(a);this.stickyRowObserver=i;let s=performance.now(),n=t.scrollHeight,o=()=>{if(!this.stickToListBottom)return;let a=t.scrollHeight;a!==n&&(t.scrollTop=a,n=a),performance.now()-s<3e4?requestAnimationFrame(o):(this.stickToListBottom=!1,this.stickyRowObserver?.disconnect(),this.stickyRowObserver=null)};requestAnimationFrame(o)}openNoteMenu(t,e){if(!e.file)return;let i=e.file,s=new F.Menu;s.addItem(d=>d.setTitle("Open in new Stashpad tab").setIcon("layout-grid").onClick(()=>{this.openInNewStashpadTab(e.id)})),s.addItem(d=>d.setTitle("Open in editor").setIcon("file-text").onClick(()=>{this.openFileAtEnd(i)})),s.addItem(d=>d.setTitle("Focus in Stashpad").setIcon("arrow-right").onClick(()=>this.navigateTo(e.id))),s.addSeparator(),s.addItem(d=>d.setTitle("Split note\u2026").setIcon("split").onClick(()=>void this.cmdSplit(e))),s.addItem(d=>d.setTitle("Clone (duplicate / copy)").setIcon("files").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdClone()})),s.addItem(d=>d.setTitle("Copy text").setIcon("copy").onClick(()=>{l(),this.cmdCopy()})),s.addItem(d=>d.setTitle("Fork into a separate note\u2026").setIcon("git-branch").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdForkNote()})),s.addItem(d=>d.setTitle("Export to .stash").setIcon("package").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdExportStash()})),this.plugin.settings.okfEnabled&&s.addItem(d=>d.setTitle("Export as OKF\u2026").setIcon("book-marked").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdExportOkf()})),this.plugin.encryption?.isConfigured?.()&&s.addItem(d=>d.setTitle("Encrypt (lock) note + children").setIcon("lock").onClick(async()=>{let h=this.order.getOrder(this.noteFolder,e.parent??k),g=h.indexOf(e.id),u=g>0?h[g-1]:null;await this.plugin.lockNoteSubtree(this.noteFolder,e.id,u)&&this.render()})),s.addSeparator(),s.addItem(d=>d.setTitle("Move to\u2026").setIcon("move").onClick(()=>this.cmdMovePicker())),s.addItem(d=>d.setTitle("Move to Home").setIcon("home").onClick(async()=>{await this.changeParent(e,k),this.plugin.settings.autoNavOnMoveOut&&this.focusId!==k&&this.navigateTo(k)}));let n={folder:this.noteFolder,id:e.id},o=this.plugin.isPinned(n);s.addItem(d=>d.setTitle(o?"Unpin from sidebar":"Pin to sidebar").setIcon(o?"pin-off":"pin").onClick(async()=>{o?await this.plugin.unpinNote(n):await this.plugin.pinNote(n)}));let a=this.isListPinned(e.id);s.addItem(d=>d.setTitle(a?"Unpin from top of list":"Pin to top of list").setIcon(a?"pin-off":"arrow-up-to-line").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdToggleListPin()})),s.addItem(d=>d.setTitle("Set color\u2026").setIcon("palette").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdSetColor()}));let l=()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id)},c=d=>{let h=this.isTask(e);if(h){let g=this.isCompleted(e);d.addItem(u=>u.setTitle(g?"Mark incomplete":"Mark complete").setIcon(g?"circle":"check-circle").onClick(()=>{l(),this.cmdToggleComplete()}))}else d.addItem(g=>g.setTitle("Mark complete").setIcon("check-circle").onClick(()=>{l(),this.toggleCompletedForNode(e)})),d.addItem(g=>g.setTitle("Turn into task").setIcon("check-square").onClick(()=>{l(),this.cmdToggleTask()}));d.addItem(g=>g.setTitle("Assign / schedule\u2026").setIcon("user-plus").onClick(()=>{l(),this.cmdAssign()})),h&&d.addItem(g=>g.setTitle("Remove from tasks").setIcon("square").onClick(()=>{l(),this.cmdToggleTask()}))};s.addItem(d=>{d.setTitle("Task").setIcon("check-square");let h=typeof d.setSubmenu=="function"?d.setSubmenu():null;h&&typeof h.addItem=="function"?c(h):d.onClick(()=>this.openCommandPalette())}),s.addSeparator(),s.addItem(d=>d.setTitle("Delete").setIcon("trash").onClick(async()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),await this.cmdDelete()})),s.addSeparator(),s.addItem(d=>d.setTitle("More commands\u2026").setIcon("terminal").onClick(()=>this.openCommandPalette())),s.showAtMouseEvent(t)}async deleteNote(t){if(!t.file)return;let e=[],i=p=>{for(let f of this.tree.getChildren(p.id))i(f),e.push(f)};i(t);let s=[...e,t],n=s.filter(p=>!!p.file),o=await Promise.all(n.map(p=>this.app.vault.cachedRead(p.file))),a=[];for(let p=0;p{let f=await this.snapshotNotes(s,p),I=0;if(p)for(let D of l){let H=this.app.metadataCache.getFirstLinkpathDest(D,"");if(H)try{await this.app.fileManager.trashFile(H),await this.log.append({type:"attachment_remove",id:k,payload:{path:H.path}}),this.plugin.notifications.show({message:`Deleted attachment "${H.name}"`,kind:"warning",category:"attachment",affectedPaths:[H.path],folder:this.noteFolder}),I+=1}catch{}}let m=new Set;for(let D of s)D.parent&&m.add(D.parent);let C=this.currentChildren.findIndex(D=>D.id===t.id),B=null;if(C>=0){for(let D=C+1;D=0;D--)if(this.currentChildren[D].id!==t.id){B=this.currentChildren[D].id;break}}}for(let D of s)if(D.file){try{await this.app.fileManager.trashFile(D.file)}catch{}await this.log.append({type:"delete",id:D.id,payload:{path:D.file.path,attachmentsRemoved:p?l:[]}})}this.selection.clear(),this.cursorIdx=-1,B&&(this.pendingFocusIds=[B]),this.tree.rebuild(this.noteFolder),this.render({kind:"follow-cursor"});for(let D of m)s.some(H=>H.id===D)||this.fmSync.scheduleParentOfDeleted(D);let w=this.noteFolder,y=`Delete "${this.titleForNode(t)}"`,Q=t.id,v=I>0?` with ${I} attachment${I===1?"":"s"}`:"",E=!1,S=async()=>{E||(E=!0,this.selection.clear(),this.cursorIdx=-1,await this.restoreSnapshots(f,[Q]))};this.plugin.notifications.show({message:`Deleted "${this.titleForNode(t)}"${v}`,kind:"warning",category:"delete",duration:0,affectedIds:[t.id],affectedAuthorIds:c,folder:this.noteFolder,actions:[{label:"Undo delete",onClick:()=>void S()}]}),this.plugin.getUndoStack(w).push({label:y,undo:async()=>{await S()},redo:async()=>{this.selection.clear(),this.cursorIdx=-1,E=!1,await this.trashNotesAndAttachments(f)}})},h=X(),g=e.length>0&&h.confirmBulkDelete,u=l.length>0&&h.confirmAttachmentDelete;if(!g&&!u){await d(!1),this.focusView();return}new We(this.app,this.titleForNode(t),e.length,l.length,u,async p=>{await d(p),this.focusView()}).open()}async cmdSwapWithParent(){let t=this.cursorIdx>=0?this.currentChildren[this.cursorIdx]:null;if(!t?.file){new F.Notice("Pick a note first (move the cursor onto it).");return}if(!t.parent||t.parent===k){new F.Notice("Already at Home \u2014 no parent to swap with.");return}let e=this.tree.get(t.parent);if(!e?.file){new F.Notice("Couldn't find the parent note.");return}let i=e.parent??k,s=this.titleForNode(t),n=this.titleForNode(e),o=this.tree.getChildren(e.id).filter(l=>l.id!==t.id).length,a=[`"${n}" becomes a child of "${s}".`];o>0&&a.push(`${o} sibling${o===1?"":"s"} move with it.`),new et(this.app,"Swap notes?",a.join(` +${cs(s,i)}`}formatTimeInline(t){if(!t)return"";let e=(0,F.moment)(t);if(!e.isValid())return"";if(X().useTemplatesFormat){let s=Ts(this.app);if(s){let n=/:ss/.test(s.timeFormat)?s.timeFormat:s.timeFormat.replace(/(:mm)/,"$1:ss");return`${e.format(s.dateFormat)} ${e.format(n)}`}}return`${e.format("YYYY.MM.DD")} ${e.format("HH:mm:ss A")}`}scrollListToBottom(){let t=this.listEl;if(!t)return;if(this.stickToListBottom=!0,t.scrollTop=t.scrollHeight,F.Platform.isMobile){let a=0,l=()=>{!this.stickToListBottom||a>=8||(a++,Date.now()>=this.keyboardTransitionUntil&&(t.scrollTop=t.scrollHeight),window.setTimeout(l,120))};window.setTimeout(l,60);return}this.stickyRowObserver?.disconnect();let e=()=>{if(!this.stickToListBottom){this.stickyRowObserver?.disconnect(),this.stickyRowObserver=null;return}t.scrollTop=t.scrollHeight},i=new ResizeObserver(e);for(let a of Array.from(t.children))a instanceof HTMLElement&&i.observe(a);this.stickyRowObserver=i;let s=performance.now(),n=t.scrollHeight,o=()=>{if(!this.stickToListBottom)return;let a=t.scrollHeight;a!==n&&(t.scrollTop=a,n=a),performance.now()-s<3e4?requestAnimationFrame(o):(this.stickToListBottom=!1,this.stickyRowObserver?.disconnect(),this.stickyRowObserver=null)};requestAnimationFrame(o)}openNoteMenu(t,e){if(!e.file)return;let i=e.file,s=new F.Menu;s.addItem(d=>d.setTitle("Open in new Stashpad tab").setIcon("layout-grid").onClick(()=>{this.openInNewStashpadTab(e.id)})),s.addItem(d=>d.setTitle("Open in editor").setIcon("file-text").onClick(()=>{this.openFileAtEnd(i)})),s.addItem(d=>d.setTitle("Focus in Stashpad").setIcon("arrow-right").onClick(()=>this.navigateTo(e.id))),s.addSeparator(),s.addItem(d=>d.setTitle("Split note\u2026").setIcon("split").onClick(()=>void this.cmdSplit(e))),s.addItem(d=>d.setTitle("Copy text").setIcon("copy").onClick(()=>{l(),this.cmdCopy()})),s.addItem(d=>d.setTitle("Clone (duplicate / copy)").setIcon("files").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdClone()})),s.addItem(d=>d.setTitle("Fork into a separate note\u2026").setIcon("git-branch").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdForkNote()})),s.addItem(d=>d.setTitle("Export to .stash").setIcon("package").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdExportStash()})),this.plugin.settings.okfEnabled&&s.addItem(d=>d.setTitle("Export as OKF\u2026").setIcon("book-marked").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdExportOkf()})),this.plugin.encryption?.isConfigured?.()&&s.addItem(d=>d.setTitle("Encrypt (lock) note + children").setIcon("lock").onClick(async()=>{let h=this.order.getOrder(this.noteFolder,e.parent??k),g=h.indexOf(e.id),u=g>0?h[g-1]:null;await this.plugin.lockNoteSubtree(this.noteFolder,e.id,u)&&this.render()})),s.addSeparator(),s.addItem(d=>d.setTitle("Move to\u2026").setIcon("move").onClick(()=>this.cmdMovePicker())),s.addItem(d=>d.setTitle("Move to Home").setIcon("home").onClick(async()=>{await this.changeParent(e,k),this.plugin.settings.autoNavOnMoveOut&&this.focusId!==k&&this.navigateTo(k)}));let n={folder:this.noteFolder,id:e.id},o=this.plugin.isPinned(n);s.addItem(d=>d.setTitle(o?"Unpin from sidebar":"Pin to sidebar").setIcon(o?"pin-off":"pin").onClick(async()=>{o?await this.plugin.unpinNote(n):await this.plugin.pinNote(n)}));let a=this.isListPinned(e.id);s.addItem(d=>d.setTitle(a?"Unpin from top of list":"Pin to top of list").setIcon(a?"pin-off":"arrow-up-to-line").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdToggleListPin()})),s.addItem(d=>d.setTitle("Set color\u2026").setIcon("palette").onClick(()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),this.cmdSetColor()}));let l=()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id)},c=d=>{let h=this.isTask(e);if(h){let g=this.isCompleted(e);d.addItem(u=>u.setTitle(g?"Mark incomplete":"Mark complete").setIcon(g?"circle":"check-circle").onClick(()=>{l(),this.cmdToggleComplete()}))}else d.addItem(g=>g.setTitle("Mark complete").setIcon("check-circle").onClick(()=>{l(),this.toggleCompletedForNode(e)})),d.addItem(g=>g.setTitle("Turn into task").setIcon("check-square").onClick(()=>{l(),this.cmdToggleTask()}));d.addItem(g=>g.setTitle("Assign / schedule\u2026").setIcon("user-plus").onClick(()=>{l(),this.cmdAssign()})),h&&d.addItem(g=>g.setTitle("Remove from tasks").setIcon("square").onClick(()=>{l(),this.cmdToggleTask()}))};s.addItem(d=>{d.setTitle("Task").setIcon("check-square");let h=typeof d.setSubmenu=="function"?d.setSubmenu():null;h&&typeof h.addItem=="function"?c(h):d.onClick(()=>this.openCommandPalette())}),s.addSeparator(),s.addItem(d=>d.setTitle("Delete").setIcon("trash").onClick(async()=>{this.selection.has(e.id)||(this.selection.clear(),this.selection.add(e.id),this.lastSelected=e.id),await this.cmdDelete()})),s.addSeparator(),s.addItem(d=>d.setTitle("More commands\u2026").setIcon("terminal").onClick(()=>this.openCommandPalette())),s.showAtMouseEvent(t)}async deleteNote(t){if(!t.file)return;let e=[],i=p=>{for(let f of this.tree.getChildren(p.id))i(f),e.push(f)};i(t);let s=[...e,t],n=s.filter(p=>!!p.file),o=await Promise.all(n.map(p=>this.app.vault.cachedRead(p.file))),a=[];for(let p=0;p{let f=await this.snapshotNotes(s,p),I=0;if(p)for(let D of l){let H=this.app.metadataCache.getFirstLinkpathDest(D,"");if(H)try{await this.app.fileManager.trashFile(H),await this.log.append({type:"attachment_remove",id:k,payload:{path:H.path}}),this.plugin.notifications.show({message:`Deleted attachment "${H.name}"`,kind:"warning",category:"attachment",affectedPaths:[H.path],folder:this.noteFolder}),I+=1}catch{}}let m=new Set;for(let D of s)D.parent&&m.add(D.parent);let C=this.currentChildren.findIndex(D=>D.id===t.id),B=null;if(C>=0){for(let D=C+1;D=0;D--)if(this.currentChildren[D].id!==t.id){B=this.currentChildren[D].id;break}}}for(let D of s)if(D.file){try{await this.app.fileManager.trashFile(D.file)}catch{}await this.log.append({type:"delete",id:D.id,payload:{path:D.file.path,attachmentsRemoved:p?l:[]}})}this.selection.clear(),this.cursorIdx=-1,B&&(this.pendingFocusIds=[B]),this.tree.rebuild(this.noteFolder),this.render({kind:"follow-cursor"});for(let D of m)s.some(H=>H.id===D)||this.fmSync.scheduleParentOfDeleted(D);let w=this.noteFolder,y=`Delete "${this.titleForNode(t)}"`,Q=t.id,v=I>0?` with ${I} attachment${I===1?"":"s"}`:"",E=!1,S=async()=>{E||(E=!0,this.selection.clear(),this.cursorIdx=-1,await this.restoreSnapshots(f,[Q]))};this.plugin.notifications.show({message:`Deleted "${this.titleForNode(t)}"${v}`,kind:"warning",category:"delete",duration:0,affectedIds:[t.id],affectedAuthorIds:c,folder:this.noteFolder,actions:[{label:"Undo delete",onClick:()=>void S()}]}),this.plugin.getUndoStack(w).push({label:y,undo:async()=>{await S()},redo:async()=>{this.selection.clear(),this.cursorIdx=-1,E=!1,await this.trashNotesAndAttachments(f)}})},h=X(),g=e.length>0&&h.confirmBulkDelete,u=l.length>0&&h.confirmAttachmentDelete;if(!g&&!u){await d(!1),this.focusView();return}new We(this.app,this.titleForNode(t),e.length,l.length,u,async p=>{await d(p),this.focusView()}).open()}async cmdSwapWithParent(){let t=this.cursorIdx>=0?this.currentChildren[this.cursorIdx]:null;if(!t?.file){new F.Notice("Pick a note first (move the cursor onto it).");return}if(!t.parent||t.parent===k){new F.Notice("Already at Home \u2014 no parent to swap with.");return}let e=this.tree.get(t.parent);if(!e?.file){new F.Notice("Couldn't find the parent note.");return}let i=e.parent??k,s=this.titleForNode(t),n=this.titleForNode(e),o=this.tree.getChildren(e.id).filter(l=>l.id!==t.id).length,a=[`"${n}" becomes a child of "${s}".`];o>0&&a.push(`${o} sibling${o===1?"":"s"} move with it.`),new et(this.app,"Swap notes?",a.join(` `),"Swap",async l=>{l&&await this.swapParentChild(e,t,i)}).open()}offerSwapForDescendantMove(t,e){let i=this.tree.get(e);if(!i?.file){this.plugin.notifications.show({message:`Can't nest "${this.titleForNode(t)}" under one of its own descendants \u2014 that would create a cycle.`,kind:"warning",category:"move",affectedIds:[t.id],folder:this.noteFolder});return}if(i.parent!==t.id){this.plugin.notifications.show({message:`Can't nest "${this.titleForNode(t)}" under "${this.titleForNode(i)}" \u2014 it's a deeper descendant. Only direct parent \u2194 child swaps are supported (try moving "${this.titleForNode(i)}" up first, then swap).`,kind:"warning",category:"move",affectedIds:[t.id,i.id],folder:this.noteFolder});return}let s=this.titleForNode(t),n=this.titleForNode(i),o=this.tree.getChildren(t.id).filter(l=>l.id!==i.id).length,a=[`"${s}" becomes a child of "${n}".`];o>0&&a.push(`${o} sibling${o===1?"":"s"} move with it.`),new et(this.app,"Confirm Note Swap",a.join(` `),"Swap",async l=>{if(!l)return;let c=t.parent??k;await this.swapParentChild(t,i,c)}).open()}async swapParentChild(t,e,i){if(!t.file||!e.file)return;if(e.parent!==t.id){new F.Notice("Swap aborted: parent/child relationship changed.");return}let s=this.noteFolder,n=t.parent,o=this.tree.getChildren(t.id).filter(u=>u.id!==e.id).filter(u=>!!u.file),a=o.map(u=>({id:u.id,path:u.file.path,was:u.parent})),l=this.order.getOrder(s,i).slice(),c=this.order.getOrder(s,e.id).slice(),d=this.order.getOrder(s,t.id).slice();await this.app.fileManager.processFrontMatter(e.file,u=>{u.parent=i}),this.fmSync.scheduleParentChange(e.id,t.id,i),await this.app.fileManager.processFrontMatter(t.file,u=>{u.parent=e.id}),this.fmSync.scheduleParentChange(t.id,n,e.id);for(let u of o)await this.app.fileManager.processFrontMatter(u.file,p=>{p.parent=e.id}),this.fmSync.scheduleParentChange(u.id,t.id,e.id);if(l.length>0){let u=l.includes(t.id)?l.map(p=>p===t.id?e.id:p):[...l.filter(p=>p!==e.id),e.id];this.order.setOrder(s,i,u)}let h=o.map(u=>u.id),g=[t.id,...c.filter(u=>u!==t.id&&!h.includes(u)),...h];this.order.setOrder(s,e.id,g),this.order.setOrder(s,t.id,[]),await this.order.save(s),await this.log.append({type:"parent_change",id:e.id,payload:{from:t.id,to:i,reason:"swap"}}),await this.log.append({type:"parent_change",id:t.id,payload:{from:n,to:e.id,reason:"swap"}});for(let u of a)await this.log.append({type:"parent_change",id:u.id,payload:{from:u.was,to:e.id,reason:"swap"}});this.tree.rebuild(s),this.pendingFocusIds=[e.id],this.render({kind:"follow-cursor"}),this.plugin.notifications.show({message:`Swapped "${this.titleForNode(e)}" \u2194 "${this.titleForNode(t)}".`,kind:"success",category:"move",affectedIds:[e.id,t.id,...h],folder:s}),this.plugin.getUndoStack(s).push({label:`Swap "${this.titleForNode(e)}" \u2194 parent`,undo:async()=>{let u=this.tree.get(t.id),p=this.tree.get(e.id);u?.file&&await this.app.fileManager.processFrontMatter(u.file,f=>{n==null||n===k?(delete f.parent,f.parent=k):f.parent=n}),p?.file&&await this.app.fileManager.processFrontMatter(p.file,f=>{f.parent=t.id});for(let f of a){let I=this.app.vault.getAbstractFileByPath(f.path);I&&await this.app.fileManager.processFrontMatter(I,m=>{f.was==null?m.parent=k:m.parent=f.was})}this.order.setOrder(s,i,l),this.order.setOrder(s,e.id,c),this.order.setOrder(s,t.id,d),await this.order.save(s),this.tree.rebuild(s),this.pendingFocusIds=[t.id],this.render({kind:"follow-cursor"})},redo:async()=>{await this.swapParentChild(t,e,i)}})}async changeParent(t,e,i={record:!0}){if(!t.file)return!1;let s=t.file,n=t.parent,o=l=>l??k;if(o(n)===o(e)){if(!i.quiet){let l=this.titleForNode(t),c=e===k?"Home":`"${this.titleForNode(this.tree.get(e)??t)}"`;this.plugin.notifications.show({message:`"${l}" is already under ${c}.`,kind:"info",category:"move",affectedIds:[t.id],folder:this.noteFolder})}return!1}if(e===t.id)return i.quiet||this.plugin.notifications.show({message:`Can't move "${this.titleForNode(t)}" into itself.`,kind:"warning",category:"move",affectedIds:[t.id],folder:this.noteFolder}),!1;if(e!==k&&this.isDescendant(e,t.id))return i.quiet||this.offerSwapForDescendantMove(t,e),!1;let a=this.authorship.collectAuthorIds([t]);if(await this.app.fileManager.processFrontMatter(s,l=>{l.parent=e}),this.fmSync.scheduleParentChange(t.id,n,e),await this.log.append({type:"parent_change",id:t.id,payload:{from:n,to:e}}),this.pendingFocusIds=[t.id],this.focusId!==e&&this.focusId!==n?(this.selection.clear(),this.cursorIdx=-1):this.focusId===n&&(this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=null),!i.quiet&&!i.silentSuccess){let l=this.tree.get(e),c=l?this.titleForNode(l):"(root)";this.plugin.notifications.show({message:`Reparented "${this.titleForNode(t)}" \u2192 "${c}"`,kind:"success",category:"move",affectedIds:[t.id],affectedAuthorIds:a,folder:this.noteFolder,actions:e===k?[]:[{label:"Jump to parent",onClick:()=>this.navigateTo(e)}]})}if(i.record!==!1){let l=this.noteFolder,c=s.path,d=t.id;this.plugin.getUndoStack(l).push({label:"Move note",undo:async()=>{let h=this.app.vault.getAbstractFileByPath(c);if(h){await this.app.fileManager.processFrontMatter(h,g=>{g.parent=n}),this.pendingFocusIds=[d],this.focusId!==n&&this.focusId!==e?(this.selection.clear(),this.cursorIdx=-1):this.focusId===e&&(this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=null),this.tree.rebuild(l),this.render({kind:"follow-cursor"});{let g=this.selectionGuardKey,u=()=>{if(this.selectionGuardKey!==g||this.selection.has(d))return;let p=this.currentChildren.findIndex(f=>f.id===d);p<0||(this.selection.add(d),this.cursorIdx=p,this.render({kind:"follow-cursor"}))};setTimeout(u,120),setTimeout(u,400)}}},redo:async()=>{let h=this.app.vault.getAbstractFileByPath(c);if(h){await this.app.fileManager.processFrontMatter(h,g=>{g.parent=e}),this.pendingFocusIds=[d],this.focusId!==e&&this.focusId!==n?(this.selection.clear(),this.cursorIdx=-1):this.focusId===n&&(this.selection.clear(),this.cursorIdx=-1,this.pendingFocusIds=null),this.tree.rebuild(l),this.render({kind:"follow-cursor"});{let g=this.selectionGuardKey,u=()=>{if(this.selectionGuardKey!==g||this.selection.has(d))return;let p=this.currentChildren.findIndex(f=>f.id===d);p<0||(this.selection.add(d),this.cursorIdx=p,this.render({kind:"follow-cursor"}))};setTimeout(u,120),setTimeout(u,400)}}}})}return!0}notifyBatchMove(t,e,i){if(!t.length)return;let s=this.tree.get(e),n=e===k?"Home":`"${s?this.titleForNode(s):"the destination"}"`,o=l=>i.get(l.id)??0,a;if(t.length===1){let l=this.titleForNode(t[0]),c=o(t[0]);a=c>0?`Moved "${l}" and its ${c} ${c===1?"child":"children"} \u2192 ${n}`:`Moved "${l}" \u2192 ${n}`}else{let l=t.reduce((c,d)=>c+o(d),0);a=l>0?`Moved ${t.length} notes (${l} nested) \u2192 ${n}`:`Moved ${t.length} notes \u2192 ${n}`}this.plugin.notifications.show({message:a,kind:"success",category:"move",duration:e===k?void 0:0,affectedIds:t.map(l=>l.id),affectedAuthorIds:this.authorship.collectAuthorIds(t),folder:this.noteFolder,actions:e===k?[]:[{label:"Jump to destination",onClick:()=>this.navigateTo(e)}]})}};es.AIMED_TAP_WINDOW_MS=600;var ln=es,Ho=class extends F.SuggestModal{constructor(t,e,i){super(t);this.folders=e;this.onPick=i;this.setPlaceholder("Move to which archive folder?")}getSuggestions(t){let e=t.toLowerCase();return this.folders.filter(i=>i.toLowerCase().includes(e))}renderSuggestion(t,e){e.createDiv({text:t.split("/").pop()||t}),e.createEl("small",{text:t,cls:"stashpad-suggest-path"})}onChooseSuggestion(t){this.onPick(t)}},cn=class extends F.SuggestModal{constructor(t,e,i){super(t);this.entries=e;this.onPick=i;this.setPlaceholder("Restore which deleted note?")}getSuggestions(t){let e=t.toLowerCase();return this.entries.filter(i=>`${i.label} ${i.folder}`.toLowerCase().includes(e))}renderSuggestion(t,e){e.createDiv({text:t.label}),e.createEl("small",{text:`from ${t.folder}`,cls:"stashpad-suggest-path"})}onChooseSuggestion(t){this.onPick(t.blob)}};var ie=require("obsidian");rt();kt();var Kc=ie.moment,An=class extends ie.ItemView{constructor(t,e){super(t);this.plugin=e;this.renderPending=!1;this.renderGen=0;this.selected=new Set;this.order=[];this.anchorIdx=null}getViewType(){return Je}getDisplayText(){return"Encrypted trash"}getIcon(){return"trash-2"}async onOpen(){this.containerEl.addClass("stashpad-trash-view"),this.registerEvent(this.app.vault.on("create",t=>{t.path.startsWith("_deleted/")&&this.scheduleRender()})),this.registerEvent(this.app.vault.on("delete",t=>{t.path.startsWith("_deleted/")&&this.scheduleRender()})),this.registerDomEvent(document,"keydown",t=>{if(this.app.workspace.activeLeaf!==this.leaf)return;let e=t.target;if(!(e&&(e.tagName==="INPUT"||e.tagName==="TEXTAREA"||e.isContentEditable))&&(t.metaKey||t.ctrlKey)&&!t.altKey&&(t.key==="a"||t.key==="A")){if(this.order.length===0)return;t.preventDefault(),this.selectAll()}}),await this.render()}scheduleRender(){this.renderPending||(this.renderPending=!0,window.setTimeout(()=>{this.renderPending=!1,this.render()},150))}async render(){let t=++this.renderGen,e=this.contentEl;e.empty(),e.addClass("stashpad-trash-view-body");let i=e.createDiv({cls:"stashpad-trash-view-header"});i.createEl("h3",{text:"Encrypted trash"});let s=i.createEl("button",{cls:"stashpad-trash-iconbtn"});if((0,ie.setIcon)(s,"refresh-cw"),s.setAttr("aria-label","Refresh"),s.onclick=()=>void this.render(),!this.plugin.encryption?.isConfigured?.()){e.createDiv({cls:"stashpad-trash-empty",text:"Encryption isn't set up."});return}let n=await this.plugin.listDeletedTrash();if(t!==this.renderGen)return;if(n.length===0){e.createDiv({cls:"stashpad-trash-empty",text:"Nothing in the encrypted trash. Notes you securely delete land here, recoverable with your password."});return}let o=i.createEl("button",{cls:"stashpad-trash-restore",text:"Restore all"});(0,ie.setIcon)(o.createSpan({cls:"stashpad-btn-icon"}),"rotate-ccw"),o.onclick=async()=>{o.disabled=!0,await this.plugin.restoreAllTrash(),this.clearSelection(),await this.render()};let a=new Set(n.map(d=>d.blob));for(let d of[...this.selected])a.has(d)||this.selected.delete(d);if(this.selected.size>0){let d=e.createDiv({cls:"stashpad-trash-selbar"});d.createSpan({cls:"stashpad-trash-selcount",text:`${this.selected.size} selected`});let h=d.createEl("button",{cls:"stashpad-trash-restore",text:"Restore selected"});h.onclick=async()=>{h.disabled=!0;for(let p of[...this.selected])await this.plugin.restoreDeletedAt(p,{silent:!0});this.clearSelection(),await this.render()};let g=d.createEl("button",{cls:"stashpad-trash-delete mod-warning",text:"Delete selected"});g.onclick=()=>this.confirmPurge([...this.selected]);let u=d.createEl("button",{cls:"stashpad-trash-iconbtn",text:"Clear"});u.onclick=()=>{this.clearSelection(),this.render()}}let l=new Map;for(let d of n){let h=d.meta?.title?d.meta.originalFolder||"(unknown folder)":" hidden";(l.get(h)??l.set(h,[]).get(h)).push(d)}let c=[...l.keys()].sort((d,h)=>d===" hidden"?1:h===" hidden"?-1:d.localeCompare(h));this.order=[];for(let d of c){let h=d===" hidden",g=e.createDiv({cls:"stashpad-trash-group"}),u=g.createDiv({cls:"stashpad-trash-group-head"});(0,ie.setIcon)(u.createSpan({cls:"stashpad-trash-group-icon"}),h?"lock":"folder"),u.createSpan({text:h?"Hidden (title obscured)":d.split("/").pop()||d}),u.createSpan({cls:"stashpad-trash-group-count",text:String(l.get(d).length)});for(let p of l.get(d)){let f=this.order.length;this.order.push(p.blob);let I=g.createDiv({cls:"stashpad-trash-row"});this.selected.has(p.blob)&&I.addClass("is-selected"),I.addEventListener("click",Q=>{Q.target.closest("button")||this.onRowClick(f,p.blob,Q)});let m=I.createDiv({cls:"stashpad-trash-row-main"});m.createSpan({cls:"stashpad-trash-title",text:h?"Locked note":p.meta?.title||"Locked note"});let C=p.meta?.deletedAt?`deleted ${Kc(p.meta.deletedAt).fromNow()}`:"deleted",B=p.meta&&p.meta.count>1?` \xB7 ${p.meta.count} ${p.meta.kind==="rawtrash"?"files":"notes"}`:"";m.createSpan({cls:"stashpad-trash-sub",text:C+B});let w=I.createEl("button",{cls:"stashpad-trash-restore",text:"Restore"});(0,ie.setIcon)(w.createSpan({cls:"stashpad-btn-icon"}),"rotate-ccw"),w.onclick=async()=>{w.disabled=!0,await this.plugin.restoreDeletedAt(p.blob)?await this.render():w.disabled=!1};let y=I.createEl("button",{cls:"stashpad-trash-delete",attr:{"aria-label":"Delete permanently"}});(0,ie.setIcon)(y,"trash-2"),y.onclick=()=>this.confirmPurge([p.blob])}}}clearSelection(){this.selected.clear(),this.anchorIdx=null}selectAll(){if(this.order.length!==0){for(let t of this.order)this.selected.add(t);this.anchorIdx=this.order.length-1,this.render()}}onRowClick(t,e,i){if(i.shiftKey&&this.anchorIdx!==null){let[s,n]=this.anchorIdx{if(i){for(let s of t)await this.plugin.purgeDeletedAt(s);this.clearSelection(),await this.render()}}).open()}async onClose(){this.contentEl.empty()}};async function $r(A){let{workspace:r}=A.app,t=r.getLeavesOfType(Je);if(t.length>0){r.revealLeaf(t[0]);return}let e=r.getLeaf("tab");await e.setViewState({type:Je,active:!0}),r.revealLeaf(e)}var se=require("obsidian");rt();var Vr=se.moment,dn=class extends se.ItemView{constructor(t,e){super(t);this.plugin=e;this.mode="encrypted";this.renderPending=!1}getViewType(){return Oe}getDisplayText(){return this.mode==="archived"?"All archived":"All encrypted"}getIcon(){return this.mode==="archived"?"archive":"lock"}getState(){return{...super.getState(),mode:this.mode}}async setState(t,e){(t?.mode==="archived"||t?.mode==="encrypted")&&(this.mode=t.mode),await super.setState(t,e),await this.render()}async onOpen(){this.containerEl.addClass("stashpad-aggregate-view");let t=e=>e.endsWith(".stashenc")&&!e.startsWith("_deleted/");this.registerEvent(this.app.vault.on("create",e=>{t(e.path)&&this.scheduleRender()})),this.registerEvent(this.app.vault.on("delete",e=>{t(e.path)&&this.scheduleRender()})),await this.render()}scheduleRender(){this.renderPending||(this.renderPending=!0,window.setTimeout(()=>{this.renderPending=!1,this.render()},150))}cleanFolder(t){return(t||"").replace(/\/+$/,"")}archiveFolders(){let t=new Set((this.plugin.settings.archiveFolders??[]).map(i=>this.cleanFolder(i))),e=this.plugin.settings.folderEncPrefs??{};for(let[i,s]of Object.entries(e))s?.archive&&t.add(this.cleanFolder(i));return[...t].sort((i,s)=>i.localeCompare(s))}async render(){let t=this.contentEl;t.empty(),t.addClass("stashpad-aggregate-body");let e=t.createDiv({cls:"stashpad-aggregate-header"});e.createEl("h3",{text:this.getDisplayText()});let i=e.createEl("button",{cls:"stashpad-trash-iconbtn"});if((0,se.setIcon)(i,"refresh-cw"),i.setAttr("aria-label","Refresh"),i.onclick=()=>void this.render(),this.mode==="archived"){this.renderArchived(t);return}this.renderEncrypted(t)}renderEncrypted(t){let e=this.plugin.settings.lockedSubtrees??[];if(e.length===0){t.createDiv({cls:"stashpad-trash-empty",text:"Nothing is encrypted yet. Lock a note or folder and it shows up here."});return}let i=new Map;for(let n of e){let o=this.cleanFolder(n.folder)||"(vault root)";(i.get(o)??i.set(o,[]).get(o)).push(n)}let s=[...i.keys()].sort((n,o)=>n.localeCompare(o));t.createDiv({cls:"stashpad-aggregate-sub",text:`${e.length} locked ${e.length===1?"item":"items"} in ${s.length} ${s.length===1?"folder":"folders"}.`});for(let n of s){let o=t.createDiv({cls:"stashpad-trash-group"}),a=o.createDiv({cls:"stashpad-trash-group-head"});(0,se.setIcon)(a.createSpan({cls:"stashpad-trash-group-icon"}),"folder"),a.createSpan({text:n.split("/").pop()||n}),a.createSpan({cls:"stashpad-trash-group-count",text:String(i.get(n).length)});let l=a.createEl("button",{cls:"stashpad-trash-iconbtn",text:"Open"});l.onclick=()=>void this.plugin.activateViewForFolder(n);for(let c of i.get(n)){let d=o.createDiv({cls:"stashpad-trash-row"}),h=d.createDiv({cls:"stashpad-trash-row-main"});h.createSpan({cls:"stashpad-trash-title",text:c.title||"Locked note"});let g=c.created?`locked ${Vr(c.created).fromNow()}`:"locked",u=c.count>1?` \xB7 ${c.count} notes`:"";h.createSpan({cls:"stashpad-trash-sub",text:g+u});let p=d.createEl("button",{cls:"stashpad-trash-iconbtn",text:"Export"});p.setAttr("aria-label","Export to .stash (encrypted with a password you choose)"),p.onclick=()=>void this.plugin.exportLockedSubtree(c.blob);let f=d.createSpan({cls:"stashpad-aggregate-lockbadge"});(0,se.setIcon)(f,"lock")}}}renderArchived(t){let e=this.archiveFolders();if(e.length===0){t.createDiv({cls:"stashpad-trash-empty",text:"No archive folders yet. Toggle Archive on a folder to collect it here."});return}let i=new Set(e),s=this.plugin.settings.lockedSubtrees??[],n=new Map;for(let a of s){let l=this.cleanFolder(a.folder);i.has(l)&&(n.get(l)??n.set(l,[]).get(l)).push(a)}let o=[...n.values()].reduce((a,l)=>a+l.length,0);t.createDiv({cls:"stashpad-aggregate-sub",text:`${e.length} archive ${e.length===1?"folder":"folders"}, ${o} archived ${o===1?"item":"items"}.`});for(let a of e){let l=n.get(a)??[],c=t.createDiv({cls:"stashpad-trash-group"}),d=c.createDiv({cls:"stashpad-trash-group-head"});(0,se.setIcon)(d.createSpan({cls:"stashpad-trash-group-icon"}),"archive"),d.createSpan({text:a.split("/").pop()||a}),d.createSpan({cls:"stashpad-trash-group-count",text:String(l.length)});let h=d.createEl("button",{cls:"stashpad-trash-iconbtn",text:"Open"});if(h.onclick=()=>void this.plugin.activateViewForFolder(a),l.length===0){c.createDiv({cls:"stashpad-trash-sub",text:"No archived (locked) items."});continue}for(let g of l){let u=c.createDiv({cls:"stashpad-trash-row"}),p=u.createDiv({cls:"stashpad-trash-row-main"});p.createSpan({cls:"stashpad-trash-title",text:g.title||"Locked note"});let f=g.created?`archived ${Vr(g.created).fromNow()}`:"archived",I=g.count>1?` \xB7 ${g.count} notes`:"";p.createSpan({cls:"stashpad-trash-sub",text:f+I});let m=u.createEl("button",{cls:"stashpad-trash-iconbtn",text:"Export"});m.setAttr("aria-label","Export to .stash (encrypted with a password you choose)"),m.onclick=()=>void this.plugin.exportLockedSubtree(g.blob);let C=u.createSpan({cls:"stashpad-aggregate-lockbadge"});(0,se.setIcon)(C,"lock")}}}async onClose(){this.contentEl.empty()}};async function Uo(A,r){let{workspace:t}=A.app,e=t.getLeavesOfType(Oe).find(s=>s.view?.getState?.().mode===r);if(e){t.revealLeaf(e);return}let i=t.getLeaf("tab");await i.setViewState({type:Oe,active:!0,state:{mode:r}}),t.revealLeaf(i)}rt();var Y=require("obsidian");rt();kt();var hn=class A extends Y.ItemView{constructor(t,e){super(t);this.plugin=e;this.renderTimer=null;this.pinExpanded=new Set;this.folderPinExpanded=new Set;this.homeColorByFolder=new Map}getViewType(){return ge}getDisplayText(){return"Stashpad folders"}getIcon(){return"folders"}async onOpen(){this.render(),this.registerEvent(this.app.workspace.on("active-leaf-change",()=>this.scheduleRender())),this.registerEvent(this.app.workspace.on("layout-change",()=>this.scheduleRender())),this.registerEvent(this.app.vault.on("create",()=>this.scheduleRender())),this.registerEvent(this.app.vault.on("delete",()=>this.scheduleRender())),this.registerEvent(this.app.vault.on("rename",()=>this.scheduleRender())),this.registerEvent(this.app.metadataCache.on("changed",()=>this.scheduleRender()))}refresh(){this.scheduleRender()}scheduleRender(){this.renderTimer==null&&(this.renderTimer=window.setTimeout(()=>{this.renderTimer=null,this.containerEl.isConnected&&this.render()},100))}render(){let t=this.contentEl;t.empty(),t.addClass("stashpad-folderpanel-root");let e=this.clampFrac(this.plugin.settings.folderPanelPinnedFraction??.5),i=t.createDiv({cls:"stashpad-folderpanel-section stashpad-folderpanel-pinned"});i.style.flex=`0 0 ${(e*100).toFixed(2)}%`;let s=i.createDiv({cls:"stashpad-folderpanel-heading stashpad-folderpanel-heading-row"});s.createSpan({cls:"stashpad-folderpanel-heading-title",text:"Pinned"});let n=s.createEl("button",{cls:"stashpad-folderpanel-iconbtn"});(0,Y.setIcon)(n,"list"),n.setAttr("aria-label","Pinned view options"),n.onclick=h=>{h.stopPropagation(),this.openPinnedOptionsMenu(h)},this.renderPinned(i.createDiv({cls:"stashpad-folderpanel-list stashpad-folderpanel-pins"}));let o=t.createDiv({cls:"stashpad-folderpanel-divider"});o.createDiv({cls:"stashpad-folderpanel-divider-grip"}),this.attachDividerDrag(t,i,o);let a=t.createDiv({cls:"stashpad-folderpanel-section stashpad-folderpanel-folders"});a.setCssStyles({flex:"1 1 0"});let l=a.createDiv({cls:"stashpad-folderpanel-heading stashpad-folderpanel-heading-row"}),c=l.createSpan({cls:"stashpad-folderpanel-heading-title stashpad-folderpanel-heading-switch",text:"Folders"});c.setAttr("aria-label","Open folder switcher"),c.onmousedown=h=>{h.button===0&&(h.preventDefault(),this.plugin.openFolderPicker())};let d=l.createEl("button",{cls:"stashpad-folderpanel-iconbtn stashpad-folderpanel-heading-newfolder"});if((0,Y.setIcon)(d,"folder-plus"),d.setAttr("aria-label","New Stashpad folder (folder switcher)"),d.onmousedown=h=>{h.button===0&&(h.preventDefault(),h.stopPropagation(),this.plugin.openFolderPicker())},this.plugin.encryption?.isConfigured?.()){let h=l.createEl("button",{cls:"stashpad-folderpanel-iconbtn stashpad-folderpanel-heading-trash"});(0,Y.setIcon)(h,"trash-2"),h.setAttr("aria-label","Open encrypted trash"),h.onmousedown=g=>{g.button===0&&(g.preventDefault(),g.stopPropagation(),this.plugin.openEncryptedTrash())}}this.renderFolders(a.createDiv({cls:"stashpad-folderpanel-list"}))}clampFrac(t){return Number.isFinite(t)?Math.max(.15,Math.min(.85,t)):.5}attachDividerDrag(t,e,i){let s=null,n=a=>{let l=t.getBoundingClientRect();if(l.height<=0)return;let c=this.clampFrac((a.clientY-l.top)/l.height);s=c,e.style.flex=`0 0 ${(c*100).toFixed(2)}%`},o=a=>{document.removeEventListener("pointermove",n),document.removeEventListener("pointerup",o),document.body.removeClass("stashpad-folderpanel-resizing");try{i.releasePointerCapture(a.pointerId)}catch{}s!=null&&(this.plugin.settings.folderPanelPinnedFraction=s,this.plugin.saveSettings())};i.addEventListener("pointerdown",a=>{a.preventDefault(),document.body.addClass("stashpad-folderpanel-resizing");try{i.setPointerCapture(a.pointerId)}catch{}document.addEventListener("pointermove",n),document.addEventListener("pointerup",o)})}openPinnedOptionsMenu(t){let e=this.plugin.settings.folderPanelPinnedGrouping??"pin-order",i=new Y.Menu;i.addItem(s=>s.setTitle("Sort by pin order").setChecked(e==="pin-order").onClick(()=>void this.setPinnedGrouping("pin-order"))),i.addItem(s=>s.setTitle("Group by folder").setChecked(e==="folder").onClick(()=>void this.setPinnedGrouping("folder"))),i.showAtMouseEvent(t)}async setPinnedGrouping(t){(this.plugin.settings.folderPanelPinnedGrouping??"pin-order")!==t&&(this.plugin.settings.folderPanelPinnedGrouping=t,await this.plugin.saveSettings(),this.render())}renderPinned(t){let e=this.plugin.discoverStashpadFolders().filter(n=>this.folderState(n)==="pinned"),i=this.plugin.listPinnedNotes();if(e.length===0&&i.length===0){t.createDiv({cls:"stashpad-folderpanel-empty",text:"Nothing pinned yet \u2014 pin a note or folder from its right-click menu."});return}if(e.length>0){let n=this.openFolders();for(let o of e)this.renderFolderRow(t,o,n)}if(i.length===0)return;if((this.plugin.settings.folderPanelPinnedGrouping??"pin-order")==="folder"){let n=new Map;i.forEach((l,c)=>{let d=n.get(l.folder);d||(d=[],n.set(l.folder,d)),d.push({...l,idx:c})});let o=this.plugin.lastActiveStashpadLeaf?.view?.noteFolder,a=Array.from(n.keys());o&&n.has(o)&&(a.splice(a.indexOf(o),1),a.unshift(o));for(let l of a){let c=t.createDiv({cls:"stashpad-pinned-group-header"});l===o&&c.addClass("is-active-folder"),c.createSpan({cls:"stashpad-pinned-group-name",text:l.split("/").pop()||l});for(let d of n.get(l)??[])this.renderPinNote(t,d.folder,d.id,d.file,d.idx)}}else i.forEach((n,o)=>this.renderPinNote(t,n.folder,n.id,n.file,o))}async reorderPin(t,e){let i=this.plugin.listPinnedNotes();if(t<0||t>=i.length)return;let s=i[t],n=i.filter((d,h)=>h!==t),o=Math.max(0,Math.min(e>t?e-1:e,n.length)),a=n[o-1],l=n[o],c;!a&&!l?c=Date.now():a?l?c=(a.pinnedAt+l.pinnedAt)/2:c=a.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()}renderPinNote(t,e,i,s,n){let o=this.app.metadataCache.getFileCache(s)?.frontmatter??{},a=typeof o.color=="string"?o.color:null,l=o.completed===!0,c=this.childrenOf(e,i),d=c.length>0,h=`${e}|${i}`,g=this.pinExpanded.has(h),u=t.createDiv({cls:"stashpad-pinned-row"});a&&(u.addClass("has-color"),u.style.setProperty("--stashpad-note-color",a)),l&&u.addClass("is-completed"),u.draggable=!0,u.dataset.pinIdx=String(n),u.addEventListener("dragstart",m=>{m.dataTransfer?.setData("text/plain",String(n)),m.dataTransfer&&(m.dataTransfer.effectAllowed="move"),u.addClass("is-dragging")}),u.addEventListener("dragend",()=>u.removeClass("is-dragging")),u.addEventListener("dragover",m=>{m.preventDefault(),m.dataTransfer&&(m.dataTransfer.dropEffect="move");let C=u.getBoundingClientRect(),B=m.clientY-C.top{u.removeClass("drop-before"),u.removeClass("drop-after")}),u.addEventListener("drop",m=>{m.preventDefault(),u.removeClass("drop-before"),u.removeClass("drop-after");let C=parseInt(m.dataTransfer?.getData("text/plain")??"",10);if(!Number.isFinite(C)||C===n)return;let B=u.getBoundingClientRect(),w=m.clientY-B.top{m.stopPropagation(),this.pinExpanded.has(h)?this.pinExpanded.delete(h):this.pinExpanded.add(h),this.render()});let f=u.createSpan({cls:"stashpad-pinned-icon"});(0,Y.setIcon)(f,d?"folder-tree":"file-text"),a&&(f.style.color=a);let I=u.createSpan({cls:"stashpad-pinned-label",text:this.titleFromFile(s)});if(I.onclick=()=>{this.onNavigateAway(),this.plugin.revealNoteInStashpad(s)},u.createSpan({cls:"stashpad-pinned-folder",text:e.split("/").pop()||e}),u.oncontextmenu=m=>{m.preventDefault();let C=new Y.Menu;C.addItem(B=>B.setTitle("Unpin from sidebar").setIcon("pin-off").onClick(()=>void this.plugin.unpinNote({folder:e,id:i}))),C.showAtMouseEvent(m)},d&&g){let m=t.createDiv({cls:"stashpad-pinned-children"});this.renderPinSubtree(m,e,i,1)}}renderPinSubtree(t,e,i,s){for(let n of this.childrenOf(e,i)){let o=this.app.metadataCache.getFileCache(n)?.frontmatter??{},a=typeof o.id=="string"?o.id:null;if(!a)continue;let l=typeof o.color=="string"?o.color:null,c=o.completed===!0,d=this.childrenOf(e,a),h=d.length>0,g=`${e}|${a}`,u=this.pinExpanded.has(g),p=t.createDiv({cls:"stashpad-pinned-subrow"});c&&p.addClass("is-completed"),p.style.paddingLeft=`${s*16}px`;let f=p.createSpan({cls:"stashpad-pinned-toggle"});h&&(Ie(f,d.length,u),f.onclick=C=>{C.stopPropagation(),this.pinExpanded.has(g)?this.pinExpanded.delete(g):this.pinExpanded.add(g),this.render()});let I=p.createSpan({cls:"stashpad-pinned-icon"});(0,Y.setIcon)(I,"file-text"),l&&(I.style.color=l);let m=p.createSpan({cls:"stashpad-pinned-label",text:this.titleFromFile(n)});m.onclick=()=>{this.onNavigateAway(),this.plugin.revealNoteInStashpad(n)},h&&u&&this.renderPinSubtree(t,e,a,s+1)}}childrenOf(t,e){let i=[];for(let s of this.app.vault.getMarkdownFiles()){if((s.parent?.path?.replace(/\/+$/,"")??"")!==t)continue;let o=this.app.metadataCache.getFileCache(s)?.frontmatter;if(!o||typeof o.id!="string")continue;let a=o.parent;if(a===e||e===k&&(a==null||a===k)){if(o.id===k)continue;i.push(s)}}return i.sort((s,n)=>{let o=this.app.metadataCache.getFileCache(s)?.frontmatter?.created??"",a=this.app.metadataCache.getFileCache(n)?.frontmatter?.created??"";return String(o).localeCompare(String(a))}),i}onNavigateAway(){Y.Platform.isMobile&&(this.plugin.suppressComposerAutofocusUntil=Date.now()+1500,this.app.workspace.leftSplit?.collapse?.())}titleFromFile(t){return t.basename.replace(/-[a-z0-9]{4,12}$/,"").replace(/-/g," ").trim()||t.basename}openFolders(){let t=new Set,e=(this.plugin.settings.folder||"Stashpad").replace(/\/+$/,"");for(let i of this.app.workspace.getLeavesOfType(q)){let s=(i.view?.noteFolder??"").replace(/\/+$/,"");s||(s=(((i.getViewState?.()?.state??{}).folderOverride??"")||e).replace(/\/+$/,"")),s&&t.add(s)}return t}static clean(t){return t.replace(/\/+$/,"")}folderState(t){let e=A.clean(t),i=this.plugin.settings;return(i.folderPanelPinned??[]).includes(e)?"pinned":(i.folderPanelDownranked??[]).includes(e)?"downranked":(i.folderPanelHidden??[]).includes(e)?"hidden":"normal"}async setFolderState(t,e){let i=A.clean(t),s=this.plugin.settings;s.folderPanelPinned=(s.folderPanelPinned??[]).filter(n=>n!==i),s.folderPanelDownranked=(s.folderPanelDownranked??[]).filter(n=>n!==i),s.folderPanelHidden=(s.folderPanelHidden??[]).filter(n=>n!==i),e==="pinned"?s.folderPanelPinned.push(i):e==="downranked"?s.folderPanelDownranked.push(i):e==="hidden"&&s.folderPanelHidden.push(i),await this.plugin.saveSettings(),this.render()}folderHomeColor(t){return this.homeColorByFolder.get(A.clean(t))??null}rebuildHomeColors(){this.homeColorByFolder.clear();for(let t of this.app.vault.getMarkdownFiles()){let e=this.app.metadataCache.getFileCache(t)?.frontmatter;if(!e||e.id!==k||typeof e.color!="string"||!e.color.trim())continue;let i=(t.parent?.path??"").replace(/\/+$/,"");i&&this.homeColorByFolder.set(i,e.color)}}renderFolders(t){let e=this.plugin.discoverStashpadFolders();if(e.length===0){t.createDiv({cls:"stashpad-folderpanel-empty",text:"No Stashpad folders yet."});return}this.rebuildHomeColors();let i=this.openFolders(),s=[],n=[],o=[],a=[];for(let c of e)switch(this.folderState(c)){case"pinned":s.push(c);break;case"downranked":o.push(c);break;case"hidden":a.push(c);break;default:n.push(c)}let l=[...s,...n,...o];if(l.length===0&&a.length===0){t.createDiv({cls:"stashpad-folderpanel-empty",text:"No Stashpad folders yet."});return}for(let c of l)this.renderFolderRow(t,c,i);a.length>0&&this.renderHiddenSection(t,a)}renderFolderRow(t,e,i){let s=this.folderState(e),n=i.has(A.clean(e)),o=t.createDiv({cls:"stashpad-folderpanel-row stashpad-folderpanel-folder-row"});n&&o.addClass("is-open"),s==="downranked"&&o.addClass("is-downranked"),s==="pinned"&&o.addClass("is-pinned");let a=o.createSpan({cls:"stashpad-folderpanel-dot"});if(a.setAttr("aria-label",n?"Open in a tab":"Not open"),n&&a.setAttr("title","Open in a tab"),s==="pinned"){let m=o.createSpan({cls:"stashpad-folderpanel-pinmark"});(0,Y.setIcon)(m,"pin"),m.setAttr("aria-label","Pinned")}let l=this.folderHomePinnedNotes(e),c=A.clean(e),d=this.folderPinExpanded.has(c);if(l.length>0){let m=o.createSpan({cls:"stashpad-folderpanel-pinreveal"});Ie(m,l.length,d),m.setAttr("aria-label",d?"Hide pinned notes":`${l.length} pinned note${l.length===1?"":"s"}`),m.addEventListener("mousedown",C=>{C.stopPropagation(),C.preventDefault()}),m.onclick=C=>{C.stopPropagation(),this.folderPinExpanded.has(c)?this.folderPinExpanded.delete(c):this.folderPinExpanded.add(c),this.render()}}let h=this.plugin.isArchiveFolder(e),g=o.createSpan({cls:"stashpad-folderpanel-folder-icon"});(0,Y.setIcon)(g,this.plugin.getFolderIcon(e)??(h?"archive":"folder")),h&&g.setAttr("aria-label","Archive folder \u2014 notes moved in are auto-encrypted");let u=this.folderHomeColor(e);u&&(g.style.color=u);let p=e.split("/").pop()||e;o.createSpan({cls:"stashpad-folderpanel-row-label",text:p});let I=o.createDiv({cls:"stashpad-folderpanel-actions"}).createEl("button",{cls:"stashpad-folderpanel-iconbtn"});if((0,Y.setIcon)(I,"plus-square"),I.setAttr("aria-label","Open in new tab"),I.onmousedown=m=>{m.button===0&&(m.preventDefault(),m.stopPropagation(),this.onNavigateAway(),this.plugin.activateViewForFolder(e))},o.addEventListener("mousedown",m=>{m.button===0&&(m.target?.closest?.(".stashpad-folderpanel-actions")||(this.onNavigateAway(),this.jumpToFolder(e)))}),o.oncontextmenu=m=>{m.preventDefault(),this.openFolderMenu(m,e)},l.length>0&&d){let m=t.createDiv({cls:"stashpad-folderpanel-pinlist"});for(let C of l){let B=m.createDiv({cls:"stashpad-folderpanel-pinrow"}),w=this.app.metadataCache.getFileCache(C)?.frontmatter??{},y=B.createSpan({cls:"stashpad-folderpanel-pinrow-icon"});(0,Y.setIcon)(y,"arrow-up-to-line"),typeof w.color=="string"&&(y.style.color=w.color),B.createSpan({cls:"stashpad-folderpanel-pinrow-label",text:this.titleFromFile(C)}),B.onclick=()=>{this.onNavigateAway(),this.plugin.revealNoteInStashpad(C)}}}}folderHomePinnedNotes(t){return this.childrenOf(t,k).filter(e=>this.app.metadataCache.getFileCache(e)?.frontmatter?.listPinned===!0)}renderHiddenSection(t,e){let i=t.createDiv({cls:"stashpad-folderpanel-hidden"}),s=i.createDiv({cls:"stashpad-folderpanel-hidden-header"}),n=s.createSpan({cls:"stashpad-folderpanel-hidden-caret"});(0,Y.setIcon)(n,"chevron-right"),s.createSpan({cls:"stashpad-folderpanel-hidden-title",text:`Hidden (${e.length})`});let o=i.createDiv({cls:"stashpad-folderpanel-hidden-body"});o.setCssStyles({display:"none"}),s.onclick=()=>{let a=o.style.display!=="none";o.setCssStyles({display:a?"none":""}),(0,Y.setIcon)(n,a?"chevron-right":"chevron-down")};for(let a of e){let l=o.createDiv({cls:"stashpad-folderpanel-row stashpad-folderpanel-hidden-row"}),c=a.split("/").pop()||a;l.createSpan({cls:"stashpad-folderpanel-row-label",text:c});let d=l.createEl("button",{cls:"stashpad-folderpanel-iconbtn"});(0,Y.setIcon)(d,"eye"),d.setAttr("aria-label","Unhide"),d.onclick=h=>{h.stopPropagation(),this.setFolderState(a,"normal")}}}jumpToFolder(t){this.plugin.openFolderInStashpad(t)}revealFolder(t){let e=this.app.vault.getAbstractFileByPath(t.replace(/\/+$/,""));if(!(e instanceof Y.TFolder)){new Y.Notice("Couldn't find that folder.");return}let i=this.app.workspace.getLeavesOfType("file-explorer")[0];if(!i){new Y.Notice("File explorer isn't available.");return}this.app.workspace.revealLeaf(i),i.view?.revealInFolder?.(e)}openFolderMenu(t,e){let i=new Y.Menu;i.addItem(n=>n.setTitle("Open in new tab").setIcon("plus-square").onClick(()=>void this.plugin.activateViewForFolder(e))),i.addItem(n=>n.setTitle("Reveal in file explorer").setIcon("folder-search").onClick(()=>this.revealFolder(e))),i.addSeparator();let s=this.folderState(e);if(i.addItem(n=>n.setTitle(s==="pinned"?"Unpin":"Pin to top").setIcon("pin").onClick(()=>void this.setFolderState(e,s==="pinned"?"normal":"pinned"))),i.addItem(n=>n.setTitle(s==="downranked"?"Remove downrank":"Downrank").setIcon("arrow-down").onClick(()=>void this.setFolderState(e,s==="downranked"?"normal":"downranked"))),i.addItem(n=>n.setTitle("Hide from list").setIcon("eye-off").onClick(()=>void this.setFolderState(e,"hidden"))),i.addSeparator(),i.addItem(n=>n.setTitle("Rename\u2026").setIcon("pencil").onClick(()=>this.renameFolder(e))),this.plugin.encryption?.isConfigured?.()){i.addSeparator(),i.addItem(a=>a.setTitle("Encrypt (lock) all notes in folder").setIcon("lock").onClick(()=>void this.plugin.lockFolder(e))),this.app.vault.getFiles().some(a=>a.extension==="stashenc"&&(a.parent?.path?.replace(/\/+$/,"")??"")===e.replace(/\/+$/,""))&&i.addItem(a=>a.setTitle("Decrypt (unlock) all notes in folder").setIcon("unlock").onClick(()=>void this.plugin.unlockFolder(e)));let n=e.replace(/\/+$/,""),o=this.plugin.isArchiveFolder(n);i.addItem(a=>a.setTitle(o?"Unmark archive folder":"Mark as archive folder\u2026").setIcon("archive").onClick(async()=>{if(o){this.plugin.settings.archiveFolders=(this.plugin.settings.archiveFolders??[]).filter(l=>l!==n),await this.plugin.saveSettings(),new Y.Notice(`"${n.split("/").pop()}" is no longer an archive folder. Existing locked notes stay locked.`,0),this.render();return}new et(this.app,`Make "${n.split("/").pop()}" an archive folder?`,["An archive folder automatically LOCKS (encrypts) any note you move into it.","","What that means in plain terms:",`\u2022 "Encrypting" scrambles the note with your encryption password so its text can't be read by anyone \u2014 or any app \u2014 without that password.`,"\u2022 The normal, readable copy is permanently removed from your vault. What's left is an unreadable, locked \u{1F512} placeholder.","\u2022 To read or edit the note again, you unlock it with your encryption password (one click on the placeholder). Then you can re-archive it later.","\u2022 If you ever lose your encryption password, the locked notes are gone for good \u2014 there is no backdoor or recovery, on purpose.",'\u2022 Notes ALREADY in this folder are not touched \u2014 only notes moved in from now on. (To lock the ones already here, use "Encrypt all notes in folder".)',"","Good for folders of things you want kept private at rest: finished or sensitive material you'd rather not have readable if someone opened your vault."].join(` `),"Make it an archive folder",async l=>{l&&(this.plugin.settings.archiveFolders=[...this.plugin.settings.archiveFolders??[],n],await this.plugin.saveSettings(),new Y.Notice(`"${n.split("/").pop()}" is now an archive folder \u2014 notes moved in will be encrypted.`,0),this.render())}).open()})),i.addItem(a=>a.setTitle("Open encrypted trash").setIcon("rotate-ccw").onClick(()=>this.plugin.openEncryptedTrash()))}i.addSeparator(),i.addItem(n=>{n.setTitle("Delete folder\u2026").setIcon("trash").onClick(()=>this.deleteFolder(e)),n.setWarning?.(!0)}),i.showAtMouseEvent(t)}renameFolder(t){let e=t.replace(/\/+$/,""),i=this.app.vault.getAbstractFileByPath(e);if(!(i instanceof Y.TFolder)){new Y.Notice("Couldn't find that folder.");return}let s=i.name;new Ro(this.app,s,async n=>{let o=n.trim().replace(/[\\/:]+/g,"").trim();if(!o||o===s)return;let l=`${i.parent?.path&&i.parent.path!=="/"?`${i.parent.path}/`:""}${o}`;if(this.app.vault.getAbstractFileByPath(l)){new Y.Notice(`"${o}" already exists.`);return}try{await this.app.fileManager.renameFile(i,l),(this.plugin.settings.folder||"").replace(/\/+$/,"")===e&&(this.plugin.settings.folder=l,await this.plugin.saveSettings()),new Y.Notice(`Renamed to "${o}".`)}catch(c){console.warn("[Stashpad] folder rename failed",c),new Y.Notice("Rename failed (see console).")}}).open()}deleteFolder(t){let e=t.replace(/\/+$/,""),i=this.app.vault.getAbstractFileByPath(e);if(!(i instanceof Y.TFolder)){new Y.Notice("Couldn't find that folder.");return}let s=this.app.vault.getMarkdownFiles().filter(o=>(o.parent?.path?.replace(/\/+$/,"")??"")===e||o.path.startsWith(e+"/")).length,n=i.name;new et(this.app,`Delete "${n}"?`,`This moves the entire folder \u2014 about ${s} note${s===1?"":"s"} plus its attachments and exports \u2014 to the trash. diff --git a/manifest.json b/manifest.json index 2005bab..7ef67b4 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "stashpad", "name": "Stashpad", - "version": "0.122.9", + "version": "0.122.10", "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 719b492..a44ecd4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "stashpad-obsidian", - "version": "0.122.9", + "version": "0.122.10", "private": true, "scripts": { "dev": "node esbuild.config.mjs", diff --git a/release-notes/0.122.10.md b/release-notes/0.122.10.md new file mode 100644 index 0000000..6d72d39 --- /dev/null +++ b/release-notes/0.122.10.md @@ -0,0 +1,13 @@ +# 0.122.10 + +A focused follow-up to 0.122.9. + +- **Due-date / assign modal — time picker focus.** Clicking the clock to open the + numpad time picker no longer drops the cursor into the date field. The picker + popover is now hosted inside the modal (it previously lived in the document + body, outside the modal's focusable area, so the modal pulled focus back to its + first field), and the hour field is focused once the modal's own focus handling + settles. The search When-builder's time picker was already correct and is + unchanged. +- **Note context menu order.** "Copy text" now sits above "Clone (duplicate / + copy)". diff --git a/src/modals.ts b/src/modals.ts index 605b93d..e227b8c 100644 --- a/src/modals.ts +++ b/src/modals.ts @@ -1756,7 +1756,16 @@ export class DueDatePickerModal extends Modal { const period: "am" | "pm" = h24 >= 12 ? "pm" : "am"; const seedH = h24 === 0 ? 12 : (h24 > 12 ? h24 - 12 : h24); - const pop = doc.body.createDiv({ cls: "stashpad-when-popover stashpad-due-time-pop" }); + // 0.122.10: host the popover INSIDE the modal element, not doc.body. When + // it lived in body (outside the modal's focusable subtree) the modal's + // focus management pulled focus back to the first field (the date input) + // the instant the time picker focused its hour field — so clicking the + // clock landed you in the date box. Keeping it inside modalEl mirrors the + // search When-builder (whose picker is hosted in its own focusable region) + // and lets the hour field keep focus. position:fixed still anchors to the + // viewport. Falls back to doc.body if modalEl is somehow unavailable. + const host = (this.modalEl as HTMLElement | undefined) ?? doc.body; + const pop = host.createDiv({ cls: "stashpad-when-popover stashpad-due-time-pop" }); // Above the modal (Obsidian modals sit ~var(--layer-modal)). pop.setCssStyles({ position: "fixed", zIndex: "9999" }); @@ -1793,6 +1802,9 @@ export class DueDatePickerModal extends Modal { setTimeout(() => { doc.addEventListener("mousedown", outside, true); doc.addEventListener("keydown", onKey, true); + // 0.122.10: re-assert focus on the hour field after the modal's own + // focus handling has settled, so the picker opens ready for numeric entry. + pop.querySelector(".stashpad-when-time-field")?.focus(); }, 0); } diff --git a/src/view.ts b/src/view.ts index 76c2fd3..6d0b75a 100644 --- a/src/view.ts +++ b/src/view.ts @@ -11219,14 +11219,15 @@ export class StashpadView extends ItemView { menu.addItem((it: any) => it.setTitle("Focus in Stashpad").setIcon("arrow-right").onClick(() => this.navigateTo(node.id))); menu.addSeparator(); menu.addItem((it: any) => it.setTitle("Split note…").setIcon("split").onClick(() => void this.cmdSplit(node))); + // 0.122.2 (#9): copy the note's text. `focusClicked` (defined below) + // normalises selection to the right-clicked row. + // 0.122.10: ordered above Clone so the plain "Copy text" reads first. + menu.addItem((it: any) => it.setTitle("Copy text").setIcon("copy").onClick(() => { focusClicked(); void this.cmdCopy(); })); menu.addItem((it: any) => it.setTitle("Clone (duplicate / copy)").setIcon("files").onClick(() => { // Operate on the right-clicked row even if it isn't selected. if (!this.selection.has(node.id)) { this.selection.clear(); this.selection.add(node.id); this.lastSelected = node.id; } void this.cmdClone(); })); - // 0.122.2 (#9): copy the note's text, or cut the whole note (for paste/move). - // `focusClicked` (defined below) normalises selection to the right-clicked row. - menu.addItem((it: any) => it.setTitle("Copy text").setIcon("copy").onClick(() => { focusClicked(); void this.cmdCopy(); })); // 0.122.7: "Cut note" pulled from the menu for now — cut/paste has known bugs // and cutting a parent/home note from the context menu is too easy a footgun. // Still available via the cutNotes hotkey. (See ui-polish todos.)