mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-31 04:51:31 +08:00 
			
		
		
		
	hoisting support in mobile view WIP
This commit is contained in:
		
							parent
							
								
									2957e1d78a
								
							
						
					
					
						commit
						ca968a9e31
					
				
							
								
								
									
										4
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -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": { | ||||
|  | ||||
| @ -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; | ||||
|         } | ||||
|  | ||||
| @ -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() { | ||||
|  | ||||
| @ -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}); | ||||
|  | ||||
| @ -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; | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -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() { | ||||
|  | ||||
| @ -101,6 +101,11 @@ span.fancytree-expander { | ||||
|     margin-right: 16px; | ||||
|     display: none; | ||||
| } | ||||
| 
 | ||||
| .tree-wrapper .unhoist-button { | ||||
|     display: block; | ||||
|     font-size: 200%; | ||||
| } | ||||
| </style>`; | ||||
| 
 | ||||
| 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') | ||||
|  | ||||
| @ -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 | ||||
| }; | ||||
|  | ||||
| @ -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; | ||||
|                 } | ||||
| 
 | ||||
|  | ||||
| @ -116,7 +116,8 @@ | ||||
|         isDev: <%= isDev %>, | ||||
|         appCssNoteIds: <%- JSON.stringify(appCssNoteIds) %>, | ||||
|         isProtectedSessionAvailable: <%= isProtectedSessionAvailable %>, | ||||
|         assetPath: "<%= assetPath %>" | ||||
|         assetPath: "<%= assetPath %>", | ||||
|         isMainWindow: true | ||||
|     }; | ||||
| </script> | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 zadam
						zadam