Merge remote-tracking branch 'origin/next58' into next58

This commit is contained in:
zadam 2022-12-02 15:27:30 +01:00
commit 0d50cdb0f5
86 changed files with 630 additions and 518 deletions

View File

@ -1,24 +1,26 @@
import froca from "./froca.js";
import bundleService from "./bundle.js";
import froca from "../services/froca.js";
import bundleService from "../services/bundle.js";
import RootCommandExecutor from "./root_command_executor.js";
import Entrypoints from "./entrypoints.js";
import options from "./options.js";
import utils from "./utils.js";
import zoomService from "./zoom.js";
import options from "../services/options.js";
import utils from "../services/utils.js";
import zoomComponent from "./zoom.js";
import TabManager from "./tab_manager.js";
import treeService from "./tree.js";
import Component from "../widgets/component.js";
import keyboardActionsService from "./keyboard_actions.js";
import MobileScreenSwitcherExecutor from "../widgets/mobile_widgets/mobile_screen_switcher.js";
import treeService from "../services/tree.js";
import Component from "./component.js";
import keyboardActionsService from "../services/keyboard_actions.js";
import MobileScreenSwitcherExecutor from "./mobile_screen_switcher.js";
import MainTreeExecutors from "./main_tree_executors.js";
import toast from "./toast.js";
import toast from "../services/toast.js";
import ShortcutComponent from "./shortcut_component.js";
class AppContext extends Component {
constructor(isMainWindow) {
super();
this.isMainWindow = isMainWindow;
this.executors = [];
// non-widget/layout components needed for the application
this.components = [];
this.beforeUnloadListeners = [];
}
@ -27,7 +29,9 @@ class AppContext extends Component {
}
async start() {
this.showWidgets();
this.initComponents();
this.renderWidgets();
await Promise.all([froca.initializedPromise, options.initializedPromise]);
@ -36,7 +40,31 @@ class AppContext extends Component {
setTimeout(() => bundleService.executeStartupBundles(), 2000);
}
showWidgets() {
initComponents() {
this.tabManager = new TabManager();
this.components = [
this.tabManager,
new RootCommandExecutor(),
new Entrypoints(),
new MainTreeExecutors(),
new ShortcutComponent()
];
if (utils.isMobile()) {
this.components.push(new MobileScreenSwitcherExecutor());
}
for (const component of this.components) {
this.child(component);
}
if (utils.isElectron()) {
this.child(zoomComponent);
}
}
renderWidgets() {
const rootWidget = this.layout.getRootWidget(this);
const $renderedWidget = rootWidget.render();
@ -52,29 +80,8 @@ class AppContext extends Component {
component.triggerCommand(commandName, {$el: $(this)});
});
this.tabManager = new TabManager();
this.executors = [
this.tabManager,
new RootCommandExecutor(),
new Entrypoints(),
new MainTreeExecutors()
];
if (utils.isMobile()) {
this.executors.push(new MobileScreenSwitcherExecutor());
}
this.child(rootWidget);
for (const executor of this.executors) {
this.child(executor);
}
if (utils.isElectron()) {
this.child(zoomService);
}
this.triggerEvent('initialRenderComplete');
}
@ -85,7 +92,7 @@ class AppContext extends Component {
/** @returns {Promise} */
triggerCommand(name, data = {}) {
for (const executor of this.executors) {
for (const executor of this.components) {
const fun = executor[name + "Command"];
if (fun) {

View File

@ -1,13 +1,13 @@
import utils from "./utils.js";
import dateNoteService from "./date_notes.js";
import protectedSessionHolder from './protected_session_holder.js';
import server from "./server.js";
import utils from "../services/utils.js";
import dateNoteService from "../services/date_notes.js";
import protectedSessionHolder from '../services/protected_session_holder.js';
import server from "../services/server.js";
import appContext from "./app_context.js";
import Component from "../widgets/component.js";
import toastService from "./toast.js";
import ws from "./ws.js";
import bundleService from "./bundle.js";
import froca from "./froca.js";
import Component from "./component.js";
import toastService from "../services/toast.js";
import ws from "../services/ws.js";
import bundleService from "../services/bundle.js";
import froca from "../services/froca.js";
export default class Entrypoints extends Component {
constructor() {

View File

@ -1,8 +1,8 @@
import appContext from "./app_context.js";
import noteCreateService from "./note_create.js";
import treeService from "./tree.js";
import hoistedNoteService from "./hoisted_note.js";
import Component from "../widgets/component.js";
import noteCreateService from "../services/note_create.js";
import treeService from "../services/tree.js";
import hoistedNoteService from "../services/hoisted_note.js";
import Component from "./component.js";
/**
* This class contains command executors which logically belong to the NoteTree widget, but for better user experience

View File

@ -1,4 +1,4 @@
import Component from "../component.js";
import Component from "./component.js";
export default class MobileScreenSwitcherExecutor extends Component {
setActiveScreenCommand({screen}) {
@ -12,4 +12,4 @@ export default class MobileScreenSwitcherExecutor extends Component {
initialRenderCompleteEvent() {
this.setActiveScreenCommand({screen: 'tree'});
}
}
}

View File

@ -1,12 +1,12 @@
import protectedSessionHolder from "./protected_session_holder.js";
import server from "./server.js";
import utils from "./utils.js";
import protectedSessionHolder from "../services/protected_session_holder.js";
import server from "../services/server.js";
import utils from "../services/utils.js";
import appContext from "./app_context.js";
import treeService from "./tree.js";
import Component from "../widgets/component.js";
import froca from "./froca.js";
import hoistedNoteService from "./hoisted_note.js";
import options from "./options.js";
import treeService from "../services/tree.js";
import Component from "./component.js";
import froca from "../services/froca.js";
import hoistedNoteService from "../services/hoisted_note.js";
import options from "../services/options.js";
class NoteContext extends Component {
/**

View File

@ -1,11 +1,11 @@
import Component from "../widgets/component.js";
import Component from "./component.js";
import appContext from "./app_context.js";
import dateNoteService from "../services/date_notes.js";
import treeService from "../services/tree.js";
import openService from "./open.js";
import protectedSessionService from "./protected_session.js";
import options from "./options.js";
import froca from "./froca.js";
import openService from "../services/open.js";
import protectedSessionService from "../services/protected_session.js";
import options from "../services/options.js";
import froca from "../services/froca.js";
export default class RootCommandExecutor extends Component {
editReadOnlyNoteCommand() {
@ -46,7 +46,7 @@ export default class RootCommandExecutor extends Component {
openNoteExternallyCommand() {
const noteId = appContext.tabManager.getActiveContextNoteId();
const mime = appContext.tabManager.getActiveContextNoteMime()
if (noteId) {
openService.openNoteExternally(noteId, mime);
}
@ -72,7 +72,7 @@ export default class RootCommandExecutor extends Component {
options.toggle('leftPaneVisible');
}
async showLaunchBarShortcutsCommand() {
async showLaunchBarSubtreeCommand() {
await appContext.tabManager.openContextWithNote('lb_root', true, null, 'lb_root');
}

View File

@ -0,0 +1,40 @@
import appContext from "./app_context.js";
import shortcutService from "../services/shortcuts.js";
import server from "../services/server.js";
import Component from "./component.js";
import froca from "../services/froca.js";
export default class ShortcutComponent extends Component {
constructor() {
super();
server.get('keyboard-shortcuts-for-notes').then(shortcutAttributes => {
for (const attr of shortcutAttributes) {
this.bindNoteShortcutHandler(attr);
}
});
}
bindNoteShortcutHandler(label) {
const handler = () => appContext.tabManager.getActiveContext().setNote(label.noteId);
const namespace = label.attributeId;
if (label.isDeleted) {
shortcutService.removeGlobalShortcut(namespace);
} else {
shortcutService.bindGlobalShortcut(label.value, handler, namespace);
}
}
async entitiesReloadedEvent({loadResults}) {
for (const attr of loadResults.getAttributes()) {
if (attr.type === 'label' && attr.name === 'keyboardShortcut') {
const note = await froca.getNote(attr.noteId);
// launcher shortcuts are handled specifically
if (note && note.type !== 'launcher') {
this.bindNoteShortcutHandler(attr);
}
}
}
}
}

View File

@ -1,10 +1,10 @@
import Component from "../widgets/component.js";
import SpacedUpdate from "./spaced_update.js";
import server from "./server.js";
import options from "./options.js";
import froca from "./froca.js";
import treeService from "./tree.js";
import utils from "./utils.js";
import Component from "./component.js";
import SpacedUpdate from "../services/spaced_update.js";
import server from "../services/server.js";
import options from "../services/options.js";
import froca from "../services/froca.js";
import treeService from "../services/tree.js";
import utils from "../services/utils.js";
import NoteContext from "./note_context.js";
import appContext from "./app_context.js";
import Mutex from "../utils/mutex.js";

View File

@ -1,11 +1,11 @@
import options from "./options.js";
import Component from "../widgets/component.js";
import options from "../services/options.js";
import Component from "./component.js";
import utils from "../services/utils.js";
const MIN_ZOOM = 0.5;
const MAX_ZOOM = 2.0;
class ZoomService extends Component {
class ZoomComponent extends Component {
constructor() {
super();
@ -59,6 +59,6 @@ class ZoomService extends Component {
}
}
const zoomService = new ZoomService();
const zoomService = new ZoomComponent();
export default zoomService;

View File

@ -1,4 +1,4 @@
import appContext from "./services/app_context.js";
import appContext from "./components/app_context.js";
import utils from './services/utils.js';
import noteTooltipService from './services/note_tooltip.js';
import bundleService from "./services/bundle.js";
@ -7,7 +7,7 @@ import macInit from './services/mac_init.js';
import contextMenu from "./menus/context_menu.js";
import DesktopLayout from "./layouts/desktop_layout.js";
import glob from "./services/glob.js";
import zoomService from './services/zoom.js';
import zoomService from './components/zoom.js';
bundleService.getWidgetBundlesByParent().then(widgetBundles => {
appContext.setLayout(new DesktopLayout(widgetBundles));

View File

@ -0,0 +1 @@
<p>Keyboard shortcut for this launcher action can be configured in Options -> Shortcuts.</p>

View File

@ -21,7 +21,7 @@ const NOTE_TYPE_ICONS = {
"mermaid": "bx bx-selection",
"canvas": "bx bx-pen",
"web-view": "bx bx-globe-alt",
"shortcut": "bx bx-link",
"launcher": "bx bx-link",
"doc": "bx bxs-file-doc"
};
@ -827,7 +827,7 @@ class NoteShort {
}
isLaunchBarConfig() {
return this.type === 'shortcut' || this.noteId.startsWith("lb_");
return this.type === 'launcher' || this.noteId.startsWith("lb_");
}
}

View File

@ -72,7 +72,7 @@ import OptionsDialog from "../widgets/dialogs/options.js";
import FloatingButtons from "../widgets/floating_buttons/floating_buttons.js";
import RelationMapButtons from "../widgets/floating_buttons/relation_map_buttons.js";
import MermaidExportButton from "../widgets/floating_buttons/mermaid_export_button.js";
import ShortcutContainer from "../widgets/containers/shortcut_container.js";
import LauncherContainer from "../widgets/containers/launcher_container.js";
import NoteRevisionsButton from "../widgets/buttons/note_revisions_button.js";
import EditableCodeButtonsWidget from "../widgets/type_widgets/editable_code_buttons.js";
import ApiLogWidget from "../widgets/api_log.js";
@ -104,7 +104,7 @@ export default class DesktopLayout {
.id("launcher-pane")
.css("width", "53px")
.child(new GlobalMenuWidget())
.child(new ShortcutContainer())
.child(new LauncherContainer())
.child(new LeftPaneToggleWidget())
)
.child(new LeftPaneContainer()

View File

@ -4,7 +4,7 @@ import contextMenu from "./context_menu.js";
import dialogService from "../services/dialog.js";
import server from "../services/server.js";
export default class ShortcutContextMenu {
export default class LauncherContextMenu {
/**
* @param {NoteTreeWidget} treeWidget
* @param {FancytreeNode} node
@ -27,38 +27,38 @@ export default class ShortcutContextMenu {
const note = await froca.getNote(this.node.data.noteId);
const parentNoteId = this.node.getParent().data.noteId;
const isVisibleRoot = note.noteId === 'lb_visibleshortcuts';
const isAvailableRoot = note.noteId === 'lb_availableshortcuts';
const isVisibleItem = parentNoteId === 'lb_visibleshortcuts';
const isAvailableItem = parentNoteId === 'lb_availableshortcuts';
const isVisibleRoot = note.noteId === 'lb_visiblelaunchers';
const isAvailableRoot = note.noteId === 'lb_availablelaunchers';
const isVisibleItem = parentNoteId === 'lb_visiblelaunchers';
const isAvailableItem = parentNoteId === 'lb_availablelaunchers';
const isItem = isVisibleItem || isAvailableItem;
const canBeDeleted = !note.noteId.startsWith("lb_");
const canBeReset = note.noteId.startsWith("lb_");
return [
(isVisibleRoot || isAvailableRoot) ? { title: 'Add note shortcut', command: 'addNoteShortcut', uiIcon: "bx bx-plus" } : null,
(isVisibleRoot || isAvailableRoot) ? { title: 'Add script shortcut', command: 'addScriptShortcut', uiIcon: "bx bx-plus" } : null,
(isVisibleRoot || isAvailableRoot) ? { title: 'Add widget shortcut', command: 'addWidgetShortcut', uiIcon: "bx bx-plus" } : null,
(isVisibleRoot || isAvailableRoot) ? { title: 'Add spacer', command: 'addSpacerShortcut', uiIcon: "bx bx-plus" } : null,
(isVisibleRoot || isAvailableRoot) ? { title: 'Add a note launcher', command: 'addNoteLauncher', uiIcon: "bx bx-plus" } : null,
(isVisibleRoot || isAvailableRoot) ? { title: 'Add a script launcher', command: 'addScriptLauncher', uiIcon: "bx bx-plus" } : null,
(isVisibleRoot || isAvailableRoot) ? { title: 'Add a custom widget', command: 'addWidgetLauncher', uiIcon: "bx bx-plus" } : null,
(isVisibleRoot || isAvailableRoot) ? { title: 'Add spacer', command: 'addSpacerLauncher', uiIcon: "bx bx-plus" } : null,
(isVisibleRoot || isAvailableRoot) ? { title: "----" } : null,
{ title: 'Delete <kbd data-command="deleteNotes"></kbd>', command: "deleteNotes", uiIcon: "bx bx-trash", enabled: canBeDeleted },
{ title: 'Reset', command: "resetShortcut", uiIcon: "bx bx-empty", enabled: canBeReset},
{ title: 'Reset', command: "resetLauncher", uiIcon: "bx bx-empty", enabled: canBeReset},
{ title: "----" },
isAvailableItem ? { title: 'Move to visible shortcuts', command: "moveShortcutToVisible", uiIcon: "bx bx-show", enabled: true } : null,
isVisibleItem ? { title: 'Move to available shortcuts', command: "moveShortcutToAvailable", uiIcon: "bx bx-hide", enabled: true } : null,
{ title: `Duplicate shortcut <kbd data-command="duplicateSubtree">`, command: "duplicateSubtree", uiIcon: "bx bx-empty",
isAvailableItem ? { title: 'Move to visible launchers', command: "moveLauncherToVisible", uiIcon: "bx bx-show", enabled: true } : null,
isVisibleItem ? { title: 'Move to available launchers', command: "moveLauncherToAvailable", uiIcon: "bx bx-hide", enabled: true } : null,
{ title: `Duplicate launcher <kbd data-command="duplicateSubtree">`, command: "duplicateSubtree", uiIcon: "bx bx-empty",
enabled: isItem }
].filter(row => row !== null);
}
async selectMenuItemHandler({command}) {
if (command === 'resetShortcut') {
if (command === 'resetLauncher') {
const confirmed = await dialogService.confirm(`Do you really want to reset "${this.node.title}"?
All data / settings in this shortcut (and its children) will be lost
and the shortcut will be returned to its original location.`);
All data / settings in this note (and its children) will be lost
and the launcher will be returned to its original location.`);
if (confirmed) {
await server.post(`special-notes/shortcuts/${this.node.data.noteId}/reset`);
await server.post(`special-notes/launchers/${this.node.data.noteId}/reset`);
}
return;

View File

@ -1,5 +1,5 @@
import contextMenu from "./context_menu.js";
import appContext from "../services/app_context.js";
import appContext from "../components/app_context.js";
function openContextMenu(notePath, e) {
contextMenu.show({

View File

@ -3,7 +3,7 @@ import froca from "../services/froca.js";
import clipboard from '../services/clipboard.js';
import noteCreateService from "../services/note_create.js";
import contextMenu from "./context_menu.js";
import appContext from "../services/app_context.js";
import appContext from "../components/app_context.js";
import noteTypesService from "../services/note_types.js";
export default class TreeContextMenu {

View File

@ -1,8 +1,8 @@
import appContext from "./services/app_context.js";
import appContext from "./components/app_context.js";
import MobileLayout from "./layouts/mobile_layout.js";
import glob from "./services/glob.js";
glob.setupGlobs();
appContext.setLayout(new MobileLayout());
appContext.start();
appContext.start();

View File

@ -4,13 +4,13 @@ import toastService from "./toast.js";
import froca from "./froca.js";
import hoistedNoteService from "./hoisted_note.js";
import ws from "./ws.js";
import appContext from "./app_context.js";
import appContext from "../components/app_context.js";
async function moveBeforeBranch(branchIdsToMove, beforeBranchId) {
branchIdsToMove = filterRootNote(branchIdsToMove);
branchIdsToMove = filterSearchBranches(branchIdsToMove);
if (['root', 'lb_root', 'lb_availableshortcuts', 'lb_visibleshortcuts'].includes(beforeBranchId)) {
if (['root', 'lb_root', 'lb_availablelaunchers', 'lb_visiblelaunchers'].includes(beforeBranchId)) {
toastService.showError('Cannot move notes here.');
return;
}
@ -35,8 +35,8 @@ async function moveAfterBranch(branchIdsToMove, afterBranchId) {
'root',
hoistedNoteService.getHoistedNoteId(),
'lb_root',
'lb_availableshortcuts',
'lb_visibleshortcuts'
'lb_availablelaunchers',
'lb_visiblelaunchers'
];
if (forbiddenNoteIds.includes(afterNote.noteId)) {

View File

@ -1,4 +1,4 @@
import appContext from "./app_context.js";
import appContext from "../components/app_context.js";
async function info(message) {
return new Promise(res =>

View File

@ -1,5 +1,5 @@
import ws from "./ws.js";
import appContext from "./app_context.js";
import appContext from "../components/app_context.js";
const fileModificationStatus = {};

View File

@ -2,7 +2,7 @@ import Branch from "../entities/branch.js";
import NoteShort from "../entities/note_short.js";
import Attribute from "../entities/attribute.js";
import server from "./server.js";
import appContext from "./app_context.js";
import appContext from "../components/app_context.js";
import NoteComplement from "../entities/note_complement.js";
/**

View File

@ -76,7 +76,7 @@ async function processEntityChanges(entityChanges) {
noteAttributeCache.invalidate();
}
const appContext = (await import("./app_context.js")).default;
const appContext = (await import("../components/app_context.js")).default;
await appContext.triggerEvent('entitiesReloaded', {loadResults});
}
}

View File

@ -9,10 +9,11 @@ import dateNotesService from './date_notes.js';
import searchService from './search.js';
import CollapsibleWidget from '../widgets/collapsible_widget.js';
import ws from "./ws.js";
import appContext from "./app_context.js";
import appContext from "../components/app_context.js";
import NoteContextAwareWidget from "../widgets/note_context_aware_widget.js";
import BasicWidget from "../widgets/basic_widget.js";
import SpacedUpdate from "./spaced_update.js";
import shortcutService from "./shortcuts.js";
/**
* This is the main frontend API interface for scripts. It's published in the local "api" object.
@ -508,8 +509,10 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
* @method
* @param {string} keyboardShortcut - e.g. "ctrl+shift+a"
* @param {function} handler
* @param {string} [namespace] - specify namespace of the handler for the cases where call for bind may be repeated.
* If a handler with this ID exists, it's replaced by the new handler.
*/
this.bindGlobalShortcut = utils.bindGlobalShortcut;
this.bindGlobalShortcut = shortcutService.bindGlobalShortcut;
/**
* Trilium runs in backend and frontend process, when something is changed on the backend from script,

View File

@ -1,5 +1,5 @@
import utils from "./utils.js";
import appContext from "./app_context.js";
import appContext from "../components/app_context.js";
import server from "./server.js";
import libraryLoader from "./library_loader.js";
import ws from "./ws.js";

View File

@ -1,4 +1,4 @@
import appContext from "./app_context.js";
import appContext from "../components/app_context.js";
import treeService from "./tree.js";
import dialogService from "./dialog.js";
import froca from "./froca.js";

View File

@ -2,7 +2,7 @@ import toastService from "./toast.js";
import server from "./server.js";
import ws from "./ws.js";
import utils from "./utils.js";
import appContext from "./app_context.js";
import appContext from "../components/app_context.js";
export async function uploadFiles(parentNoteId, files, options) {
if (files.length === 0) {

View File

@ -1,6 +1,6 @@
import server from "./server.js";
import utils from "./utils.js";
import appContext from "./app_context.js";
import appContext from "../components/app_context.js";
import shortcutService from "./shortcuts.js";
const keyboardActionRepo = {};
@ -31,7 +31,7 @@ async function setupActionsForElement(scope, $el, component) {
for (const action of actions) {
for (const shortcut of action.effectiveShortcuts) {
utils.bindElShortcut($el, shortcut, () => component.triggerCommand(action.actionName, {ntxId: appContext.tabManager.activeNtxId}));
shortcutService.bindElShortcut($el, shortcut, () => component.triggerCommand(action.actionName, {ntxId: appContext.tabManager.activeNtxId}));
}
}
}
@ -39,37 +39,11 @@ async function setupActionsForElement(scope, $el, component) {
getActionsForScope("window").then(actions => {
for (const action of actions) {
for (const shortcut of action.effectiveShortcuts) {
utils.bindGlobalShortcut(shortcut, () => appContext.triggerCommand(action.actionName, {ntxId: appContext.tabManager.activeNtxId}));
shortcutService.bindGlobalShortcut(shortcut, () => appContext.triggerCommand(action.actionName, {ntxId: appContext.tabManager.activeNtxId}));
}
}
});
server.get('keyboard-shortcuts-for-notes').then(shortcutForNotes => {
for (const shortcut in shortcutForNotes) {
utils.bindGlobalShortcut(shortcut, async () => {
appContext.tabManager.getActiveContext().setNote(shortcutForNotes[shortcut]);
});
}
});
function setElementActionHandler($el, actionName, handler) {
keyboardActionsLoaded.then(() => {
const action = keyboardActionRepo[actionName];
if (!action) {
throw new Error(`Cannot find keyboard action '${actionName}'`);
}
// not setting action.handler since this is not global
for (const shortcut of action.effectiveShortcuts) {
if (shortcut) {
utils.bindElShortcut($el, shortcut, handler);
}
}
});
}
async function getAction(actionName, silent = false) {
await keyboardActionsLoaded;
@ -116,10 +90,8 @@ function updateDisplayedShortcuts($container) {
}
export default {
setElementActionHandler,
updateDisplayedShortcuts,
setupActionsForElement,
getActions,
getActionsForScope,
getAction
getActionsForScope
};

View File

@ -1,6 +1,6 @@
import treeService from './tree.js';
import linkContextMenuService from "../menus/link_context_menu.js";
import appContext from "./app_context.js";
import appContext from "../components/app_context.js";
import froca from "./froca.js";
import utils from "./utils.js";

View File

@ -2,15 +2,16 @@
* Mac specific initialization
*/
import utils from "./utils.js";
import shortcutService from "./shortcuts.js";
function init() {
if (utils.isElectron() && utils.isMac()) {
utils.bindGlobalShortcut('meta+c', () => exec("copy"));
utils.bindGlobalShortcut('meta+v', () => exec('paste'));
utils.bindGlobalShortcut('meta+x', () => exec('cut'));
utils.bindGlobalShortcut('meta+a', () => exec('selectAll'));
utils.bindGlobalShortcut('meta+z', () => exec('undo'));
utils.bindGlobalShortcut('meta+y', () => exec('redo'));
shortcutService.bindGlobalShortcut('meta+c', () => exec("copy"));
shortcutService.bindGlobalShortcut('meta+v', () => exec('paste'));
shortcutService.bindGlobalShortcut('meta+x', () => exec('cut'));
shortcutService.bindGlobalShortcut('meta+a', () => exec('selectAll'));
shortcutService.bindGlobalShortcut('meta+z', () => exec('undo'));
shortcutService.bindGlobalShortcut('meta+y', () => exec('redo'));
}
}
@ -22,4 +23,4 @@ function exec(cmd) {
export default {
init
}
}

View File

@ -1,5 +1,5 @@
import server from "./server.js";
import appContext from "./app_context.js";
import appContext from "../components/app_context.js";
import utils from './utils.js';
import noteCreateService from './note_create.js';
import treeService from './tree.js';

View File

@ -1,4 +1,4 @@
import appContext from "./app_context.js";
import appContext from "../components/app_context.js";
import utils from "./utils.js";
import protectedSessionHolder from "./protected_session_holder.js";
import server from "./server.js";

View File

@ -2,7 +2,7 @@ import server from './server.js';
import protectedSessionHolder from './protected_session_holder.js';
import toastService from "./toast.js";
import ws from "./ws.js";
import appContext from "./app_context.js";
import appContext from "../components/app_context.js";
import froca from "./froca.js";
import utils from "./utils.js";
import options from "./options.js";

View File

@ -3,7 +3,7 @@ import utils from './utils.js';
const REQUEST_LOGGING_ENABLED = false;
async function getHeaders(headers) {
const appContext = (await import('./app_context.js')).default;
const appContext = (await import('../components/app_context.js')).default;
const activeNoteContext = appContext.tabManager ? appContext.tabManager.getActiveContext() : null;
// headers need to be lowercase because node.js automatically converts them to lower case

View File

@ -0,0 +1,57 @@
import utils from "./utils.js";
function removeGlobalShortcut(namespace) {
bindGlobalShortcut('', null, namespace);
}
function bindGlobalShortcut(keyboardShortcut, handler, namespace = null) {
bindElShortcut($(document), keyboardShortcut, handler, namespace);
}
function bindElShortcut($el, keyboardShortcut, handler, namespace = null) {
if (utils.isDesktop()) {
keyboardShortcut = normalizeShortcut(keyboardShortcut);
let eventName = 'keydown';
if (namespace) {
eventName += "." + namespace;
// if there's a namespace then we replace the existing event handler with the new one
$el.off(eventName);
}
// method can be called to remove the shortcut (e.g. when keyboardShortcut label is deleted)
if (keyboardShortcut) {
$el.bind(eventName, keyboardShortcut, e => {
handler(e);
e.preventDefault();
e.stopPropagation();
});
}
}
}
/**
* Normalize to the form expected by the jquery.hotkeys.js
*/
function normalizeShortcut(shortcut) {
if (!shortcut) {
return shortcut;
}
return shortcut
.toLowerCase()
.replace("enter", "return")
.replace("delete", "del")
.replace("ctrl+alt", "alt+ctrl")
.replace("meta+alt", "alt+meta"); // alt needs to be first;
}
export default {
bindGlobalShortcut,
bindElShortcut,
removeGlobalShortcut,
normalizeShortcut
}

View File

@ -3,7 +3,7 @@ import utils from './utils.js';
import server from './server.js';
import froca from './froca.js';
import hoistedNoteService from '../services/hoisted_note.js';
import appContext from "./app_context.js";
import appContext from "../components/app_context.js";
/**
* @return {string|null}

View File

@ -132,35 +132,6 @@ function randomString(len) {
return text;
}
function bindGlobalShortcut(keyboardShortcut, handler) {
bindElShortcut($(document), keyboardShortcut, handler);
}
function bindElShortcut($el, keyboardShortcut, handler) {
if (isDesktop()) {
keyboardShortcut = normalizeShortcut(keyboardShortcut);
$el.bind('keydown', keyboardShortcut, e => {
handler(e);
e.preventDefault();
e.stopPropagation();
});
}
}
/**
* Normalize to the form expected by the jquery.hotkeys.js
*/
function normalizeShortcut(shortcut) {
return shortcut
.toLowerCase()
.replace("enter", "return")
.replace("delete", "del")
.replace("ctrl+alt", "alt+ctrl")
.replace("meta+alt", "alt+meta"); // alt needs to be first;
}
function isMobile() {
return window.device === "mobile"
// window.device is not available in setup
@ -387,8 +358,6 @@ export default {
formatLabel,
toObject,
randomString,
bindGlobalShortcut,
bindElShortcut,
isMobile,
isDesktop,
setCookie,
@ -402,7 +371,6 @@ export default {
focusSavedElement,
isHtmlEmpty,
clearBrowserCache,
normalizeShortcut,
copySelectionToClipboard,
dynamicRequire,
timeLimit,

View File

@ -3,7 +3,7 @@ import toastService from "./toast.js";
import server from "./server.js";
import options from "./options.js";
import frocaUpdater from "./froca_updater.js";
import appContext from "./app_context.js";
import appContext from "../components/app_context.js";
const messageHandlers = [];

View File

@ -8,6 +8,7 @@ import promotedAttributeDefinitionParser from '../../services/promoted_attribute
import NoteContextAwareWidget from "../note_context_aware_widget.js";
import SpacedUpdate from "../../services/spaced_update.js";
import utils from "../../services/utils.js";
import shortcutService from "../../services/shortcuts.js";
const TPL = `
<div class="attr-detail">
@ -271,8 +272,8 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
this.$widget = $(TPL);
utils.bindElShortcut(this.$widget, 'ctrl+return', () => this.saveAndClose());
utils.bindElShortcut(this.$widget, 'esc', () => this.cancelAndClose());
shortcutService.bindElShortcut(this.$widget, 'ctrl+return', () => this.saveAndClose());
shortcutService.bindElShortcut(this.$widget, 'esc', () => this.cancelAndClose());
this.$title = this.$widget.find('.attr-detail-title');

View File

@ -1,4 +1,4 @@
import Component from "./component.js";
import Component from "../components/component.js";
class BasicWidget extends Component {
constructor() {

View File

@ -2,7 +2,7 @@ import libraryLoader from "../../services/library_loader.js";
import utils from "../../services/utils.js";
import dateNoteService from "../../services/date_notes.js";
import server from "../../services/server.js";
import appContext from "../../services/app_context.js";
import appContext from "../../components/app_context.js";
import RightDropdownButtonWidget from "./right_dropdown_button.js";
import toastService from "../../services/toast.js";

View File

@ -1,5 +1,5 @@
import ButtonWidget from "./button_widget.js";
import appContext from "../../services/app_context.js";
import appContext from "../../components/app_context.js";
import attributeService from "../../services/attributes.js";
import protectedSessionHolder from "../../services/protected_session_holder.js";

View File

@ -124,9 +124,9 @@ const TPL = `
<kbd ></kbd>
</li>
<li class="dropdown-item" data-trigger-command="showLaunchBarShortcuts">
<li class="dropdown-item" data-trigger-command="showLaunchBarSubtree">
<span class="bx bx-sidebar"></span>
Configure launchbar shortcuts
Configure launchbar
</li>
<li class="dropdown-item" data-trigger-command="showShareSubtree">

View File

@ -11,6 +11,6 @@ export default class NoteRevisionsButton extends ButtonWidget {
}
isEnabled() {
return super.isEnabled() && !['shortcut', 'doc'].includes(this.note?.type);
return super.isEnabled() && !['launcher', 'doc'].includes(this.note?.type);
}
}
}

View File

@ -1,5 +1,5 @@
import ButtonWidget from "./button_widget.js";
import appContext from "../../services/app_context.js";
import appContext from "../../components/app_context.js";
import froca from "../../services/froca.js";
// FIXME: this widget might not be useful anymore

View File

@ -0,0 +1,149 @@
import ButtonWidget from "../buttons/button_widget.js";
import dialogService from "../../services/dialog.js";
import appContext from "../../components/app_context.js";
import CalendarWidget from "../buttons/calendar.js";
import SpacerWidget from "../spacer.js";
import BookmarkButtons from "../bookmark_buttons.js";
import ProtectedSessionStatusWidget from "../buttons/protected_session_status.js";
import SyncStatusWidget from "../sync_status.js";
import BackInHistoryButtonWidget from "../buttons/history/history_back.js";
import ForwardInHistoryButtonWidget from "../buttons/history/history_forward.js";
import BasicWidget from "../basic_widget.js";
import shortcutService from "../../services/shortcuts.js";
export default class LauncherWidget extends BasicWidget {
constructor(launcherNote) {
super();
if (launcherNote.type !== 'launcher') {
throw new Error(`Note '${this.note.noteId}' '${this.note.title}' is not a launcher even though it's in the launcher subtree`);
}
this.note = launcherNote;
this.innerWidget = null;
this.handler = null;
}
isEnabled() {
return this.innerWidget.isEnabled();
}
doRender() {
this.$widget = this.innerWidget.render();
}
async initLauncher() {
const launcherType = this.note.getLabelValue("launcherType");
if (launcherType === 'command') {
this.handler = () => this.triggerCommand(this.note.getLabelValue("command"));
this.innerWidget = new ButtonWidget()
.title(this.note.title)
.icon(this.note.getIcon())
.onClick(this.handler);
} else if (launcherType === 'note') {
// 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 (but major) downside is more work in setting up the typical case where you actually want to have both title and icon in sync.
this.handler = () => {
const targetNoteId = this.note.getRelationValue('targetNote');
if (!targetNoteId) {
dialogService.info("This launcher doesn't define target note.");
return;
}
appContext.tabManager.openTabWithNoteWithHoisting(targetNoteId, true)
};
this.innerWidget = new ButtonWidget()
.title(this.note.title)
.icon(this.note.getIcon())
.onClick(this.handler);
} else if (launcherType === 'script') {
this.handler = async () => {
const script = await this.note.getRelationTarget('script');
await script.executeScript();
};
this.innerWidget = new ButtonWidget()
.title(this.note.title)
.icon(this.note.getIcon())
.onClick(this.handler);
} else if (launcherType === 'customWidget') {
const widget = await this.note.getRelationTarget('widget');
if (widget) {
this.innerWidget = await widget.executeScript();
} else {
throw new Error(`Could not initiate custom widget of launcher '${this.note.noteId}' '${this.note.title}`);
}
} else if (launcherType === 'builtinWidget') {
const builtinWidget = this.note.getLabelValue("builtinWidget");
if (builtinWidget) {
if (builtinWidget === 'calendar') {
this.innerWidget = new CalendarWidget(this.note.title, this.note.getIcon());
} else if (builtinWidget === 'spacer') {
// || has to be inside since 0 is a valid value
const baseSize = parseInt(this.note.getLabelValue("baseSize") || "40");
const growthFactor = parseInt(this.note.getLabelValue("growthFactor") || "100");
this.innerWidget = new SpacerWidget(baseSize, growthFactor);
} else if (builtinWidget === 'bookmarks') {
this.innerWidget = new BookmarkButtons();
} else if (builtinWidget === 'protectedSession') {
this.innerWidget = new ProtectedSessionStatusWidget();
} else if (builtinWidget === 'syncStatus') {
this.innerWidget = new SyncStatusWidget();
} else if (builtinWidget === 'backInHistoryButton') {
this.innerWidget = new BackInHistoryButtonWidget();
} else if (builtinWidget === 'forwardInHistoryButton') {
this.innerWidget = new ForwardInHistoryButtonWidget();
} else {
throw new Error(`Unrecognized builtin widget ${builtinWidget} for launcher ${this.note.noteId} "${this.note.title}"`);
}
}
} else {
throw new Error(`Unrecognized launcher type '${launcherType}' for launcher '${this.note.noteId}' title ${this.note.title}`);
}
if (!this.innerWidget) {
throw new Error(`Unknown initialization error for note '${this.note.noteId}', title '${this.note.title}'`);
}
for (const label of this.note.getLabels('keyboardShortcut')) {
this.bindNoteShortcutHandler(label);
}
this.child(this.innerWidget);
}
bindNoteShortcutHandler(label) {
if (!this.handler) {
return;
}
const namespace = label.attributeId;
if (label.isDeleted) {
shortcutService.removeGlobalShortcut(namespace);
} else {
shortcutService.bindGlobalShortcut(label.value, this.handler, namespace);
}
}
entitiesReloadedEvent({loadResults}) {
for (const attr of loadResults.getAttributes()) {
if (attr.noteId === this.note.noteId && attr.type === 'label' && attr.name === 'keyboardShortcut') {
this.bindNoteShortcutHandler(attr);
}
}
}
}

View File

@ -0,0 +1,70 @@
import FlexContainer from "./flex_container.js";
import froca from "../../services/froca.js";
import appContext from "../../components/app_context.js";
import LauncherWidget from "./launcher.js";
export default class LauncherContainer extends FlexContainer {
constructor() {
super('column');
this.id('launcher-container');
this.css('height', '100%');
this.filling();
this.load();
}
async load() {
this.children = [];
const visibleLaunchersRoot = await froca.getNote('lb_visiblelaunchers', true);
if (!visibleLaunchersRoot) {
console.log("Visible launchers root note doesn't exist.");
return;
}
await Promise.allSettled(
(await visibleLaunchersRoot.getChildNotes())
.map(async launcherNote => {
try {
const launcherWidget = new LauncherWidget(launcherNote);
await launcherWidget.initLauncher();
this.child(launcherWidget);
}
catch (e) {
console.error(e.message);
}
})
);
this.$widget.empty();
this.renderChildren();
await this.handleEventInChildren('initialRenderComplete');
const activeContext = appContext.tabManager.getActiveContext();
if (activeContext) {
await this.handleEvent('setNoteContext', {
noteContext: activeContext
});
if (activeContext.notePath) {
await this.handleEvent('noteSwitched', {
noteContext: activeContext,
notePath: activeContext.notePath
});
}
}
}
entitiesReloadedEvent({loadResults}) {
if (loadResults.getNoteIds().find(noteId => froca.notes[noteId]?.isLaunchBarConfig())
|| loadResults.getBranches().find(branch => branch.parentNoteId.startsWith("lb_"))
|| loadResults.getAttributes().find(attr => froca.notes[attr.noteId]?.isLaunchBarConfig())) {
this.load();
}
}
}

View File

@ -1,156 +0,0 @@
import FlexContainer from "./flex_container.js";
import froca from "../../services/froca.js";
import ButtonWidget from "../buttons/button_widget.js";
import CalendarWidget from "../buttons/calendar.js";
import appContext from "../../services/app_context.js";
import SpacerWidget from "../spacer.js";
import BookmarkButtons from "../bookmark_buttons.js";
import ProtectedSessionStatusWidget from "../buttons/protected_session_status.js";
import SyncStatusWidget from "../sync_status.js";
import BackInHistoryButtonWidget from "../buttons/history/history_back.js";
import ForwardInHistoryButtonWidget from "../buttons/history/history_forward.js";
import dialogService from "../../services/dialog.js";
export default class ShortcutContainer extends FlexContainer {
constructor() {
super('column');
this.id('shortcut-container');
this.css('height', '100%');
this.filling();
this.load();
}
async load() {
this.children = [];
const visibleShortcutsRoot = await froca.getNote('lb_visibleshortcuts', true);
if (!visibleShortcutsRoot) {
console.log("Visible shortcuts root note doesn't exist.");
return;
}
await Promise.allSettled(
(await visibleShortcutsRoot.getChildNotes())
.map(shortcut => this.initShortcut(shortcut))
);
this.$widget.empty();
this.renderChildren();
await this.handleEventInChildren('initialRenderComplete');
const activeContext = appContext.tabManager.getActiveContext();
if (activeContext) {
await this.handleEvent('setNoteContext', {
noteContext: activeContext
});
if (activeContext.notePath) {
await this.handleEvent('noteSwitched', {
noteContext: activeContext,
notePath: activeContext.notePath
});
}
}
}
async initShortcut(shortcut) {
try {
if (shortcut.type !== 'shortcut') {
console.warn(`Note ${shortcut.noteId} is not a shortcut even though it's in shortcut subtree`);
return;
}
const shortcutType = shortcut.getLabelValue("shortcutType");
if (shortcutType === 'command') {
this.child(new ButtonWidget()
.title(shortcut.title)
.icon(shortcut.getIcon())
.command(shortcut.getLabelValue("command")));
} else if (shortcutType === 'note') {
// we're intentionally displaying the shortcut title and icon instead of the target
// e.g. you want to make shortcuts 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 (but major) downside is more work in setting up the typical case where you actually want to have both title and icon in sync.
this.child(new ButtonWidget()
.title(shortcut.title)
.icon(shortcut.getIcon())
.onClick(() => {
const targetNoteId = shortcut.getRelationValue('targetNote');
if (!targetNoteId) {
dialogService.info("This shortcut doesn't define target note.");
return;
}
appContext.tabManager.openTabWithNoteWithHoisting(targetNoteId, true)
}));
} else if (shortcutType === 'script') {
this.child(new ButtonWidget()
.title(shortcut.title)
.icon(shortcut.getIcon())
.onClick(async () => {
const script = await shortcut.getRelationTarget('script');
await script.executeScript();
}));
} else if (shortcutType === 'customWidget') {
const widget = await shortcut.getRelationTarget('widget');
if (widget) {
const res = await widget.executeScript();
this.child(res);
}
} else if (shortcutType === 'builtinWidget') {
const builtinWidget = shortcut.getLabelValue("builtinWidget");
if (builtinWidget) {
if (builtinWidget === 'calendar') {
this.child(new CalendarWidget(shortcut.title, shortcut.getIcon()));
} else if (builtinWidget === 'spacer') {
// || has to be inside since 0 is a valid value
const baseSize = parseInt(shortcut.getLabelValue("baseSize") || "40");
const growthFactor = parseInt(shortcut.getLabelValue("growthFactor") || "100");
this.child(new SpacerWidget(baseSize, growthFactor));
} else if (builtinWidget === 'bookmarks') {
this.child(new BookmarkButtons());
} else if (builtinWidget === 'protectedSession') {
this.child(new ProtectedSessionStatusWidget());
} else if (builtinWidget === 'syncStatus') {
this.child(new SyncStatusWidget());
} else if (builtinWidget === 'backInHistoryButton') {
this.child(new BackInHistoryButtonWidget());
} else if (builtinWidget === 'forwardInHistoryButton') {
this.child(new ForwardInHistoryButtonWidget());
} else {
console.warn(`Unrecognized builtin widget ${builtinWidget} for shortcut ${shortcut.noteId} "${shortcut.title}"`);
}
}
} else {
console.warn(`Unrecognized shortcut type ${shortcutType} for shortcut '${shortcut.noteId}' title ${shortcut.title}`);
}
}
catch (e) {
console.error(`Initialization of shortcut '${shortcut.noteId}' with title '${shortcut.title}' failed with error: ${e.message} ${e.stack}`);
}
}
entitiesReloadedEvent({loadResults}) {
if (loadResults.getNoteIds().find(noteId => froca.notes[noteId]?.isLaunchBarConfig())
|| loadResults.getBranches().find(branch => branch.parentNoteId.startsWith("lb_"))
|| loadResults.getAttributes().find(attr => froca.notes[attr.noteId]?.isLaunchBarConfig())) {
this.load();
}
}
}

View File

@ -1,5 +1,5 @@
import FlexContainer from "./flex_container.js";
import appContext from "../../services/app_context.js";
import appContext from "../../components/app_context.js";
export default class SplitNoteContainer extends FlexContainer {
constructor(widgetFactory) {

View File

@ -4,7 +4,7 @@ import froca from "../../services/froca.js";
import toastService from "../../services/toast.js";
import utils from "../../services/utils.js";
import BasicWidget from "../basic_widget.js";
import appContext from "../../services/app_context.js";
import appContext from "../../components/app_context.js";
let branchId;

View File

@ -4,7 +4,7 @@ import treeService from "../../services/tree.js";
import toastService from "../../services/toast.js";
import froca from "../../services/froca.js";
import branchService from "../../services/branches.js";
import appContext from "../../services/app_context.js";
import appContext from "../../components/app_context.js";
import BasicWidget from "../basic_widget.js";
const TPL = `

View File

@ -1,7 +1,8 @@
import noteAutocompleteService from '../../services/note_autocomplete.js';
import utils from "../../services/utils.js";
import appContext from "../../services/app_context.js";
import appContext from "../../components/app_context.js";
import BasicWidget from "../basic_widget.js";
import shortcutService from "../../services/shortcuts.js";
const TPL = `<div class="jump-to-note-dialog modal mx-auto" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg" role="document">
@ -42,7 +43,7 @@ export default class JumpToNoteDialog extends BasicWidget {
this.$showInFullTextButton = this.$widget.find(".show-in-full-text-button");
this.$showInFullTextButton.on('click', e => this.showInFullText(e));
utils.bindElShortcut(this.$widget, 'ctrl+return', e => this.showInFullText(e));
shortcutService.bindElShortcut(this.$widget, 'ctrl+return', e => this.showInFullText(e));
}
async jumpToNoteEvent() {

View File

@ -1,8 +1,9 @@
import libraryLoader from "../../services/library_loader.js";
import toastService from "../../services/toast.js";
import utils from "../../services/utils.js";
import appContext from "../../services/app_context.js";
import appContext from "../../components/app_context.js";
import BasicWidget from "../basic_widget.js";
import shortcutService from "../../services/shortcuts.js";
const TPL = `
<div class="markdown-import-dialog modal fade mx-auto" tabindex="-1" role="dialog">
@ -42,7 +43,7 @@ export default class MarkdownImportDialog extends BasicWidget {
this.$widget.on('shown.bs.modal', () => this.$importTextarea.trigger('focus'));
utils.bindElShortcut(this.$widget, 'ctrl+return', () => this.sendForm());
shortcutService.bindElShortcut(this.$widget, 'ctrl+return', () => this.sendForm());
}
async convertMarkdownToHtml(text) {

View File

@ -1,7 +1,7 @@
import utils from '../../services/utils.js';
import server from '../../services/server.js';
import toastService from "../../services/toast.js";
import appContext from "../../services/app_context.js";
import appContext from "../../components/app_context.js";
import libraryLoader from "../../services/library_loader.js";
import openService from "../../services/open.js";
import protectedSessionHolder from "../../services/protected_session_holder.js";

View File

@ -1,4 +1,4 @@
import appContext from "../../services/app_context.js";
import appContext from "../../components/app_context.js";
import BasicWidget from "../basic_widget.js";
import utils from "../../services/utils.js";

View File

@ -1,6 +1,6 @@
import server from "../../../services/server.js";
import utils from "../../../services/utils.js";
import appContext from "../../../services/app_context.js";
import appContext from "../../../components/app_context.js";
import OptionsTab from "./options_tab.js";
const FONT_FAMILIES = [

View File

@ -3,7 +3,7 @@ import utils from '../../services/utils.js';
import server from '../../services/server.js';
import treeService from "../../services/tree.js";
import froca from "../../services/froca.js";
import appContext from "../../services/app_context.js";
import appContext from "../../components/app_context.js";
import hoistedNoteService from "../../services/hoisted_note.js";
import BasicWidget from "../basic_widget.js";
import dialogService from "../../services/dialog.js";

View File

@ -3,7 +3,7 @@
// for consistency
import libraryLoader from "../services/library_loader.js";
import utils from "../services/utils.js";
import appContext from "../services/app_context.js";
import appContext from "../components/app_context.js";
const FIND_RESULT_SELECTED_CSS_CLASSNAME = "ck-find-result_selected";
const FIND_RESULT_CSS_CLASSNAME = "ck-find-result";

View File

@ -1,5 +1,5 @@
import BasicWidget from "../basic_widget.js";
import appContext from "../../services/app_context.js";
import appContext from "../../components/app_context.js";
import contextMenu from "../../menus/context_menu.js";
import noteCreateService from "../../services/note_create.js";
import branchService from "../../services/branches.js";

View File

@ -1,5 +1,5 @@
import BasicWidget from "./basic_widget.js";
import appContext from "../services/app_context.js";
import appContext from "../components/app_context.js";
export default class NoteContextAwareWidget extends BasicWidget {
isNoteContext(ntxId) {

View File

@ -3,7 +3,7 @@ import protectedSessionHolder from "../services/protected_session_holder.js";
import SpacedUpdate from "../services/spaced_update.js";
import server from "../services/server.js";
import libraryLoader from "../services/library_loader.js";
import appContext from "../services/app_context.js";
import appContext from "../components/app_context.js";
import keyboardActionsService from "../services/keyboard_actions.js";
import noteCreateService from "../services/note_create.js";
import attributeService from "../services/attributes.js";
@ -197,7 +197,7 @@ export default class NoteDetailWidget extends NoteContextAwareWidget {
type = 'editable-code';
}
if (type === 'shortcut') {
if (type === 'launcher') {
type = 'doc';
}

View File

@ -2,7 +2,7 @@ import libraryLoader from "../services/library_loader.js";
import server from "../services/server.js";
import attributeService from "../services/attributes.js";
import hoistedNoteService from "../services/hoisted_note.js";
import appContext from "../services/app_context.js";
import appContext from "../components/app_context.js";
import NoteContextAwareWidget from "./note_context_aware_widget.js";
import linkContextMenuService from "../menus/link_context_menu.js";

View File

@ -1,10 +1,10 @@
import NoteContextAwareWidget from "./note_context_aware_widget.js";
import utils from "../services/utils.js";
import protectedSessionHolder from "../services/protected_session_holder.js";
import server from "../services/server.js";
import SpacedUpdate from "../services/spaced_update.js";
import appContext from "../services/app_context.js";
import appContext from "../components/app_context.js";
import branchService from "../services/branches.js";
import shortcutService from "../services/shortcuts.js";
const TPL = `
<div class="note-title-widget">
@ -58,13 +58,13 @@ export default class NoteTitleWidget extends NoteContextAwareWidget {
this.deleteNoteOnEscape = false;
});
utils.bindElShortcut(this.$noteTitle, 'esc', () => {
shortcutService.bindElShortcut(this.$noteTitle, 'esc', () => {
if (this.deleteNoteOnEscape && this.noteContext.isActive()) {
branchService.deleteNotes(Object.values(this.noteContext.note.parentToBranch));
}
});
utils.bindElShortcut(this.$noteTitle, 'return', () => {
shortcutService.bindElShortcut(this.$noteTitle, 'return', () => {
this.triggerCommand('focusOnDetail', {ntxId: this.noteContext.ntxId});
});
}
@ -73,7 +73,7 @@ export default class NoteTitleWidget extends NoteContextAwareWidget {
this.$noteTitle.val(note.title);
this.$noteTitle.prop("readonly", (note.isProtected && !protectedSessionHolder.isProtectedSessionAvailable())
|| ["lb_root", "lb_availableshortcuts", "lb_visibleshortcuts"].includes(note.noteId));
|| ["lb_root", "lb_availablelaunchers", "lb_visiblelaunchers"].includes(note.noteId));
this.setProtectedStatus(note);
}

View File

@ -9,7 +9,7 @@ import NoteContextAwareWidget from "./note_context_aware_widget.js";
import server from "../services/server.js";
import noteCreateService from "../services/note_create.js";
import toastService from "../services/toast.js";
import appContext from "../services/app_context.js";
import appContext from "../components/app_context.js";
import keyboardActionsService from "../services/keyboard_actions.js";
import clipboard from "../services/clipboard.js";
import protectedSessionService from "../services/protected_session.js";
@ -18,6 +18,7 @@ import syncService from "../services/sync.js";
import options from "../services/options.js";
import protectedSessionHolder from "../services/protected_session_holder.js";
import dialogService from "../services/dialog.js";
import shortcutService from "../services/shortcuts.js";
const TPL = `
<div class="tree-wrapper">
@ -396,7 +397,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
autoExpandMS: 600,
preventLazyParents: false,
dragStart: (node, data) => {
if (['root', 'hidden', 'lb_root', 'lb_availableshortcuts', 'lb_visibleshortcuts'].includes(node.data.noteId)) {
if (['root', 'hidden', 'lb_root', 'lb_availablelaunchers', 'lb_visiblelaunchers'].includes(node.data.noteId)) {
return false;
}
@ -426,7 +427,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
return false;
} else if (node.data.noteId === 'lb_root') {
return false;
} else if (node.data.noteType === 'shortcut') {
} else if (node.data.noteType === 'launcher') {
return ['before', 'after'];
} else {
return true;
@ -563,7 +564,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
$span.append($refreshSearchButton);
}
if (!['search', 'shortcut'].includes(note.type)) {
if (!['search', 'launcher'].includes(note.type)) {
const $createChildNoteButton = $('<span class="tree-item-button add-note-button bx bx-plus" title="Create child note"></span>');
$span.append($createChildNoteButton);
@ -603,8 +604,8 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
const node = $.ui.fancytree.getNode(e);
if (hoistedNoteService.getHoistedNoteId() === 'lb_root') {
import("../menus/shortcut_context_menu.js").then(({default: ShortcutContextMenu}) => {
const shortcutContextMenu = new ShortcutContextMenu(this, node);
import("../menus/launcher_context_menu.js").then(({LauncherContextMenu: ShortcutContextMenu}) => {
const shortcutContextMenu = new LauncherContextMenu(this, node);
shortcutContextMenu.show(e);
});
} else {
@ -1331,7 +1332,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
for (const action of actions) {
for (const shortcut of action.effectiveShortcuts) {
hotKeyMap[utils.normalizeShortcut(shortcut)] = node => {
hotKeyMap[shortcutService.normalizeShortcut(shortcut)] = node => {
const notePath = treeService.getNotePath(node);
this.triggerCommand(action.actionName, {node, notePath});
@ -1550,11 +1551,11 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
}
moveShortcutToVisibleCommand({node, selectedOrActiveBranchIds}) {
branchService.moveToParentNote(selectedOrActiveBranchIds, 'lb_visibleshortcuts');
branchService.moveToParentNote(selectedOrActiveBranchIds, 'lb_visiblelaunchers');
}
moveShortcutToAvailableCommand({node, selectedOrActiveBranchIds}) {
branchService.moveToParentNote(selectedOrActiveBranchIds, 'lb_availableshortcuts');
branchService.moveToParentNote(selectedOrActiveBranchIds, 'lb_availablelaunchers');
}
addNoteShortcutCommand({node}) {
@ -1573,8 +1574,8 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
this.createShortcutNote(node, 'spacer');
}
async createShortcutNote(node, shortcutType) {
const resp = await server.post(`special-notes/shortcuts/${node.data.noteId}/${shortcutType}`);
async createShortcutNote(node, launcherType) {
const resp = await server.post(`special-notes/shortcuts/${node.data.noteId}/${launcherType}`);
if (!resp.success) {
alert(resp.message);

View File

@ -8,7 +8,7 @@ const NOTE_TYPES = [
{ type: "image", title: "Image", selectable: false },
{ type: "search", title: "Saved Search", selectable: false },
{ type: "note-map", mime: '', title: "Note Map", selectable: false },
{ type: "shortcut", mime: '', title: "Shortcut", selectable: false },
{ type: "launcher", mime: '', title: "Launcher", selectable: false },
{ type: "doc", mime: '', title: "Doc", selectable: false },
{ type: "text", mime: "text/html", title: "Text", selectable: true },

View File

@ -1,10 +1,10 @@
import BasicWidget from "./basic_widget.js";
import server from "../services/server.js";
import linkService from "../services/link.js";
import dateNotesService from "../services/date_notes.js";
import froca from "../services/froca.js";
import utils from "../services/utils.js";
import appContext from "../services/app_context.js";
import appContext from "../components/app_context.js";
import shortcutService from "../services/shortcuts.js";
const TPL = `
<div class="quick-search input-group input-group-sm">
@ -66,7 +66,7 @@ export default class QuickSearchWidget extends BasicWidget {
})
}
utils.bindElShortcut(this.$searchString, 'return', () => {
shortcutService.bindElShortcut(this.$searchString, 'return', () => {
if (this.$dropdownMenu.is(":visible")) {
this.search(); // just update already visible dropdown
} else {
@ -76,11 +76,11 @@ export default class QuickSearchWidget extends BasicWidget {
this.$searchString.focus();
});
utils.bindElShortcut(this.$searchString, 'down', () => {
shortcutService.bindElShortcut(this.$searchString, 'down', () => {
this.$dropdownMenu.find('.dropdown-item:first').focus();
});
utils.bindElShortcut(this.$searchString, 'esc', () => {
shortcutService.bindElShortcut(this.$searchString, 'esc', () => {
this.$dropdownToggle.dropdown('hide');
});
@ -120,7 +120,7 @@ export default class QuickSearchWidget extends BasicWidget {
appContext.tabManager.getActiveContext().setNote(note.noteId);
}
});
utils.bindElShortcut($link, 'return', () => {
shortcutService.bindElShortcut($link, 'return', () => {
this.$dropdownToggle.dropdown("hide");
appContext.tabManager.getActiveContext().setNote(note.noteId);
@ -140,9 +140,9 @@ export default class QuickSearchWidget extends BasicWidget {
$showInFullButton.on('click', () => this.showInFullSearch());
utils.bindElShortcut($showInFullButton, 'return', () => this.showInFullSearch());
shortcutService.bindElShortcut($showInFullButton, 'return', () => this.showInFullSearch());
utils.bindElShortcut(this.$dropdownMenu.find('.dropdown-item:first'), 'up', () => this.$searchString.focus());
shortcutService.bindElShortcut(this.$dropdownMenu.find('.dropdown-item:first'), 'up', () => this.$searchString.focus());
this.$dropdownToggle.dropdown('update');
}

View File

@ -13,7 +13,7 @@ import OrderBy from "../search_options/order_by.js";
import SearchScript from "../search_options/search_script.js";
import Limit from "../search_options/limit.js";
import Debug from "../search_options/debug.js";
import appContext from "../../services/app_context.js";
import appContext from "../../components/app_context.js";
import bulkActionService from "../../services/bulk_action.js";
const TPL = `

View File

@ -1,6 +1,6 @@
import server from "../../services/server.js";
import ws from "../../services/ws.js";
import Component from "../component.js";
import Component from "../../components/component.js";
import utils from "../../services/utils.js";
export default class AbstractSearchOption extends Component {

View File

@ -1,7 +1,7 @@
import AbstractSearchOption from "./abstract_search_option.js";
import utils from "../../services/utils.js";
import SpacedUpdate from "../../services/spaced_update.js";
import server from "../../services/server.js";
import shortcutService from "../../services/shortcuts.js";
const TPL = `
<tr>
@ -45,7 +45,7 @@ export default class SearchString extends AbstractSearchOption {
this.$searchString = $option.find('.search-string');
this.$searchString.on('input', () => this.spacedUpdate.scheduleUpdate());
utils.bindElShortcut(this.$searchString, 'return', async () => {
shortcutService.bindElShortcut(this.$searchString, 'return', async () => {
// this also in effect disallows new lines in query string.
// on one hand this makes sense since search string is a label
// on the other hand it could be nice for structuring long search string. It's probably a niche case though.

View File

@ -2,7 +2,7 @@ import BasicWidget from "./basic_widget.js";
import contextMenu from "../menus/context_menu.js";
import utils from "../services/utils.js";
import keyboardActionService from "../services/keyboard_actions.js";
import appContext from "../services/app_context.js";
import appContext from "../components/app_context.js";
import froca from "../services/froca.js";
import attributeService from "../services/attributes.js";

View File

@ -1,5 +1,5 @@
import TypeWidget from "./type_widget.js";
import appContext from "../../services/app_context.js";
import appContext from "../../components/app_context.js";
import froca from "../../services/froca.js";
import linkService from "../../services/link.js";
import noteContentRenderer from "../../services/note_content_renderer.js";

View File

@ -1,6 +1,6 @@
import server from "../../services/server.js";
import ws from "../../services/ws.js";
import appContext from "../../services/app_context.js";
import appContext from "../../components/app_context.js";
import toastService from "../../services/toast.js";
import treeService from "../../services/tree.js";
import NoteContextAwareWidget from "../note_context_aware_widget.js";

View File

@ -8,7 +8,7 @@ import treeService from "../../services/tree.js";
import noteCreateService from "../../services/note_create.js";
import AbstractTextTypeWidget from "./abstract_text_type_widget.js";
import link from "../../services/link.js";
import appContext from "../../services/app_context.js";
import appContext from "../../components/app_context.js";
const ENABLE_INSPECTOR = false;

View File

@ -1,6 +1,6 @@
import noteAutocompleteService from '../../services/note_autocomplete.js';
import TypeWidget from "./type_widget.js";
import appContext from "../../services/app_context.js";
import appContext from "../../components/app_context.js";
import searchService from "../../services/search.js";
const TPL = `

View File

@ -5,7 +5,7 @@ import contextMenu from "../../menus/context_menu.js";
import toastService from "../../services/toast.js";
import attributeAutocompleteService from "../../services/attribute_autocomplete.js";
import TypeWidget from "./type_widget.js";
import appContext from "../../services/app_context.js";
import appContext from "../../components/app_context.js";
import utils from "../../services/utils.js";
import froca from "../../services/froca.js";
import dialogService from "../../services/dialog.js";

View File

@ -1,5 +1,5 @@
import NoteContextAwareWidget from "../note_context_aware_widget.js";
import appContext from "../../services/app_context.js";
import appContext from "../../components/app_context.js";
export default class TypeWidget extends NoteContextAwareWidget {
// for overriding
@ -40,7 +40,7 @@ export default class TypeWidget extends NoteContextAwareWidget {
/**
* @returns {Promise|*} promise resolving content or directly the content
*/
*/
getContent() {}
focus() {}

View File

@ -8,15 +8,10 @@ function getKeyboardActions() {
}
function getShortcutsForNotes() {
const attrs = becca.findAttributes('label', 'keyboardShortcut');
const labels = becca.findAttributes('label', 'keyboardShortcut');
const map = {};
for (const attr of attrs) {
map[attr.value] = attr.noteId;
}
return map;
// launchers have different handling
return labels.filter(attr => becca.getNote(attr.noteId)?.type !== 'launcher');
}
module.exports = {

View File

@ -66,12 +66,12 @@ function getHoistedNote() {
return becca.getNote(cls.getHoistedNoteId());
}
function createShortcut(req) {
return specialNotesService.createShortcut(req.params.parentNoteId, req.params.shortcutType);
function createLauncher(req) {
return specialNotesService.createLauncher(req.params.parentNoteId, req.params.launcherType);
}
function resetShortcut(req) {
return specialNotesService.resetShortcut(req.params.noteId);
function resetLauncher(req) {
return specialNotesService.resetLauncher(req.params.noteId);
}
module.exports = {
@ -85,6 +85,6 @@ module.exports = {
saveSqlConsole,
createSearchNote,
saveSearchNote,
createShortcut,
resetShortcut
createLauncher,
resetLauncher
};

View File

@ -326,8 +326,8 @@ function register(app) {
apiRoute(POST, '/api/special-notes/save-sql-console', specialNotesRoute.saveSqlConsole);
apiRoute(POST, '/api/special-notes/search-note', specialNotesRoute.createSearchNote);
apiRoute(POST, '/api/special-notes/save-search-note', specialNotesRoute.saveSearchNote);
apiRoute(POST, '/api/special-notes/shortcuts/:noteId/reset', specialNotesRoute.resetShortcut);
apiRoute(POST, '/api/special-notes/shortcuts/:parentNoteId/:shortcutType', specialNotesRoute.createShortcut);
apiRoute(POST, '/api/special-notes/launchers/:noteId/reset', specialNotesRoute.resetLauncher);
apiRoute(POST, '/api/special-notes/launchers/:parentNoteId/:launcherType', specialNotesRoute.createLauncher);
// :filename is not used by trilium, but instead used for "save as" to assign a human-readable filename
route(GET, '/api/images/:noteId/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImage);

View File

@ -11,6 +11,6 @@ module.exports = [
'mermaid',
'canvas',
'web-view',
'shortcut',
'launcher',
'doc'
];

View File

@ -110,16 +110,16 @@ function getAndValidateParent(params) {
throw new Error(`Parent note "${params.parentNoteId}" not found.`);
}
if (parentNote.type === 'shortcut') {
throw new Error(`Shortcuts should not have child notes.`);
if (parentNote.type === 'launcher') {
throw new Error(`Launchers should not have child notes.`);
}
if (!params.ignoreForbiddenParents && ['lb_root'].includes(parentNote.noteId)) {
throw new Error(`Creating child notes into '${parentNote.noteId}' is not allowed.`);
}
if (['lb_availableshortcuts', 'lb_visibleshortcuts'].includes(parentNote.noteId) && params.type !== 'shortcut') {
throw new Error(`Creating child notes into '${parentNote.noteId}' is only possible for type 'shortcut'.`);
if (['lb_availablelaunchers', 'lb_visiblelaunchers'].includes(parentNote.noteId) && params.type !== 'launcher') {
throw new Error(`Creating child notes into '${parentNote.noteId}' is only possible for type 'launcher'.`);
}
return parentNote;

View File

@ -8,7 +8,7 @@ const dateUtils = require("./date_utils");
const LBTPL_ROOT = "lbtpl_root";
const LBTPL_BASE = "lbtpl_base";
const LBTPL_COMMAND = "lbtpl_command";
const LBTPL_NOTE_SHORTCUT = "lbtpl_noteshortcut";
const LBTPL_NOTE_LAUNCHER = "lbtpl_notelauncher";
const LBTPL_SCRIPT = "lbtpl_script";
const LBTPL_BUILTIN_WIDGET = "lbtpl_builtinwidget";
const LBTPL_SPACER = "lbtpl_spacer";
@ -276,14 +276,14 @@ function getLaunchBarRoot() {
return note;
}
function getLaunchBarAvailableShortcutsRoot() {
let note = becca.getNote('lb_availableshortcuts');
function getLaunchBarAvailableLaunchersRoot() {
let note = becca.getNote('lb_availablelaunchers');
if (!note) {
note = noteService.createNewNote({
branchId: 'lb_availableshortcuts',
noteId: 'lb_availableshortcuts',
title: 'Available shortcuts',
branchId: 'lb_availablelaunchers',
noteId: 'lb_availablelaunchers',
title: 'Available launchers',
type: 'doc',
content: '',
parentNoteId: getLaunchBarRoot().noteId,
@ -294,7 +294,7 @@ function getLaunchBarAvailableShortcutsRoot() {
note.addLabel("docName", "launchbar_intro");
}
const branch = becca.getBranch('lb_availableshortcuts');
const branch = becca.getBranch('lb_availablelaunchers');
if (!branch.isExpanded) {
branch.isExpanded = true;
branch.save();
@ -303,14 +303,14 @@ function getLaunchBarAvailableShortcutsRoot() {
return note;
}
function getLaunchBarVisibleShortcutsRoot() {
let note = becca.getNote('lb_visibleshortcuts');
function getLaunchBarVisibleLaunchersRoot() {
let note = becca.getNote('lb_visiblelaunchers');
if (!note) {
note = noteService.createNewNote({
branchId: 'lb_visibleshortcuts',
noteId: 'lb_visibleshortcuts',
title: 'Visible shortcuts',
branchId: 'lb_visiblelaunchers',
noteId: 'lb_visiblelaunchers',
title: 'Visible launchers',
type: 'doc',
content: '',
parentNoteId: getLaunchBarRoot().noteId,
@ -321,7 +321,7 @@ function getLaunchBarVisibleShortcutsRoot() {
note.addLabel("docName", "launchbar_intro");
}
const branch = becca.getBranch('lb_visibleshortcuts');
const branch = becca.getBranch('lb_visiblelaunchers');
if (!branch.isExpanded) {
branch.isExpanded = true;
branch.save();
@ -330,20 +330,20 @@ function getLaunchBarVisibleShortcutsRoot() {
return note;
}
const shortcuts = [
// visible shortcuts:
const launchers = [
// visible launchers:
{ id: 'lb_newnote', command: 'createNoteIntoInbox', title: 'New note', icon: 'bx bx-file-blank', isVisible: true },
{ id: 'lb_search', command: 'searchNotes', title: 'Search notes', icon: 'bx bx-search', isVisible: true },
{ id: 'lb_jumpto', command: 'jumpToNote', title: 'Jump to note', icon: 'bx bx-send', isVisible: true },
{ id: 'lb_notemap', targetNoteId: 'globalnotemap', title: 'Note map', icon: 'bx bx-map-alt', isVisible: true },
{ id: 'lb_calendar', builtinWidget: 'calendar', title: 'Calendar', icon: 'bx bx-calendar', isVisible: true },
{ id: 'lb_spacer1', builtinWidget: 'spacer', title: 'Spacer', isVisible: true, baseSize: 50, growthFactor: 0 },
{ id: 'lb_spacer1', builtinWidget: 'spacer', title: 'Spacer', isVisible: true, baseSize: "50", growthFactor: "0" },
{ id: 'lb_bookmarks', builtinWidget: 'bookmarks', title: 'Bookmarks', icon: 'bx bx-bookmark', isVisible: true },
{ id: 'lb_spacer2', builtinWidget: 'spacer', title: 'Spacer', isVisible: true, baseSize: 0, growthFactor: 1 },
{ id: 'lb_spacer2', builtinWidget: 'spacer', title: 'Spacer', isVisible: true, baseSize: "0", growthFactor: "1" },
{ id: 'lb_protectedsession', builtinWidget: 'protectedSession', title: 'Protected session', icon: 'bx bx bx-shield-quarter', isVisible: true },
{ id: 'lb_syncstatus', builtinWidget: 'syncStatus', title: 'Sync status', icon: 'bx bx-wifi', isVisible: true },
// available shortcuts:
// available launchers:
{ id: 'lb_recentchanges', command: 'showRecentChanges', title: 'Recent changes', icon: 'bx bx-history', isVisible: false },
{ id: 'lb_backinhistory', builtinWidget: 'backInHistoryButton', title: 'Back in history', icon: 'bx bxs-left-arrow-square', isVisible: false },
{ id: 'lb_forwardinhistory', builtinWidget: 'forwardInHistoryButton', title: 'Forward in history', icon: 'bx bxs-right-arrow-square', isVisible: false },
@ -353,53 +353,53 @@ function createMissingSpecialNotes() {
getSqlConsoleRoot();
getGlobalNoteMap();
getBulkActionNote();
createShortcutTemplates();
createLauncherTemplates();
getLaunchBarRoot();
getLaunchBarAvailableShortcutsRoot();
getLaunchBarVisibleShortcutsRoot();
getLaunchBarAvailableLaunchersRoot();
getLaunchBarVisibleLaunchersRoot();
getShareRoot();
for (const shortcut of shortcuts) {
let note = becca.getNote(shortcut.id);
for (const launcher of launchers) {
let note = becca.getNote(launcher.id);
if (note) {
continue;
}
const parentNoteId = shortcut.isVisible
? getLaunchBarVisibleShortcutsRoot().noteId
: getLaunchBarAvailableShortcutsRoot().noteId;
const parentNoteId = launcher.isVisible
? getLaunchBarVisibleLaunchersRoot().noteId
: getLaunchBarAvailableLaunchersRoot().noteId;
note = noteService.createNewNote({
noteId: shortcut.id,
title: shortcut.title,
type: 'shortcut',
noteId: launcher.id,
title: launcher.title,
type: 'launcher',
content: '',
parentNoteId: parentNoteId
}).note;
if (shortcut.icon) {
note.addLabel('iconClass', shortcut.icon);
if (launcher.icon) {
note.addLabel('iconClass', launcher.icon);
}
if (shortcut.command) {
if (launcher.command) {
note.addRelation('template', LBTPL_COMMAND);
note.addLabel('command', shortcut.command);
} else if (shortcut.builtinWidget) {
if (shortcut.builtinWidget === 'spacer') {
note.addLabel('command', launcher.command);
} else if (launcher.builtinWidget) {
if (launcher.builtinWidget === 'spacer') {
note.addRelation('template', LBTPL_SPACER);
note.addLabel("baseSize", shortcut.baseSize);
note.addLabel("growthFactor", shortcut.growthFactor);
note.addLabel("baseSize", launcher.baseSize);
note.addLabel("growthFactor", launcher.growthFactor);
} else {
note.addRelation('template', LBTPL_BUILTIN_WIDGET);
}
note.addLabel('builtinWidget', shortcut.builtinWidget);
} else if (shortcut.targetNoteId) {
note.addRelation('template', LBTPL_NOTE_SHORTCUT);
note.addRelation('targetNote', shortcut.targetNoteId);
note.addLabel('builtinWidget', launcher.builtinWidget);
} else if (launcher.targetNoteId) {
note.addRelation('template', LBTPL_NOTE_LAUNCHER);
note.addRelation('targetNote', launcher.targetNoteId);
} else {
throw new Error(`No action defined for shortcut ${JSON.stringify(shortcut)}`);
throw new Error(`No action defined for launcher ${JSON.stringify(launcher)}`);
}
}
@ -412,47 +412,47 @@ function createMissingSpecialNotes() {
}
}
function createShortcut(parentNoteId, shortcutType) {
function createLauncher(parentNoteId, launcherType) {
let note;
if (shortcutType === 'note') {
if (launcherType === 'note') {
note = noteService.createNewNote({
title: "Note shortcut",
type: 'shortcut',
title: "Note launcher",
type: 'launcher',
content: '',
parentNoteId: parentNoteId
}).note;
note.addRelation('template', LBTPL_NOTE_SHORTCUT);
} else if (shortcutType === 'script') {
note.addRelation('template', LBTPL_NOTE_LAUNCHER);
} else if (launcherType === 'script') {
note = noteService.createNewNote({
title: "Script shortcut",
type: 'shortcut',
title: "Script launcher",
type: 'launcher',
content: '',
parentNoteId: parentNoteId
}).note;
note.addRelation('template', LBTPL_SCRIPT);
} else if (shortcutType === 'customWidget') {
} else if (launcherType === 'customWidget') {
note = noteService.createNewNote({
title: "Widget shortcut",
type: 'shortcut',
title: "Widget launcher",
type: 'launcher',
content: '',
parentNoteId: parentNoteId
}).note;
note.addRelation('template', LBTPL_CUSTOM_WIDGET);
} else if (shortcutType === 'spacer') {
} else if (launcherType === 'spacer') {
note = noteService.createNewNote({
title: "Spacer",
type: 'shortcut',
type: 'launcher',
content: '',
parentNoteId: parentNoteId
}).note;
note.addRelation('template', LBTPL_SPACER);
} else {
throw new Error(`Unrecognized shortcut type ${shortcutType}`);
throw new Error(`Unrecognized launcher type ${launcherType}`);
}
return {
@ -461,7 +461,7 @@ function createShortcut(parentNoteId, shortcutType) {
};
}
function createShortcutTemplates() {
function createLauncherTemplates() {
if (!(LBTPL_ROOT in becca.notes)) {
noteService.createNewNote({
branchId: LBTPL_ROOT,
@ -474,46 +474,46 @@ function createShortcutTemplates() {
}
if (!(LBTPL_BASE in becca.notes)) {
const tpl = noteService.createNewNote({
noteService.createNewNote({
branchId: LBTPL_BASE,
noteId: LBTPL_BASE,
title: 'Launch bar base shortcut',
title: 'Launch bar base launcher',
type: 'doc',
content: '',
parentNoteId: getHiddenRoot().noteId
}).note;
tpl.addLabel('label:keyboardShortcut', 'promoted,text');
});
}
if (!(LBTPL_COMMAND in becca.notes)) {
const tpl = noteService.createNewNote({
branchId: LBTPL_COMMAND,
noteId: LBTPL_COMMAND,
title: 'Command shortcut',
title: 'Command launcher',
type: 'doc',
content: '',
parentNoteId: LBTPL_ROOT
}).note;
tpl.addRelation('template', LBTPL_BASE);
tpl.addLabel('shortcutType', 'command');
tpl.addLabel('launcherType', 'command');
tpl.addLabel('docName', 'launchbar_command_launcher');
}
if (!(LBTPL_NOTE_SHORTCUT in becca.notes)) {
if (!(LBTPL_NOTE_LAUNCHER in becca.notes)) {
const tpl = noteService.createNewNote({
branchId: LBTPL_NOTE_SHORTCUT,
noteId: LBTPL_NOTE_SHORTCUT,
title: 'Note shortcut',
branchId: LBTPL_NOTE_LAUNCHER,
noteId: LBTPL_NOTE_LAUNCHER,
title: 'Note launcher',
type: 'doc',
content: '',
parentNoteId: LBTPL_ROOT
}).note;
tpl.addRelation('template', LBTPL_BASE);
tpl.addLabel('shortcutType', 'note');
tpl.addLabel('launcherType', 'note');
tpl.addLabel('relation:targetNote', 'promoted');
tpl.addLabel('docName', 'launchbar_note_shortcut');
tpl.addLabel('docName', 'launchbar_note_launcher');
tpl.addLabel('label:keyboardShortcut', 'promoted,text');
}
if (!(LBTPL_SCRIPT in becca.notes)) {
@ -527,9 +527,10 @@ function createShortcutTemplates() {
}).note;
tpl.addRelation('template', LBTPL_BASE);
tpl.addLabel('shortcutType', 'script');
tpl.addLabel('launcherType', 'script');
tpl.addLabel('relation:script', 'promoted');
tpl.addLabel('docName', 'launchbar_script_shortcut');
tpl.addLabel('docName', 'launchbar_script_launcher');
tpl.addLabel('label:keyboardShortcut', 'promoted,text');
}
if (!(LBTPL_BUILTIN_WIDGET in becca.notes)) {
@ -543,7 +544,7 @@ function createShortcutTemplates() {
}).note;
tpl.addRelation('template', LBTPL_BASE);
tpl.addLabel('shortcutType', 'builtinWidget');
tpl.addLabel('launcherType', 'builtinWidget');
}
if (!(LBTPL_SPACER in becca.notes)) {
@ -575,13 +576,13 @@ function createShortcutTemplates() {
}).note;
tpl.addRelation('template', LBTPL_BASE);
tpl.addLabel('shortcutType', 'customWidget');
tpl.addLabel('launcherType', 'customWidget');
tpl.addLabel('relation:widget', 'promoted');
tpl.addLabel('docName', 'launchbar_widget_shortcut');
tpl.addLabel('docName', 'launchbar_widget_launcher');
}
}
function resetShortcut(noteId) {
function resetLauncher(noteId) {
if (noteId.startsWith('lb_')) {
const note = becca.getNote(noteId);
@ -598,7 +599,7 @@ function resetShortcut(noteId) {
log.info(`Note ${noteId} has not been found and cannot be reset.`);
}
} else {
log.info(`Note ${noteId} is not a resettable shortcut note.`);
log.info(`Note ${noteId} is not a resettable launcher note.`);
}
createMissingSpecialNotes();
@ -614,6 +615,6 @@ module.exports = {
getShareRoot,
getHiddenRoot,
getBulkActionNote,
createShortcut,
resetShortcut
createLauncher,
resetLauncher
};

View File

@ -30,7 +30,7 @@ function getNotes(noteIds) {
}
function validateParentChild(parentNoteId, childNoteId, branchId = null) {
if (['root', 'hidden', 'share', 'lb_root', 'lb_availableshortcuts', 'lb_visibleshortcuts'].includes(childNoteId)) {
if (['root', 'hidden', 'share', 'lb_root', 'lb_availablelaunchers', 'lb_visiblelaunchers'].includes(childNoteId)) {
return { success: false, message: `Cannot change this note's location.`};
}
@ -58,10 +58,10 @@ function validateParentChild(parentNoteId, childNoteId, branchId = null) {
};
}
if (becca.getNote(parentNoteId).type === 'shortcut') {
if (becca.getNote(parentNoteId).type === 'launcher') {
return {
success: false,
message: 'Shortcut note cannot have any children.'
message: 'Launcher note cannot have any children.'
};
}