import { t } from "../../../services/i18n.js"; import AbstractLauncher from "./abstract_launcher.js"; import dialogService from "../../../services/dialog.js"; import appContext from "../../../components/app_context.js"; import utils from "../../../services/utils.js"; import linkContextMenuService from "../../../menus/link_context_menu.js"; import type FNote from "../../../entities/fnote.js"; // 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 default class NoteLauncher extends AbstractLauncher { constructor(launcherNote: FNote) { super(launcherNote); this.title(() => this.launcherNote.title) .icon(() => this.launcherNote.getIcon()) .onClick((widget, evt) => this.launch(evt)) .onAuxClick((widget, evt) => this.launch(evt)) .onContextMenu(async (evt) => { let targetNoteId = await Promise.resolve(this.getTargetNoteId()); if (!targetNoteId || !evt) { return; } const hoistedNoteId = this.getHoistedNoteId(); linkContextMenuService.openContextMenu(targetNoteId, evt, {}, hoistedNoteId); }); } async launch(evt?: JQuery.ClickEvent | JQuery.ContextMenuEvent | JQuery.TriggeredEvent) { // await because subclass overrides can be async const targetNoteId = await this.getTargetNoteId(); if (!targetNoteId || evt?.which === 3) { return; } const hoistedNoteId = await this.getHoistedNoteId(); if (!hoistedNoteId) { return; } if (!evt) { // keyboard shortcut // TODO: Fix once tabManager is ported. //@ts-ignore await appContext.tabManager.openInSameTab(targetNoteId, hoistedNoteId); } else { const ctrlKey = utils.isCtrlKey(evt); if ((evt.which === 1 && ctrlKey) || evt.which === 2) { // TODO: Fix once tabManager is ported. //@ts-ignore await appContext.tabManager.openInNewTab(targetNoteId, hoistedNoteId); } else { // TODO: Fix once tabManager is ported. //@ts-ignore await appContext.tabManager.openInSameTab(targetNoteId, hoistedNoteId); } } } getTargetNoteId(): void | string | Promise { const targetNoteId = this.launcherNote.getRelationValue("target"); if (!targetNoteId) { dialogService.info(t("note_launcher.this_launcher_doesnt_define_target_note")); return; } return targetNoteId; } getHoistedNoteId() { return this.launcherNote.getRelationValue("hoistedNote") || appContext.tabManager.getActiveContext().hoistedNoteId; } getTitle() { const shortcuts = this.launcherNote .getLabels("keyboardShortcut") .map((l) => l.value) .filter((v) => !!v) .join(", "); let title = super.getTitle(); if (shortcuts) { title += ` (${shortcuts})`; } return title; } }