From 2e8ac7047faef9b520c497649edad7ea6c345360 Mon Sep 17 00:00:00 2001 From: Olivier Legendre Date: Wed, 10 Jun 2026 21:45:16 -0400 Subject: [PATCH] =?UTF-8?q?refactor:=20simplify=20bookmark=20menus=20?= =?UTF-8?q?=E2=80=94=20visible=20=E2=8B=AF=20button,=20flat=20context=20me?= =?UTF-8?q?nus?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Header: - Replace hidden right-click with visible ⋯ button (more-horizontal icon) - Menu: Add current file / Add as parent note / New group / separator / Add spacer File bookmark right-click (5 items, flat): Open in new tab / Rename / Change icon / Remove Group/parent note right-click (7 items max, flat): Open in new tab (only if linked) / Rename / Change icon / Expand|Collapse / Add child bookmark / Add child note / New sub-group / Remove Separator/Spacer right-click (1 item): Remove Removed dead code: insertAdjacent, collectGroups, collectDescendantIds, moveBookmarkToGroup — all moving is now drag-and-drop only --- main.js | 18 ++-- src/views/waypoint-view.ts | 202 +++++++++++-------------------------- styles.css | 22 ++++ todo.md | 2 + 4 files changed, 93 insertions(+), 151 deletions(-) diff --git a/main.js b/main.js index 0926c52..200a60f 100644 --- a/main.js +++ b/main.js @@ -2,15 +2,15 @@ THIS IS A GENERATED/BUNDLED FILE BY ESBUILD */ -var $=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var H=Object.getOwnPropertyNames;var _=Object.prototype.hasOwnProperty;var U=(v,p)=>{for(var a in p)$(v,a,{get:p[a],enumerable:!0})},K=(v,p,a,t)=>{if(p&&typeof p=="object"||typeof p=="function")for(let n of H(p))!_.call(v,n)&&n!==a&&$(v,n,{get:()=>p[n],enumerable:!(t=z(p,n))||t.enumerable});return v};var X=v=>K($({},"__esModule",{value:!0}),v);var ee={};U(ee,{default:()=>R});module.exports=X(ee);var u=require("obsidian");var j={calendar:{firstDayOfWeek:1,showNoteIndicators:!0},daily:{folder:"periodic/daily",templateFile:"Templates/Daily note",nameFormat:"YYYY-MM-DD",typeProperty:"daily-note"},weekly:{folder:"periodic/weekly",templateFile:"Templates/Weekly note",nameFormat:"GGGG-[W]WW",typeProperty:"weekly-note"},monthly:{folder:"periodic/monthly",templateFile:"Templates/Monthly note",nameFormat:"YYYY-MM",typeProperty:"monthly-note"},quarterly:{folder:"periodic/quarterly",templateFile:"Templates/Quarterly note",nameFormat:"YYYY-[Q]Q",typeProperty:"quarterly-note"},yearly:{folder:"periodic/yearly",templateFile:"Templates/Yearly note",nameFormat:"YYYY",typeProperty:"yearly-note"},recentFiles:{maxItems:50,updateOn:"file-open",omittedPaths:[],omittedTags:[]}};var g=require("obsidian"),W=class extends g.PluginSettingTab{constructor(p,a,t,n){super(p,a),this.plugin=a,this.settings=t,this.onSettingsChange=n}display(){let{containerEl:p}=this;p.empty(),new g.Setting(p).setHeading().setName("Calendar"),new g.Setting(p).setName("First day of week").setDesc("Which day the calendar week starts on.").addDropdown(n=>{n.addOption("0","Sunday").addOption("1","Monday").setValue(String(this.settings.calendar.firstDayOfWeek)).onChange(s=>{this.settings.calendar.firstDayOfWeek=parseInt(s,10),this.saveAndRefresh()})}),new g.Setting(p).setName("Show note indicators").setDesc("Show a dot on days that have existing notes.").addToggle(n=>{n.setValue(this.settings.calendar.showNoteIndicators).onChange(s=>{this.settings.calendar.showNoteIndicators=s,this.saveAndRefresh()})}),new g.Setting(p).setHeading().setName("Periodic Note Paths"),this.addPeriodNoteSettings("Daily",this.settings.daily),this.addPeriodNoteSettings("Weekly",this.settings.weekly),this.addPeriodNoteSettings("Monthly",this.settings.monthly),this.addPeriodNoteSettings("Quarterly",this.settings.quarterly),this.addPeriodNoteSettings("Yearly",this.settings.yearly),new g.Setting(p).setHeading().setName("Recent Files"),new g.Setting(p).setName("Max items").setDesc("Maximum number of recent files to track.").addText(n=>{n.inputEl.setAttr("type","number"),n.inputEl.setAttr("placeholder","50"),n.setValue(String(this.settings.recentFiles.maxItems)),n.inputEl.onblur=()=>{let s=parseInt(n.getValue(),10);!isNaN(s)&&s>0&&(this.settings.recentFiles.maxItems=s,this.saveAndRefresh())}}),new g.Setting(p).setName("Update on").setDesc("When to add a file to the recent list.").addDropdown(n=>{n.addOption("file-open","File opened").addOption("file-edit","File changed").setValue(this.settings.recentFiles.updateOn).onChange(s=>{this.settings.recentFiles.updateOn=s,this.saveAndRefresh()})});let a=new DocumentFragment;a.appendText("Regex patterns for paths to exclude. One per line."),new g.Setting(p).setName("Omitted paths").setDesc(a).addTextArea(n=>{n.inputEl.setAttr("rows",4),n.setPlaceholder(`^archives/ -\\.png$`),n.setValue(this.settings.recentFiles.omittedPaths.join(` -`)),n.inputEl.onblur=()=>{this.settings.recentFiles.omittedPaths=n.getValue().split(` -`).filter(s=>s.trim()),this.saveAndRefresh()}});let t=new DocumentFragment;t.appendText("Regex patterns for frontmatter tags to exclude. One per line."),new g.Setting(p).setName("Omitted tags").setDesc(t).addTextArea(n=>{n.inputEl.setAttr("rows",4),n.setPlaceholder(`ignore -archive`),n.setValue(this.settings.recentFiles.omittedTags.join(` -`)),n.inputEl.onblur=()=>{this.settings.recentFiles.omittedTags=n.getValue().split(` -`).filter(s=>s.trim()),this.saveAndRefresh()}})}addPeriodNoteSettings(p,a){new g.Setting(this.containerEl).setHeading().setName(p),new g.Setting(this.containerEl).setName("Folder").setDesc(`Folder path for ${p.toLowerCase()} notes.`).addText(t=>{t.setPlaceholder("periodic/daily"),t.setValue(a.folder),t.onChange(n=>{a.folder=n,this.saveAndRefresh()})}),new g.Setting(this.containerEl).setName("Name format").setDesc(`Date format for ${p.toLowerCase()} note filenames (moment.js format).`).addText(t=>{t.setPlaceholder("yyyy-MM-dd"),t.setValue(a.nameFormat),t.onChange(n=>{a.nameFormat=n,this.saveAndRefresh()})}),new g.Setting(this.containerEl).setName("Template file").setDesc("Path to the template file (without .md extension).").addText(t=>{t.setPlaceholder("Templates/Daily note"),t.setValue(a.templateFile),t.onChange(n=>{a.templateFile=n,this.saveAndRefresh()})}),new g.Setting(this.containerEl).setName("Type property").setDesc("Value for the 'type' frontmatter property.").addText(t=>{t.setPlaceholder("daily-note"),t.setValue(a.typeProperty),t.onChange(n=>{a.typeProperty=n,this.saveAndRefresh()})})}async saveAndRefresh(){await this.plugin.saveData(this.settings),this.onSettingsChange()}};var h=require("obsidian");var T=require("obsidian");function Q(v,p,a){let t=(0,T.moment)({year:v,month:p,day:1}),n=(0,T.moment)(t).endOf("month"),s=(0,T.moment)(t).subtract((t.day()-a+7)%7,"days"),e=(0,T.moment)().startOf("day"),r=[],i=(0,T.moment)(s);for(;i.isBefore(n)||i.month()===p;){let o=[];for(let l=0;l<7;l++)o.push({date:(0,T.moment)(i),dayOfMonth:i.date(),isToday:i.isSame(e,"day"),isCurrentMonth:i.month()===p,isoWeekNumber:i.isoWeek()}),i.add(1,"day");if(r.push({weekNumber:o[0].isoWeekNumber,days:o}),r.length>=6)break}return r}var I="waypoint-view",Y=class extends h.ItemView{constructor(a,t){super(a);this.redraw=()=>{this.contentEl.empty(),this.contentEl.addClass("waypoint-view"),this.renderFavorites(),this.renderRecentFiles(),this.renderCalendar()};this.currentDisplayMonth=(0,h.moment)().month();this.currentDisplayYear=(0,h.moment)().year();this.dragId=null;this.plugin=t}getViewType(){return I}getDisplayText(){return"Waypoint"}getIcon(){return"compass"}async onOpen(){this.redraw()}async onClose(){}renderCalendar(){let a=this.contentEl.createDiv({cls:"waypoint-section"});a.createDiv({cls:"waypoint-section-header",text:"Calendar"});let t=a.createDiv({cls:"waypoint-calendar"}),n=(0,h.moment)(),s=(0,h.moment)({year:this.currentDisplayYear,month:this.currentDisplayMonth,day:1}),e=t.createDiv({cls:"waypoint-calendar-top"}),r=e.createDiv({cls:"waypoint-calendar-breadcrumb"}),i=s.format("[Q]Q");r.createSpan({cls:"waypoint-clickable",text:i}).addEventListener("click",()=>{this.plugin.openPeriodNote("quarter",s)});let l=s.format("MMMM");r.createSpan({cls:"waypoint-clickable",text:l}).addEventListener("click",()=>{this.plugin.openPeriodNote("month",s)});let d=s.format("YYYY");r.createSpan({cls:"waypoint-clickable",text:d}).addEventListener("click",()=>{this.plugin.openPeriodNote("year",s)});let k=e.createDiv({cls:"waypoint-calendar-today-group"}),x=k.createEl("button",{cls:"waypoint-calendar-nav-btn"});(0,h.setIcon)(x,"chevron-left"),x.addEventListener("click",()=>this.navigateMonth(-1)),k.createEl("button",{cls:"waypoint-calendar-today-btn",text:"Today"}).addEventListener("click",()=>{this.currentDisplayMonth=(0,h.moment)().month(),this.currentDisplayYear=(0,h.moment)().year(),this.redraw()});let M=k.createEl("button",{cls:"waypoint-calendar-nav-btn"});(0,h.setIcon)(M,"chevron-right"),M.addEventListener("click",()=>this.navigateMonth(1));let P=t.createEl("table"),E=P.createEl("thead").createEl("tr");E.createEl("th",{text:""});let f=["sun","mon","tue","wed","thu","fri","sat"],B=this.plugin.settings.calendar.firstDayOfWeek;for(let y=0;y<7;y++){let L=(B+y)%7;E.createEl("th",{text:f[L]})}let w=P.createEl("tbody"),b=Q(this.currentDisplayYear,this.currentDisplayMonth,this.plugin.settings.calendar.firstDayOfWeek);for(let y of b){let L=w.createEl("tr"),N=L.createEl("td",{cls:"waypoint-weeknum"});N.setText(String(y.weekNumber)),N.addEventListener("click",()=>{let D=y.days[0].date;this.plugin.openPeriodNote("week",D)});for(let D of y.days){let C=L.createEl("td",{cls:"waypoint-day"});if(C.setText(String(D.dayOfMonth)),D.isCurrentMonth||C.addClass("other-month"),D.isToday&&C.addClass("today"),this.plugin.settings.calendar.showNoteIndicators){let O=D.date.format("YYYY-MM-DD");this.plugin.app.vault.getFiles().some(V=>V.extension==="md"&&V.basename===O)&&C.addClass("has-note")}C.addEventListener("click",()=>{this.plugin.openPeriodNote("day",D.date)})}}}navigateMonth(a){let t=(0,h.moment)({year:this.currentDisplayYear,month:this.currentDisplayMonth}).add(a,"month");this.currentDisplayMonth=t.month(),this.currentDisplayYear=t.year(),this.redraw()}renderRecentFiles(){let a=this.contentEl.createDiv({cls:"waypoint-section waypoint-recent-files"});if(a.createDiv({cls:"waypoint-section-header",text:"Recent Files"}),this.plugin.recentFiles.length===0){a.createDiv({cls:"nav-file",text:"No recent files"});return}let t=this.app.workspace.getActiveFile(),n=a.createDiv({cls:"nav-folder mod-root"}),s=n.createDiv({cls:"nav-folder-children"});for(let e of this.plugin.recentFiles){let r=s.createDiv({cls:"tree-item nav-file"}),i=r.createDiv({cls:"tree-item-self is-clickable nav-file-title"});i.createDiv({cls:"tree-item-inner nav-file-title-content"}).setText(e.basename);let l=i.createDiv({cls:"tree-item-spacer"}),c=i.createDiv({cls:"waypoint-recent-remove"});(0,h.setIcon)(c,"x"),c.addEventListener("click",d=>{d.stopPropagation(),this.plugin.recentFiles=this.plugin.recentFiles.filter(m=>m.path!==e.path),this.plugin.saveSettings(),this.redraw()}),(0,h.setTooltip)(r,e.path),t&&e.path===t.path&&i.addClass("is-active"),i.setAttr("draggable","true"),i.addEventListener("dragstart",d=>{let m=this.app.metadataCache.getFirstLinkpathDest(e.path,"");m&&(this.app.dragManager.dragFile(d,m),this.app.dragManager.onDragStart(d,this.app.dragManager.dragFile(d,m)))}),i.addEventListener("mouseover",d=>{this.app.workspace.trigger("hover-link",{event:d,source:I,hoverParent:n,targetEl:r,linktext:e.path})}),i.addEventListener("contextmenu",d=>{let m=new h.Menu;m.addItem(x=>x.setSection("action").setTitle("Open in new tab").setIcon("file-plus").onClick(()=>this.focusFile(e,"tab")));let k=this.app.vault.getAbstractFileByPath(e.path);k&&this.app.workspace.trigger("file-menu",m,k,"link-context-menu"),m.showAtPosition({x:d.clientX,y:d.clientY})}),i.addEventListener("click",d=>{let m=h.Keymap.isModEvent(d);this.focusFile(e,m)}),i.addEventListener("mousedown",d=>{d.button===1&&(d.preventDefault(),this.focusFile(e,"tab"))})}}focusFile(a,t){let n=this.app.vault.getFiles().find(s=>s.path===a.path);n?this.app.workspace.getLeaf(t).openFile(n):(new h.Notice("Cannot find file"),this.plugin.recentFiles=this.plugin.recentFiles.filter(s=>s.path!==a.path),this.plugin.saveSettings(),this.redraw())}renderFavorites(){let a=this.contentEl.createDiv({cls:"waypoint-section waypoint-favorites"}),t=a.createDiv({cls:"waypoint-section-header"});if(t.setText("Waypoint Bookmarks"),t.addEventListener("contextmenu",n=>{let s=new h.Menu;s.addItem(e=>{e.setTitle("Add current file").setIcon("file-plus").onClick(()=>{let r=this.app.workspace.getActiveFile();r&&this.plugin.addBookmark(r.path,r.basename,"file")})}),s.addItem(e=>{e.setTitle("Add as parent note").setIcon("folder-plus").onClick(()=>{let r=this.app.workspace.getActiveFile();if(!r)return;let i=this.plugin.addBookmark(r.path,r.basename,"group","");i.filePath=r.path,this.plugin.saveWaypointData(),this.redraw()})}),s.addItem(e=>{e.setTitle("New group").setIcon("folder-plus").onClick(()=>{this.plugin.addBookmark("","New Group","group","")})}),s.addItem(e=>{e.setTitle("Add separator").setIcon("minus").onClick(()=>{this.plugin.addBookmark("","","separator")})}),s.addItem(e=>{e.setTitle("Add spacer").setIcon("space").onClick(()=>{this.plugin.addBookmark("","","spacer")})}),s.showAtPosition({x:n.clientX,y:n.clientY})}),this.plugin.waypointData.bookmarks.length===0){a.createDiv({cls:"waypoint-bookmark-item",text:"No bookmarks"});return}this.renderBookmarkList(a,this.plugin.waypointData.bookmarks,0)}renderBookmarkList(a,t,n){for(let s=0;s{this.dragId=e.id,l.dataTransfer.effectAllowed="move",l.dataTransfer.setData("text/plain",e.id),o.addClass("waypoint-bm-dragging")}),o.addEventListener("dragend",()=>{this.dragId=null,a.querySelectorAll(".waypoint-bm-dragging, .waypoint-bm-drop-line, .waypoint-bm-drop-below").forEach(l=>{l.removeClass("waypoint-bm-dragging"),l.removeClass("waypoint-bm-drop-line"),l.removeClass("waypoint-bm-drop-below")})}),o.addEventListener("dragenter",l=>{l.preventDefault(),!(!this.dragId||this.dragId===e.id)&&this.showDropIndicator(o,l)}),o.addEventListener("dragover",l=>{l.preventDefault(),!(!this.dragId||this.dragId===e.id)&&this.showDropIndicator(o,l)}),o.addEventListener("dragleave",()=>{o.removeClass("waypoint-bm-drop-line"),o.removeClass("waypoint-bm-drop-below")}),o.addEventListener("drop",l=>{var m;l.preventDefault(),this.dragId=null,o.removeClass("waypoint-bm-drop-line"),o.removeClass("waypoint-bm-drop-below");let c=(m=l.dataTransfer)==null?void 0:m.getData("text/plain");if(!c||c===e.id)return;let d=o.__dropAbove;this.moveBookmarkToPosition(c,e.id,d)}),o.addEventListener("contextmenu",l=>{l.stopPropagation(),l.preventDefault(),this.showBookmarkContextMenu(l,e)});continue}if(e.type==="spacer"){let o=a.createDiv({cls:"waypoint-bookmark-item waypoint-bookmark-spacer"});o.setAttr("draggable","true"),o.setAttr("data-bm-id",e.id),o.style.paddingLeft=`${8+n*16}px`,o.style.cursor="grab",o.addEventListener("dragstart",l=>{this.dragId=e.id,l.dataTransfer.effectAllowed="move",l.dataTransfer.setData("text/plain",e.id),o.addClass("waypoint-bm-dragging")}),o.addEventListener("dragend",()=>{this.dragId=null,a.querySelectorAll(".waypoint-bm-dragging, .waypoint-bm-drop-line, .waypoint-bm-drop-below").forEach(l=>{l.removeClass("waypoint-bm-dragging"),l.removeClass("waypoint-bm-drop-line"),l.removeClass("waypoint-bm-drop-below")})}),o.addEventListener("dragenter",l=>{l.preventDefault(),!(!this.dragId||this.dragId===e.id)&&this.showDropIndicator(o,l)}),o.addEventListener("dragover",l=>{l.preventDefault(),!(!this.dragId||this.dragId===e.id)&&this.showDropIndicator(o,l)}),o.addEventListener("dragleave",()=>{o.removeClass("waypoint-bm-drop-line"),o.removeClass("waypoint-bm-drop-below")}),o.addEventListener("drop",l=>{var m;l.preventDefault(),this.dragId=null,o.removeClass("waypoint-bm-drop-line"),o.removeClass("waypoint-bm-drop-below");let c=(m=l.dataTransfer)==null?void 0:m.getData("text/plain");if(!c||c===e.id)return;let d=o.__dropAbove;this.moveBookmarkToPosition(c,e.id,d)}),o.addEventListener("contextmenu",l=>{l.stopPropagation(),l.preventDefault(),this.showBookmarkContextMenu(l,e)});continue}let r=e.type==="group",i=a.createDiv({cls:`waypoint-bookmark-item${r?" waypoint-bookmark-group":""}${e.collapsed?" collapsed":""}`});if(i.setAttr("draggable","true"),i.setAttr("data-bm-id",e.id),r||(i.style.paddingLeft=`${8+n*16}px`),i.addEventListener("dragstart",o=>{this.dragId=e.id,o.dataTransfer.effectAllowed="move",o.dataTransfer.setData("text/plain",e.id),i.addClass("waypoint-bm-dragging")}),i.addEventListener("dragend",()=>{this.dragId=null,a.querySelectorAll(".waypoint-bm-dragging, .waypoint-bm-drop-line, .waypoint-bm-drop-below").forEach(o=>{o.removeClass("waypoint-bm-dragging"),o.removeClass("waypoint-bm-drop-line"),o.removeClass("waypoint-bm-drop-below")})}),i.addEventListener("dragenter",o=>{o.preventDefault(),!(!this.dragId||this.dragId===e.id)&&this.showDropIndicator(i,o)}),i.addEventListener("dragover",o=>{o.preventDefault(),!(!this.dragId||this.dragId===e.id)&&this.showDropIndicator(i,o)}),i.addEventListener("dragleave",()=>{i.removeClass("waypoint-bm-drop-line"),i.removeClass("waypoint-bm-drop-below")}),i.addEventListener("drop",o=>{var d;o.preventDefault(),this.dragId=null,i.removeClass("waypoint-bm-drop-line"),i.removeClass("waypoint-bm-drop-below");let l=(d=o.dataTransfer)==null?void 0:d.getData("text/plain");if(!l||l===e.id)return;let c=i.__dropAbove;this.moveBookmarkToPosition(l,e.id,c)}),r){let o=i.createDiv({cls:"waypoint-bm-chevron"});(0,h.setIcon)(o,"chevron-down"),o.addEventListener("click",m=>{m.stopPropagation(),this.plugin.updateBookmark(e.id,{collapsed:!e.collapsed})});let l=i.createDiv({cls:"waypoint-bm-icon"});e.icon&&(0,h.setIcon)(l,e.icon);let c=i.createDiv({cls:"waypoint-bm-label",text:e.label});i.addEventListener("click",m=>{if(e.filePath){let k=this.app.vault.getFileByPath(e.filePath);if(k){let x=h.Keymap.isModEvent(m);this.app.workspace.getLeaf(x).openFile(k);return}}this.plugin.updateBookmark(e.id,{collapsed:!e.collapsed})}),i.addEventListener("mousedown",m=>{if(m.button===1&&e.filePath){m.preventDefault();let k=this.app.vault.getFileByPath(e.filePath);k&&this.app.workspace.getLeaf("tab").openFile(k)}});let d=a.createDiv({cls:`waypoint-bookmark-children${e.collapsed?" collapsed":""}`});e.children&&e.children.length>0&&this.renderBookmarkList(d,e.children,n+1)}else{if(e.children&&e.children.length>0){let c=i.createDiv({cls:"waypoint-bm-chevron"});(0,h.setIcon)(c,"chevron-down"),c.addEventListener("click",d=>{d.stopPropagation(),this.plugin.updateBookmark(e.id,{collapsed:!e.collapsed})}),e.collapsed&&(i.addClass("collapsed"),c.style.transform="rotate(-90deg)")}let o=i.createDiv({cls:"waypoint-bm-icon"});e.icon&&(0,h.setIcon)(o,e.icon);let l=i.createDiv({cls:"waypoint-bm-label",text:e.label});if((0,h.setTooltip)(i,e.filePath),i.addEventListener("click",c=>{if(e.filePath){let d=this.app.vault.getFileByPath(e.filePath);if(d){let m=h.Keymap.isModEvent(c);this.app.workspace.getLeaf(m).openFile(d)}else new h.Notice("File not found"),this.plugin.removeBookmark(e.id)}}),i.addEventListener("mousedown",c=>{if(c.button===1&&e.filePath){c.preventDefault();let d=this.app.vault.getFileByPath(e.filePath);d&&this.app.workspace.getLeaf("tab").openFile(d)}}),e.children&&e.children.length>0){let c=a.createDiv({cls:`waypoint-bookmark-children${e.collapsed?" collapsed":""}`});this.renderBookmarkList(c,e.children,n+1)}}i.addEventListener("contextmenu",o=>{o.stopPropagation(),o.preventDefault(),this.showBookmarkContextMenu(o,e)})}}showBookmarkContextMenu(a,t){let n=new h.Menu;t.type==="file"&&(n.addItem(i=>i.setTitle("Open in new tab").setIcon("file-plus").onClick(()=>{let o=this.app.vault.getFileByPath(t.filePath);o&&this.app.workspace.getLeaf("tab").openFile(o)})),n.addSeparator()),t.type!=="separator"&&t.type!=="spacer"&&(n.addItem(i=>i.setTitle("Rename").setIcon("pencil").onClick(()=>this.promptRename(t))),n.addItem(i=>i.setTitle("Change icon").setIcon("image").onClick(()=>this.promptIcon(t))));let s=this.collectGroups(this.plugin.waypointData.bookmarks),e=this.collectDescendantIds(t),r=s.filter(i=>!e.includes(i.id)&&i.id!==t.id);if((r.length>0||t.type==="file"||t.type==="group")&&t.type!=="separator"&&t.type!=="spacer"){if(n.addSeparator(),r.length>0)for(let i of r)n.addItem(o=>o.setTitle(` ${i.label}`).setIcon(i.icon||"folder").onClick(()=>{this.moveBookmarkToGroup(t.id,i.id)}));n.addItem(i=>i.setTitle(" (Root)").setIcon("layout").onClick(()=>{this.moveBookmarkToGroup(t.id,null)}))}t.type==="group"&&(n.addItem(i=>i.setTitle(t.collapsed?"Expand":"Collapse").setIcon(t.collapsed?"chevron-down":"chevron-up").onClick(()=>{this.plugin.updateBookmark(t.id,{collapsed:!t.collapsed})})),n.addSeparator(),n.addItem(i=>i.setTitle("Add bookmark here").setIcon("file-plus").onClick(()=>{let o=this.app.workspace.getActiveFile();if(!o){new h.Notice("No active file");return}let l={id:`bm-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:"file",label:o.basename,filePath:o.path,icon:"",children:[],collapsed:!1,indent:t.indent+1};t.children.push(l),this.plugin.saveWaypointData(),this.redraw()})),n.addItem(i=>i.setTitle("Add child note").setIcon("file-plus").onClick(()=>{let o=this.app.workspace.getActiveFile();if(!o){new h.Notice("No active file");return}let l={id:`bm-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:"group",label:o.basename,filePath:o.path,icon:"",children:[],collapsed:!1,indent:t.indent+1};t.children.push(l),this.plugin.saveWaypointData(),this.redraw()})),n.addItem(i=>i.setTitle("New sub-group").setIcon("folder-plus").onClick(()=>{let o={id:`bm-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:"group",label:"New Group",filePath:"",icon:"",children:[],collapsed:!1,indent:t.indent+1};t.children.push(o),this.plugin.saveWaypointData(),this.redraw()}))),n.addSeparator(),n.addItem(i=>i.setTitle("Insert separator above").setIcon("separator-vertical").onClick(()=>this.insertAdjacent(t.id,"separator","above"))),n.addItem(i=>i.setTitle("Insert separator below").setIcon("separator-vertical").onClick(()=>this.insertAdjacent(t.id,"separator","below"))),n.addItem(i=>i.setTitle("Insert spacer above").setIcon("space").onClick(()=>this.insertAdjacent(t.id,"spacer","above"))),n.addItem(i=>i.setTitle("Insert spacer below").setIcon("space").onClick(()=>this.insertAdjacent(t.id,"spacer","below"))),n.addSeparator(),n.addItem(i=>i.setTitle("Remove").setIcon("trash").onClick(()=>{this.plugin.removeBookmark(t.id)})),n.showAtPosition({x:a.clientX,y:a.clientY})}insertAdjacent(a,t,n){let s={id:`bm-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:t,label:"",filePath:"",icon:"",children:[],collapsed:!1,indent:0},e=r=>{let i=r.findIndex(o=>o.id===a);if(i>=0){let o=n==="above"?i:i+1;return r.splice(o,0,s),!0}for(let o of r)if(o.children&&e(o.children))return!0;return!1};e(this.plugin.waypointData.bookmarks),this.plugin.saveWaypointData(),this.redraw()}collectGroups(a){let t=[];for(let n of a)n.type==="group"&&(t.push(n),t.push(...this.collectGroups(n.children)));return t}collectDescendantIds(a){let t=[];for(let n of a.children)t.push(n.id),t.push(...this.collectDescendantIds(n));return t}showDropIndicator(a,t){let n=a.parentElement;n&&n.querySelectorAll(".waypoint-bm-drop-line, .waypoint-bm-drop-below").forEach(i=>{i.removeClass("waypoint-bm-drop-line"),i.removeClass("waypoint-bm-drop-below")});let s=a.getBoundingClientRect(),e=s.top+s.height/2,r=t.clientY{let r=e.findIndex(i=>i.id===a);if(r>=0){let[i]=e.splice(r,1);return i}for(let i of e){let o=n(i.children);if(o)return o}return null},s=n(this.plugin.waypointData.bookmarks);if(s){if(t){let e=i=>{for(let o of i){if(o.id===t)return o;let l=e(o.children);if(l)return l}return null},r=e(this.plugin.waypointData.bookmarks);r&&(s.indent=r.indent+1,r.children.push(s))}else s.indent=0,this.plugin.waypointData.bookmarks.push(s);this.plugin.saveWaypointData(),this.redraw()}}moveBookmarkToPosition(a,t,n){let s=o=>{let l=o.findIndex(c=>c.id===a);if(l>=0){let[c]=o.splice(l,1);return{item:c,parent:o}}for(let c of o)if(c.children){let d=s(c.children);if(d.item)return d}return{item:null,parent:[]}},{item:e}=s(this.plugin.waypointData.bookmarks);if(!e)return;let r=o=>{let l=o.findIndex(c=>c.id===t);if(l>=0)return{parent:o,idx:l};for(let c of o)if(c.children){let d=r(c.children);if(d)return d}return null},i=r(this.plugin.waypointData.bookmarks);if(!i)e.indent=0,this.plugin.waypointData.bookmarks.push(e);else{let o=n?i.idx:i.idx+1;i.parent.splice(o,0,e)}this.plugin.saveWaypointData(),this.redraw()}promptRename(a){new q(this.app,a.label,t=>{t&&t.trim()&&this.plugin.updateBookmark(a.id,{label:t.trim()})}).open()}promptIcon(a){new G(this.app,a.icon,t=>{t&&this.plugin.updateBookmark(a.id,{icon:t})}).open()}},q=class extends h.Modal{constructor(p,a,t){super(p),this.currentValue=a,this.onSubmit=t}onOpen(){this.titleEl.setText("Rename bookmark");let p=this.contentEl.createEl("input",{type:"text",value:this.currentValue});p.style.width="100%",p.style.marginBottom="12px",p.focus(),p.select();let a=this.contentEl.createDiv({cls:"modal-button-container"}),t=a.createEl("button",{text:"Cancel",cls:"mod-cta"});t.style.marginRight="8px",t.addEventListener("click",()=>this.close()),a.createEl("button",{text:"Save",cls:"mod-cta"}).addEventListener("click",()=>{this.onSubmit(p.value),this.close()}),p.addEventListener("keydown",s=>{s.key==="Enter"&&(this.onSubmit(p.value),this.close())})}onClose(){this.contentEl.empty()}},G=class extends h.Modal{constructor(a,t,n){super(a);this.allIcons=[];this.tagsMap={};this.loaded=!1;this.selected=t,this.onSubmit=n}async onOpen(){let a=this.contentEl;a.style.display="flex",a.style.flexDirection="column",a.style.gap="10px",this.titleEl.setText("Change icon");let t=a.createDiv({cls:"waypoint-icon-preview"});t.style.display="flex",t.style.alignItems="center",t.style.gap="10px",t.style.padding="12px 16px",t.style.borderRadius="8px",t.style.background="var(--background-secondary)",t.style.minHeight="48px";let n=t.createSpan();n.style.display="flex",this.selected&&(0,h.setIcon)(n,this.selected);let s=t.createSpan();s.style.fontWeight="var(--font-medium)",s.style.fontSize="var(--font-ui-medium)",s.setText(this.selected||"No icon");let e=a.createEl("input",{type:"text",placeholder:"Type to search (e.g. arrow, chart, home)..."});Object.assign(e.style,{width:"100%",boxSizing:"border-box",padding:"8px 10px",borderRadius:"6px",border:"1px solid var(--background-modifier-border)",background:"var(--background-primary)",color:"var(--text-normal)",fontSize:"var(--font-ui-medium)"}),e.focus();let r=a.createDiv({cls:"waypoint-icon-grid"});r.style.display="grid",r.style.gridTemplateColumns="repeat(auto-fill, minmax(52px, 1fr))",r.style.gap="4px",r.style.maxHeight="320px",r.style.overflowY="auto",r.style.padding="2px 0";let i=a.createDiv();i.style.display="flex",i.style.justifyContent="space-between",i.style.alignItems="center",i.style.fontSize="var(--font-ui-smaller)",i.style.color="var(--text-muted)",i.style.padding="0 4px";let o=i.createSpan();o.setText("Loading\u2026");let l=i.createSpan();l.style.cursor="var(--cursor)",l.style.color="var(--text-accent)",l.setText("No icon"),l.addEventListener("click",()=>{this.onSubmit(""),this.close()}),this.loadIcons().then(()=>{this.loaded=!0,o.setText(this.allIcons.length+" icons"),d(e.value)});let c=null,d=F=>{if(r.empty(),!this.loaded){r.createDiv({text:"Loading\u2026"});return}let M=F.toLowerCase().trim(),P=M?this.allIcons.filter(w=>{if(w.includes(M))return!0;let b=this.tagsMap[w];return b?b.some(y=>y.includes(M)):!1}).slice(0,80):this.allIcons.slice(0,80);if(P.length===0){let w=r.createDiv();w.style.gridColumn="1 / -1",w.style.textAlign="center",w.style.color="var(--text-muted)",w.style.padding="20px",w.setText('No icons match "'+F+'"');return}for(var A=0;Anew Y(e,this)),this.addSettingTab(new W(this.app,this,this.settings,()=>this.redrawAll())),this.addCommand({id:"waypoint-open-view",name:"Open Waypoint sidebar",callback:async()=>{let e=this.app.workspace.getLeavesOfType(I);if(e.length>0)await this.app.workspace.revealLeaf(e[0]);else{let r=this.app.workspace.getLeftLeaf(!1);r&&(await r.setViewState({type:I}),await this.app.workspace.revealLeaf(r))}}}),this.addCommand({id:"waypoint-add-bookmark",name:"Add current file as Waypoint bookmark",callback:async()=>{let e=this.app.workspace.getActiveFile();if(!e){new u.Notice("No active file");return}this.addBookmark(e.path,e.basename,"file"),new u.Notice(`Bookmarked: ${e.basename}`)}}),this.addCommand({id:"waypoint-go-to-daily",name:"Go to daily note",hotkeys:[{modifiers:["Mod","Shift","Alt"],key:"d"}],callback:async()=>{await this.openPeriodNote("day",(0,u.moment)())}}),this.addCommand({id:"waypoint-go-to-weekly",name:"Go to weekly note",hotkeys:[{modifiers:["Mod","Shift","Alt"],key:"w"}],callback:async()=>{await this.openPeriodNote("week",(0,u.moment)())}}),this.addCommand({id:"waypoint-go-to-monthly",name:"Go to monthly note",hotkeys:[{modifiers:["Mod","Shift","Alt"],key:"m"}],callback:async()=>{await this.openPeriodNote("month",(0,u.moment)())}}),this.addCommand({id:"waypoint-go-to-quarterly",name:"Go to quarterly note",hotkeys:[{modifiers:["Mod","Shift","Alt"],key:"q"}],callback:async()=>{await this.openPeriodNote("quarter",(0,u.moment)())}}),this.addCommand({id:"waypoint-go-to-yearly",name:"Go to yearly note",hotkeys:[{modifiers:["Mod","Shift","Alt"],key:"y"}],callback:async()=>{await this.openPeriodNote("year",(0,u.moment)())}});let a=["next","prev"],t=["daily","weekly","monthly","quarterly","yearly"],n={next:"Next",prev:"Previous"};for(let e of t)for(let r of a){let i=`waypoint-go-to-${r}-${e}`,o=`${n[r]} ${e} note`;this.addCommand({id:i,name:o,callback:async()=>{await this.navigatePeriodNote(r)}})}this.registerEvent(this.app.workspace.on("file-open",e=>{e&&this.onFileOpen(e)})),this.registerEvent(this.app.vault.on("create",()=>this.onVaultChange())),this.registerEvent(this.app.vault.on("delete",()=>this.onVaultChange())),this.registerEvent(this.app.vault.on("rename",(e,r)=>this.onRename(e,r))),this.app.workspace.onLayoutReady(()=>{if(this.app.workspace.getLeavesOfType(I).length===0){let r=this.app.workspace.getLeftLeaf(!1);r&&r.setViewState({type:I})}});let s=new Date().toDateString();this.registerInterval(window.setInterval(()=>{let e=new Date().toDateString();e!==s&&(s=e,this.redrawAll())},6e5))}async onunload(){this.app.workspace.detachLeavesOfType(I)}async loadSettings(){let a=await this.loadData(),t=(a==null?void 0:a.settings)||{};this.settings=Object.assign({},j,t)}async saveSettings(){let a=await this.loadData()||{};a.settings=this.settings,await this.saveData(a)}async loadWaypointData(){let a=await this.loadData(),t=(a==null?void 0:a.waypointData)||{};this.waypointData=Object.assign({},Z,t)}async saveWaypointData(){let a=await this.loadData()||{};a.waypointData=this.waypointData,await this.saveData(a)}onFileOpen(a){this.settings.recentFiles.updateOn!=="file-edit"&&this.addToRecentFiles(a)}addToRecentFiles(a){this.recentFiles=this.recentFiles.filter(t=>t.path!==a.path),this.recentFiles.unshift({path:a.path,basename:a.basename}),this.recentFiles.length>this.settings.recentFiles.maxItems&&(this.recentFiles=this.recentFiles.slice(0,this.settings.recentFiles.maxItems)),this.broadcastRedraw()}onRename(a,t){let n=this.recentFiles.find(s=>s.path===t);n&&(n.path=a.path,n.basename=a.basename||a.name.replace(/\.[^/.]+$/,""),this.broadcastRedraw()),this.updateBookmarkPath(t,a.path)}onVaultChange(){this.broadcastRedraw()}addBookmark(a,t,n="file",s=""){let r={id:`bm-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:n,label:t,filePath:n==="file"?a:"",icon:s,children:[],collapsed:!1,indent:0};return this.waypointData.bookmarks.push(r),this.saveWaypointData(),this.broadcastRedraw(),r}removeBookmark(a){let t=n=>{let s=n.findIndex(e=>e.id===a);if(s>=0)return n.splice(s,1),!0;for(let e of n)if(e.children&&t(e.children))return!0;return!1};t(this.waypointData.bookmarks),this.saveWaypointData(),this.broadcastRedraw()}updateBookmark(a,t){let n=e=>{for(let r of e){if(r.id===a)return r;if(r.children){let i=n(r.children);if(i)return i}}return null},s=n(this.waypointData.bookmarks);s&&(Object.assign(s,t),this.saveWaypointData(),this.broadcastRedraw())}updateBookmarkPath(a,t){let n=s=>{for(let e of s)e.filePath===a&&(e.filePath=t),e.children&&n(e.children)};n(this.waypointData.bookmarks)}async openPeriodNote(a,t){let s={day:{settings:this.settings.daily,label:"Daily"},week:{settings:this.settings.weekly,label:"Weekly"},month:{settings:this.settings.monthly,label:"Monthly"},quarter:{settings:this.settings.quarterly,label:"Quarterly"},year:{settings:this.settings.yearly,label:"Yearly"}}[a];if(!s)return;let{settings:e}=s,r=t.format(e.nameFormat)+".md",i=e.folder?`${e.folder}/${r}`:r,o=this.app.vault.getFileByPath(i);if(!o){try{let l=e.templateFile+".md",c=this.app.vault.getFileByPath(l);if(c){let d=await this.app.vault.read(c);o=await this.app.vault.create(i,d)}else{let d=`--- +var $=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var H=Object.getOwnPropertyNames;var _=Object.prototype.hasOwnProperty;var U=(v,p)=>{for(var t in p)$(v,t,{get:p[t],enumerable:!0})},X=(v,p,t,a)=>{if(p&&typeof p=="object"||typeof p=="function")for(let i of H(p))!_.call(v,i)&&i!==t&&$(v,i,{get:()=>p[i],enumerable:!(a=z(p,i))||a.enumerable});return v};var K=v=>X($({},"__esModule",{value:!0}),v);var ee={};U(ee,{default:()=>R});module.exports=K(ee);var u=require("obsidian");var Q={calendar:{firstDayOfWeek:1,showNoteIndicators:!0},daily:{folder:"periodic/daily",templateFile:"Templates/Daily note",nameFormat:"YYYY-MM-DD",typeProperty:"daily-note"},weekly:{folder:"periodic/weekly",templateFile:"Templates/Weekly note",nameFormat:"GGGG-[W]WW",typeProperty:"weekly-note"},monthly:{folder:"periodic/monthly",templateFile:"Templates/Monthly note",nameFormat:"YYYY-MM",typeProperty:"monthly-note"},quarterly:{folder:"periodic/quarterly",templateFile:"Templates/Quarterly note",nameFormat:"YYYY-[Q]Q",typeProperty:"quarterly-note"},yearly:{folder:"periodic/yearly",templateFile:"Templates/Yearly note",nameFormat:"YYYY",typeProperty:"yearly-note"},recentFiles:{maxItems:50,updateOn:"file-open",omittedPaths:[],omittedTags:[]}};var g=require("obsidian"),W=class extends g.PluginSettingTab{constructor(p,t,a,i){super(p,t),this.plugin=t,this.settings=a,this.onSettingsChange=i}display(){let{containerEl:p}=this;p.empty(),new g.Setting(p).setHeading().setName("Calendar"),new g.Setting(p).setName("First day of week").setDesc("Which day the calendar week starts on.").addDropdown(i=>{i.addOption("0","Sunday").addOption("1","Monday").setValue(String(this.settings.calendar.firstDayOfWeek)).onChange(n=>{this.settings.calendar.firstDayOfWeek=parseInt(n,10),this.saveAndRefresh()})}),new g.Setting(p).setName("Show note indicators").setDesc("Show a dot on days that have existing notes.").addToggle(i=>{i.setValue(this.settings.calendar.showNoteIndicators).onChange(n=>{this.settings.calendar.showNoteIndicators=n,this.saveAndRefresh()})}),new g.Setting(p).setHeading().setName("Periodic Note Paths"),this.addPeriodNoteSettings("Daily",this.settings.daily),this.addPeriodNoteSettings("Weekly",this.settings.weekly),this.addPeriodNoteSettings("Monthly",this.settings.monthly),this.addPeriodNoteSettings("Quarterly",this.settings.quarterly),this.addPeriodNoteSettings("Yearly",this.settings.yearly),new g.Setting(p).setHeading().setName("Recent Files"),new g.Setting(p).setName("Max items").setDesc("Maximum number of recent files to track.").addText(i=>{i.inputEl.setAttr("type","number"),i.inputEl.setAttr("placeholder","50"),i.setValue(String(this.settings.recentFiles.maxItems)),i.inputEl.onblur=()=>{let n=parseInt(i.getValue(),10);!isNaN(n)&&n>0&&(this.settings.recentFiles.maxItems=n,this.saveAndRefresh())}}),new g.Setting(p).setName("Update on").setDesc("When to add a file to the recent list.").addDropdown(i=>{i.addOption("file-open","File opened").addOption("file-edit","File changed").setValue(this.settings.recentFiles.updateOn).onChange(n=>{this.settings.recentFiles.updateOn=n,this.saveAndRefresh()})});let t=new DocumentFragment;t.appendText("Regex patterns for paths to exclude. One per line."),new g.Setting(p).setName("Omitted paths").setDesc(t).addTextArea(i=>{i.inputEl.setAttr("rows",4),i.setPlaceholder(`^archives/ +\\.png$`),i.setValue(this.settings.recentFiles.omittedPaths.join(` +`)),i.inputEl.onblur=()=>{this.settings.recentFiles.omittedPaths=i.getValue().split(` +`).filter(n=>n.trim()),this.saveAndRefresh()}});let a=new DocumentFragment;a.appendText("Regex patterns for frontmatter tags to exclude. One per line."),new g.Setting(p).setName("Omitted tags").setDesc(a).addTextArea(i=>{i.inputEl.setAttr("rows",4),i.setPlaceholder(`ignore +archive`),i.setValue(this.settings.recentFiles.omittedTags.join(` +`)),i.inputEl.onblur=()=>{this.settings.recentFiles.omittedTags=i.getValue().split(` +`).filter(n=>n.trim()),this.saveAndRefresh()}})}addPeriodNoteSettings(p,t){new g.Setting(this.containerEl).setHeading().setName(p),new g.Setting(this.containerEl).setName("Folder").setDesc(`Folder path for ${p.toLowerCase()} notes.`).addText(a=>{a.setPlaceholder("periodic/daily"),a.setValue(t.folder),a.onChange(i=>{t.folder=i,this.saveAndRefresh()})}),new g.Setting(this.containerEl).setName("Name format").setDesc(`Date format for ${p.toLowerCase()} note filenames (moment.js format).`).addText(a=>{a.setPlaceholder("yyyy-MM-dd"),a.setValue(t.nameFormat),a.onChange(i=>{t.nameFormat=i,this.saveAndRefresh()})}),new g.Setting(this.containerEl).setName("Template file").setDesc("Path to the template file (without .md extension).").addText(a=>{a.setPlaceholder("Templates/Daily note"),a.setValue(t.templateFile),a.onChange(i=>{t.templateFile=i,this.saveAndRefresh()})}),new g.Setting(this.containerEl).setName("Type property").setDesc("Value for the 'type' frontmatter property.").addText(a=>{a.setPlaceholder("daily-note"),a.setValue(t.typeProperty),a.onChange(i=>{t.typeProperty=i,this.saveAndRefresh()})})}async saveAndRefresh(){await this.plugin.saveData(this.settings),this.onSettingsChange()}};var h=require("obsidian");var F=require("obsidian");function j(v,p,t){let a=(0,F.moment)({year:v,month:p,day:1}),i=(0,F.moment)(a).endOf("month"),n=(0,F.moment)(a).subtract((a.day()-t+7)%7,"days"),e=(0,F.moment)().startOf("day"),r=[],s=(0,F.moment)(n);for(;s.isBefore(i)||s.month()===p;){let o=[];for(let l=0;l<7;l++)o.push({date:(0,F.moment)(s),dayOfMonth:s.date(),isToday:s.isSame(e,"day"),isCurrentMonth:s.month()===p,isoWeekNumber:s.isoWeek()}),s.add(1,"day");if(r.push({weekNumber:o[0].isoWeekNumber,days:o}),r.length>=6)break}return r}var E="waypoint-view",Y=class extends h.ItemView{constructor(t,a){super(t);this.redraw=()=>{this.contentEl.empty(),this.contentEl.addClass("waypoint-view"),this.renderFavorites(),this.renderRecentFiles(),this.renderCalendar()};this.currentDisplayMonth=(0,h.moment)().month();this.currentDisplayYear=(0,h.moment)().year();this.dragId=null;this.plugin=a}getViewType(){return E}getDisplayText(){return"Waypoint"}getIcon(){return"compass"}async onOpen(){this.redraw()}async onClose(){}renderCalendar(){let t=this.contentEl.createDiv({cls:"waypoint-section"});t.createDiv({cls:"waypoint-section-header",text:"Calendar"});let a=t.createDiv({cls:"waypoint-calendar"}),i=(0,h.moment)(),n=(0,h.moment)({year:this.currentDisplayYear,month:this.currentDisplayMonth,day:1}),e=a.createDiv({cls:"waypoint-calendar-top"}),r=e.createDiv({cls:"waypoint-calendar-breadcrumb"}),s=n.format("[Q]Q");r.createSpan({cls:"waypoint-clickable",text:s}).addEventListener("click",()=>{this.plugin.openPeriodNote("quarter",n)});let l=n.format("MMMM");r.createSpan({cls:"waypoint-clickable",text:l}).addEventListener("click",()=>{this.plugin.openPeriodNote("month",n)});let d=n.format("YYYY");r.createSpan({cls:"waypoint-clickable",text:d}).addEventListener("click",()=>{this.plugin.openPeriodNote("year",n)});let w=e.createDiv({cls:"waypoint-calendar-today-group"}),x=w.createEl("button",{cls:"waypoint-calendar-nav-btn"});(0,h.setIcon)(x,"chevron-left"),x.addEventListener("click",()=>this.navigateMonth(-1)),w.createEl("button",{cls:"waypoint-calendar-today-btn",text:"Today"}).addEventListener("click",()=>{this.currentDisplayMonth=(0,h.moment)().month(),this.currentDisplayYear=(0,h.moment)().year(),this.redraw()});let L=w.createEl("button",{cls:"waypoint-calendar-nav-btn"});(0,h.setIcon)(L,"chevron-right"),L.addEventListener("click",()=>this.navigateMonth(1));let P=a.createEl("table"),I=P.createEl("thead").createEl("tr");I.createEl("th",{text:""});let f=["sun","mon","tue","wed","thu","fri","sat"],N=this.plugin.settings.calendar.firstDayOfWeek;for(let y=0;y<7;y++){let M=(N+y)%7;I.createEl("th",{text:f[M]})}let k=P.createEl("tbody"),b=j(this.currentDisplayYear,this.currentDisplayMonth,this.plugin.settings.calendar.firstDayOfWeek);for(let y of b){let M=k.createEl("tr"),B=M.createEl("td",{cls:"waypoint-weeknum"});B.setText(String(y.weekNumber)),B.addEventListener("click",()=>{let D=y.days[0].date;this.plugin.openPeriodNote("week",D)});for(let D of y.days){let C=M.createEl("td",{cls:"waypoint-day"});if(C.setText(String(D.dayOfMonth)),D.isCurrentMonth||C.addClass("other-month"),D.isToday&&C.addClass("today"),this.plugin.settings.calendar.showNoteIndicators){let O=D.date.format("YYYY-MM-DD");this.plugin.app.vault.getFiles().some(G=>G.extension==="md"&&G.basename===O)&&C.addClass("has-note")}C.addEventListener("click",()=>{this.plugin.openPeriodNote("day",D.date)})}}}navigateMonth(t){let a=(0,h.moment)({year:this.currentDisplayYear,month:this.currentDisplayMonth}).add(t,"month");this.currentDisplayMonth=a.month(),this.currentDisplayYear=a.year(),this.redraw()}renderRecentFiles(){let t=this.contentEl.createDiv({cls:"waypoint-section waypoint-recent-files"});if(t.createDiv({cls:"waypoint-section-header",text:"Recent Files"}),this.plugin.recentFiles.length===0){t.createDiv({cls:"nav-file",text:"No recent files"});return}let a=this.app.workspace.getActiveFile(),i=t.createDiv({cls:"nav-folder mod-root"}),n=i.createDiv({cls:"nav-folder-children"});for(let e of this.plugin.recentFiles){let r=n.createDiv({cls:"tree-item nav-file"}),s=r.createDiv({cls:"tree-item-self is-clickable nav-file-title"});s.createDiv({cls:"tree-item-inner nav-file-title-content"}).setText(e.basename);let l=s.createDiv({cls:"tree-item-spacer"}),c=s.createDiv({cls:"waypoint-recent-remove"});(0,h.setIcon)(c,"x"),c.addEventListener("click",d=>{d.stopPropagation(),this.plugin.recentFiles=this.plugin.recentFiles.filter(m=>m.path!==e.path),this.plugin.saveSettings(),this.redraw()}),(0,h.setTooltip)(r,e.path),a&&e.path===a.path&&s.addClass("is-active"),s.setAttr("draggable","true"),s.addEventListener("dragstart",d=>{let m=this.app.metadataCache.getFirstLinkpathDest(e.path,"");m&&(this.app.dragManager.dragFile(d,m),this.app.dragManager.onDragStart(d,this.app.dragManager.dragFile(d,m)))}),s.addEventListener("mouseover",d=>{this.app.workspace.trigger("hover-link",{event:d,source:E,hoverParent:i,targetEl:r,linktext:e.path})}),s.addEventListener("contextmenu",d=>{let m=new h.Menu;m.addItem(x=>x.setSection("action").setTitle("Open in new tab").setIcon("file-plus").onClick(()=>this.focusFile(e,"tab")));let w=this.app.vault.getAbstractFileByPath(e.path);w&&this.app.workspace.trigger("file-menu",m,w,"link-context-menu"),m.showAtPosition({x:d.clientX,y:d.clientY})}),s.addEventListener("click",d=>{let m=h.Keymap.isModEvent(d);this.focusFile(e,m)}),s.addEventListener("mousedown",d=>{d.button===1&&(d.preventDefault(),this.focusFile(e,"tab"))})}}focusFile(t,a){let i=this.app.vault.getFiles().find(n=>n.path===t.path);i?this.app.workspace.getLeaf(a).openFile(i):(new h.Notice("Cannot find file"),this.plugin.recentFiles=this.plugin.recentFiles.filter(n=>n.path!==t.path),this.plugin.saveSettings(),this.redraw())}renderFavorites(){let t=this.contentEl.createDiv({cls:"waypoint-section waypoint-favorites"}),a=t.createDiv({cls:"waypoint-section-header"});a.setText("Waypoint Bookmarks");let i=a.createEl("button",{cls:"waypoint-header-more"});if((0,h.setIcon)(i,"more-horizontal"),(0,h.setTooltip)(i,"Add bookmark"),i.addEventListener("click",n=>{let e=new h.Menu;e.addItem(r=>{r.setTitle("Add current file").setIcon("file-plus").onClick(()=>{let s=this.app.workspace.getActiveFile();s&&this.plugin.addBookmark(s.path,s.basename,"file")})}),e.addItem(r=>{r.setTitle("Add as parent note").setIcon("folder-plus").onClick(()=>{let s=this.app.workspace.getActiveFile();if(!s)return;let o=this.plugin.addBookmark(s.path,s.basename,"group","");o.filePath=s.path,this.plugin.saveWaypointData(),this.redraw()})}),e.addItem(r=>{r.setTitle("New group").setIcon("folder-plus").onClick(()=>{this.plugin.addBookmark("","New Group","group","")})}),e.addSeparator(),e.addItem(r=>{r.setTitle("Add separator").setIcon("minus").onClick(()=>{this.plugin.addBookmark("","","separator")})}),e.addItem(r=>{r.setTitle("Add spacer").setIcon("space").onClick(()=>{this.plugin.addBookmark("","","spacer")})}),e.showAtPosition({x:n.clientX,y:n.clientY})}),this.plugin.waypointData.bookmarks.length===0){t.createDiv({cls:"waypoint-bookmark-item",text:"No bookmarks"});return}this.renderBookmarkList(t,this.plugin.waypointData.bookmarks,0)}renderBookmarkList(t,a,i){for(let n=0;n{this.dragId=e.id,l.dataTransfer.effectAllowed="move",l.dataTransfer.setData("text/plain",e.id),o.addClass("waypoint-bm-dragging")}),o.addEventListener("dragend",()=>{this.dragId=null,t.querySelectorAll(".waypoint-bm-dragging, .waypoint-bm-drop-line, .waypoint-bm-drop-below").forEach(l=>{l.removeClass("waypoint-bm-dragging"),l.removeClass("waypoint-bm-drop-line"),l.removeClass("waypoint-bm-drop-below")})}),o.addEventListener("dragenter",l=>{l.preventDefault(),!(!this.dragId||this.dragId===e.id)&&this.showDropIndicator(o,l)}),o.addEventListener("dragover",l=>{l.preventDefault(),!(!this.dragId||this.dragId===e.id)&&this.showDropIndicator(o,l)}),o.addEventListener("dragleave",()=>{o.removeClass("waypoint-bm-drop-line"),o.removeClass("waypoint-bm-drop-below")}),o.addEventListener("drop",l=>{var m;l.preventDefault(),this.dragId=null,o.removeClass("waypoint-bm-drop-line"),o.removeClass("waypoint-bm-drop-below");let c=(m=l.dataTransfer)==null?void 0:m.getData("text/plain");if(!c||c===e.id)return;let d=o.__dropAbove;this.moveBookmarkToPosition(c,e.id,d)}),o.addEventListener("contextmenu",l=>{l.stopPropagation(),l.preventDefault(),this.showBookmarkContextMenu(l,e)});continue}if(e.type==="spacer"){let o=t.createDiv({cls:"waypoint-bookmark-item waypoint-bookmark-spacer"});o.setAttr("draggable","true"),o.setAttr("data-bm-id",e.id),o.style.paddingLeft=`${8+i*16}px`,o.style.cursor="grab",o.addEventListener("dragstart",l=>{this.dragId=e.id,l.dataTransfer.effectAllowed="move",l.dataTransfer.setData("text/plain",e.id),o.addClass("waypoint-bm-dragging")}),o.addEventListener("dragend",()=>{this.dragId=null,t.querySelectorAll(".waypoint-bm-dragging, .waypoint-bm-drop-line, .waypoint-bm-drop-below").forEach(l=>{l.removeClass("waypoint-bm-dragging"),l.removeClass("waypoint-bm-drop-line"),l.removeClass("waypoint-bm-drop-below")})}),o.addEventListener("dragenter",l=>{l.preventDefault(),!(!this.dragId||this.dragId===e.id)&&this.showDropIndicator(o,l)}),o.addEventListener("dragover",l=>{l.preventDefault(),!(!this.dragId||this.dragId===e.id)&&this.showDropIndicator(o,l)}),o.addEventListener("dragleave",()=>{o.removeClass("waypoint-bm-drop-line"),o.removeClass("waypoint-bm-drop-below")}),o.addEventListener("drop",l=>{var m;l.preventDefault(),this.dragId=null,o.removeClass("waypoint-bm-drop-line"),o.removeClass("waypoint-bm-drop-below");let c=(m=l.dataTransfer)==null?void 0:m.getData("text/plain");if(!c||c===e.id)return;let d=o.__dropAbove;this.moveBookmarkToPosition(c,e.id,d)}),o.addEventListener("contextmenu",l=>{l.stopPropagation(),l.preventDefault(),this.showBookmarkContextMenu(l,e)});continue}let r=e.type==="group",s=t.createDiv({cls:`waypoint-bookmark-item${r?" waypoint-bookmark-group":""}${e.collapsed?" collapsed":""}`});if(s.setAttr("draggable","true"),s.setAttr("data-bm-id",e.id),r||(s.style.paddingLeft=`${8+i*16}px`),s.addEventListener("dragstart",o=>{this.dragId=e.id,o.dataTransfer.effectAllowed="move",o.dataTransfer.setData("text/plain",e.id),s.addClass("waypoint-bm-dragging")}),s.addEventListener("dragend",()=>{this.dragId=null,t.querySelectorAll(".waypoint-bm-dragging, .waypoint-bm-drop-line, .waypoint-bm-drop-below").forEach(o=>{o.removeClass("waypoint-bm-dragging"),o.removeClass("waypoint-bm-drop-line"),o.removeClass("waypoint-bm-drop-below")})}),s.addEventListener("dragenter",o=>{o.preventDefault(),!(!this.dragId||this.dragId===e.id)&&this.showDropIndicator(s,o)}),s.addEventListener("dragover",o=>{o.preventDefault(),!(!this.dragId||this.dragId===e.id)&&this.showDropIndicator(s,o)}),s.addEventListener("dragleave",()=>{s.removeClass("waypoint-bm-drop-line"),s.removeClass("waypoint-bm-drop-below")}),s.addEventListener("drop",o=>{var d;o.preventDefault(),this.dragId=null,s.removeClass("waypoint-bm-drop-line"),s.removeClass("waypoint-bm-drop-below");let l=(d=o.dataTransfer)==null?void 0:d.getData("text/plain");if(!l||l===e.id)return;let c=s.__dropAbove;this.moveBookmarkToPosition(l,e.id,c)}),r){let o=s.createDiv({cls:"waypoint-bm-chevron"});(0,h.setIcon)(o,"chevron-down"),o.addEventListener("click",m=>{m.stopPropagation(),this.plugin.updateBookmark(e.id,{collapsed:!e.collapsed})});let l=s.createDiv({cls:"waypoint-bm-icon"});e.icon&&(0,h.setIcon)(l,e.icon);let c=s.createDiv({cls:"waypoint-bm-label",text:e.label});s.addEventListener("click",m=>{if(e.filePath){let w=this.app.vault.getFileByPath(e.filePath);if(w){let x=h.Keymap.isModEvent(m);this.app.workspace.getLeaf(x).openFile(w);return}}this.plugin.updateBookmark(e.id,{collapsed:!e.collapsed})}),s.addEventListener("mousedown",m=>{if(m.button===1&&e.filePath){m.preventDefault();let w=this.app.vault.getFileByPath(e.filePath);w&&this.app.workspace.getLeaf("tab").openFile(w)}});let d=t.createDiv({cls:`waypoint-bookmark-children${e.collapsed?" collapsed":""}`});e.children&&e.children.length>0&&this.renderBookmarkList(d,e.children,i+1)}else{if(e.children&&e.children.length>0){let c=s.createDiv({cls:"waypoint-bm-chevron"});(0,h.setIcon)(c,"chevron-down"),c.addEventListener("click",d=>{d.stopPropagation(),this.plugin.updateBookmark(e.id,{collapsed:!e.collapsed})}),e.collapsed&&(s.addClass("collapsed"),c.style.transform="rotate(-90deg)")}let o=s.createDiv({cls:"waypoint-bm-icon"});e.icon&&(0,h.setIcon)(o,e.icon);let l=s.createDiv({cls:"waypoint-bm-label",text:e.label});if((0,h.setTooltip)(s,e.filePath),s.addEventListener("click",c=>{if(e.filePath){let d=this.app.vault.getFileByPath(e.filePath);if(d){let m=h.Keymap.isModEvent(c);this.app.workspace.getLeaf(m).openFile(d)}else new h.Notice("File not found"),this.plugin.removeBookmark(e.id)}}),s.addEventListener("mousedown",c=>{if(c.button===1&&e.filePath){c.preventDefault();let d=this.app.vault.getFileByPath(e.filePath);d&&this.app.workspace.getLeaf("tab").openFile(d)}}),e.children&&e.children.length>0){let c=t.createDiv({cls:`waypoint-bookmark-children${e.collapsed?" collapsed":""}`});this.renderBookmarkList(c,e.children,i+1)}}s.addEventListener("contextmenu",o=>{o.stopPropagation(),o.preventDefault(),this.showBookmarkContextMenu(o,e)})}}showBookmarkContextMenu(t,a){let i=new h.Menu;if(a.type==="separator"||a.type==="spacer"){i.addItem(n=>n.setTitle("Remove").setIcon("trash").onClick(()=>this.plugin.removeBookmark(a.id))),i.showAtPosition({x:t.clientX,y:t.clientY});return}a.type==="file"?(i.addItem(n=>n.setTitle("Open in new tab").setIcon("file-plus").onClick(()=>{let e=this.app.vault.getFileByPath(a.filePath);e&&this.app.workspace.getLeaf("tab").openFile(e)})),i.addSeparator(),i.addItem(n=>n.setTitle("Rename").setIcon("pencil").onClick(()=>this.promptRename(a))),i.addItem(n=>n.setTitle("Change icon").setIcon("image").onClick(()=>this.promptIcon(a))),i.addSeparator(),i.addItem(n=>n.setTitle("Remove").setIcon("trash").onClick(()=>this.plugin.removeBookmark(a.id)))):a.type==="group"&&(a.filePath&&(i.addItem(n=>n.setTitle("Open in new tab").setIcon("file-plus").onClick(()=>{let e=this.app.vault.getFileByPath(a.filePath);e&&this.app.workspace.getLeaf("tab").openFile(e)})),i.addSeparator()),i.addItem(n=>n.setTitle("Rename").setIcon("pencil").onClick(()=>this.promptRename(a))),i.addItem(n=>n.setTitle("Change icon").setIcon("image").onClick(()=>this.promptIcon(a))),i.addItem(n=>n.setTitle(a.collapsed?"Expand":"Collapse").setIcon(a.collapsed?"chevron-down":"chevron-up").onClick(()=>this.plugin.updateBookmark(a.id,{collapsed:!a.collapsed}))),i.addSeparator(),i.addItem(n=>n.setTitle("Add child bookmark").setIcon("file-plus").onClick(()=>{let e=this.app.workspace.getActiveFile();if(!e){new h.Notice("No active file");return}let r={id:`bm-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:"file",label:e.basename,filePath:e.path,icon:"",children:[],collapsed:!1,indent:a.indent+1};a.children.push(r),this.plugin.saveWaypointData(),this.redraw()})),i.addItem(n=>n.setTitle("Add child note").setIcon("folder-plus").onClick(()=>{let e=this.app.workspace.getActiveFile();if(!e){new h.Notice("No active file");return}let r={id:`bm-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:"group",label:e.basename,filePath:e.path,icon:"",children:[],collapsed:!1,indent:a.indent+1};a.children.push(r),this.plugin.saveWaypointData(),this.redraw()})),i.addItem(n=>n.setTitle("New sub-group").setIcon("folder-plus").onClick(()=>{let e={id:`bm-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:"group",label:"New Group",filePath:"",icon:"",children:[],collapsed:!1,indent:a.indent+1};a.children.push(e),this.plugin.saveWaypointData(),this.redraw()})),i.addSeparator(),i.addItem(n=>n.setTitle("Remove").setIcon("trash").onClick(()=>this.plugin.removeBookmark(a.id)))),i.showAtPosition({x:t.clientX,y:t.clientY})}showDropIndicator(t,a){let i=t.parentElement;i&&i.querySelectorAll(".waypoint-bm-drop-line, .waypoint-bm-drop-below").forEach(s=>{s.removeClass("waypoint-bm-drop-line"),s.removeClass("waypoint-bm-drop-below")});let n=t.getBoundingClientRect(),e=n.top+n.height/2,r=a.clientY{let r=e.findIndex(s=>s.id===t);if(r>=0){let[s]=e.splice(r,1);return s}for(let s of e){let o=i(s.children);if(o)return o}return null},n=i(this.plugin.waypointData.bookmarks);if(n){if(a){let e=s=>{for(let o of s){if(o.id===a)return o;let l=e(o.children);if(l)return l}return null},r=e(this.plugin.waypointData.bookmarks);r&&(n.indent=r.indent+1,r.children.push(n))}else n.indent=0,this.plugin.waypointData.bookmarks.push(n);this.plugin.saveWaypointData(),this.redraw()}}moveBookmarkToPosition(t,a,i){let n=o=>{let l=o.findIndex(c=>c.id===t);if(l>=0){let[c]=o.splice(l,1);return{item:c,parent:o}}for(let c of o)if(c.children){let d=n(c.children);if(d.item)return d}return{item:null,parent:[]}},{item:e}=n(this.plugin.waypointData.bookmarks);if(!e)return;let r=o=>{let l=o.findIndex(c=>c.id===a);if(l>=0)return{parent:o,idx:l};for(let c of o)if(c.children){let d=r(c.children);if(d)return d}return null},s=r(this.plugin.waypointData.bookmarks);if(!s)e.indent=0,this.plugin.waypointData.bookmarks.push(e);else{let o=i?s.idx:s.idx+1;s.parent.splice(o,0,e)}this.plugin.saveWaypointData(),this.redraw()}promptRename(t){new q(this.app,t.label,a=>{a&&a.trim()&&this.plugin.updateBookmark(t.id,{label:a.trim()})}).open()}promptIcon(t){new V(this.app,t.icon,a=>{a&&this.plugin.updateBookmark(t.id,{icon:a})}).open()}},q=class extends h.Modal{constructor(p,t,a){super(p),this.currentValue=t,this.onSubmit=a}onOpen(){this.titleEl.setText("Rename bookmark");let p=this.contentEl.createEl("input",{type:"text",value:this.currentValue});p.style.width="100%",p.style.marginBottom="12px",p.focus(),p.select();let t=this.contentEl.createDiv({cls:"modal-button-container"}),a=t.createEl("button",{text:"Cancel",cls:"mod-cta"});a.style.marginRight="8px",a.addEventListener("click",()=>this.close()),t.createEl("button",{text:"Save",cls:"mod-cta"}).addEventListener("click",()=>{this.onSubmit(p.value),this.close()}),p.addEventListener("keydown",n=>{n.key==="Enter"&&(this.onSubmit(p.value),this.close())})}onClose(){this.contentEl.empty()}},V=class extends h.Modal{constructor(t,a,i){super(t);this.allIcons=[];this.tagsMap={};this.loaded=!1;this.selected=a,this.onSubmit=i}async onOpen(){let t=this.contentEl;t.style.display="flex",t.style.flexDirection="column",t.style.gap="10px",this.titleEl.setText("Change icon");let a=t.createDiv({cls:"waypoint-icon-preview"});a.style.display="flex",a.style.alignItems="center",a.style.gap="10px",a.style.padding="12px 16px",a.style.borderRadius="8px",a.style.background="var(--background-secondary)",a.style.minHeight="48px";let i=a.createSpan();i.style.display="flex",this.selected&&(0,h.setIcon)(i,this.selected);let n=a.createSpan();n.style.fontWeight="var(--font-medium)",n.style.fontSize="var(--font-ui-medium)",n.setText(this.selected||"No icon");let e=t.createEl("input",{type:"text",placeholder:"Type to search (e.g. arrow, chart, home)..."});Object.assign(e.style,{width:"100%",boxSizing:"border-box",padding:"8px 10px",borderRadius:"6px",border:"1px solid var(--background-modifier-border)",background:"var(--background-primary)",color:"var(--text-normal)",fontSize:"var(--font-ui-medium)"}),e.focus();let r=t.createDiv({cls:"waypoint-icon-grid"});r.style.display="grid",r.style.gridTemplateColumns="repeat(auto-fill, minmax(52px, 1fr))",r.style.gap="4px",r.style.maxHeight="320px",r.style.overflowY="auto",r.style.padding="2px 0";let s=t.createDiv();s.style.display="flex",s.style.justifyContent="space-between",s.style.alignItems="center",s.style.fontSize="var(--font-ui-smaller)",s.style.color="var(--text-muted)",s.style.padding="0 4px";let o=s.createSpan();o.setText("Loading\u2026");let l=s.createSpan();l.style.cursor="var(--cursor)",l.style.color="var(--text-accent)",l.setText("No icon"),l.addEventListener("click",()=>{this.onSubmit(""),this.close()}),this.loadIcons().then(()=>{this.loaded=!0,o.setText(this.allIcons.length+" icons"),d(e.value)});let c=null,d=T=>{if(r.empty(),!this.loaded){r.createDiv({text:"Loading\u2026"});return}let L=T.toLowerCase().trim(),P=L?this.allIcons.filter(k=>{if(k.includes(L))return!0;let b=this.tagsMap[k];return b?b.some(y=>y.includes(L)):!1}).slice(0,80):this.allIcons.slice(0,80);if(P.length===0){let k=r.createDiv();k.style.gridColumn="1 / -1",k.style.textAlign="center",k.style.color="var(--text-muted)",k.style.padding="20px",k.setText('No icons match "'+T+'"');return}for(var A=0;Anew Y(e,this)),this.addSettingTab(new W(this.app,this,this.settings,()=>this.redrawAll())),this.addCommand({id:"waypoint-open-view",name:"Open Waypoint sidebar",callback:async()=>{let e=this.app.workspace.getLeavesOfType(E);if(e.length>0)await this.app.workspace.revealLeaf(e[0]);else{let r=this.app.workspace.getLeftLeaf(!1);r&&(await r.setViewState({type:E}),await this.app.workspace.revealLeaf(r))}}}),this.addCommand({id:"waypoint-add-bookmark",name:"Add current file as Waypoint bookmark",callback:async()=>{let e=this.app.workspace.getActiveFile();if(!e){new u.Notice("No active file");return}this.addBookmark(e.path,e.basename,"file"),new u.Notice(`Bookmarked: ${e.basename}`)}}),this.addCommand({id:"waypoint-go-to-daily",name:"Go to daily note",hotkeys:[{modifiers:["Mod","Shift","Alt"],key:"d"}],callback:async()=>{await this.openPeriodNote("day",(0,u.moment)())}}),this.addCommand({id:"waypoint-go-to-weekly",name:"Go to weekly note",hotkeys:[{modifiers:["Mod","Shift","Alt"],key:"w"}],callback:async()=>{await this.openPeriodNote("week",(0,u.moment)())}}),this.addCommand({id:"waypoint-go-to-monthly",name:"Go to monthly note",hotkeys:[{modifiers:["Mod","Shift","Alt"],key:"m"}],callback:async()=>{await this.openPeriodNote("month",(0,u.moment)())}}),this.addCommand({id:"waypoint-go-to-quarterly",name:"Go to quarterly note",hotkeys:[{modifiers:["Mod","Shift","Alt"],key:"q"}],callback:async()=>{await this.openPeriodNote("quarter",(0,u.moment)())}}),this.addCommand({id:"waypoint-go-to-yearly",name:"Go to yearly note",hotkeys:[{modifiers:["Mod","Shift","Alt"],key:"y"}],callback:async()=>{await this.openPeriodNote("year",(0,u.moment)())}});let t=["next","prev"],a=["daily","weekly","monthly","quarterly","yearly"],i={next:"Next",prev:"Previous"};for(let e of a)for(let r of t){let s=`waypoint-go-to-${r}-${e}`,o=`${i[r]} ${e} note`;this.addCommand({id:s,name:o,callback:async()=>{await this.navigatePeriodNote(r)}})}this.registerEvent(this.app.workspace.on("file-open",e=>{e&&this.onFileOpen(e)})),this.registerEvent(this.app.vault.on("create",()=>this.onVaultChange())),this.registerEvent(this.app.vault.on("delete",()=>this.onVaultChange())),this.registerEvent(this.app.vault.on("rename",(e,r)=>this.onRename(e,r))),this.app.workspace.onLayoutReady(()=>{if(this.app.workspace.getLeavesOfType(E).length===0){let r=this.app.workspace.getLeftLeaf(!1);r&&r.setViewState({type:E})}});let n=new Date().toDateString();this.registerInterval(window.setInterval(()=>{let e=new Date().toDateString();e!==n&&(n=e,this.redrawAll())},6e5))}async onunload(){this.app.workspace.detachLeavesOfType(E)}async loadSettings(){let t=await this.loadData(),a=(t==null?void 0:t.settings)||{};this.settings=Object.assign({},Q,a)}async saveSettings(){let t=await this.loadData()||{};t.settings=this.settings,await this.saveData(t)}async loadWaypointData(){let t=await this.loadData(),a=(t==null?void 0:t.waypointData)||{};this.waypointData=Object.assign({},Z,a)}async saveWaypointData(){let t=await this.loadData()||{};t.waypointData=this.waypointData,await this.saveData(t)}onFileOpen(t){this.settings.recentFiles.updateOn!=="file-edit"&&this.addToRecentFiles(t)}addToRecentFiles(t){this.recentFiles=this.recentFiles.filter(a=>a.path!==t.path),this.recentFiles.unshift({path:t.path,basename:t.basename}),this.recentFiles.length>this.settings.recentFiles.maxItems&&(this.recentFiles=this.recentFiles.slice(0,this.settings.recentFiles.maxItems)),this.broadcastRedraw()}onRename(t,a){let i=this.recentFiles.find(n=>n.path===a);i&&(i.path=t.path,i.basename=t.basename||t.name.replace(/\.[^/.]+$/,""),this.broadcastRedraw()),this.updateBookmarkPath(a,t.path)}onVaultChange(){this.broadcastRedraw()}addBookmark(t,a,i="file",n=""){let r={id:`bm-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:i,label:a,filePath:i==="file"?t:"",icon:n,children:[],collapsed:!1,indent:0};return this.waypointData.bookmarks.push(r),this.saveWaypointData(),this.broadcastRedraw(),r}removeBookmark(t){let a=i=>{let n=i.findIndex(e=>e.id===t);if(n>=0)return i.splice(n,1),!0;for(let e of i)if(e.children&&a(e.children))return!0;return!1};a(this.waypointData.bookmarks),this.saveWaypointData(),this.broadcastRedraw()}updateBookmark(t,a){let i=e=>{for(let r of e){if(r.id===t)return r;if(r.children){let s=i(r.children);if(s)return s}}return null},n=i(this.waypointData.bookmarks);n&&(Object.assign(n,a),this.saveWaypointData(),this.broadcastRedraw())}updateBookmarkPath(t,a){let i=n=>{for(let e of n)e.filePath===t&&(e.filePath=a),e.children&&i(e.children)};i(this.waypointData.bookmarks)}async openPeriodNote(t,a){let n={day:{settings:this.settings.daily,label:"Daily"},week:{settings:this.settings.weekly,label:"Weekly"},month:{settings:this.settings.monthly,label:"Monthly"},quarter:{settings:this.settings.quarterly,label:"Quarterly"},year:{settings:this.settings.yearly,label:"Yearly"}}[t];if(!n)return;let{settings:e}=n,r=a.format(e.nameFormat)+".md",s=e.folder?`${e.folder}/${r}`:r,o=this.app.vault.getFileByPath(s);if(!o){try{let l=e.templateFile+".md",c=this.app.vault.getFileByPath(l);if(c){let d=await this.app.vault.read(c);o=await this.app.vault.create(s,d)}else{let d=`--- type: ${e.typeProperty} -date: ${t.format("YYYY-MM-DD")} +date: ${a.format("YYYY-MM-DD")} --- -`;o=await this.app.vault.create(i,d)}}catch(l){new u.Notice(`Failed to create ${s.label.toLowerCase()} note: ${l.message}`);return}new u.Notice(`Created ${s.label.toLowerCase()} note: ${r}`)}o&&await this.app.workspace.getLeaf(!1).openFile(o)}detectPeriodType(a){return/^\d{4}-\d{2}-\d{2}$/.test(a)?{period:"day",date:(0,u.moment)(a,"YYYY-MM-DD")}:/^\d{4}-W\d{2}$/.test(a)?{period:"week",date:(0,u.moment)(a,"GGGG-[W]WW")}:/^\d{4}-\d{2}$/.test(a)?{period:"month",date:(0,u.moment)(a,"YYYY-MM")}:/^\d{4}-Q[1-4]$/.test(a)?{period:"quarter",date:(0,u.moment)(a,"YYYY-[Q]Q")}:/^\d{4}$/.test(a)?{period:"year",date:(0,u.moment)(a,"YYYY")}:null}async navigatePeriodNote(a){let t=this.app.workspace.getActiveFile();if(!t){new u.Notice("No active file");return}let n=this.detectPeriodType(t.basename);if(!n){new u.Notice("Current file is not a periodic note (daily/weekly/monthly/quarterly/yearly)");return}let{period:s,date:e}=n;if(!e.isValid()){new u.Notice(`Could not parse date from filename: ${t.basename}`);return}let r=a==="next"?1:-1,i=s==="quarter"?e.clone().add(r*3,"months"):e.clone().add(r,`${s}s`);await this.openPeriodNote(s,i)}redrawAll(){this.broadcastRedraw()}broadcastRedraw(){let a=this.app.workspace.getLeavesOfType(I);for(let t of a)t.view instanceof Y&&t.view.redraw()}async getNotesForDate(a){return this.app.vault.getFiles().filter(t=>t.extension==="md"&&t.basename===a)}async hasNoteForDate(a){return this.app.vault.getFiles().some(t=>t.extension==="md"&&t.basename===a)}}; +`;o=await this.app.vault.create(s,d)}}catch(l){new u.Notice(`Failed to create ${n.label.toLowerCase()} note: ${l.message}`);return}new u.Notice(`Created ${n.label.toLowerCase()} note: ${r}`)}o&&await this.app.workspace.getLeaf(!1).openFile(o)}detectPeriodType(t){return/^\d{4}-\d{2}-\d{2}$/.test(t)?{period:"day",date:(0,u.moment)(t,"YYYY-MM-DD")}:/^\d{4}-W\d{2}$/.test(t)?{period:"week",date:(0,u.moment)(t,"GGGG-[W]WW")}:/^\d{4}-\d{2}$/.test(t)?{period:"month",date:(0,u.moment)(t,"YYYY-MM")}:/^\d{4}-Q[1-4]$/.test(t)?{period:"quarter",date:(0,u.moment)(t,"YYYY-[Q]Q")}:/^\d{4}$/.test(t)?{period:"year",date:(0,u.moment)(t,"YYYY")}:null}async navigatePeriodNote(t){let a=this.app.workspace.getActiveFile();if(!a){new u.Notice("No active file");return}let i=this.detectPeriodType(a.basename);if(!i){new u.Notice("Current file is not a periodic note (daily/weekly/monthly/quarterly/yearly)");return}let{period:n,date:e}=i;if(!e.isValid()){new u.Notice(`Could not parse date from filename: ${a.basename}`);return}let r=t==="next"?1:-1,s=n==="quarter"?e.clone().add(r*3,"months"):e.clone().add(r,`${n}s`);await this.openPeriodNote(n,s)}redrawAll(){this.broadcastRedraw()}broadcastRedraw(){let t=this.app.workspace.getLeavesOfType(E);for(let a of t)a.view instanceof Y&&a.view.redraw()}async getNotesForDate(t){return this.app.vault.getFiles().filter(a=>a.extension==="md"&&a.basename===t)}async hasNoteForDate(t){return this.app.vault.getFiles().some(a=>a.extension==="md"&&a.basename===t)}}; diff --git a/src/views/waypoint-view.ts b/src/views/waypoint-view.ts index 434097f..f8f8670 100644 --- a/src/views/waypoint-view.ts +++ b/src/views/waypoint-view.ts @@ -303,8 +303,11 @@ export class WaypointView extends ItemView { const headerEl = section.createDiv({ cls: 'waypoint-section-header' }); headerEl.setText('Waypoint Bookmarks'); - // Right-click on header area → add bookmark / group - headerEl.addEventListener('contextmenu', (event: MouseEvent) => { + // ⋯ button — visible add menu + const moreBtn = headerEl.createEl('button', { cls: 'waypoint-header-more' }); + setIcon(moreBtn, 'more-horizontal'); + setTooltip(moreBtn, 'Add bookmark'); + moreBtn.addEventListener('click', (event: MouseEvent) => { const menu = new Menu(); menu.addItem((item) => { item @@ -337,6 +340,7 @@ export class WaypointView extends ItemView { this.plugin.addBookmark('', 'New Group', 'group', ''); }); }); + menu.addSeparator(); menu.addItem((item) => { item .setTitle('Add separator') @@ -353,7 +357,6 @@ export class WaypointView extends ItemView { this.plugin.addBookmark('', '', 'spacer'); }); }); - menu.showAtPosition({ x: event.clientX, y: event.clientY }); }); @@ -655,6 +658,17 @@ export class WaypointView extends ItemView { private showBookmarkContextMenu(event: MouseEvent, item: BookmarkItem): void { const menu = new Menu(); + if (item.type === 'separator' || item.type === 'spacer') { + menu.addItem((i) => + i + .setTitle('Remove') + .setIcon('trash') + .onClick(() => this.plugin.removeBookmark(item.id)), + ); + menu.showAtPosition({ x: event.clientX, y: event.clientY }); + return; + } + if (item.type === 'file') { menu.addItem((i) => i @@ -662,80 +676,69 @@ export class WaypointView extends ItemView { .setIcon('file-plus') .onClick(() => { const tfile = this.app.vault.getFileByPath(item.filePath); - if (tfile) { - this.app.workspace.getLeaf('tab').openFile(tfile); - } + if (tfile) this.app.workspace.getLeaf('tab').openFile(tfile); }), ); menu.addSeparator(); - } - - if (item.type !== 'separator' && item.type !== 'spacer') { menu.addItem((i) => i .setTitle('Rename') .setIcon('pencil') .onClick(() => this.promptRename(item)), ); - menu.addItem((i) => i .setTitle('Change icon') .setIcon('image') .onClick(() => this.promptIcon(item)), ); - } - - // ── Move to group options ── - const allGroups = this.collectGroups(this.plugin.waypointData.bookmarks); - const ownIds = this.collectDescendantIds(item); - const availableGroups = allGroups.filter(g => !ownIds.includes(g.id) && g.id !== item.id); - - if ((availableGroups.length > 0 || item.type === 'file' || item.type === 'group') && item.type !== 'separator' && item.type !== 'spacer') { menu.addSeparator(); - if (availableGroups.length > 0) { - for (const group of availableGroups) { - menu.addItem((mi) => - mi - .setTitle(` ${group.label}`) - .setIcon(group.icon || 'folder') - .onClick(() => { - this.moveBookmarkToGroup(item.id, group.id); - }), - ); - } - } - // Add "Root" option for ungrouping - menu.addItem((mi) => - mi - .setTitle(' (Root)') - .setIcon('layout') - .onClick(() => { - this.moveBookmarkToGroup(item.id, null); - }), + menu.addItem((i) => + i + .setTitle('Remove') + .setIcon('trash') + .onClick(() => this.plugin.removeBookmark(item.id)), ); - } + } else if (item.type === 'group') { + if (item.filePath) { + menu.addItem((i) => + i + .setTitle('Open in new tab') + .setIcon('file-plus') + .onClick(() => { + const tfile = this.app.vault.getFileByPath(item.filePath); + if (tfile) this.app.workspace.getLeaf('tab').openFile(tfile); + }), + ); + menu.addSeparator(); + } - if (item.type === 'group') { + menu.addItem((i) => + i + .setTitle('Rename') + .setIcon('pencil') + .onClick(() => this.promptRename(item)), + ); + menu.addItem((i) => + i + .setTitle('Change icon') + .setIcon('image') + .onClick(() => this.promptIcon(item)), + ); menu.addItem((i) => i .setTitle(item.collapsed ? 'Expand' : 'Collapse') .setIcon(item.collapsed ? 'chevron-down' : 'chevron-up') - .onClick(() => { - this.plugin.updateBookmark(item.id, { collapsed: !item.collapsed }); - }), + .onClick(() => this.plugin.updateBookmark(item.id, { collapsed: !item.collapsed })), ); menu.addSeparator(); menu.addItem((i) => i - .setTitle('Add bookmark here') + .setTitle('Add child bookmark') .setIcon('file-plus') .onClick(() => { const file = this.app.workspace.getActiveFile(); - if (!file) { - new Notice('No active file'); - return; - } + if (!file) { new Notice('No active file'); return; } const child: BookmarkItem = { id: `bm-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`, type: 'file', @@ -754,13 +757,10 @@ export class WaypointView extends ItemView { menu.addItem((i) => i .setTitle('Add child note') - .setIcon('file-plus') + .setIcon('folder-plus') .onClick(() => { const file = this.app.workspace.getActiveFile(); - if (!file) { - new Notice('No active file'); - return; - } + if (!file) { new Notice('No active file'); return; } const child: BookmarkItem = { id: `bm-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`, type: 'group', @@ -796,100 +796,18 @@ export class WaypointView extends ItemView { this.redraw(); }), ); + menu.addSeparator(); + menu.addItem((i) => + i + .setTitle('Remove') + .setIcon('trash') + .onClick(() => this.plugin.removeBookmark(item.id)), + ); } - menu.addSeparator(); - - // ── Insert separator / spacer ── - menu.addItem((i) => - i - .setTitle('Insert separator above') - .setIcon('separator-vertical') - .onClick(() => this.insertAdjacent(item.id, 'separator', 'above')), - ); - menu.addItem((i) => - i - .setTitle('Insert separator below') - .setIcon('separator-vertical') - .onClick(() => this.insertAdjacent(item.id, 'separator', 'below')), - ); - menu.addItem((i) => - i - .setTitle('Insert spacer above') - .setIcon('space') - .onClick(() => this.insertAdjacent(item.id, 'spacer', 'above')), - ); - menu.addItem((i) => - i - .setTitle('Insert spacer below') - .setIcon('space') - .onClick(() => this.insertAdjacent(item.id, 'spacer', 'below')), - ); - - menu.addSeparator(); - - menu.addItem((i) => - i - .setTitle('Remove') - .setIcon('trash') - .onClick(() => { - this.plugin.removeBookmark(item.id); - }), - ); - menu.showAtPosition({ x: event.clientX, y: event.clientY }); } - private insertAdjacent(targetId: string, type: 'separator' | 'spacer', position: 'above' | 'below'): void { - const newItem: BookmarkItem = { - id: `bm-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`, - type, - label: '', - filePath: '', - icon: '', - children: [], - collapsed: false, - indent: 0, - }; - - const insert = (items: BookmarkItem[]): boolean => { - const idx = items.findIndex(i => i.id === targetId); - if (idx >= 0) { - const insertIdx = position === 'above' ? idx : idx + 1; - items.splice(insertIdx, 0, newItem); - return true; - } - for (const item of items) { - if (item.children && insert(item.children)) return true; - } - return false; - }; - - insert(this.plugin.waypointData.bookmarks); - this.plugin.saveWaypointData(); - this.redraw(); - } - - private collectGroups(items: BookmarkItem[]): BookmarkItem[] { - const groups: BookmarkItem[] = []; - for (const item of items) { - if (item.type === 'group') { - groups.push(item); - groups.push(...this.collectGroups(item.children)); - } - } - return groups; - } - - private collectDescendantIds(item: BookmarkItem): string[] { - const ids: string[] = []; - for (const child of item.children) { - ids.push(child.id); - ids.push(...this.collectDescendantIds(child)); - } - return ids; - } - private showDropIndicator(el: HTMLElement, e: MouseEvent): void { // Clear indicator from all siblings first const parent = el.parentElement; diff --git a/styles.css b/styles.css index 6b41f16..7aea6cc 100644 --- a/styles.css +++ b/styles.css @@ -27,6 +27,28 @@ margin-bottom: 4px; padding-bottom: 4px; border-bottom: 1px solid var(--background-modifier-border); + display: flex; + align-items: center; + gap: 6px; +} + +.waypoint-header-more { + margin-left: auto; + background: none; + border: none; + cursor: var(--cursor); + color: var(--text-faint); + padding: 2px 4px; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: center; + transition: color 80ms, background 80ms; +} + +.waypoint-header-more:hover { + color: var(--text-accent); + background-color: var(--background-modifier-active-hover); } /* ── Calendar ── */ diff --git a/todo.md b/todo.md index 21e264d..a220d9b 100644 --- a/todo.md +++ b/todo.md @@ -3,6 +3,8 @@ - [ ] in the bookmarks, i want to have notes that are parents to other notes - [ ] by default, the bookmark should have no icon - [ ] the way to search for icons should be improved. on the lucide icon website, the search works by more than only the icon’s title. i want to be able to load all the icon (not by default though) + - [ ] add a right click menu on the recent files to make them bookmarks + - [ ] improve the drag and drop to have identations and groups - [ ] calendar - [ ] middle click on a date/week/etc. should open it in a new tab - [ ] i want to improve the look of the calendar. more space, a bit more height