refactor: simplify bookmark menus — visible ⋯ button, flat context menus
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
This commit is contained in:
+60
-142
@@ -303,8 +303,11 @@ export class WaypointView extends ItemView {
|
|||||||
const headerEl = section.createDiv({ cls: 'waypoint-section-header' });
|
const headerEl = section.createDiv({ cls: 'waypoint-section-header' });
|
||||||
headerEl.setText('Waypoint Bookmarks');
|
headerEl.setText('Waypoint Bookmarks');
|
||||||
|
|
||||||
// Right-click on header area → add bookmark / group
|
// ⋯ button — visible add menu
|
||||||
headerEl.addEventListener('contextmenu', (event: MouseEvent) => {
|
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();
|
const menu = new Menu();
|
||||||
menu.addItem((item) => {
|
menu.addItem((item) => {
|
||||||
item
|
item
|
||||||
@@ -337,6 +340,7 @@ export class WaypointView extends ItemView {
|
|||||||
this.plugin.addBookmark('', 'New Group', 'group', '');
|
this.plugin.addBookmark('', 'New Group', 'group', '');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
menu.addSeparator();
|
||||||
menu.addItem((item) => {
|
menu.addItem((item) => {
|
||||||
item
|
item
|
||||||
.setTitle('Add separator')
|
.setTitle('Add separator')
|
||||||
@@ -353,7 +357,6 @@ export class WaypointView extends ItemView {
|
|||||||
this.plugin.addBookmark('', '', 'spacer');
|
this.plugin.addBookmark('', '', 'spacer');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
menu.showAtPosition({ x: event.clientX, y: event.clientY });
|
menu.showAtPosition({ x: event.clientX, y: event.clientY });
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -655,6 +658,17 @@ export class WaypointView extends ItemView {
|
|||||||
private showBookmarkContextMenu(event: MouseEvent, item: BookmarkItem): void {
|
private showBookmarkContextMenu(event: MouseEvent, item: BookmarkItem): void {
|
||||||
const menu = new Menu();
|
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') {
|
if (item.type === 'file') {
|
||||||
menu.addItem((i) =>
|
menu.addItem((i) =>
|
||||||
i
|
i
|
||||||
@@ -662,80 +676,69 @@ export class WaypointView extends ItemView {
|
|||||||
.setIcon('file-plus')
|
.setIcon('file-plus')
|
||||||
.onClick(() => {
|
.onClick(() => {
|
||||||
const tfile = this.app.vault.getFileByPath(item.filePath);
|
const tfile = this.app.vault.getFileByPath(item.filePath);
|
||||||
if (tfile) {
|
if (tfile) this.app.workspace.getLeaf('tab').openFile(tfile);
|
||||||
this.app.workspace.getLeaf('tab').openFile(tfile);
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
}
|
|
||||||
|
|
||||||
if (item.type !== 'separator' && item.type !== 'spacer') {
|
|
||||||
menu.addItem((i) =>
|
menu.addItem((i) =>
|
||||||
i
|
i
|
||||||
.setTitle('Rename')
|
.setTitle('Rename')
|
||||||
.setIcon('pencil')
|
.setIcon('pencil')
|
||||||
.onClick(() => this.promptRename(item)),
|
.onClick(() => this.promptRename(item)),
|
||||||
);
|
);
|
||||||
|
|
||||||
menu.addItem((i) =>
|
menu.addItem((i) =>
|
||||||
i
|
i
|
||||||
.setTitle('Change icon')
|
.setTitle('Change icon')
|
||||||
.setIcon('image')
|
.setIcon('image')
|
||||||
.onClick(() => this.promptIcon(item)),
|
.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();
|
menu.addSeparator();
|
||||||
if (availableGroups.length > 0) {
|
menu.addItem((i) =>
|
||||||
for (const group of availableGroups) {
|
i
|
||||||
menu.addItem((mi) =>
|
.setTitle('Remove')
|
||||||
mi
|
.setIcon('trash')
|
||||||
.setTitle(` ${group.label}`)
|
.onClick(() => this.plugin.removeBookmark(item.id)),
|
||||||
.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);
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
} 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) =>
|
menu.addItem((i) =>
|
||||||
i
|
i
|
||||||
.setTitle(item.collapsed ? 'Expand' : 'Collapse')
|
.setTitle(item.collapsed ? 'Expand' : 'Collapse')
|
||||||
.setIcon(item.collapsed ? 'chevron-down' : 'chevron-up')
|
.setIcon(item.collapsed ? 'chevron-down' : 'chevron-up')
|
||||||
.onClick(() => {
|
.onClick(() => this.plugin.updateBookmark(item.id, { collapsed: !item.collapsed })),
|
||||||
this.plugin.updateBookmark(item.id, { collapsed: !item.collapsed });
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
menu.addItem((i) =>
|
menu.addItem((i) =>
|
||||||
i
|
i
|
||||||
.setTitle('Add bookmark here')
|
.setTitle('Add child bookmark')
|
||||||
.setIcon('file-plus')
|
.setIcon('file-plus')
|
||||||
.onClick(() => {
|
.onClick(() => {
|
||||||
const file = this.app.workspace.getActiveFile();
|
const file = this.app.workspace.getActiveFile();
|
||||||
if (!file) {
|
if (!file) { new Notice('No active file'); return; }
|
||||||
new Notice('No active file');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const child: BookmarkItem = {
|
const child: BookmarkItem = {
|
||||||
id: `bm-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
|
id: `bm-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
|
||||||
type: 'file',
|
type: 'file',
|
||||||
@@ -754,13 +757,10 @@ export class WaypointView extends ItemView {
|
|||||||
menu.addItem((i) =>
|
menu.addItem((i) =>
|
||||||
i
|
i
|
||||||
.setTitle('Add child note')
|
.setTitle('Add child note')
|
||||||
.setIcon('file-plus')
|
.setIcon('folder-plus')
|
||||||
.onClick(() => {
|
.onClick(() => {
|
||||||
const file = this.app.workspace.getActiveFile();
|
const file = this.app.workspace.getActiveFile();
|
||||||
if (!file) {
|
if (!file) { new Notice('No active file'); return; }
|
||||||
new Notice('No active file');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const child: BookmarkItem = {
|
const child: BookmarkItem = {
|
||||||
id: `bm-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
|
id: `bm-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
|
||||||
type: 'group',
|
type: 'group',
|
||||||
@@ -796,100 +796,18 @@ export class WaypointView extends ItemView {
|
|||||||
this.redraw();
|
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 });
|
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 {
|
private showDropIndicator(el: HTMLElement, e: MouseEvent): void {
|
||||||
// Clear indicator from all siblings first
|
// Clear indicator from all siblings first
|
||||||
const parent = el.parentElement;
|
const parent = el.parentElement;
|
||||||
|
|||||||
+22
@@ -27,6 +27,28 @@
|
|||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
border-bottom: 1px solid var(--background-modifier-border);
|
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 ── */
|
/* ── Calendar ── */
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
- [ ] in the bookmarks, i want to have notes that are parents to other notes
|
- [ ] in the bookmarks, i want to have notes that are parents to other notes
|
||||||
- [ ] by default, the bookmark should have no icon
|
- [ ] 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)
|
- [ ] 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
|
- [ ] calendar
|
||||||
- [ ] middle click on a date/week/etc. should open it in a new tab
|
- [ ] 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
|
- [ ] i want to improve the look of the calendar. more space, a bit more height
|
||||||
|
|||||||
Reference in New Issue
Block a user