From 8300acd30b32c28479203e1a82ac0b6d67f1bd42 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 22 Nov 2024 20:36:08 +0200 Subject: [PATCH 01/36] refactor(client): add support for optional children in layout --- src/public/app/layouts/desktop_layout.js | 16 +++++++++------- src/public/app/widgets/basic_widget.js | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/public/app/layouts/desktop_layout.js b/src/public/app/layouts/desktop_layout.js index 34fe4454b..4f0a2d2f5 100644 --- a/src/public/app/layouts/desktop_layout.js +++ b/src/public/app/layouts/desktop_layout.js @@ -92,15 +92,17 @@ export default class DesktopLayout { getRootWidget(appContext) { appContext.noteTreeWidget = new NoteTreeWidget(); + const launcherPaneIsHorizontal = true; + const launcherPane = new FlexContainer("column") + .id("launcher-pane") + .css("width", "53px") + .child(new GlobalMenuWidget()) + .child(new LauncherContainer()) + .child(new LeftPaneToggleWidget()); + return new RootContainer() .setParent(appContext) - .child(new FlexContainer("column") - .id("launcher-pane") - .css("width", "53px") - .child(new GlobalMenuWidget()) - .child(new LauncherContainer()) - .child(new LeftPaneToggleWidget()) - ) + .optChild(!launcherPaneIsHorizontal, launcherPane) .child(new LeftPaneContainer() .child(new QuickSearchWidget()) .child(appContext.noteTreeWidget) diff --git a/src/public/app/widgets/basic_widget.js b/src/public/app/widgets/basic_widget.js index 4dd580bd2..bf38552c8 100644 --- a/src/public/app/widgets/basic_widget.js +++ b/src/public/app/widgets/basic_widget.js @@ -40,6 +40,21 @@ class BasicWidget extends Component { return this; } + /** + * Conditionally adds the given components as children to this component. + * + * @param {boolean} condition whether to add the components. + * @param {...any} components the components to be added as children to this component provided the condition is truthy. + * @returns self for chaining. + */ + optChild(condition, ...components) { + if (condition) { + return this.child(...components); + } else { + return this; + } + } + id(id) { this.attrs.id = id; return this; From efc84722a9e4ccd017fd7d4d252cf601ab6ef211 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 22 Nov 2024 21:05:45 +0200 Subject: [PATCH 02/36] feat(client): implement top launcher pane --- src/public/app/layouts/desktop_layout.js | 194 +++++++++--------- .../widgets/containers/launcher_container.js | 6 +- .../app/widgets/containers/root_container.js | 2 +- 3 files changed, 103 insertions(+), 99 deletions(-) diff --git a/src/public/app/layouts/desktop_layout.js b/src/public/app/layouts/desktop_layout.js index 4f0a2d2f5..68f365172 100644 --- a/src/public/app/layouts/desktop_layout.js +++ b/src/public/app/layouts/desktop_layout.js @@ -93,113 +93,117 @@ export default class DesktopLayout { appContext.noteTreeWidget = new NoteTreeWidget(); const launcherPaneIsHorizontal = true; - const launcherPane = new FlexContainer("column") + const launcherPane = new FlexContainer(launcherPaneIsHorizontal ? "row" : "column") .id("launcher-pane") - .css("width", "53px") + .css(launcherPaneIsHorizontal ? "height" : "width", "53px") .child(new GlobalMenuWidget()) - .child(new LauncherContainer()) + .child(new LauncherContainer(launcherPaneIsHorizontal)) .child(new LeftPaneToggleWidget()); return new RootContainer() .setParent(appContext) - .optChild(!launcherPaneIsHorizontal, launcherPane) - .child(new LeftPaneContainer() - .child(new QuickSearchWidget()) - .child(appContext.noteTreeWidget) - .child(...this.customWidgets.get('left-pane')) - ) - .child(new FlexContainer('column') - .id('rest-pane') + .optChild(launcherPaneIsHorizontal, launcherPane) + .child(new FlexContainer('row') .css("flex-grow", "1") - .child(new FlexContainer('row') - .child(new TabRowWidget()) - .child(new TitleBarButtonsWidget()) - .css('height', '40px') + .optChild(!launcherPaneIsHorizontal, launcherPane) + .child(new LeftPaneContainer() + .child(new QuickSearchWidget()) + .child(appContext.noteTreeWidget) + .child(...this.customWidgets.get('left-pane')) ) - .child(new FlexContainer('row') - .filling() - .collapsible() - .child(new FlexContainer('column') + .child(new FlexContainer('column') + .id('rest-pane') + .css("flex-grow", "1") + .child(new FlexContainer('row') + .child(new TabRowWidget()) + .child(new TitleBarButtonsWidget()) + .css('height', '40px') + ) + .child(new FlexContainer('row') .filling() .collapsible() - .id('center-pane') - .child(new SplitNoteContainer(() => - new NoteWrapperWidget() - .child(new FlexContainer('row').class('title-row') - .css("height", "50px") - .css("min-height", "50px") - .css('align-items', "center") - .cssBlock('.title-row > * { margin: 5px; }') - .child(new NoteIconWidget()) - .child(new NoteTitleWidget()) - .child(new SpacerWidget(0, 1)) - .child(new MovePaneButton(true)) - .child(new MovePaneButton(false)) - .child(new ClosePaneButton()) - .child(new CreatePaneButton()) - ) - .child( - new RibbonContainer() - // the order of the widgets matter. Some of these want to "activate" themselves - // when visible. When this happens to multiple of them, the first one "wins". - // promoted attributes should always win. - .ribbon(new ClassicEditorToolbar()) - .ribbon(new PromotedAttributesWidget()) - .ribbon(new ScriptExecutorWidget()) - .ribbon(new SearchDefinitionWidget()) - .ribbon(new EditedNotesWidget()) - .ribbon(new BookPropertiesWidget()) - .ribbon(new NotePropertiesWidget()) - .ribbon(new FilePropertiesWidget()) - .ribbon(new ImagePropertiesWidget()) - .ribbon(new BasicPropertiesWidget()) - .ribbon(new OwnedAttributeListWidget()) - .ribbon(new InheritedAttributesWidget()) - .ribbon(new NotePathsWidget()) - .ribbon(new NoteMapRibbonWidget()) - .ribbon(new SimilarNotesWidget()) - .ribbon(new NoteInfoWidget()) - .button(new RevisionsButton()) - .button(new NoteActionsWidget()) - ) - .child(new SharedInfoWidget()) - .child(new WatchedFileUpdateStatusWidget()) - .child(new FloatingButtons() - .child(new EditButton()) - .child(new ShowTocWidgetButton()) - .child(new ShowHighlightsListWidgetButton()) - .child(new CodeButtonsWidget()) - .child(new RelationMapButtons()) - .child(new CopyImageReferenceButton()) - .child(new SvgExportButton()) - .child(new BacklinksWidget()) - .child(new HideFloatingButtonsButton()) - ) - .child(new MermaidWidget()) - .child( - new ScrollingContainer() - .filling() - .child(new SqlTableSchemasWidget()) - .child(new NoteDetailWidget()) - .child(new NoteListWidget()) - .child(new SearchResultWidget()) - .child(new SqlResultWidget()) - .child(new ScrollPaddingWidget()) - ) - .child(new ApiLogWidget()) - .child(new FindWidget()) - .child( - ...this.customWidgets.get('node-detail-pane'), // typo, let's keep it for a while as BC - ...this.customWidgets.get('note-detail-pane') - ) + .child(new FlexContainer('column') + .filling() + .collapsible() + .id('center-pane') + .child(new SplitNoteContainer(() => + new NoteWrapperWidget() + .child(new FlexContainer('row').class('title-row') + .css("height", "50px") + .css("min-height", "50px") + .css('align-items', "center") + .cssBlock('.title-row > * { margin: 5px; }') + .child(new NoteIconWidget()) + .child(new NoteTitleWidget()) + .child(new SpacerWidget(0, 1)) + .child(new MovePaneButton(true)) + .child(new MovePaneButton(false)) + .child(new ClosePaneButton()) + .child(new CreatePaneButton()) + ) + .child( + new RibbonContainer() + // the order of the widgets matter. Some of these want to "activate" themselves + // when visible. When this happens to multiple of them, the first one "wins". + // promoted attributes should always win. + .ribbon(new ClassicEditorToolbar()) + .ribbon(new PromotedAttributesWidget()) + .ribbon(new ScriptExecutorWidget()) + .ribbon(new SearchDefinitionWidget()) + .ribbon(new EditedNotesWidget()) + .ribbon(new BookPropertiesWidget()) + .ribbon(new NotePropertiesWidget()) + .ribbon(new FilePropertiesWidget()) + .ribbon(new ImagePropertiesWidget()) + .ribbon(new BasicPropertiesWidget()) + .ribbon(new OwnedAttributeListWidget()) + .ribbon(new InheritedAttributesWidget()) + .ribbon(new NotePathsWidget()) + .ribbon(new NoteMapRibbonWidget()) + .ribbon(new SimilarNotesWidget()) + .ribbon(new NoteInfoWidget()) + .button(new RevisionsButton()) + .button(new NoteActionsWidget()) + ) + .child(new SharedInfoWidget()) + .child(new WatchedFileUpdateStatusWidget()) + .child(new FloatingButtons() + .child(new EditButton()) + .child(new ShowTocWidgetButton()) + .child(new ShowHighlightsListWidgetButton()) + .child(new CodeButtonsWidget()) + .child(new RelationMapButtons()) + .child(new CopyImageReferenceButton()) + .child(new SvgExportButton()) + .child(new BacklinksWidget()) + .child(new HideFloatingButtonsButton()) + ) + .child(new MermaidWidget()) + .child( + new ScrollingContainer() + .filling() + .child(new SqlTableSchemasWidget()) + .child(new NoteDetailWidget()) + .child(new NoteListWidget()) + .child(new SearchResultWidget()) + .child(new SqlResultWidget()) + .child(new ScrollPaddingWidget()) + ) + .child(new ApiLogWidget()) + .child(new FindWidget()) + .child( + ...this.customWidgets.get('node-detail-pane'), // typo, let's keep it for a while as BC + ...this.customWidgets.get('note-detail-pane') + ) + ) ) + .child(...this.customWidgets.get('center-pane')) + ) + .child(new RightPaneContainer() + .child(new TocWidget()) + .child(new HighlightsListWidget()) + .child(...this.customWidgets.get('right-pane')) ) - .child(...this.customWidgets.get('center-pane')) - ) - .child(new RightPaneContainer() - .child(new TocWidget()) - .child(new HighlightsListWidget()) - .child(...this.customWidgets.get('right-pane')) ) ) ) diff --git a/src/public/app/widgets/containers/launcher_container.js b/src/public/app/widgets/containers/launcher_container.js index c5fb7d27d..01bf52bf7 100644 --- a/src/public/app/widgets/containers/launcher_container.js +++ b/src/public/app/widgets/containers/launcher_container.js @@ -4,11 +4,11 @@ import appContext from "../../components/app_context.js"; import LauncherWidget from "./launcher.js"; export default class LauncherContainer extends FlexContainer { - constructor() { - super('column'); + constructor(horizontal) { + super(horizontal ? "row" : "column"); this.id('launcher-container'); - this.css('height', '100%'); + this.css(horizontal ? "width" : 'height', '100%'); this.filling(); this.load(); diff --git a/src/public/app/widgets/containers/root_container.js b/src/public/app/widgets/containers/root_container.js index e17967756..e6a4a4a7a 100644 --- a/src/public/app/widgets/containers/root_container.js +++ b/src/public/app/widgets/containers/root_container.js @@ -2,7 +2,7 @@ import FlexContainer from "./flex_container.js"; export default class RootContainer extends FlexContainer { constructor() { - super('row'); + super('column'); this.id('root-widget'); this.css('height', '100%'); From c9f2a2bd6bff9dcdbe938024ccb5d8b04152cc01 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 22 Nov 2024 21:10:49 +0200 Subject: [PATCH 03/36] feat(client): reorder buttons on horizontal bar --- src/public/app/layouts/desktop_layout.js | 28 +++++++++++++++++++----- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/public/app/layouts/desktop_layout.js b/src/public/app/layouts/desktop_layout.js index 68f365172..c394fa4e0 100644 --- a/src/public/app/layouts/desktop_layout.js +++ b/src/public/app/layouts/desktop_layout.js @@ -93,12 +93,7 @@ export default class DesktopLayout { appContext.noteTreeWidget = new NoteTreeWidget(); const launcherPaneIsHorizontal = true; - const launcherPane = new FlexContainer(launcherPaneIsHorizontal ? "row" : "column") - .id("launcher-pane") - .css(launcherPaneIsHorizontal ? "height" : "width", "53px") - .child(new GlobalMenuWidget()) - .child(new LauncherContainer(launcherPaneIsHorizontal)) - .child(new LeftPaneToggleWidget()); + const launcherPane = this.#buildLauncherPane(launcherPaneIsHorizontal); return new RootContainer() .setParent(appContext) @@ -231,4 +226,25 @@ export default class DesktopLayout { .child(new ConfirmDialog()) .child(new PromptDialog()); } + + #buildLauncherPane(isHorizontal) { + let launcherPane; + + if (isHorizontal) { + launcherPane = new FlexContainer("row") + .css("height", "53px") + .child(new LeftPaneToggleWidget()) + .child(new LauncherContainer(isHorizontal)) + .child(new GlobalMenuWidget()) + } else { + launcherPane = new FlexContainer("column") + .css("width", "53px") + .child(new GlobalMenuWidget()) + .child(new LauncherContainer(isHorizontal)) + .child(new LeftPaneToggleWidget()); + } + + launcherPane.id("launcher-pane"); + return launcherPane; + } } From c858630678dbc8a96d9abc366d1294544780c12a Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 22 Nov 2024 21:14:50 +0200 Subject: [PATCH 04/36] fix(client): fix size for horizontal launcher bar --- src/public/app/layouts/desktop_layout.js | 2 ++ src/public/stylesheets/style.css | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/public/app/layouts/desktop_layout.js b/src/public/app/layouts/desktop_layout.js index c394fa4e0..70b3561ff 100644 --- a/src/public/app/layouts/desktop_layout.js +++ b/src/public/app/layouts/desktop_layout.js @@ -233,12 +233,14 @@ export default class DesktopLayout { if (isHorizontal) { launcherPane = new FlexContainer("row") .css("height", "53px") + .class("horizontal") .child(new LeftPaneToggleWidget()) .child(new LauncherContainer(isHorizontal)) .child(new GlobalMenuWidget()) } else { launcherPane = new FlexContainer("column") .css("width", "53px") + .class("vertical") .child(new GlobalMenuWidget()) .child(new LauncherContainer(isHorizontal)) .child(new LeftPaneToggleWidget()); diff --git a/src/public/stylesheets/style.css b/src/public/stylesheets/style.css index b543d2cca..107199164 100644 --- a/src/public/stylesheets/style.css +++ b/src/public/stylesheets/style.css @@ -1123,11 +1123,20 @@ li.dropdown-submenu:hover > ul.dropdown-menu { cursor: pointer; border: none; color: var(--launcher-pane-text-color); - background-color: var(--launcher-pane-background-color); - height: 53px; - width: 100%; + background-color: var(--launcher-pane-background-color); } +#launcher-pane.vertical .launcher-button { + width: 100%; + height: 53px; +} + +#launcher-pane.horizontal .launcher-button { + width: 53px; + height: 100%; +} + + #launcher-pane .icon-action:hover { background-color: var(--hover-item-background-color); } From d1550db08dbe9402730dafcb738eff1d47e231a6 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 22 Nov 2024 21:35:47 +0200 Subject: [PATCH 05/36] fix(client): experiment with full-width tab bar --- src/public/app/layouts/desktop_layout.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/public/app/layouts/desktop_layout.js b/src/public/app/layouts/desktop_layout.js index 70b3561ff..a06c89a63 100644 --- a/src/public/app/layouts/desktop_layout.js +++ b/src/public/app/layouts/desktop_layout.js @@ -94,10 +94,16 @@ export default class DesktopLayout { const launcherPaneIsHorizontal = true; const launcherPane = this.#buildLauncherPane(launcherPaneIsHorizontal); + const fullWidthTabBar = launcherPaneIsHorizontal && true; + const tabBar = new TabRowWidget(); return new RootContainer() .setParent(appContext) .optChild(launcherPaneIsHorizontal, launcherPane) + .optChild(fullWidthTabBar, new FlexContainer('row') + .child(tabBar) + .css('height', '40px') + ) .child(new FlexContainer('row') .css("flex-grow", "1") .optChild(!launcherPaneIsHorizontal, launcherPane) @@ -109,8 +115,8 @@ export default class DesktopLayout { .child(new FlexContainer('column') .id('rest-pane') .css("flex-grow", "1") - .child(new FlexContainer('row') - .child(new TabRowWidget()) + .optChild(!fullWidthTabBar, new FlexContainer('row') + .child(tabBar) .child(new TitleBarButtonsWidget()) .css('height', '40px') ) From 91c4ea333eebf9684067e9df248d89eb1231c630 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 22 Nov 2024 21:37:54 +0200 Subject: [PATCH 06/36] feat(client): move tab bar on horizontal layout --- src/public/app/layouts/desktop_layout.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/public/app/layouts/desktop_layout.js b/src/public/app/layouts/desktop_layout.js index a06c89a63..4fbbe43c5 100644 --- a/src/public/app/layouts/desktop_layout.js +++ b/src/public/app/layouts/desktop_layout.js @@ -94,16 +94,15 @@ export default class DesktopLayout { const launcherPaneIsHorizontal = true; const launcherPane = this.#buildLauncherPane(launcherPaneIsHorizontal); - const fullWidthTabBar = launcherPaneIsHorizontal && true; const tabBar = new TabRowWidget(); return new RootContainer() .setParent(appContext) - .optChild(launcherPaneIsHorizontal, launcherPane) - .optChild(fullWidthTabBar, new FlexContainer('row') + .optChild(launcherPaneIsHorizontal, new FlexContainer('row') .child(tabBar) .css('height', '40px') ) + .optChild(launcherPaneIsHorizontal, launcherPane) .child(new FlexContainer('row') .css("flex-grow", "1") .optChild(!launcherPaneIsHorizontal, launcherPane) @@ -115,7 +114,7 @@ export default class DesktopLayout { .child(new FlexContainer('column') .id('rest-pane') .css("flex-grow", "1") - .optChild(!fullWidthTabBar, new FlexContainer('row') + .optChild(!launcherPaneIsHorizontal, new FlexContainer('row') .child(tabBar) .child(new TitleBarButtonsWidget()) .css('height', '40px') From 15b9f38439e5cb0ef60cd68281f3487f5a5e025a Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 22 Nov 2024 21:41:23 +0200 Subject: [PATCH 07/36] style(client): improve background for full-width tab bar --- src/public/app/layouts/desktop_layout.js | 2 +- src/public/app/widgets/tab_row.js | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/public/app/layouts/desktop_layout.js b/src/public/app/layouts/desktop_layout.js index 4fbbe43c5..cc94a62a0 100644 --- a/src/public/app/layouts/desktop_layout.js +++ b/src/public/app/layouts/desktop_layout.js @@ -99,7 +99,7 @@ export default class DesktopLayout { return new RootContainer() .setParent(appContext) .optChild(launcherPaneIsHorizontal, new FlexContainer('row') - .child(tabBar) + .child(tabBar.class("full-width")) .css('height', '40px') ) .optChild(launcherPaneIsHorizontal, launcherPane) diff --git a/src/public/app/widgets/tab_row.js b/src/public/app/widgets/tab_row.js index 3437660ee..6ac6e177f 100644 --- a/src/public/app/widgets/tab_row.js +++ b/src/public/app/widgets/tab_row.js @@ -55,6 +55,10 @@ const TAB_ROW_TPL = ` background: var(--main-background-color); overflow: hidden; } + + .tab-row-widget.full-width { + background: var(--launcher-pane-background-color); + } .tab-row-widget * { box-sizing: inherit; From 045c8699a9b1ffc4dd77f4481711536dc87f7187 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 22 Nov 2024 21:56:34 +0200 Subject: [PATCH 08/36] refactor(client): use switch instead of chained-if --- src/public/app/widgets/containers/launcher.js | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/public/app/widgets/containers/launcher.js b/src/public/app/widgets/containers/launcher.js index a4697c76f..fc83d7e17 100644 --- a/src/public/app/widgets/containers/launcher.js +++ b/src/public/app/widgets/containers/launcher.js @@ -86,28 +86,28 @@ export default class LauncherWidget extends BasicWidget { initBuiltinWidget(note) { const builtinWidget = note.getLabelValue("builtinWidget"); - - if (builtinWidget === 'calendar') { + switch (builtinWidget) { + case "calendar": return new CalendarWidget(note.title, note.getIcon()); - } else if (builtinWidget === 'spacer') { + case "spacer": // || has to be inside since 0 is a valid value const baseSize = parseInt(note.getLabelValue("baseSize") || "40"); const growthFactor = parseInt(note.getLabelValue("growthFactor") || "100"); return new SpacerWidget(baseSize, growthFactor); - } else if (builtinWidget === 'bookmarks') { + case "bookmarks": return new BookmarkButtons(); - } else if (builtinWidget === 'protectedSession') { + case "protectedSession": return new ProtectedSessionStatusWidget(); - } else if (builtinWidget === 'syncStatus') { + case "syncStatus": return new SyncStatusWidget(); - } else if (builtinWidget === 'backInHistoryButton') { + case "backInHistoryButton": return new HistoryNavigationButton(note, "backInNoteHistory"); - } else if (builtinWidget === 'forwardInHistoryButton') { + case "forwardInHistoryButton": return new HistoryNavigationButton(note, "forwardInNoteHistory"); - } else if (builtinWidget === 'todayInJournal') { + case "todayInJournal": return new TodayLauncher(note); - } else { + default: throw new Error(`Unrecognized builtin widget ${builtinWidget} for launcher ${note.noteId} "${note.title}"`); } } From 20b0215364c6ad736dfcdfb2276de77fcd3b3e70 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 22 Nov 2024 21:57:03 +0200 Subject: [PATCH 09/36] feat(client): set up quick search as launcher --- src/public/app/layouts/desktop_layout.js | 2 +- src/public/app/widgets/containers/launcher.js | 29 ++++++++++--------- src/public/stylesheets/style.css | 3 ++ src/services/hidden_subtree.ts | 3 +- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/public/app/layouts/desktop_layout.js b/src/public/app/layouts/desktop_layout.js index cc94a62a0..afb1bfedb 100644 --- a/src/public/app/layouts/desktop_layout.js +++ b/src/public/app/layouts/desktop_layout.js @@ -107,7 +107,7 @@ export default class DesktopLayout { .css("flex-grow", "1") .optChild(!launcherPaneIsHorizontal, launcherPane) .child(new LeftPaneContainer() - .child(new QuickSearchWidget()) + .optChild(!launcherPaneIsHorizontal, new QuickSearchWidget()) .child(appContext.noteTreeWidget) .child(...this.customWidgets.get('left-pane')) ) diff --git a/src/public/app/widgets/containers/launcher.js b/src/public/app/widgets/containers/launcher.js index fc83d7e17..bb3e5c9ad 100644 --- a/src/public/app/widgets/containers/launcher.js +++ b/src/public/app/widgets/containers/launcher.js @@ -10,6 +10,7 @@ import CommandButtonWidget from "../buttons/command_button.js"; import utils from "../../services/utils.js"; import TodayLauncher from "../buttons/launcher/today_launcher.js"; import HistoryNavigationButton from "../buttons/history_navigation.js"; +import QuickSearchWidget from "../quick_search.js"; export default class LauncherWidget extends BasicWidget { constructor() { @@ -88,27 +89,29 @@ export default class LauncherWidget extends BasicWidget { const builtinWidget = note.getLabelValue("builtinWidget"); switch (builtinWidget) { case "calendar": - return new CalendarWidget(note.title, note.getIcon()); + return new CalendarWidget(note.title, note.getIcon()); case "spacer": - // || has to be inside since 0 is a valid value - const baseSize = parseInt(note.getLabelValue("baseSize") || "40"); - const growthFactor = parseInt(note.getLabelValue("growthFactor") || "100"); - - return new SpacerWidget(baseSize, growthFactor); + // || has to be inside since 0 is a valid value + const baseSize = parseInt(note.getLabelValue("baseSize") || "40"); + const growthFactor = parseInt(note.getLabelValue("growthFactor") || "100"); + + return new SpacerWidget(baseSize, growthFactor); case "bookmarks": - return new BookmarkButtons(); + return new BookmarkButtons(); case "protectedSession": - return new ProtectedSessionStatusWidget(); + return new ProtectedSessionStatusWidget(); case "syncStatus": - return new SyncStatusWidget(); + return new SyncStatusWidget(); case "backInHistoryButton": - return new HistoryNavigationButton(note, "backInNoteHistory"); + return new HistoryNavigationButton(note, "backInNoteHistory"); case "forwardInHistoryButton": - return new HistoryNavigationButton(note, "forwardInNoteHistory"); + return new HistoryNavigationButton(note, "forwardInNoteHistory"); case "todayInJournal": - return new TodayLauncher(note); + return new TodayLauncher(note); + case "quickSearch": + return new QuickSearchWidget(); default: - throw new Error(`Unrecognized builtin widget ${builtinWidget} for launcher ${note.noteId} "${note.title}"`); + throw new Error(`Unrecognized builtin widget ${builtinWidget} for launcher ${note.noteId} "${note.title}"`); } } } diff --git a/src/public/stylesheets/style.css b/src/public/stylesheets/style.css index 107199164..f298c8306 100644 --- a/src/public/stylesheets/style.css +++ b/src/public/stylesheets/style.css @@ -1136,6 +1136,9 @@ li.dropdown-submenu:hover > ul.dropdown-menu { height: 100%; } +#launcher-pane.horizontal .quick-search { + width: 350px; +} #launcher-pane .icon-action:hover { background-color: var(--hover-item-background-color); diff --git a/src/services/hidden_subtree.ts b/src/services/hidden_subtree.ts index 558362d5e..b73dbf0ff 100644 --- a/src/services/hidden_subtree.ts +++ b/src/services/hidden_subtree.ts @@ -34,7 +34,7 @@ interface Item { baseSize?: string; growthFactor?: string; targetNoteId?: "_backendLog" | "_globalNoteMap"; - builtinWidget?: "bookmarks" | "spacer" | "backInHistoryButton" | "forwardInHistoryButton" | "syncStatus" | "protectedSession" | "todayInJournal" | "calendar"; + builtinWidget?: "bookmarks" | "spacer" | "backInHistoryButton" | "forwardInHistoryButton" | "syncStatus" | "protectedSession" | "todayInJournal" | "calendar" | "quickSearch"; command?: keyof typeof Command; } @@ -240,6 +240,7 @@ const HIDDEN_SUBTREE_DEFINITION: Item = { { id: '_lbBookmarks', title: 'Bookmarks', type: 'launcher', builtinWidget: 'bookmarks', icon: 'bx bx-bookmark' }, { id: '_lbToday', title: "Open Today's Journal Note", type: 'launcher', builtinWidget: 'todayInJournal', icon: 'bx bx-calendar-star' }, { id: '_lbSpacer2', title: 'Spacer', type: 'launcher', builtinWidget: 'spacer', baseSize: "0", growthFactor: "1" }, + { id: '_lbQuickSearch', title: "Quick Search", type: "launcher", builtinWidget: "quickSearch", icon: "bx bx-rectangle" }, { id: '_lbProtectedSession', title: 'Protected Session', type: 'launcher', builtinWidget: 'protectedSession', icon: 'bx bx bx-shield-quarter' }, { id: '_lbSyncStatus', title: 'Sync Status', type: 'launcher', builtinWidget: 'syncStatus', icon: 'bx bx-wifi' }, { id: '_lbSettings', title: 'Settings', type: 'launcher', command: 'showOptions', icon: 'bx bx-cog' } From 50bf94875c6a92603da47396b8e238469e49c6ea Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 22 Nov 2024 22:16:48 +0200 Subject: [PATCH 10/36] fix(client): global submenu not working in horizontal layout --- src/public/stylesheets/style.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/public/stylesheets/style.css b/src/public/stylesheets/style.css index f298c8306..c4a5c9de6 100644 --- a/src/public/stylesheets/style.css +++ b/src/public/stylesheets/style.css @@ -1022,6 +1022,10 @@ li.dropdown-submenu:hover > ul.dropdown-menu { overflow: auto; } +#launcher-pane.horizontal .dropdown-submenu > .dropdown-menu { + left: calc(-100% + 10px); +} + /* rotate caret on hover */ .dropdown-menu > li > a:hover:after { text-decoration: underline; From f62e860b6182806b03d3214abeb8de381a30fb2d Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 22 Nov 2024 22:44:34 +0200 Subject: [PATCH 11/36] feat(client): use hamburger menu for horizontal layout --- src/public/app/layouts/desktop_layout.js | 4 +- src/public/app/widgets/buttons/global_menu.js | 56 +++++++++++-------- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/public/app/layouts/desktop_layout.js b/src/public/app/layouts/desktop_layout.js index afb1bfedb..bc6ccf3c9 100644 --- a/src/public/app/layouts/desktop_layout.js +++ b/src/public/app/layouts/desktop_layout.js @@ -241,12 +241,12 @@ export default class DesktopLayout { .class("horizontal") .child(new LeftPaneToggleWidget()) .child(new LauncherContainer(isHorizontal)) - .child(new GlobalMenuWidget()) + .child(new GlobalMenuWidget(true)) } else { launcherPane = new FlexContainer("column") .css("width", "53px") .class("vertical") - .child(new GlobalMenuWidget()) + .child(new GlobalMenuWidget(false)) .child(new LauncherContainer(isHorizontal)) .child(new LeftPaneToggleWidget()); } diff --git a/src/public/app/widgets/buttons/global_menu.js b/src/public/app/widgets/buttons/global_menu.js index c93dd4c2a..63026db68 100644 --- a/src/public/app/widgets/buttons/global_menu.js +++ b/src/public/app/widgets/buttons/global_menu.js @@ -107,22 +107,6 @@ const TPL = ` @@ -265,18 +249,40 @@ const TPL = ` `; export default class GlobalMenuWidget extends BasicWidget { - constructor() { + constructor(isHorizontalLayout) { super(); this.updateAvailableWidget = new UpdateAvailableWidget(); + this.isHorizontalLayout = isHorizontalLayout; } doRender() { this.$widget = $(TPL); - this.dropdown = bootstrap.Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']")); + const $globalMenuButton = this.$widget.find(".global-menu-button") + if (!this.isHorizontalLayout) { + $globalMenuButton.prepend($(`\ + + + + + + + + + + + + + + + `)); + this.tooltip = new bootstrap.Tooltip(this.$widget.find("[data-bs-toggle='tooltip']"), { trigger: "hover" }); + } else { + $globalMenuButton.toggleClass("bx bx-menu"); + } - this.tooltip = new bootstrap.Tooltip(this.$widget.find("[data-bs-toggle='tooltip']"), { trigger: "hover" }); + this.dropdown = bootstrap.Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']")); this.$widget.find(".show-about-dialog-button").on('click', () => this.triggerCommand("openAboutDialog")); @@ -300,7 +306,7 @@ export default class GlobalMenuWidget extends BasicWidget { if ($(e.target).children(".dropdown-menu").length === 1 || $(e.target).hasClass('dropdown-toggle')) { e.stopPropagation(); } - }) + }) this.$widget.find(".global-menu-button-update-available").append( this.updateAvailableWidget.render() @@ -316,10 +322,14 @@ export default class GlobalMenuWidget extends BasicWidget { this.$zoomState = this.$widget.find(".zoom-state"); this.$widget.on('show.bs.dropdown', () => { this.updateZoomState(); - this.tooltip.hide(); - this.tooltip.disable(); + if (this.tooltip) { + this.tooltip.hide(); + this.tooltip.disable(); + } }); - this.$widget.on('hide.bs.dropdown', () => this.tooltip.enable()); + if (this.tooltip) { + this.$widget.on('hide.bs.dropdown', () => this.tooltip.enable()); + } this.$widget.find(".zoom-buttons").on("click", // delay to wait for the actual zoom change From 13a997beb0651e33d5cb3dc78d961f694ca44329 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 22 Nov 2024 23:02:43 +0200 Subject: [PATCH 12/36] fix(client): add new tab not working in horizontal layout --- src/public/app/components/component.js | 7 +++++-- src/public/app/layouts/desktop_layout.js | 8 ++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/public/app/components/component.js b/src/public/app/components/component.js index 0f614bcbf..490b70b35 100644 --- a/src/public/app/components/component.js +++ b/src/public/app/components/component.js @@ -88,8 +88,11 @@ export default class Component { if (fun) { return this.callMethod(fun, data); - } - else { + } else { + if (!this.parent) { + throw new Error(`Component "${this.componentId}" does not have a parent attached to propagate a command.`); + } + return this.parent.triggerCommand(name, data); } } diff --git a/src/public/app/layouts/desktop_layout.js b/src/public/app/layouts/desktop_layout.js index bc6ccf3c9..6273e8e4a 100644 --- a/src/public/app/layouts/desktop_layout.js +++ b/src/public/app/layouts/desktop_layout.js @@ -94,13 +94,13 @@ export default class DesktopLayout { const launcherPaneIsHorizontal = true; const launcherPane = this.#buildLauncherPane(launcherPaneIsHorizontal); - const tabBar = new TabRowWidget(); return new RootContainer() .setParent(appContext) - .optChild(launcherPaneIsHorizontal, new FlexContainer('row') - .child(tabBar.class("full-width")) + .optChild(launcherPaneIsHorizontal, new FlexContainer('row') + .child(new TabRowWidget().class("full-width")) .css('height', '40px') + .setParent(appContext) ) .optChild(launcherPaneIsHorizontal, launcherPane) .child(new FlexContainer('row') @@ -115,7 +115,7 @@ export default class DesktopLayout { .id('rest-pane') .css("flex-grow", "1") .optChild(!launcherPaneIsHorizontal, new FlexContainer('row') - .child(tabBar) + .child(new TabRowWidget()) .child(new TitleBarButtonsWidget()) .css('height', '40px') ) From fd8f9506d4746331109b538d5ec5b270e1605fa9 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 22 Nov 2024 23:58:15 +0200 Subject: [PATCH 13/36] fix(client): tooltip position for launcher on horizontal layout --- src/public/app/widgets/buttons/abstract_button.js | 7 ++++--- src/public/app/widgets/containers/launcher.js | 6 +++++- src/public/app/widgets/containers/launcher_container.js | 9 +++++---- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/public/app/widgets/buttons/abstract_button.js b/src/public/app/widgets/buttons/abstract_button.js index 8c8a3dd4b..38b47429b 100644 --- a/src/public/app/widgets/buttons/abstract_button.js +++ b/src/public/app/widgets/buttons/abstract_button.js @@ -23,7 +23,10 @@ export default class AbstractButtonWidget extends NoteContextAwareWidget { doRender() { this.$widget = $(TPL); this.tooltip = new bootstrap.Tooltip(this.$widget, { - html: true, title: () => this.getTitle(), trigger: 'hover' + html: true, + title: () => this.getTitle(), + trigger: 'hover', + placement: this.settings.titlePlacement }) if (this.settings.onContextMenu) { @@ -36,8 +39,6 @@ export default class AbstractButtonWidget extends NoteContextAwareWidget { }); } - this.$widget.attr("data-placement", this.settings.titlePlacement); - super.doRender(); } diff --git a/src/public/app/widgets/containers/launcher.js b/src/public/app/widgets/containers/launcher.js index bb3e5c9ad..03c24c630 100644 --- a/src/public/app/widgets/containers/launcher.js +++ b/src/public/app/widgets/containers/launcher.js @@ -13,10 +13,11 @@ import HistoryNavigationButton from "../buttons/history_navigation.js"; import QuickSearchWidget from "../quick_search.js"; export default class LauncherWidget extends BasicWidget { - constructor() { + constructor(isHorizontalLayout) { super(); this.innerWidget = null; + this.isHorizontalLayout = isHorizontalLayout; } isEnabled() { @@ -64,6 +65,9 @@ export default class LauncherWidget extends BasicWidget { } this.child(this.innerWidget); + if (this.isHorizontalLayout && this.innerWidget.settings) { + this.innerWidget.settings.titlePlacement = "bottom"; + } return true; } diff --git a/src/public/app/widgets/containers/launcher_container.js b/src/public/app/widgets/containers/launcher_container.js index 01bf52bf7..e20969da4 100644 --- a/src/public/app/widgets/containers/launcher_container.js +++ b/src/public/app/widgets/containers/launcher_container.js @@ -4,12 +4,13 @@ import appContext from "../../components/app_context.js"; import LauncherWidget from "./launcher.js"; export default class LauncherContainer extends FlexContainer { - constructor(horizontal) { - super(horizontal ? "row" : "column"); + constructor(isHorizontalLayout) { + super(isHorizontalLayout ? "row" : "column"); this.id('launcher-container'); - this.css(horizontal ? "width" : 'height', '100%'); + this.css(isHorizontalLayout ? "width" : 'height', '100%'); this.filling(); + this.isHorizontalLayout = isHorizontalLayout; this.load(); } @@ -29,7 +30,7 @@ export default class LauncherContainer extends FlexContainer { for (const launcherNote of await visibleLaunchersRoot.getChildNotes()) { try { - const launcherWidget = new LauncherWidget(); + const launcherWidget = new LauncherWidget(this.isHorizontalLayout); const success = await launcherWidget.initLauncher(launcherNote); if (success) { From 7e5fea8cd269f36c9c843ec7ff8dad647afa04c8 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 23 Nov 2024 00:07:40 +0200 Subject: [PATCH 14/36] fix(client): tooltip position for hide left pane button --- src/public/app/layouts/desktop_layout.js | 8 ++++---- src/public/app/widgets/buttons/abstract_button.js | 3 ++- src/public/app/widgets/buttons/left_pane_toggle.js | 7 ++++++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/public/app/layouts/desktop_layout.js b/src/public/app/layouts/desktop_layout.js index 6273e8e4a..223068f4a 100644 --- a/src/public/app/layouts/desktop_layout.js +++ b/src/public/app/layouts/desktop_layout.js @@ -239,16 +239,16 @@ export default class DesktopLayout { launcherPane = new FlexContainer("row") .css("height", "53px") .class("horizontal") - .child(new LeftPaneToggleWidget()) - .child(new LauncherContainer(isHorizontal)) + .child(new LeftPaneToggleWidget(true)) + .child(new LauncherContainer(true)) .child(new GlobalMenuWidget(true)) } else { launcherPane = new FlexContainer("column") .css("width", "53px") .class("vertical") .child(new GlobalMenuWidget(false)) - .child(new LauncherContainer(isHorizontal)) - .child(new LeftPaneToggleWidget()); + .child(new LauncherContainer(false)) + .child(new LeftPaneToggleWidget(false)); } launcherPane.id("launcher-pane"); diff --git a/src/public/app/widgets/buttons/abstract_button.js b/src/public/app/widgets/buttons/abstract_button.js index 38b47429b..98236d5a8 100644 --- a/src/public/app/widgets/buttons/abstract_button.js +++ b/src/public/app/widgets/buttons/abstract_button.js @@ -26,7 +26,8 @@ export default class AbstractButtonWidget extends NoteContextAwareWidget { html: true, title: () => this.getTitle(), trigger: 'hover', - placement: this.settings.titlePlacement + placement: this.settings.titlePlacement, + fallbackPlacements: [ this.settings.titlePlacement ] }) if (this.settings.onContextMenu) { diff --git a/src/public/app/widgets/buttons/left_pane_toggle.js b/src/public/app/widgets/buttons/left_pane_toggle.js index 82a4758b5..eb5f15376 100644 --- a/src/public/app/widgets/buttons/left_pane_toggle.js +++ b/src/public/app/widgets/buttons/left_pane_toggle.js @@ -4,7 +4,7 @@ import CommandButtonWidget from "./command_button.js"; import { t } from "../../services/i18n.js"; export default class LeftPaneToggleWidget extends CommandButtonWidget { - constructor() { + constructor(isHorizontalLayout) { super(); this.class("launcher-button"); @@ -20,6 +20,11 @@ export default class LeftPaneToggleWidget extends CommandButtonWidget { this.settings.command = () => options.is('leftPaneVisible') ? "hideLeftPane" : "showLeftPane"; + + if (isHorizontalLayout) { + this.settings.titlePlacement = "bottom"; + } + console.log(this.settings); } refreshIcon() { From 5f9439a9e0b528b2eb588057a1f13e3630bc9c73 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 23 Nov 2024 00:11:49 +0200 Subject: [PATCH 15/36] fix(client): dropdown tooltip placement for horizontal layout --- .../app/widgets/buttons/right_dropdown_button.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/public/app/widgets/buttons/right_dropdown_button.js b/src/public/app/widgets/buttons/right_dropdown_button.js index ab6ca0bc2..2894782c8 100644 --- a/src/public/app/widgets/buttons/right_dropdown_button.js +++ b/src/public/app/widgets/buttons/right_dropdown_button.js @@ -8,7 +8,7 @@ const TPL = ` } - @@ -25,6 +25,10 @@ export default class RightDropdownButtonWidget extends BasicWidget { this.iconClass = iconClass; this.title = title; this.dropdownTpl = dropdownTpl; + + this.settings = { + titlePlacement: "bottom" + }; } doRender() { @@ -33,7 +37,10 @@ export default class RightDropdownButtonWidget extends BasicWidget { this.dropdown = bootstrap.Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']")); this.$tooltip = this.$widget.find(".tooltip-trigger").attr("title", this.title); - this.tooltip = new bootstrap.Tooltip(this.$tooltip); + this.tooltip = new bootstrap.Tooltip(this.$tooltip, { + placement: this.settings.titlePlacement, + fallbackPlacements: [ this.settings.titlePlacement ] + }); this.$widget.find(".right-dropdown-button") .addClass(this.iconClass) From 23873b72bf9d5b1de5c2845d239b92a0eb79cee5 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 23 Nov 2024 00:15:50 +0200 Subject: [PATCH 16/36] fix(client): dropdown width for horizontal layout --- src/public/app/widgets/buttons/left_pane_toggle.js | 1 - src/public/app/widgets/buttons/right_dropdown_button.js | 6 ------ src/public/stylesheets/style.css | 8 ++++++++ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/public/app/widgets/buttons/left_pane_toggle.js b/src/public/app/widgets/buttons/left_pane_toggle.js index eb5f15376..f03d2dcd5 100644 --- a/src/public/app/widgets/buttons/left_pane_toggle.js +++ b/src/public/app/widgets/buttons/left_pane_toggle.js @@ -24,7 +24,6 @@ export default class LeftPaneToggleWidget extends CommandButtonWidget { if (isHorizontalLayout) { this.settings.titlePlacement = "bottom"; } - console.log(this.settings); } refreshIcon() { diff --git a/src/public/app/widgets/buttons/right_dropdown_button.js b/src/public/app/widgets/buttons/right_dropdown_button.js index 2894782c8..ef4ab234e 100644 --- a/src/public/app/widgets/buttons/right_dropdown_button.js +++ b/src/public/app/widgets/buttons/right_dropdown_button.js @@ -2,12 +2,6 @@ import BasicWidget from "../basic_widget.js"; const TPL = `