hoisting support in mobile view WIP

This commit is contained in:
zadam 2022-12-13 16:57:46 +01:00
parent 2957e1d78a
commit ca968a9e31
10 changed files with 63 additions and 52 deletions

4
package-lock.json generated
View file

@ -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": {

View file

@ -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;
}

View file

@ -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() {

View file

@ -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});

View file

@ -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;
}

View file

@ -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() {

View file

@ -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')

View file

@ -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
};

View file

@ -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;
}

View file

@ -116,7 +116,8 @@
isDev: <%= isDev %>,
appCssNoteIds: <%- JSON.stringify(appCssNoteIds) %>,
isProtectedSessionAvailable: <%= isProtectedSessionAvailable %>,
assetPath: "<%= assetPath %>"
assetPath: "<%= assetPath %>",
isMainWindow: true
};
</script>