chore(react/launch_bar): port bookmark_folder

This commit is contained in:
Elian Doran 2025-12-04 14:41:07 +02:00
parent 48cbb80e79
commit cdab86bd83
No known key found for this signature in database
6 changed files with 77 additions and 101 deletions

View File

@ -34,14 +34,6 @@ export default class BookmarkButtons extends FlexContainer<Component> {
let buttonWidget: OpenNoteButtonWidget | BookmarkFolderWidget = note.isLabelTruthy("bookmarkFolder") let buttonWidget: OpenNoteButtonWidget | BookmarkFolderWidget = note.isLabelTruthy("bookmarkFolder")
? new BookmarkFolderWidget(note); ? new BookmarkFolderWidget(note);
if (this.settings.titlePlacement) {
if (!("settings" in buttonWidget)) {
(buttonWidget as any).settings = {};
}
(buttonWidget as any).settings.titlePlacement = this.settings.titlePlacement;
}
this.child(buttonWidget); this.child(buttonWidget);
this.$widget.append(buttonWidget.render()); this.$widget.append(buttonWidget.render());

View File

@ -1,88 +0,0 @@
import RightDropdownButtonWidget from "./right_dropdown_button.js";
import linkService from "../../services/link.js";
import utils from "../../services/utils.js";
import type FNote from "../../entities/fnote.js";
const DROPDOWN_TPL = `
<div class="bookmark-folder-widget">
<style>
.bookmark-folder-widget {
min-width: 400px;
max-height: 500px;
padding: 7px 15px 0 15px;
font-size: 1.2rem;
overflow: auto;
}
.bookmark-folder-widget ul {
padding: 0;
list-style-type: none;
}
.bookmark-folder-widget .note-link {
display: block;
padding: 5px 10px 5px 5px;
}
.bookmark-folder-widget .note-link:hover {
background-color: var(--accented-background-color);
text-decoration: none;
}
.dropdown-menu .bookmark-folder-widget a:hover {
text-decoration: none;
background: transparent !important;
}
.bookmark-folder-widget li .note-link {
padding-inline-start: 35px;
}
</style>
<div class="parent-note"></div>
<ul class="children-notes"></ul>
</div>`;
interface LinkOptions {
showTooltip: boolean;
showNoteIcon: boolean;
}
export default class BookmarkFolderWidget extends RightDropdownButtonWidget {
private note: FNote;
private $parentNote!: JQuery<HTMLElement>;
private $childrenNotes!: JQuery<HTMLElement>;
declare $dropdownContent: JQuery<HTMLElement>;
constructor(note: FNote) {
super(utils.escapeHtml(note.title), note.getIcon(), DROPDOWN_TPL);
this.note = note;
}
doRender(): void {
super.doRender();
this.$parentNote = this.$dropdownContent.find(".parent-note");
this.$childrenNotes = this.$dropdownContent.find(".children-notes");
}
async dropdownShown(): Promise<void> {
this.$parentNote.empty();
this.$childrenNotes.empty();
const linkOptions: LinkOptions = {
showTooltip: false,
showNoteIcon: true
};
this.$parentNote.append((await linkService.createLink(this.note.noteId, linkOptions)).addClass("note-link"));
for (const childNote of await this.note.getChildNotes()) {
this.$childrenNotes.append($("<li>").append((await linkService.createLink(childNote.noteId, linkOptions)).addClass("note-link")));
}
}
refreshIcon(): void {}
}

View File

@ -0,0 +1,31 @@
.bookmark-folder-widget {
min-width: 400px;
max-height: 500px;
padding: 7px 15px 0 15px;
font-size: 1.2rem;
overflow: auto;
}
.bookmark-folder-widget ul {
padding: 0;
list-style-type: none;
}
.bookmark-folder-widget .note-link {
display: block;
padding: 5px 10px 5px 5px;
}
.bookmark-folder-widget .note-link:hover {
background-color: var(--accented-background-color);
text-decoration: none;
}
.dropdown-menu .bookmark-folder-widget a:hover:not(.disabled) {
text-decoration: none;
background-color: transparent !important;
}
.bookmark-folder-widget li .note-link {
padding-inline-start: 35px;
}

View File

@ -2,12 +2,16 @@ import { useMemo } from "preact/hooks";
import type { LaunchBarWidgetProps } from "./launch_bar_widget"; import type { LaunchBarWidgetProps } from "./launch_bar_widget";
import { CSSProperties } from "preact"; import { CSSProperties } from "preact";
import type FNote from "../../entities/fnote"; import type FNote from "../../entities/fnote";
import { useChildNotes, useNoteLabel, useNoteProperty } from "../react/hooks"; import { useChildNotes, useNoteLabel, useNoteLabelBoolean, useNoteProperty } from "../react/hooks";
import Dropdown from "../react/Dropdown";
import ActionButton from "../react/ActionButton"; import ActionButton from "../react/ActionButton";
import appContext from "../../components/app_context"; import appContext from "../../components/app_context";
import { escapeHtml, isCtrlKey } from "../../services/utils"; import { escapeHtml, isCtrlKey } from "../../services/utils";
import link_context_menu from "../../menus/link_context_menu"; import link_context_menu from "../../menus/link_context_menu";
import "./BookmarkButtons.css";
import Dropdown from "../react/Dropdown";
import Icon from "../react/Icon";
import NoteList from "../react/NoteList";
import NoteLink from "../react/NoteLink";
const PARENT_NOTE_ID = "_lbBookmarks"; const PARENT_NOTE_ID = "_lbBookmarks";
@ -27,7 +31,10 @@ export default function BookmarkButtons({ isHorizontalLayout }: LaunchBarWidgetP
} }
function SingleBookmark({ note }: { note: FNote }) { function SingleBookmark({ note }: { note: FNote }) {
return <OpenNoteButtonWidget note={note} /> const [ bookmarkFolder ] = useNoteLabelBoolean(note, "bookmarkFolder");
return bookmarkFolder
? <BookmarkFolder note={note} />
: <OpenNoteButtonWidget note={note} />
} }
function OpenNoteButtonWidget({ note }: { note: FNote }) { function OpenNoteButtonWidget({ note }: { note: FNote }) {
@ -66,6 +73,36 @@ function OpenNoteButtonWidget({ note }: { note: FNote }) {
) )
} }
function BookmarkFolder({ note }: { note: FNote }) {
const [ iconClass ] = useNoteLabel(note, "iconClass");
const title = useNoteProperty(note, "title");
const childNotes = useChildNotes(note.noteId);
return title && iconClass && (
<Dropdown
className="right-dropdown-widget"
buttonClassName="right-dropdown-button launcher-button"
hideToggleArrow
title={escapeHtml(title)}
text={<Icon icon={iconClass} />}
>
<div className="bookmark-folder-widget">
<div className="parent-note">
<NoteLink notePath={note.noteId} noPreview showNoteIcon containerClassName="note-link" noTnLink />
</div>
<ul className="children-notes">
{childNotes.map(childNote => (
<li>
<NoteLink notePath={childNote.noteId} noPreview showNoteIcon containerClassName="note-link" noTnLink />
</li>
))}
</ul>
</div>
</Dropdown>
)
}
function getHoistedNoteId(noteToOpen: FNote) { function getHoistedNoteId(noteToOpen: FNote) {
return noteToOpen.getRelationValue("hoistedNote") || appContext.tabManager.getActiveContext()?.hoistedNoteId; return noteToOpen.getRelationValue("hoistedNote") || appContext.tabManager.getActiveContext()?.hoistedNoteId;
} }

