From ca968a9e31edc381e4e3da83819fc5d076a60c60 Mon Sep 17 00:00:00 2001 From: zadam Date: Tue, 13 Dec 2022 16:57:46 +0100 Subject: [PATCH] hoisting support in mobile view WIP --- package-lock.json | 4 +- src/public/app/components/app_context.js | 12 +---- src/public/app/components/entrypoints.js | 10 ++-- .../app/components/mobile_screen_switcher.js | 5 +- src/public/app/components/note_context.js | 8 ++- src/public/app/components/tab_manager.js | 52 +++++++++---------- src/public/app/layouts/mobile_layout.js | 10 +++- src/public/app/services/tree.js | 9 ++++ src/public/app/widgets/note_tree.js | 2 +- src/views/mobile.ejs | 3 +- 10 files changed, 63 insertions(+), 52 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3ea3c36e5..5efe20284 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { "name": "trilium", - "version": "0.57.3", + "version": "0.57.4", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "0.57.3", + "version": "0.57.4", "hasInstallScript": true, "license": "AGPL-3.0-only", "dependencies": { diff --git a/src/public/app/components/app_context.js b/src/public/app/components/app_context.js index 8b3cbf2aa..daf27d09a 100644 --- a/src/public/app/components/app_context.js +++ b/src/public/app/components/app_context.js @@ -150,19 +150,11 @@ $(window).on('beforeunload', () => { } }); -function isNotePathInAddress() { - const [notePath, ntxId] = treeService.getHashValueFromAddress(); - - return notePath.startsWith("root") - // empty string is for empty/uninitialized tab - || (notePath === '' && !!ntxId); -} - $(window).on('hashchange', function() { - if (isNotePathInAddress()) { + if (treeService.isNotePathInAddress()) { const [notePath, ntxId] = treeService.getHashValueFromAddress(); - if (!notePath) { + if (!notePath && !ntxId) { console.log(`Invalid hash value "${document.location.hash}", ignoring.`); return; } diff --git a/src/public/app/components/entrypoints.js b/src/public/app/components/entrypoints.js index a93d972e9..1b35cc183 100644 --- a/src/public/app/components/entrypoints.js +++ b/src/public/app/components/entrypoints.js @@ -190,16 +190,20 @@ export default class Entrypoints extends Component { toastService.showMessage("Note executed"); } - hideAllTooltips() { + hideAllPopups() { $(".tooltip").removeClass("show"); + + if (utils.isDesktop()) { + $(".aa-input").autocomplete("close"); + } } noteSwitchedEvent() { - this.hideAllTooltips(); + this.hideAllPopups(); } activeContextChangedEvent() { - this.hideAllTooltips(); + this.hideAllPopups(); } async forceSaveNoteRevisionCommand() { diff --git a/src/public/app/components/mobile_screen_switcher.js b/src/public/app/components/mobile_screen_switcher.js index 3db8ec8f3..fe0af1a32 100644 --- a/src/public/app/components/mobile_screen_switcher.js +++ b/src/public/app/components/mobile_screen_switcher.js @@ -1,4 +1,5 @@ import Component from "./component.js"; +import appContext from "./app_context.js"; export default class MobileScreenSwitcherExecutor extends Component { setActiveScreenCommand({screen}) { @@ -6,7 +7,9 @@ export default class MobileScreenSwitcherExecutor extends Component { this.activeScreen = screen; if (screen === 'tree') { - document.location.hash = ''; + const activeNoteContext = appContext.tabManager.getActiveContext(); + + activeNoteContext.setEmpty(); } this.triggerEvent('activeScreenChanged', {activeScreen: screen}); diff --git a/src/public/app/components/note_context.js b/src/public/app/components/note_context.js index 60d9a675b..47161069f 100644 --- a/src/public/app/components/note_context.js +++ b/src/public/app/components/note_context.js @@ -80,10 +80,7 @@ class NoteContext extends Component { await this.setHoistedNoteId(hoistedNoteId); } - if (utils.isDesktop()) { - // close dangling autocompletes after closing the tab - $(".aa-input").autocomplete("close"); - } else if (utils.isMobile()) { + if (utils.isMobile()) { this.triggerCommand('setActiveScreen', {screen: 'detail'}); } } @@ -171,7 +168,8 @@ class NoteContext extends Component { } getTabState() { - if (!this.notePath) { + if (!this.notePath && this.hoistedNoteId === 'root') { + // keeping empty hoisted tab is esp. important for mobile (e.g. opened launcher config) return null; } diff --git a/src/public/app/components/tab_manager.js b/src/public/app/components/tab_manager.js index e370ec2db..8868000ba 100644 --- a/src/public/app/components/tab_manager.js +++ b/src/public/app/components/tab_manager.js @@ -25,10 +25,14 @@ export default class TabManager extends Component { return; } + console.log("Pre-saving", this.noteContexts); + const openTabs = this.noteContexts .map(nc => nc.getTabState()) .filter(t => !!t); + console.log("Saving", openTabs); + await server.put('options', { openTabs: JSON.stringify(openTabs) }); @@ -52,34 +56,10 @@ export default class TabManager extends Component { ? (options.getJson('openTabs') || []) : []; - // if there's notePath in the URL, make sure it's open and active - // (useful, among others, for opening clipped notes from clipper) - if (window.location.hash) { - const notePath = window.location.hash.substr(1); - const noteId = treeService.getNoteIdFromNotePath(notePath); - - if (noteId && await froca.noteExists(noteId)) { - for (const tab of tabsToOpen) { - tab.active = false; - } - - const foundTab = tabsToOpen.find(tab => noteId === treeService.getNoteIdFromNotePath(tab.notePath)); - - if (foundTab) { - foundTab.active = true; - } - else { - tabsToOpen.push({ - notePath: notePath, - active: true, - hoistedNoteId: glob.extraHoistedNoteId || 'root' - }); - } - } - } - let filteredTabs = []; + console.log(document.location.hash, tabsToOpen); + for (const openTab of tabsToOpen) { const noteId = treeService.getNoteIdFromNotePath(openTab.notePath); @@ -111,6 +91,14 @@ export default class TabManager extends Component { await this.openContextWithNote(tab.notePath, tab.active, tab.ntxId, tab.hoistedNoteId, tab.mainNtxId); } }); + + // if there's notePath in the URL, make sure it's open and active + // (useful, among others, for opening clipped notes from clipper) + if (treeService.isNotePathInAddress()) { + const [notePath, ntxId] = treeService.getHashValueFromAddress(); + + await appContext.tabManager.switchToNoteContext(ntxId, notePath); + } } noteSwitchedEvent({noteContext}) { @@ -205,11 +193,19 @@ export default class TabManager extends Component { } async switchToNoteContext(ntxId, notePath) { + console.log("Looking for " + ntxId); + console.log("Existing", this.noteContexts); + const noteContext = this.noteContexts.find(nc => nc.ntxId === ntxId) || await this.openEmptyTab(); - this.activateNoteContext(noteContext.ntxId); - await noteContext.setNote(notePath); + console.log(noteContext); + + await this.activateNoteContext(noteContext.ntxId); + + if (notePath) { + await noteContext.setNote(notePath); + } } async openAndActivateEmptyTab() { diff --git a/src/public/app/layouts/mobile_layout.js b/src/public/app/layouts/mobile_layout.js index 76ee76c1a..c58486150 100644 --- a/src/public/app/layouts/mobile_layout.js +++ b/src/public/app/layouts/mobile_layout.js @@ -101,6 +101,11 @@ span.fancytree-expander { margin-right: 16px; display: none; } + +.tree-wrapper .unhoist-button { + display: block; + font-size: 200%; +} `; export default class MobileLayout { @@ -119,13 +124,16 @@ export default class MobileLayout { .child(new ScreenContainer("tree", 'column') .class("d-sm-flex d-md-flex d-lg-flex d-xl-flex col-12 col-sm-5 col-md-4 col-lg-3 col-xl-3") .css("max-height", "100%") - .css('padding-left', 0) + .css('padding-left', "0") + .css('padding-right', "0") .css('contain', 'content') .child(new QuickSearchWidget()) .child(new NoteTreeWidget() .cssBlock(FANCYTREE_CSS))) .child(new ScreenContainer("detail", "column") .class("d-sm-flex d-md-flex d-lg-flex d-xl-flex col-12 col-sm-7 col-md-8 col-lg-9") + .css("padding-left", "0") + .css("padding-right", "0") .css('max-height', '100%') .child(new FlexContainer('row').contentSized() .css('font-size', 'larger') diff --git a/src/public/app/services/tree.js b/src/public/app/services/tree.js index d68d689c6..eb6f4645c 100644 --- a/src/public/app/services/tree.js +++ b/src/public/app/services/tree.js @@ -304,6 +304,14 @@ function getHashValueFromAddress() { return str.split("-"); } +function isNotePathInAddress() { + const [notePath, ntxId] = getHashValueFromAddress(); + + return notePath.startsWith("root") + // empty string is for empty/uninitialized tab + || (notePath === '' && !!ntxId); +} + function parseNotePath(notePath) { let noteIds = notePath.split('/'); @@ -332,6 +340,7 @@ export default { getNotePathTitle, getNoteTitleWithPathAsSuffix, getHashValueFromAddress, + isNotePathInAddress, parseNotePath, isNotePathInHiddenSubtree }; diff --git a/src/public/app/widgets/note_tree.js b/src/public/app/widgets/note_tree.js index 80396a84c..3b3333b95 100644 --- a/src/public/app/widgets/note_tree.js +++ b/src/public/app/widgets/note_tree.js @@ -535,7 +535,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { const note = await froca.getNote(node.data.noteId, true); - if (!note || note.isDeleted || note.isLaunchBarConfig()) { + if (!note || note.isDeleted) { return; } diff --git a/src/views/mobile.ejs b/src/views/mobile.ejs index c0b3569e1..c6ad8f887 100644 --- a/src/views/mobile.ejs +++ b/src/views/mobile.ejs @@ -116,7 +116,8 @@ isDev: <%= isDev %>, appCssNoteIds: <%- JSON.stringify(appCssNoteIds) %>, isProtectedSessionAvailable: <%= isProtectedSessionAvailable %>, - assetPath: "<%= assetPath %>" + assetPath: "<%= assetPath %>", + isMainWindow: true };