From a459230aa9f413256695ccbefa3f5fe55438fb63 Mon Sep 17 00:00:00 2001 From: zadam Date: Sun, 27 Nov 2022 23:43:25 +0100 Subject: [PATCH] shortcuts improvements --- .../doc_notes/launchbar_script_shortcut.html | 6 + .../doc_notes/launchbar_widget_shortcut.html | 33 +++++ src/public/app/entities/note_short.js | 4 +- .../app/services/frontend_script_api.js | 16 --- src/public/app/widgets/component.js | 23 ++-- .../widgets/containers/shortcut_container.js | 122 ++++++++++++------ .../widgets/note_context_caching_widget.js | 99 -------------- src/public/app/widgets/note_tree.js | 4 +- src/public/app/widgets/type_widgets/doc.js | 7 + src/services/notes.js | 28 +++- 10 files changed, 168 insertions(+), 174 deletions(-) delete mode 100644 src/public/app/widgets/note_context_caching_widget.js diff --git a/src/public/app/doc_notes/launchbar_script_shortcut.html b/src/public/app/doc_notes/launchbar_script_shortcut.html index 2bad3c1ea..39168e1c7 100644 --- a/src/public/app/doc_notes/launchbar_script_shortcut.html +++ b/src/public/app/doc_notes/launchbar_script_shortcut.html @@ -1,3 +1,9 @@

Please define the target script note in the promoted attributes. This script will be executed immediately upon clicking the launchbar icon.

Launchbar displays the title / icon from the shortcut which does not necessarily mirrors those of the target script note.

+ +

Example script

+ +
+alert("Current note is " + api.getActiveContextNote().title);
+
diff --git a/src/public/app/doc_notes/launchbar_widget_shortcut.html b/src/public/app/doc_notes/launchbar_widget_shortcut.html index 19b4c4703..3df3afa9c 100644 --- a/src/public/app/doc_notes/launchbar_widget_shortcut.html +++ b/src/public/app/doc_notes/launchbar_widget_shortcut.html @@ -1 +1,34 @@

Please define the target widget note in the promoted attributes. The widget will be used to render the launchbar icon.

+ +

Example launchbar widget

