refactor(react/launch_bar): port command buttons

This commit is contained in:
Elian Doran 2025-12-04 16:04:08 +02:00
parent c3b22ff737
commit 1e05dc937c
No known key found for this signature in database
4 changed files with 24 additions and 84 deletions

View File

@ -1,73 +0,0 @@
import { ActionKeyboardShortcut } from "@triliumnext/commons";
import type { CommandNames } from "../../components/app_context.js";
import keyboardActionsService from "../../services/keyboard_actions.js";
import AbstractButtonWidget, { type AbstractButtonWidgetSettings } from "./abstract_button.js";
import type { ButtonNoteIdProvider } from "./button_from_note.js";
let actions: ActionKeyboardShortcut[];
keyboardActionsService.getActions().then((as) => (actions = as));
// TODO: Is this actually used?
export type ClickHandler = (widget: CommandButtonWidget, e: JQuery.ClickEvent<any, any, any, any>) => void;
type CommandOrCallback = CommandNames | (() => CommandNames);
interface CommandButtonWidgetSettings extends AbstractButtonWidgetSettings {
command?: CommandOrCallback;
onClick?: ClickHandler;
buttonNoteIdProvider?: ButtonNoteIdProvider | null;
}
export default class CommandButtonWidget extends AbstractButtonWidget<CommandButtonWidgetSettings> {
constructor() {
super();
this.settings = {
titlePlacement: "right",
title: null,
icon: null,
onContextMenu: null
};
}
doRender() {
super.doRender();
if (this.settings.command) {
this.$widget.on("click", () => {
this.tooltip.hide();
if (this._command) {
this.triggerCommand(this._command);
}
});
} else {
console.warn(`Button widget '${this.componentId}' has no defined command`, this.settings);
}
}
getTitle() {
const title = super.getTitle();
const action = actions.find((act) => act.actionName === this._command);
if (action?.effectiveShortcuts && action.effectiveShortcuts.length > 0) {
return `${title} (${action.effectiveShortcuts.join(", ")})`;
} else {
return title;
}
}
onClick(handler: ClickHandler) {
this.settings.onClick = handler;
return this;
}
command(command: CommandOrCallback) {
this.settings.command = command;
return this;
}
get _command() {
return typeof this.settings.command === "function" ? this.settings.command() : this.settings.command;
}
}

View File

@ -3,17 +3,17 @@ import SyncStatusWidget from "../sync_status.js";
import BasicWidget, { wrapReactWidgets } from "../basic_widget.js"; import BasicWidget, { wrapReactWidgets } from "../basic_widget.js";
import NoteLauncher from "../buttons/launcher/note_launcher.js"; import NoteLauncher from "../buttons/launcher/note_launcher.js";
import ScriptLauncher from "../buttons/launcher/script_launcher.js"; import ScriptLauncher from "../buttons/launcher/script_launcher.js";
import CommandButtonWidget from "../buttons/command_button.js";
import utils from "../../services/utils.js"; import utils from "../../services/utils.js";
import TodayLauncher from "../buttons/launcher/today_launcher.js"; import TodayLauncher from "../buttons/launcher/today_launcher.js";
import QuickSearchLauncherWidget from "../quick_search_launcher.js"; import QuickSearchLauncherWidget from "../quick_search_launcher.js";
import type FNote from "../../entities/fnote.js"; import type FNote from "../../entities/fnote.js";
import type { CommandNames } from "../../components/app_context.js";
import BookmarkButtons from "../launch_bar/BookmarkButtons.jsx"; import BookmarkButtons from "../launch_bar/BookmarkButtons.jsx";
import SpacerWidget from "../launch_bar/SpacerWidget.jsx"; import SpacerWidget from "../launch_bar/SpacerWidget.jsx";
import HistoryNavigationButton from "../launch_bar/HistoryNavigation.jsx"; import HistoryNavigationButton from "../launch_bar/HistoryNavigation.jsx";
import AiChatButton from "../launch_bar/AiChatButton.jsx"; import AiChatButton from "../launch_bar/AiChatButton.jsx";
import ProtectedSessionStatusWidget from "../launch_bar/ProtectedSessionStatusWidget.jsx"; import ProtectedSessionStatusWidget from "../launch_bar/ProtectedSessionStatusWidget.jsx";
import { VNode } from "preact";
import CommandButton from "../launch_bar/CommandButton.jsx";
interface InnerWidget extends BasicWidget { interface InnerWidget extends BasicWidget {
settings?: { settings?: {
@ -54,9 +54,9 @@ export default class LauncherWidget extends BasicWidget {
return false; return false;
} }
let widget: BasicWidget; let widget: BasicWidget | VNode;
if (launcherType === "command") { if (launcherType === "command") {
widget = this.initCommandLauncherWidget(note).class("launcher-button"); widget = wrapReactWidgets<BasicWidget>([ <CommandButton launcherNote={note} /> ])[0];
} else if (launcherType === "note") { } else if (launcherType === "note") {
widget = new NoteLauncher(note).class("launcher-button"); widget = new NoteLauncher(note).class("launcher-button");
} else if (launcherType === "script") { } else if (launcherType === "script") {
@ -82,13 +82,6 @@ export default class LauncherWidget extends BasicWidget {
return true; return true;
} }
initCommandLauncherWidget(note: FNote) {
return new CommandButtonWidget()
.title(() => note.title)
.icon(() => note.getIcon())
.command(() => note.getLabelValue("command") as CommandNames);
}
async initCustomWidget(note: FNote) { async initCustomWidget(note: FNote) {
const widget = await note.getRelationTarget("widget"); const widget = await note.getRelationTarget("widget");

View File

@ -0,0 +1,19 @@
import { CommandNames } from "../../components/app_context";
import FNote from "../../entities/fnote";
import { escapeHtml } from "../../services/utils";
import { useNoteLabel, useNoteProperty } from "../react/hooks";
import { LaunchBarActionButton } from "./launch_bar_widgets";
export default function CommandButton({ launcherNote }: { launcherNote: FNote }) {
const [ iconClass ] = useNoteLabel(launcherNote, "iconClass");
const [ command ] = useNoteLabel(launcherNote, "command");
const title = useNoteProperty(launcherNote, "title");
return iconClass && title && command && (
<LaunchBarActionButton
icon={iconClass}
text={escapeHtml(title)}
triggerCommand={command as CommandNames}
/>
)
}

View File

@ -26,6 +26,7 @@ type Labels = {
// Launch bar // Launch bar
bookmarkFolder: boolean; bookmarkFolder: boolean;
command: string;
// Collection-specific // Collection-specific
viewType: string; viewType: string;