mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	hoisting support in mobile view WIP
This commit is contained in:
		
							
								
								
									
										4
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -1,11 +1,11 @@ | |||||||
| { | { | ||||||
|   "name": "trilium", |   "name": "trilium", | ||||||
|   "version": "0.57.3", |   "version": "0.57.4", | ||||||
|   "lockfileVersion": 2, |   "lockfileVersion": 2, | ||||||
|   "requires": true, |   "requires": true, | ||||||
|   "packages": { |   "packages": { | ||||||
|     "": { |     "": { | ||||||
|       "version": "0.57.3", |       "version": "0.57.4", | ||||||
|       "hasInstallScript": true, |       "hasInstallScript": true, | ||||||
|       "license": "AGPL-3.0-only", |       "license": "AGPL-3.0-only", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|   | |||||||
| @@ -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() { | $(window).on('hashchange', function() { | ||||||
|     if (isNotePathInAddress()) { |     if (treeService.isNotePathInAddress()) { | ||||||
|         const [notePath, ntxId] = treeService.getHashValueFromAddress(); |         const [notePath, ntxId] = treeService.getHashValueFromAddress(); | ||||||
|  |  | ||||||
|         if (!notePath) { |         if (!notePath && !ntxId) { | ||||||
|             console.log(`Invalid hash value "${document.location.hash}", ignoring.`); |             console.log(`Invalid hash value "${document.location.hash}", ignoring.`); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -190,16 +190,20 @@ export default class Entrypoints extends Component { | |||||||
|         toastService.showMessage("Note executed"); |         toastService.showMessage("Note executed"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     hideAllTooltips() { |     hideAllPopups() { | ||||||
|         $(".tooltip").removeClass("show"); |         $(".tooltip").removeClass("show"); | ||||||
|  |  | ||||||
|  |         if (utils.isDesktop()) { | ||||||
|  |             $(".aa-input").autocomplete("close"); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     noteSwitchedEvent() { |     noteSwitchedEvent() { | ||||||
|         this.hideAllTooltips(); |         this.hideAllPopups(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     activeContextChangedEvent() { |     activeContextChangedEvent() { | ||||||
|         this.hideAllTooltips(); |         this.hideAllPopups(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async forceSaveNoteRevisionCommand() { |     async forceSaveNoteRevisionCommand() { | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| import Component from "./component.js"; | import Component from "./component.js"; | ||||||
|  | import appContext from "./app_context.js"; | ||||||
|  |  | ||||||
| export default class MobileScreenSwitcherExecutor extends Component { | export default class MobileScreenSwitcherExecutor extends Component { | ||||||
|     setActiveScreenCommand({screen}) { |     setActiveScreenCommand({screen}) { | ||||||
| @@ -6,7 +7,9 @@ export default class MobileScreenSwitcherExecutor extends Component { | |||||||
|             this.activeScreen = screen; |             this.activeScreen = screen; | ||||||
|  |  | ||||||
|             if (screen === 'tree') { |             if (screen === 'tree') { | ||||||
|                 document.location.hash = ''; |                 const activeNoteContext = appContext.tabManager.getActiveContext(); | ||||||
|  |  | ||||||
|  |                 activeNoteContext.setEmpty(); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             this.triggerEvent('activeScreenChanged', {activeScreen: screen}); |             this.triggerEvent('activeScreenChanged', {activeScreen: screen}); | ||||||
|   | |||||||
| @@ -80,10 +80,7 @@ class NoteContext extends Component { | |||||||
|             await this.setHoistedNoteId(hoistedNoteId); |             await this.setHoistedNoteId(hoistedNoteId); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (utils.isDesktop()) { |         if (utils.isMobile()) { | ||||||
|             // close dangling autocompletes after closing the tab |  | ||||||
|             $(".aa-input").autocomplete("close"); |  | ||||||
|         } else if (utils.isMobile()) { |  | ||||||
|             this.triggerCommand('setActiveScreen', {screen: 'detail'}); |             this.triggerCommand('setActiveScreen', {screen: 'detail'}); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -171,7 +168,8 @@ class NoteContext extends Component { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     getTabState() { |     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; |             return null; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -25,10 +25,14 @@ export default class TabManager extends Component { | |||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             console.log("Pre-saving", this.noteContexts); | ||||||
|  |  | ||||||
|             const openTabs = this.noteContexts |             const openTabs = this.noteContexts | ||||||
|                 .map(nc => nc.getTabState()) |                 .map(nc => nc.getTabState()) | ||||||
|                 .filter(t => !!t); |                 .filter(t => !!t); | ||||||
|  |  | ||||||
|  |             console.log("Saving", openTabs); | ||||||
|  |  | ||||||
|             await server.put('options', { |             await server.put('options', { | ||||||
|                 openTabs: JSON.stringify(openTabs) |                 openTabs: JSON.stringify(openTabs) | ||||||
|             }); |             }); | ||||||
| @@ -52,34 +56,10 @@ export default class TabManager extends Component { | |||||||
|             ? (options.getJson('openTabs') || []) |             ? (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 = []; |         let filteredTabs = []; | ||||||
|  |  | ||||||
|  |         console.log(document.location.hash, tabsToOpen); | ||||||
|  |  | ||||||
|         for (const openTab of tabsToOpen) { |         for (const openTab of tabsToOpen) { | ||||||
|             const noteId = treeService.getNoteIdFromNotePath(openTab.notePath); |             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); |                 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}) { |     noteSwitchedEvent({noteContext}) { | ||||||
| @@ -205,12 +193,20 @@ export default class TabManager extends Component { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     async switchToNoteContext(ntxId, notePath) { |     async switchToNoteContext(ntxId, notePath) { | ||||||
|  |         console.log("Looking for " + ntxId); | ||||||
|  |         console.log("Existing", this.noteContexts); | ||||||
|  |  | ||||||
|         const noteContext = this.noteContexts.find(nc => nc.ntxId === ntxId) |         const noteContext = this.noteContexts.find(nc => nc.ntxId === ntxId) | ||||||
|             || await this.openEmptyTab(); |             || await this.openEmptyTab(); | ||||||
|  |  | ||||||
|         this.activateNoteContext(noteContext.ntxId); |         console.log(noteContext); | ||||||
|  |  | ||||||
|  |         await this.activateNoteContext(noteContext.ntxId); | ||||||
|  |  | ||||||
|  |         if (notePath) { | ||||||
|             await noteContext.setNote(notePath); |             await noteContext.setNote(notePath); | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     async openAndActivateEmptyTab() { |     async openAndActivateEmptyTab() { | ||||||
|         const noteContext = await this.openEmptyTab(); |         const noteContext = await this.openEmptyTab(); | ||||||
|   | |||||||
| @@ -101,6 +101,11 @@ span.fancytree-expander { | |||||||
|     margin-right: 16px; |     margin-right: 16px; | ||||||
|     display: none; |     display: none; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .tree-wrapper .unhoist-button { | ||||||
|  |     display: block; | ||||||
|  |     font-size: 200%; | ||||||
|  | } | ||||||
| </style>`; | </style>`; | ||||||
|  |  | ||||||
| export default class MobileLayout { | export default class MobileLayout { | ||||||
| @@ -119,13 +124,16 @@ export default class MobileLayout { | |||||||
|                 .child(new ScreenContainer("tree", 'column') |                 .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") |                     .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("max-height", "100%") | ||||||
|                     .css('padding-left', 0) |                     .css('padding-left', "0") | ||||||
|  |                     .css('padding-right', "0") | ||||||
|                     .css('contain', 'content') |                     .css('contain', 'content') | ||||||
|                     .child(new QuickSearchWidget()) |                     .child(new QuickSearchWidget()) | ||||||
|                     .child(new NoteTreeWidget() |                     .child(new NoteTreeWidget() | ||||||
|                         .cssBlock(FANCYTREE_CSS))) |                         .cssBlock(FANCYTREE_CSS))) | ||||||
|                 .child(new ScreenContainer("detail", "column") |                 .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") |                     .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%') |                     .css('max-height', '100%') | ||||||
|                     .child(new FlexContainer('row').contentSized() |                     .child(new FlexContainer('row').contentSized() | ||||||
|                         .css('font-size', 'larger') |                         .css('font-size', 'larger') | ||||||
|   | |||||||
| @@ -304,6 +304,14 @@ function getHashValueFromAddress() { | |||||||
|     return str.split("-"); |     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) { | function parseNotePath(notePath) { | ||||||
|     let noteIds = notePath.split('/'); |     let noteIds = notePath.split('/'); | ||||||
|  |  | ||||||
| @@ -332,6 +340,7 @@ export default { | |||||||
|     getNotePathTitle, |     getNotePathTitle, | ||||||
|     getNoteTitleWithPathAsSuffix, |     getNoteTitleWithPathAsSuffix, | ||||||
|     getHashValueFromAddress, |     getHashValueFromAddress, | ||||||
|  |     isNotePathInAddress, | ||||||
|     parseNotePath, |     parseNotePath, | ||||||
|     isNotePathInHiddenSubtree |     isNotePathInHiddenSubtree | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -535,7 +535,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { | |||||||
|  |  | ||||||
|                 const note = await froca.getNote(node.data.noteId, true); |                 const note = await froca.getNote(node.data.noteId, true); | ||||||
|  |  | ||||||
|                 if (!note || note.isDeleted || note.isLaunchBarConfig()) { |                 if (!note || note.isDeleted) { | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -116,7 +116,8 @@ | |||||||
|         isDev: <%= isDev %>, |         isDev: <%= isDev %>, | ||||||
|         appCssNoteIds: <%- JSON.stringify(appCssNoteIds) %>, |         appCssNoteIds: <%- JSON.stringify(appCssNoteIds) %>, | ||||||
|         isProtectedSessionAvailable: <%= isProtectedSessionAvailable %>, |         isProtectedSessionAvailable: <%= isProtectedSessionAvailable %>, | ||||||
|         assetPath: "<%= assetPath %>" |         assetPath: "<%= assetPath %>", | ||||||
|  |         isMainWindow: true | ||||||
|     }; |     }; | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user