+ +
+const TPL = `<div style="height: 53px; width: 53px;"></div>`;
+
+class ExampleLaunchbarWidget extends api.NoteContextAwareWidget {
+    doRender() {
+        this.$widget = $(TPL);
+    }
+
+    async refreshWithNote(note) {
+        this.$widget.css("background-color", this.stringToColor(note.title));
+    }
+
+    stringToColor(str) {
+        let hash = 0;
+        for (let i = 0; i < str.length; i++) {
+            hash = str.charCodeAt(i) + ((hash << 5) - hash);
+        }
+
+        let color = '#';
+        for (let i = 0; i < 3; i++) {
+            const value = (hash >> (i * 8)) & 0xFF;
+            color += ('00' + value.toString(16)).substr(-2);
+        }
+
+        return color;
+    }
+}
+
+module.exports = new ExampleLaunchbarWidget();
+
diff --git a/src/public/app/entities/note_short.js b/src/public/app/entities/note_short.js index b918d2470..d312b68b7 100644 --- a/src/public/app/entities/note_short.js +++ b/src/public/app/entities/note_short.js @@ -792,10 +792,10 @@ class NoteShort { if (env === "frontend") { const bundleService = (await import("../services/bundle.js")).default; - await bundleService.getAndExecuteBundle(this.noteId); + return await bundleService.getAndExecuteBundle(this.noteId); } else if (env === "backend") { - await server.post('script/run/' + this.noteId); + return await server.post('script/run/' + this.noteId); } else { throw new Error(`Unrecognized env type ${env} for note ${this.noteId}`); diff --git a/src/public/app/services/frontend_script_api.js b/src/public/app/services/frontend_script_api.js index 1506a1af9..7b32a23ac 100644 --- a/src/public/app/services/frontend_script_api.js +++ b/src/public/app/services/frontend_script_api.js @@ -11,7 +11,6 @@ import CollapsibleWidget from '../widgets/collapsible_widget.js'; import ws from "./ws.js"; import appContext from "./app_context.js"; import NoteContextAwareWidget from "../widgets/note_context_aware_widget.js"; -import NoteContextCachingWidget from "../widgets/note_context_caching_widget.js"; import BasicWidget from "../widgets/basic_widget.js"; import SpacedUpdate from "./spaced_update.js"; @@ -40,24 +39,9 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain /** @property {CollapsibleWidget} */ this.CollapsibleWidget = CollapsibleWidget; - /** - * @property {NoteContextAwareWidget} - * @deprecated use NoteContextAwareWidget instead - */ - this.TabAwareWidget = NoteContextAwareWidget; - /** @property {NoteContextAwareWidget} */ this.NoteContextAwareWidget = NoteContextAwareWidget; - /** - * @property {NoteContextCachingWidget} - * @deprecated use NoteContextCachingWidget instead - */ - this.TabCachingWidget = NoteContextCachingWidget; - - /** @property {NoteContextAwareWidget} */ - this.NoteContextCachingWidget = NoteContextCachingWidget; - /** @property {BasicWidget} */ this.BasicWidget = BasicWidget; diff --git a/src/public/app/widgets/component.js b/src/public/app/widgets/component.js index 0d594461a..c9b78ee9c 100644 --- a/src/public/app/widgets/component.js +++ b/src/public/app/widgets/component.js @@ -42,16 +42,23 @@ export default class Component { /** @returns {Promise} */ handleEvent(name, data) { - const callMethodPromise = this.initialized - ? this.initialized.then(() => this.callMethod(this[name + 'Event'], data)) - : this.callMethod(this[name + 'Event'], data); + try { + const callMethodPromise = this.initialized + ? this.initialized.then(() => this.callMethod(this[name + 'Event'], data)) + : this.callMethod(this[name + 'Event'], data); - const childrenPromise = this.handleEventInChildren(name, data); + const childrenPromise = this.handleEventInChildren(name, data); - // don't create promises if not needed (optimization) - return callMethodPromise && childrenPromise - ? Promise.all([callMethodPromise, childrenPromise]) - : (callMethodPromise || childrenPromise); + // don't create promises if not needed (optimization) + return callMethodPromise && childrenPromise + ? Promise.all([callMethodPromise, childrenPromise]) + : (callMethodPromise || childrenPromise); + } + catch (e) { + console.error(`Handling of event '${name}' failed in ${this.constructor.name} with error ${e.message} ${e.stack}`); + + return null; + } } /** @returns {Promise} */ diff --git a/src/public/app/widgets/containers/shortcut_container.js b/src/public/app/widgets/containers/shortcut_container.js index 9422c5812..2f5523ced 100644 --- a/src/public/app/widgets/containers/shortcut_container.js +++ b/src/public/app/widgets/containers/shortcut_container.js @@ -33,53 +33,93 @@ export default class ShortcutContainer extends FlexContainer { } for (const shortcut of await visibleShortcutsRoot.getChildNotes()) { - if (shortcut.getLabelValue("command")) { - this.child(new ButtonWidget() - .title(shortcut.title) - .icon(shortcut.getIcon()) - .command(shortcut.getLabelValue("command"))); - } else if (shortcut.hasRelation('targetNote')) { - this.child(new ButtonWidget() - .title(shortcut.title) - .icon(shortcut.getIcon()) - .onClick(() => appContext.tabManager.openTabWithNoteWithHoisting(shortcut.getRelationValue('targetNote'), true))); - } else { - 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 === 'pluginButtons') { - this.child(new FlexContainer("column") - .id("plugin-buttons") - .contentSized()); - } 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.log(`Unrecognized builtin widget ${builtinWidget} for shortcut ${shortcut.noteId} "${shortcut.title}"`); - } - } + try { + await this.initShortcut(shortcut); + } + catch (e) { + console.error(`Initialization of shortcut '${shortcut.noteId}' with title '${shortcut.title}' failed with error: ${e.message} ${e.stack}`); + continue; } } this.$widget.empty(); this.renderChildren(); - this.handleEventInChildren('initialRenderComplete'); + await this.handleEventInChildren('initialRenderComplete'); + + const activeContext = appContext.tabManager.getActiveContext(); + + await this.handleEvent('setNoteContext', { + noteContext: activeContext + }); + await this.handleEvent('noteSwitched', { + noteContext: activeContext, + notePath: activeContext.notePath + }); + } + + async initShortcut(shortcut) { + if (shortcut.type !== 'shortcut') { + console.warn(`Note ${shortcut.noteId} is not a shortcut even though it's in shortcut subtree`); + return; + } + + if (shortcut.getLabelValue("command")) { + this.child(new ButtonWidget() + .title(shortcut.title) + .icon(shortcut.getIcon()) + .command(shortcut.getLabelValue("command"))); + } else if (shortcut.hasRelation('targetNote')) { + this.child(new ButtonWidget() + .title(shortcut.title) + .icon(shortcut.getIcon()) + .onClick(() => appContext.tabManager.openTabWithNoteWithHoisting(shortcut.getRelationValue('targetNote'), true))); + } else if (shortcut.hasRelation('script')) { + this.child(new ButtonWidget() + .title(shortcut.title) + .icon(shortcut.getIcon()) + .onClick(async () => { + const script = await shortcut.getRelationTarget('script'); + + await script.executeScript(); + })); + } else if (shortcut.hasRelation('widget')) { + const widget = await shortcut.getRelationTarget('widget'); + + const res = await widget.executeScript(); + + this.child(res); + } else { + 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 === 'pluginButtons') { + this.child(new FlexContainer("column") + .id("plugin-buttons") + .contentSized()); + } 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.log(`Unrecognized builtin widget ${builtinWidget} for shortcut ${shortcut.noteId} "${shortcut.title}"`); + } + } + } } entitiesReloadedEvent({loadResults}) { diff --git a/src/public/app/widgets/note_context_caching_widget.js b/src/public/app/widgets/note_context_caching_widget.js deleted file mode 100644 index eae98b537..000000000 --- a/src/public/app/widgets/note_context_caching_widget.js +++ /dev/null @@ -1,99 +0,0 @@ -import NoteContextAwareWidget from "./note_context_aware_widget.js"; -import keyboardActionsService from "../services/keyboard_actions.js"; - -export default class NoteContextCachingWidget extends NoteContextAwareWidget { - constructor(widgetFactory) { - super(); - - this.widgetFactory = widgetFactory; - this.widgets = {}; - } - - doRender() { - return this.$widget = $(`