View File

@ -4,6 +4,7 @@ import { useImperativeSearchHighlighlighting, useTriliumEvent } from "./hooks";
interface NoteLinkOpts { interface NoteLinkOpts {
className?: string; className?: string;
containerClassName?: string;
notePath: string | string[]; notePath: string | string[];
showNotePath?: boolean; showNotePath?: boolean;
showNoteIcon?: boolean; showNoteIcon?: boolean;
@ -17,7 +18,7 @@ interface NoteLinkOpts {
noContextMenu?: boolean; noContextMenu?: boolean;
} }
export default function NoteLink({ className, notePath, showNotePath, showNoteIcon, style, noPreview, noTnLink, highlightedTokens, title, viewScope, noContextMenu }: NoteLinkOpts) { export default function NoteLink({ className, containerClassName, notePath, showNotePath, showNoteIcon, style, noPreview, noTnLink, highlightedTokens, title, viewScope, noContextMenu }: NoteLinkOpts) {
const stringifiedNotePath = Array.isArray(notePath) ? notePath.join("/") : notePath; const stringifiedNotePath = Array.isArray(notePath) ? notePath.join("/") : notePath;
const noteId = stringifiedNotePath.split("/").at(-1); const noteId = stringifiedNotePath.split("/").at(-1);
const ref = useRef<HTMLSpanElement>(null); const ref = useRef<HTMLSpanElement>(null);
@ -71,6 +72,6 @@ export default function NoteLink({ className, notePath, showNotePath, showNoteIc
$linkEl?.addClass(className); $linkEl?.addClass(className);
} }
return <span ref={ref} /> return <span className={containerClassName} ref={ref} />
} }

View File

@ -24,6 +24,9 @@ type Labels = {
orderBy: string; orderBy: string;
orderDirection: string; orderDirection: string;
// Launch bar
bookmarkFolder: boolean;
// Collection-specific // Collection-specific
viewType: string; viewType: string;
status: string; status: string;