chore(react/launch_bar): port note launcher

This commit is contained in:
Elian Doran 2025-12-04 16:33:58 +02:00
parent 06a9f95979
commit 0d6bcba023
No known key found for this signature in database
4 changed files with 33 additions and 9 deletions

View File

@ -1,7 +1,6 @@
import CalendarWidget from "../buttons/calendar.js";
import SyncStatusWidget from "../sync_status.js";
import BasicWidget, { wrapReactWidgets } from "../basic_widget.js";
import NoteLauncher from "../buttons/launcher/note_launcher.js";
import ScriptLauncher from "../buttons/launcher/script_launcher.js";
import utils from "../../services/utils.js";
import TodayLauncher from "../buttons/launcher/today_launcher.js";
@ -13,7 +12,7 @@ import HistoryNavigationButton from "../launch_bar/HistoryNavigation.jsx";
import AiChatButton from "../launch_bar/AiChatButton.jsx";
import ProtectedSessionStatusWidget from "../launch_bar/ProtectedSessionStatusWidget.jsx";
import { VNode } from "preact";
import { CommandButton } from "../launch_bar/GenericButtons.jsx";
import { CommandButton, NoteLauncher } from "../launch_bar/GenericButtons.jsx";
interface InnerWidget extends BasicWidget {
settings?: {
@ -58,7 +57,7 @@ export default class LauncherWidget extends BasicWidget {
if (launcherType === "command") {
widget = wrapReactWidgets<BasicWidget>([ <CommandButton launcherNote={note} /> ])[0];
} else if (launcherType === "note") {
widget = new NoteLauncher(note).class("launcher-button");
widget = wrapReactWidgets<BasicWidget>([ <NoteLauncher launcherNote={note} /> ])[0];
} else if (launcherType === "script") {
widget = new ScriptLauncher(note).class("launcher-button");
} else if (launcherType === "customWidget") {

View File

@ -5,7 +5,7 @@ import type FNote from "../../entities/fnote";
import { useChildNotes, useNoteLabelBoolean } from "../react/hooks";
import "./BookmarkButtons.css";
import NoteLink from "../react/NoteLink";
import { NoteLauncher } from "./GenericButtons";
import { CustomNoteLauncher } from "./GenericButtons";
const PARENT_NOTE_ID = "_lbBookmarks";
@ -28,7 +28,7 @@ function SingleBookmark({ note }: { note: FNote }) {
const [ bookmarkFolder ] = useNoteLabelBoolean(note, "bookmarkFolder");
return bookmarkFolder
? <BookmarkFolder note={note} />
: <NoteLauncher launcherNote={note} targetNoteId={note.noteId} />
: <CustomNoteLauncher launcherNote={note} targetNoteId={note.noteId} />
}
function BookmarkFolder({ note }: { note: FNote }) {

View File

@ -2,8 +2,10 @@ import appContext, { CommandNames } from "../../components/app_context";
import FNote from "../../entities/fnote";
import link_context_menu from "../../menus/link_context_menu";
import { escapeHtml, isCtrlKey } from "../../services/utils";
import { useNoteLabel, useNoteProperty } from "../react/hooks";
import { useNoteLabel, useNoteProperty, useNoteRelation } from "../react/hooks";
import { LaunchBarActionButton, useLauncherIconAndTitle } from "./launch_bar_widgets";
import dialog from "../../services/dialog";
import { t } from "../../services/i18n";
export function CommandButton({ launcherNote }: { launcherNote: FNote }) {
const { icon, title } = useLauncherIconAndTitle(launcherNote);
@ -18,13 +20,19 @@ export function CommandButton({ launcherNote }: { launcherNote: FNote }) {
)
}
export function NoteLauncher({ launcherNote, targetNoteId, hoistedNoteId }: { launcherNote: FNote, targetNoteId: string, hoistedNoteId?: string }) {
export function CustomNoteLauncher({ launcherNote, targetNoteId, hoistedNoteId }: { launcherNote: FNote, targetNoteId: string | null, hoistedNoteId?: string }) {
const { icon, title } = useLauncherIconAndTitle(launcherNote);
async function launch(evt: MouseEvent) {
if (evt.which === 3) {
return;
}
if (!targetNoteId) {
dialog.info(t("note_launcher.this_launcher_doesnt_define_target_note"));
return;
}
const hoistedNoteIdWithDefault = hoistedNoteId || launcherNote.getRelationValue("hoistedNote") || appContext.tabManager.getActiveContext()?.hoistedNoteId;
const ctrlKey = isCtrlKey(evt);
@ -44,8 +52,22 @@ export function NoteLauncher({ launcherNote, targetNoteId, hoistedNoteId }: { la
onAuxClick={launch}
onContextMenu={evt => {
evt.preventDefault();
if (targetNoteId) {
link_context_menu.openContextMenu(targetNoteId, evt);
}
}}
/>
)
}
// we're intentionally displaying the launcher title and icon instead of the target,
// e.g. you want to make launchers to 2 mermaid diagrams which both have mermaid icon (ok),
// but on the launchpad you want them distinguishable.
// for titles, the note titles may follow a different scheme than maybe desirable on the launchpad
// another reason is the discrepancy between what user sees on the launchpad and in the config (esp. icons).
// The only downside is more work in setting up the typical case
// where you actually want to have both title and icon in sync, but for those cases there are bookmarks
export function NoteLauncher({ launcherNote, ...restProps }: { launcherNote: FNote, hoistedNoteId?: string }) {
const [ targetNote ] = useNoteRelation(launcherNote, "target");
return <CustomNoteLauncher launcherNote={launcherNote} targetNoteId={targetNote ?? null} {...restProps} />
}

View File

@ -59,7 +59,10 @@ type Labels = {
*/
type Relations = [
"searchScript",
"ancestor"
"ancestor",
// Launcher-specific
"target"
];
export type LabelNames = keyof Labels;