2024-07-18 21:35:17 +03:00
|
|
|
import attributeService from "./attributes.js";
|
|
|
|
import dateNoteService from "./date_notes.js";
|
|
|
|
import becca from "../becca/becca.js";
|
|
|
|
import noteService from "./notes.js";
|
|
|
|
import dateUtils from "./date_utils.js";
|
|
|
|
import log from "./log.js";
|
|
|
|
import hoistedNoteService from "./hoisted_note.js";
|
|
|
|
import searchService from "./search/services/search.js";
|
|
|
|
import SearchContext from "./search/search_context.js";
|
|
|
|
import hiddenSubtree from "./hidden_subtree.js";
|
2024-10-25 21:04:13 +03:00
|
|
|
import { t } from "i18next";
|
2025-03-09 02:19:26 +00:00
|
|
|
const { LBTPL_NOTE, LBTPL_CUSTOM_WIDGET, LBTPL_SPACER, LBTPL_SCRIPT } = hiddenSubtree;
|
2024-04-03 23:05:06 +03:00
|
|
|
|
|
|
|
function getInboxNote(date: string) {
|
2022-12-23 15:07:48 +01:00
|
|
|
const workspaceNote = hoistedNoteService.getWorkspaceNote();
|
2024-04-03 23:05:06 +03:00
|
|
|
if (!workspaceNote) {
|
|
|
|
throw new Error("Unable to find workspace note");
|
|
|
|
}
|
2021-09-16 22:09:39 +02:00
|
|
|
|
|
|
|
let inbox;
|
|
|
|
|
2022-12-23 15:07:48 +01:00
|
|
|
if (!workspaceNote.isRoot()) {
|
2025-01-09 18:07:02 +02:00
|
|
|
inbox = workspaceNote.searchNoteInSubtree("#workspaceInbox");
|
2021-09-16 22:09:39 +02:00
|
|
|
|
|
|
|
if (!inbox) {
|
2025-01-09 18:07:02 +02:00
|
|
|
inbox = workspaceNote.searchNoteInSubtree("#inbox");
|
2021-09-16 22:09:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!inbox) {
|
2022-12-23 15:07:48 +01:00
|
|
|
inbox = workspaceNote;
|
2021-09-16 22:09:39 +02:00
|
|
|
}
|
2025-01-09 18:07:02 +02:00
|
|
|
} else {
|
|
|
|
inbox = attributeService.getNoteWithLabel("inbox") || dateNoteService.getDayNote(date);
|
2021-09-16 22:09:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return inbox;
|
|
|
|
}
|
|
|
|
|
|
|
|
function createSqlConsole() {
|
2025-01-09 18:07:02 +02:00
|
|
|
const { note } = noteService.createNewNote({
|
|
|
|
parentNoteId: getMonthlyParentNoteId("_sqlConsole", "sqlConsole"),
|
|
|
|
title: "SQL Console - " + dateUtils.localNowDate(),
|
2021-09-16 22:09:39 +02:00
|
|
|
content: "SELECT title, isDeleted, isProtected FROM notes WHERE noteId = ''\n\n\n\n",
|
2025-01-09 18:07:02 +02:00
|
|
|
type: "code",
|
|
|
|
mime: "text/x-sqlite;schema=trilium"
|
2021-09-16 22:09:39 +02:00
|
|
|
});
|
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
note.setLabel("iconClass", "bx bx-data");
|
|
|
|
note.setLabel("keepCurrentHoisting");
|
2021-09-16 22:09:39 +02:00
|
|
|
|
|
|
|
return note;
|
|
|
|
}
|
|
|
|
|
2024-04-03 23:05:06 +03:00
|
|
|
function saveSqlConsole(sqlConsoleNoteId: string) {
|
2021-09-16 22:09:39 +02:00
|
|
|
const sqlConsoleNote = becca.getNote(sqlConsoleNoteId);
|
2024-04-03 23:05:06 +03:00
|
|
|
if (!sqlConsoleNote) throw new Error(`Unable to find SQL console note ID: ${sqlConsoleNoteId}`);
|
2021-09-16 22:09:39 +02:00
|
|
|
const today = dateUtils.localNowDate();
|
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
const sqlConsoleHome = attributeService.getNoteWithLabel("sqlConsoleHome") || dateNoteService.getDayNote(today);
|
2021-09-16 22:09:39 +02:00
|
|
|
|
2021-10-24 14:53:45 +02:00
|
|
|
const result = sqlConsoleNote.cloneTo(sqlConsoleHome.noteId);
|
|
|
|
|
|
|
|
for (const parentBranch of sqlConsoleNote.getParentBranches()) {
|
2025-01-09 18:07:02 +02:00
|
|
|
if (parentBranch.parentNote?.hasAncestor("_hidden")) {
|
2021-10-24 14:53:45 +02:00
|
|
|
parentBranch.markAsDeleted();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
2021-09-16 22:09:39 +02:00
|
|
|
}
|
|
|
|
|
2024-04-03 23:05:06 +03:00
|
|
|
function createSearchNote(searchString: string, ancestorNoteId: string) {
|
2025-01-09 18:07:02 +02:00
|
|
|
const { note } = noteService.createNewNote({
|
|
|
|
parentNoteId: getMonthlyParentNoteId("_search", "search"),
|
2024-10-25 21:04:13 +03:00
|
|
|
title: `${t("special_notes.search_prefix")} ${searchString}`,
|
2021-09-16 22:09:39 +02:00
|
|
|
content: "",
|
2025-01-09 18:07:02 +02:00
|
|
|
type: "search",
|
|
|
|
mime: "application/json"
|
2021-09-16 22:09:39 +02:00
|
|
|
});
|
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
note.setLabel("searchString", searchString);
|
|
|
|
note.setLabel("keepCurrentHoisting");
|
2021-09-16 22:09:39 +02:00
|
|
|
|
|
|
|
if (ancestorNoteId) {
|
2025-01-09 18:07:02 +02:00
|
|
|
note.setRelation("ancestor", ancestorNoteId);
|
2021-09-16 22:09:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return note;
|
|
|
|
}
|
|
|
|
|
2021-10-24 14:53:45 +02:00
|
|
|
function getSearchHome() {
|
2022-12-23 15:07:48 +01:00
|
|
|
const workspaceNote = hoistedNoteService.getWorkspaceNote();
|
2024-04-03 23:05:06 +03:00
|
|
|
if (!workspaceNote) {
|
|
|
|
throw new Error("Unable to find workspace note");
|
|
|
|
}
|
2021-09-16 22:09:39 +02:00
|
|
|
|
2022-12-23 15:07:48 +01:00
|
|
|
if (!workspaceNote.isRoot()) {
|
2025-01-09 18:07:02 +02:00
|
|
|
return workspaceNote.searchNoteInSubtree("#workspaceSearchHome") || workspaceNote.searchNoteInSubtree("#searchHome") || workspaceNote;
|
2021-10-24 14:53:45 +02:00
|
|
|
} else {
|
2021-09-16 22:09:39 +02:00
|
|
|
const today = dateUtils.localNowDate();
|
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
return workspaceNote.searchNoteInSubtree("#searchHome") || dateNoteService.getDayNote(today);
|
2021-09-16 22:09:39 +02:00
|
|
|
}
|
2021-10-24 14:53:45 +02:00
|
|
|
}
|
|
|
|
|
2024-04-03 23:05:06 +03:00
|
|
|
function saveSearchNote(searchNoteId: string) {
|
2021-10-24 14:53:45 +02:00
|
|
|
const searchNote = becca.getNote(searchNoteId);
|
2024-04-03 23:05:06 +03:00
|
|
|
if (!searchNote) {
|
|
|
|
throw new Error("Unable to find search note");
|
|
|
|
}
|
|
|
|
|
2021-10-24 14:53:45 +02:00
|
|
|
const searchHome = getSearchHome();
|
|
|
|
|
|
|
|
const result = searchNote.cloneTo(searchHome.noteId);
|
|
|
|
|
|
|
|
for (const parentBranch of searchNote.getParentBranches()) {
|
2025-01-09 18:07:02 +02:00
|
|
|
if (parentBranch.parentNote?.hasAncestor("_hidden")) {
|
2021-10-24 14:53:45 +02:00
|
|
|
parentBranch.markAsDeleted();
|
|
|
|
}
|
|
|
|
}
|
2021-09-16 22:09:39 +02:00
|
|
|
|
2021-10-24 14:53:45 +02:00
|
|
|
return result;
|
2021-09-16 22:09:39 +02:00
|
|
|
}
|
|
|
|
|
2024-04-03 23:05:06 +03:00
|
|
|
function getMonthlyParentNoteId(rootNoteId: string, prefix: string) {
|
2022-12-15 16:38:05 +01:00
|
|
|
const month = dateUtils.localNowDate().substring(0, 7);
|
2022-12-23 14:18:40 +01:00
|
|
|
const labelName = `${prefix}MonthNote`;
|
2022-12-15 16:38:05 +01:00
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
let monthNote = searchService.findFirstNoteWithQuery(`#${labelName}="${month}"`, new SearchContext({ ancestorNoteId: rootNoteId }));
|
2022-12-15 16:38:05 +01:00
|
|
|
|
|
|
|
if (!monthNote) {
|
|
|
|
monthNote = noteService.createNewNote({
|
|
|
|
parentNoteId: rootNoteId,
|
|
|
|
title: month,
|
2025-01-09 18:07:02 +02:00
|
|
|
content: "",
|
2022-12-15 16:38:05 +01:00
|
|
|
isProtected: false,
|
2025-01-09 18:07:02 +02:00
|
|
|
type: "book"
|
|
|
|
}).note;
|
2022-12-15 16:38:05 +01:00
|
|
|
|
|
|
|
monthNote.addLabel(labelName, month);
|
|
|
|
}
|
|
|
|
|
|
|
|
return monthNote.noteId;
|
|
|
|
}
|
|
|
|
|
2024-04-03 23:05:06 +03:00
|
|
|
function createScriptLauncher(parentNoteId: string, forceNoteId?: string) {
|
2022-12-17 21:46:51 +01:00
|
|
|
const note = noteService.createNewNote({
|
2022-12-23 20:40:58 +01:00
|
|
|
noteId: forceNoteId,
|
2022-12-17 21:46:51 +01:00
|
|
|
title: "Script Launcher",
|
2025-01-09 18:07:02 +02:00
|
|
|
type: "launcher",
|
|
|
|
content: "",
|
2022-12-17 21:46:51 +01:00
|
|
|
parentNoteId: parentNoteId
|
|
|
|
}).note;
|
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
note.addRelation("template", LBTPL_SCRIPT);
|
2022-12-17 21:46:51 +01:00
|
|
|
return note;
|
|
|
|
}
|
|
|
|
|
2025-02-24 12:39:40 +02:00
|
|
|
export type LauncherType = "launcher" | "note" | "script" | "customWidget" | "spacer";
|
|
|
|
|
2024-04-03 23:05:06 +03:00
|
|
|
interface LauncherConfig {
|
|
|
|
parentNoteId: string;
|
2025-02-24 12:39:40 +02:00
|
|
|
launcherType: LauncherType;
|
2024-04-06 23:11:02 +03:00
|
|
|
noteId?: string;
|
2024-04-03 23:05:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function createLauncher({ parentNoteId, launcherType, noteId }: LauncherConfig) {
|
2022-08-07 15:34:59 +02:00
|
|
|
let note;
|
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
if (launcherType === "note") {
|
2022-08-07 15:34:59 +02:00
|
|
|
note = noteService.createNewNote({
|
2022-12-23 20:40:58 +01:00
|
|
|
noteId: noteId,
|
2022-12-07 12:46:41 +01:00
|
|
|
title: "Note Launcher",
|
2025-01-09 18:07:02 +02:00
|
|
|
type: "launcher",
|
|
|
|
content: "",
|
2022-08-07 15:34:59 +02:00
|
|
|
parentNoteId: parentNoteId
|
|
|
|
}).note;
|
2022-11-29 16:16:57 +01:00
|
|
|
|
2025-03-09 02:19:26 +00:00
|
|
|
note.addRelation("template", LBTPL_NOTE);
|
2025-01-09 18:07:02 +02:00
|
|
|
} else if (launcherType === "script") {
|
2022-12-23 20:40:58 +01:00
|
|
|
note = createScriptLauncher(parentNoteId, noteId);
|
2025-01-09 18:07:02 +02:00
|
|
|
} else if (launcherType === "customWidget") {
|
2022-08-07 15:34:59 +02:00
|
|
|
note = noteService.createNewNote({
|
2022-12-23 20:40:58 +01:00
|
|
|
noteId: noteId,
|
2022-12-07 12:46:41 +01:00
|
|
|
title: "Widget Launcher",
|
2025-01-09 18:07:02 +02:00
|
|
|
type: "launcher",
|
|
|
|
content: "",
|
2022-08-07 15:34:59 +02:00
|
|
|
parentNoteId: parentNoteId
|
|
|
|
}).note;
|
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
note.addRelation("template", LBTPL_CUSTOM_WIDGET);
|
|
|
|
} else if (launcherType === "spacer") {
|
2022-08-07 15:34:59 +02:00
|
|
|
note = noteService.createNewNote({
|
2022-12-23 20:40:58 +01:00
|
|
|
noteId: noteId,
|
|
|
|
branchId: noteId,
|
2022-08-07 15:34:59 +02:00
|
|
|
title: "Spacer",
|
2025-01-09 18:07:02 +02:00
|
|
|
type: "launcher",
|
|
|
|
content: "",
|
2022-08-07 15:34:59 +02:00
|
|
|
parentNoteId: parentNoteId
|
|
|
|
}).note;
|
2022-08-07 13:23:03 +02:00
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
note.addRelation("template", LBTPL_SPACER);
|
2022-08-07 15:34:59 +02:00
|
|
|
} else {
|
2022-12-07 12:46:41 +01:00
|
|
|
throw new Error(`Unrecognized launcher type '${launcherType}'`);
|
2022-08-07 13:23:03 +02:00
|
|
|
}
|
2022-08-07 15:34:59 +02:00
|
|
|
|
|
|
|
return {
|
|
|
|
success: true,
|
|
|
|
note
|
|
|
|
};
|
2022-08-07 13:23:03 +02:00
|
|
|
}
|
|
|
|
|
2024-04-03 23:05:06 +03:00
|
|
|
function resetLauncher(noteId: string) {
|
2022-12-06 23:48:44 +01:00
|
|
|
const note = becca.getNote(noteId);
|
2022-11-25 15:29:57 +01:00
|
|
|
|
2024-04-03 23:05:06 +03:00
|
|
|
if (note?.isLaunchBarConfig()) {
|
2022-11-25 15:29:57 +01:00
|
|
|
if (note) {
|
2025-01-18 18:49:36 +02:00
|
|
|
if (noteId === "_lbRoot" || noteId === "_lbMobileRoot") {
|
2022-11-25 15:29:57 +01:00
|
|
|
// deleting hoisted notes are not allowed, so we just reset the children
|
|
|
|
for (const childNote of note.getChildNotes()) {
|
|
|
|
childNote.deleteNote();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
note.deleteNote();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
log.info(`Note ${noteId} has not been found and cannot be reset.`);
|
|
|
|
}
|
|
|
|
} else {
|
2022-12-01 10:16:57 +01:00
|
|
|
log.info(`Note ${noteId} is not a resettable launcher note.`);
|
2022-11-25 15:29:57 +01:00
|
|
|
}
|
|
|
|
|
2023-01-13 11:53:25 +01:00
|
|
|
// the re-building deleted launchers will be done in handlers
|
2022-11-25 15:29:57 +01:00
|
|
|
}
|
|
|
|
|
2022-12-17 21:46:51 +01:00
|
|
|
/**
|
|
|
|
* This exists to ease transition into the new launchbar, but it's not meant to be a permanent functionality.
|
|
|
|
* Previously, the launchbar was fixed and the only way to add buttons was through this API, so a lot of buttons have been
|
|
|
|
* created just to fill this user hole.
|
|
|
|
*
|
2022-12-22 14:59:20 +01:00
|
|
|
* Another use case was for script-packages (e.g. demo Task manager) which could this way register automatically/easily
|
|
|
|
* into the launchbar - for this it's recommended to use backend API's createOrUpdateLauncher()
|
2022-12-17 21:46:51 +01:00
|
|
|
*/
|
2025-01-09 18:07:02 +02:00
|
|
|
function createOrUpdateScriptLauncherFromApi(opts: { id: string; title: string; action: string; icon?: string; shortcut?: string }) {
|
2022-12-22 14:57:00 +01:00
|
|
|
if (opts.id && !/^[a-z0-9]+$/i.test(opts.id)) {
|
|
|
|
throw new Error(`Launcher ID can be alphanumeric only, '${opts.id}' given`);
|
|
|
|
}
|
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
const launcherId = opts.id || `tb_${opts.title.toLowerCase().replace(/[^[a-z0-9]/gi, "")}`;
|
2022-12-17 21:46:51 +01:00
|
|
|
|
|
|
|
if (!opts.title) {
|
|
|
|
throw new Error("Title is mandatory property to create or update a launcher.");
|
|
|
|
}
|
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
const launcherNote = becca.getNote(launcherId) || createScriptLauncher("_lbVisibleLaunchers", launcherId);
|
2022-12-17 21:46:51 +01:00
|
|
|
|
|
|
|
launcherNote.title = opts.title;
|
2022-12-21 15:19:05 +01:00
|
|
|
launcherNote.setContent(`(${opts.action})()`);
|
2025-01-09 18:07:02 +02:00
|
|
|
launcherNote.setLabel("scriptInLauncherContent"); // there's no target note, the script is in the launcher's content
|
|
|
|
launcherNote.mime = "application/javascript;env=frontend";
|
2022-12-17 21:46:51 +01:00
|
|
|
launcherNote.save();
|
|
|
|
|
|
|
|
if (opts.shortcut) {
|
2025-01-09 18:07:02 +02:00
|
|
|
launcherNote.setLabel("keyboardShortcut", opts.shortcut);
|
2022-12-17 21:46:51 +01:00
|
|
|
} else {
|
2025-01-09 18:07:02 +02:00
|
|
|
launcherNote.removeLabel("keyboardShortcut");
|
2022-12-17 21:46:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (opts.icon) {
|
2025-01-09 18:07:02 +02:00
|
|
|
launcherNote.setLabel("iconClass", `bx bx-${opts.icon}`);
|
2022-12-17 21:46:51 +01:00
|
|
|
} else {
|
2025-01-09 18:07:02 +02:00
|
|
|
launcherNote.removeLabel("iconClass");
|
2022-12-17 21:46:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return launcherNote;
|
|
|
|
}
|
|
|
|
|
2024-07-18 21:47:30 +03:00
|
|
|
export default {
|
2021-09-16 22:09:39 +02:00
|
|
|
getInboxNote,
|
|
|
|
createSqlConsole,
|
|
|
|
saveSqlConsole,
|
|
|
|
createSearchNote,
|
2021-09-16 22:20:59 +02:00
|
|
|
saveSearchNote,
|
2022-12-01 10:16:57 +01:00
|
|
|
createLauncher,
|
2022-12-17 21:46:51 +01:00
|
|
|
resetLauncher,
|
|
|
|
createOrUpdateScriptLauncherFromApi
|
2021-09-16 22:09:39 +02:00
|
|
|
};
|