mirror of
https://github.com/zadam/trilium.git
synced 2025-01-17 04:27:56 +08:00
mobile frontend is working again
This commit is contained in:
parent
f15239c006
commit
0f4ba43463
8 changed files with 58 additions and 105 deletions
|
@ -1,99 +0,0 @@
|
||||||
import treeService from "./services/tree.js";
|
|
||||||
import treeCache from "./services/tree_cache.js";
|
|
||||||
import treeBuilder from "./services/tree_builder.js";
|
|
||||||
import contextMenuWidget from "./services/context_menu.js";
|
|
||||||
import branchService from "./services/branches.js";
|
|
||||||
import utils from "./services/utils.js";
|
|
||||||
import appContext from "./services/app_context.js";
|
|
||||||
import noteCreateService from "./services/note_create.js";
|
|
||||||
import glob from "./services/glob.js";
|
|
||||||
|
|
||||||
const $leftPane = $("#left-pane");
|
|
||||||
const $tree = $("#tree");
|
|
||||||
const $detail = $("#detail");
|
|
||||||
|
|
||||||
function togglePanes() {
|
|
||||||
if (!$leftPane.is(":visible") || !$detail.is(":visible")) {
|
|
||||||
$detail.toggleClass("d-none");
|
|
||||||
$leftPane.toggleClass("d-none");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function showDetailPane() {
|
|
||||||
if (!$detail.is(":visible")) {
|
|
||||||
$detail.removeClass("d-none");
|
|
||||||
$leftPane.addClass("d-none");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$detail.on("click", ".close-detail-button",() => {
|
|
||||||
// no page is opened
|
|
||||||
document.location.hash = '-';
|
|
||||||
|
|
||||||
togglePanes();
|
|
||||||
});
|
|
||||||
|
|
||||||
async function showTree() {
|
|
||||||
const treeData = await treeBuilder.prepareTree();
|
|
||||||
|
|
||||||
$tree.fancytree({
|
|
||||||
autoScroll: true,
|
|
||||||
extensions: ["dnd5", "clones"],
|
|
||||||
source: treeData,
|
|
||||||
scrollParent: $tree,
|
|
||||||
minExpandLevel: 2, // root can't be collapsed
|
|
||||||
click: (event, data) => {
|
|
||||||
if (data.targetType !== 'expander' && data.node.isActive()) {
|
|
||||||
// this is important for single column mobile view, otherwise it's not possible to see again previously displayed note
|
|
||||||
$tree.fancytree('getTree').reactivate(true);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
activate: async (event, data) => {
|
|
||||||
const node = data.node;
|
|
||||||
|
|
||||||
treeService.clearSelectedNodes();
|
|
||||||
|
|
||||||
showDetailPane();
|
|
||||||
|
|
||||||
const notePath = await treeService.getNotePath(node);
|
|
||||||
|
|
||||||
},
|
|
||||||
expand: (event, data) => treeService.setExpandedToServer(data.node.data.branchId, true),
|
|
||||||
collapse: (event, data) => treeService.setExpandedToServer(data.node.data.branchId, false),
|
|
||||||
init: (event, data) => treeService.treeInitialized(), // don't collapse to short form
|
|
||||||
dnd5: dragAndDropSetup,
|
|
||||||
lazyLoad: function(event, data) {
|
|
||||||
const noteId = data.node.data.noteId;
|
|
||||||
|
|
||||||
data.result = treeCache.getNote(noteId).then(note => treeBuilder.prepareBranch(note));
|
|
||||||
},
|
|
||||||
clones: {
|
|
||||||
highlightActiveClones: true
|
|
||||||
},
|
|
||||||
// this is done to automatically lazy load all expanded search notes after tree load
|
|
||||||
loadChildren: (event, data) => {
|
|
||||||
data.node.visit((subNode) => {
|
|
||||||
// Load all lazy/unloaded child nodes
|
|
||||||
// (which will trigger `loadChildren` recursively)
|
|
||||||
if (subNode.isUndefined() && subNode.isExpanded()) {
|
|
||||||
subNode.load();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
treeService.setTree($.ui.fancytree.getTree("#tree"));
|
|
||||||
}
|
|
||||||
|
|
||||||
$("#log-out-button").on('click', () => {
|
|
||||||
$("#logout-form").trigger('submit');
|
|
||||||
});
|
|
||||||
|
|
||||||
// this is done so that startNotePath is not used
|
|
||||||
if (!document.location.hash) {
|
|
||||||
document.location.hash = '-';
|
|
||||||
}
|
|
||||||
|
|
||||||
showTree();
|
|
|
@ -10,6 +10,7 @@ import TabManager from "./tab_manager.js";
|
||||||
import treeService from "./tree.js";
|
import treeService from "./tree.js";
|
||||||
import Component from "../widgets/component.js";
|
import Component from "../widgets/component.js";
|
||||||
import keyboardActionsService from "./keyboard_actions.js";
|
import keyboardActionsService from "./keyboard_actions.js";
|
||||||
|
import MobileScreenSwitcherExecutor from "../widgets/mobile_screen_switcher.js";
|
||||||
|
|
||||||
class AppContext extends Component {
|
class AppContext extends Component {
|
||||||
setLayout(layout) {
|
setLayout(layout) {
|
||||||
|
@ -48,6 +49,10 @@ class AppContext extends Component {
|
||||||
new Entrypoints()
|
new Entrypoints()
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (utils.isMobile()) {
|
||||||
|
this.executors.push(new MobileScreenSwitcherExecutor());
|
||||||
|
}
|
||||||
|
|
||||||
this.child(rootWidget);
|
this.child(rootWidget);
|
||||||
|
|
||||||
for (const executor of this.executors) {
|
for (const executor of this.executors) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import BasicWidget from "./basic_widget.js";
|
import BasicWidget from "./basic_widget.js";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<button type="button" class="close-detail-button action-button d-sm-none d-md-none d-lg-none d-xl-none" aria-label="Close">
|
<button type="button" class="action-button d-sm-none d-md-none d-lg-none d-xl-none" aria-label="Close">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>`;
|
</button>`;
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ class CloseDetailButtonWidget extends BasicWidget {
|
||||||
doRender() {
|
doRender() {
|
||||||
this.$widget = $(TPL);
|
this.$widget = $(TPL);
|
||||||
|
|
||||||
//this.$widget.find('.close-detail-button').on('click', );
|
this.$widget.on('click', () => this.triggerCommand('setActiveScreen', {screen:'tree'}));
|
||||||
|
|
||||||
return this.$widget;
|
return this.$widget;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ const WIDGET_TPL = `
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
padding: 3px 0 3px 0;
|
padding: 3px 0 3px 0;
|
||||||
margin: 0 10px 0 16px;
|
margin: 0 10px 0 16px;
|
||||||
|
font-size: larger;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import NoteTreeWidget from "./note_tree.js";
|
||||||
import MobileGlobalButtonsWidget from "./mobile_global_buttons.js";
|
import MobileGlobalButtonsWidget from "./mobile_global_buttons.js";
|
||||||
import CloseDetailButtonWidget from "./close_detail_button.js";
|
import CloseDetailButtonWidget from "./close_detail_button.js";
|
||||||
import MobileDetailMenuWidget from "./mobile_detail_menu.js";
|
import MobileDetailMenuWidget from "./mobile_detail_menu.js";
|
||||||
|
import ScreenContainer from "./screen_container.js";
|
||||||
|
|
||||||
export default class MobileLayout {
|
export default class MobileLayout {
|
||||||
getRootWidget(appContext) {
|
getRootWidget(appContext) {
|
||||||
|
@ -12,12 +13,12 @@ export default class MobileLayout {
|
||||||
.setParent(appContext)
|
.setParent(appContext)
|
||||||
.id('root-widget')
|
.id('root-widget')
|
||||||
.css('height', '100vh')
|
.css('height', '100vh')
|
||||||
.child(new FlexContainer('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-4 col-xl-4")
|
.class("d-sm-flex d-md-flex d-lg-flex d-xl-flex col-12 col-sm-5 col-md-4 col-lg-4 col-xl-4")
|
||||||
.child(new MobileGlobalButtonsWidget())
|
.child(new MobileGlobalButtonsWidget())
|
||||||
.child(new NoteTreeWidget()))
|
.child(new NoteTreeWidget()))
|
||||||
.child(new FlexContainer('column')
|
.child(new ScreenContainer("detail", "column")
|
||||||
.class("d-none d-sm-flex d-md-flex d-lg-flex d-xl-flex col-12 col-sm-7 col-md-8 col-lg-8")
|
.class("d-sm-flex d-md-flex d-lg-flex d-xl-flex col-12 col-sm-7 col-md-8 col-lg-8")
|
||||||
.child(new FlexContainer('row')
|
.child(new FlexContainer('row')
|
||||||
.child(new MobileDetailMenuWidget())
|
.child(new MobileDetailMenuWidget())
|
||||||
.child(new NoteTitleWidget())
|
.child(new NoteTitleWidget())
|
||||||
|
|
15
src/public/javascripts/widgets/mobile_screen_switcher.js
Normal file
15
src/public/javascripts/widgets/mobile_screen_switcher.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import Component from "./component.js";
|
||||||
|
|
||||||
|
export default class MobileScreenSwitcherExecutor extends Component {
|
||||||
|
setActiveScreenCommand({screen}) {
|
||||||
|
if (screen !== this.activeScreen) {
|
||||||
|
this.activeScreen = screen;
|
||||||
|
|
||||||
|
this.triggerEvent('activeScreenChanged', {activeScreen: screen});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
initialRenderCompleteEvent() {
|
||||||
|
this.setActiveScreenCommand({screen: 'tree'});
|
||||||
|
}
|
||||||
|
}
|
|
@ -66,7 +66,7 @@ export default class NoteTreeWidget extends TabAwareWidget {
|
||||||
this.$widget.fancytree({
|
this.$widget.fancytree({
|
||||||
autoScroll: true,
|
autoScroll: true,
|
||||||
keyboard: false, // we takover keyboard handling in the hotkeys plugin
|
keyboard: false, // we takover keyboard handling in the hotkeys plugin
|
||||||
extensions: utils.isMobile() ? ["clones"] : ["hotkeys", "dnd5", "clones"],
|
extensions: utils.isMobile() ? ["dnd5", "clones"] : ["hotkeys", "dnd5", "clones"],
|
||||||
source: treeData,
|
source: treeData,
|
||||||
scrollParent: this.$widget,
|
scrollParent: this.$widget,
|
||||||
minExpandLevel: 2, // root can't be collapsed
|
minExpandLevel: 2, // root can't be collapsed
|
||||||
|
@ -83,6 +83,10 @@ export default class NoteTreeWidget extends TabAwareWidget {
|
||||||
const notePath = treeService.getNotePath(node);
|
const notePath = treeService.getNotePath(node);
|
||||||
appContext.tabManager.openTabWithNote(notePath);
|
appContext.tabManager.openTabWithNote(notePath);
|
||||||
}
|
}
|
||||||
|
else if (data.node.isActive()) {
|
||||||
|
// this is important for single column mobile view, otherwise it's not possible to see again previously displayed note
|
||||||
|
this.tree.reactivate(true);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
node.setActive();
|
node.setActive();
|
||||||
|
|
||||||
|
@ -100,6 +104,10 @@ export default class NoteTreeWidget extends TabAwareWidget {
|
||||||
|
|
||||||
const activeTabContext = appContext.tabManager.getActiveTabContext();
|
const activeTabContext = appContext.tabManager.getActiveTabContext();
|
||||||
await activeTabContext.setNote(notePath);
|
await activeTabContext.setNote(notePath);
|
||||||
|
|
||||||
|
if (utils.isMobile()) {
|
||||||
|
this.triggerCommand('setActiveScreen', {screen:'detail'});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
expand: (event, data) => this.setExpandedToServer(data.node.data.branchId, true),
|
expand: (event, data) => this.setExpandedToServer(data.node.data.branchId, true),
|
||||||
collapse: (event, data) => this.setExpandedToServer(data.node.data.branchId, false),
|
collapse: (event, data) => this.setExpandedToServer(data.node.data.branchId, false),
|
||||||
|
@ -810,4 +818,8 @@ export default class NoteTreeWidget extends TabAwareWidget {
|
||||||
|
|
||||||
noteCreateService.duplicateNote(noteId, branch.parentNoteId);
|
noteCreateService.duplicateNote(noteId, branch.parentNoteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
activeScreenChangedEvent({activeScreen}) {
|
||||||
|
this.toggle(activeScreen === 'tree');
|
||||||
|
}
|
||||||
}
|
}
|
18
src/public/javascripts/widgets/screen_container.js
Normal file
18
src/public/javascripts/widgets/screen_container.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import FlexContainer from "./flex_container.js";
|
||||||
|
|
||||||
|
export default class ScreenContainer extends FlexContainer {
|
||||||
|
constructor(screenName, direction) {
|
||||||
|
super(direction);
|
||||||
|
|
||||||
|
this.screenName = screenName;
|
||||||
|
}
|
||||||
|
|
||||||
|
activeScreenChangedEvent({activeScreen}) {console.log("Active screen", activeScreen);
|
||||||
|
if (activeScreen === this.screenName) {
|
||||||
|
this.$widget.removeClass('d-none');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.$widget.addClass('d-none');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue