mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
WIP per-tab hoisting
This commit is contained in:
parent
5bbec118e4
commit
4bd86a6dfa
@ -80,14 +80,13 @@ export default class Entrypoints extends Component {
|
||||
}
|
||||
|
||||
async toggleNoteHoistingCommand() {
|
||||
const note = appContext.tabManager.getActiveTabNote();
|
||||
const tabContext = appContext.tabManager.getActiveTabContext();
|
||||
|
||||
const hoistedNoteId = hoistedNoteService.getHoistedNoteId();
|
||||
if (note.noteId === hoistedNoteId) {
|
||||
hoistedNoteService.unhoist();
|
||||
if (tabContext.note.noteId === tabContext.hoistedNoteId) {
|
||||
await tabContext.unhoist();
|
||||
}
|
||||
else if (note.type !== 'search') {
|
||||
hoistedNoteService.setHoistedNoteId(note.noteId);
|
||||
else if (tabContext.note.type !== 'search') {
|
||||
await tabContext.setHoistedNoteId(tabContext.note.noteId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import options from './options.js';
|
||||
import appContext from "./app_context.js";
|
||||
import treeService from "./tree.js";
|
||||
import treeCache from "./tree_cache.js";
|
||||
|
||||
function getHoistedNoteId() {
|
||||
return options.get('hoistedNoteId');
|
||||
@ -14,9 +13,6 @@ async function setHoistedNoteId(noteId) {
|
||||
|
||||
await options.save('hoistedNoteId', noteId);
|
||||
|
||||
await treeCache.loadInitialTree();
|
||||
|
||||
// FIXME - just use option load event
|
||||
appContext.triggerEvent('hoistedNoteChanged', {noteId});
|
||||
}
|
||||
|
||||
|
@ -11,10 +11,11 @@ class TabContext extends Component {
|
||||
/**
|
||||
* @param {string|null} tabId
|
||||
*/
|
||||
constructor(tabId = null) {
|
||||
constructor(tabId = null, hoistedNoteId = 'root') {
|
||||
super();
|
||||
|
||||
this.tabId = tabId || utils.randomString(4);
|
||||
this.hoistedNoteId = hoistedNoteId;
|
||||
}
|
||||
|
||||
setEmpty() {
|
||||
@ -123,10 +124,24 @@ class TabContext extends Component {
|
||||
return {
|
||||
tabId: this.tabId,
|
||||
notePath: this.notePath,
|
||||
hoistedNoteId: this.hoistedNoteId,
|
||||
active: this.isActive()
|
||||
}
|
||||
}
|
||||
|
||||
async unhoist() {
|
||||
await this.setHoistedNoteId('root');
|
||||
}
|
||||
|
||||
async setHoistedNoteId(noteIdToHoist) {
|
||||
this.hoistedNoteId = noteIdToHoist;
|
||||
|
||||
await this.triggerEvent('hoistedNoteChanged', {
|
||||
noteId: noteIdToHoist,
|
||||
tabId: this.tabId
|
||||
});
|
||||
}
|
||||
|
||||
async entitiesReloadedEvent({loadResults}) {
|
||||
if (loadResults.isNoteReloaded(this.noteId)) {
|
||||
const note = await treeCache.getNote(this.noteId);
|
||||
|
@ -93,7 +93,7 @@ export default class TabManager extends Component {
|
||||
|
||||
await this.tabsUpdate.allowUpdateWithoutChange(async () => {
|
||||
for (const tab of filteredTabs) {
|
||||
await this.openTabWithNote(tab.notePath, tab.active, tab.tabId);
|
||||
await this.openTabWithNote(tab.notePath, tab.active, tab.tabId, tab.hoistedNoteId);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -184,8 +184,8 @@ export default class TabManager extends Component {
|
||||
await tabContext.setEmpty();
|
||||
}
|
||||
|
||||
async openEmptyTab(tabId) {
|
||||
const tabContext = new TabContext(tabId);
|
||||
async openEmptyTab(tabId, hoistedNoteId) {
|
||||
const tabContext = new TabContext(tabId, hoistedNoteId);
|
||||
this.child(tabContext);
|
||||
|
||||
await this.triggerEvent('newTabOpened', {tabContext});
|
||||
@ -193,7 +193,7 @@ export default class TabManager extends Component {
|
||||
return tabContext;
|
||||
}
|
||||
|
||||
async openTabWithNote(notePath, activate, tabId = null) {
|
||||
async openTabWithNote(notePath, activate, tabId = null, hoistedNoteId = 'root') {
|
||||
const tabContext = await this.openEmptyTab(tabId);
|
||||
|
||||
if (notePath) {
|
||||
@ -336,16 +336,4 @@ export default class TabManager extends Component {
|
||||
|
||||
this.triggerCommand('openInWindow', {notePath});
|
||||
}
|
||||
|
||||
async hoistedNoteChangedEvent({hoistedNoteId}) {
|
||||
if (hoistedNoteId === 'root') {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const tc of this.tabContexts.splice()) {
|
||||
if (tc.notePath && !tc.notePath.split("/").includes(hoistedNoteId)) {
|
||||
await this.removeTab(tc.tabId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -254,8 +254,7 @@ class TreeCache {
|
||||
console.trace(`Can't find note "${noteId}"`);
|
||||
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return this.notes[noteId];
|
||||
}
|
||||
}).filter(note => !!note);
|
||||
|
@ -1,10 +1,9 @@
|
||||
import treeService from './tree.js';
|
||||
import treeCache from "./tree_cache.js";
|
||||
import hoistedNoteService from './hoisted_note.js';
|
||||
import clipboard from './clipboard.js';
|
||||
import protectedSessionHolder from "./protected_session_holder.js";
|
||||
import noteCreateService from "./note_create.js";
|
||||
import contextMenu from "./context_menu.js";
|
||||
import appContext from "./app_context.js";
|
||||
|
||||
class TreeContextMenu {
|
||||
/**
|
||||
@ -40,7 +39,7 @@ class TreeContextMenu {
|
||||
const note = await treeCache.getNote(this.node.data.noteId);
|
||||
const branch = treeCache.getBranch(this.node.data.branchId);
|
||||
const isNotRoot = note.noteId !== 'root';
|
||||
const isHoisted = note.noteId === hoistedNoteService.getHoistedNoteId();
|
||||
const isHoisted = note.noteId === appContext.tabManager.getActiveTabContext().hoistedNoteId;
|
||||
const parentNote = isNotRoot ? await treeCache.getNote(branch.parentNoteId) : null;
|
||||
|
||||
// some actions don't support multi-note so they are disabled when notes are selected
|
||||
@ -69,7 +68,7 @@ class TreeContextMenu {
|
||||
{ title: 'Search in subtree <kbd data-command="searchInSubtree"></kbd>', command: "searchInSubtree", uiIcon: "search",
|
||||
enabled: notSearch && noSelectedNotes },
|
||||
isHoisted ? null : { title: 'Hoist note <kbd data-command="toggleNoteHoisting"></kbd>', command: "toggleNoteHoisting", uiIcon: "empty", enabled: noSelectedNotes && notSearch },
|
||||
!isHoisted || !isNotRoot ? null : { title: 'Unhoist note <kbd data-command="ToggleNoteHoisting"></kbd>', command: "toggleNoteHoisting", uiIcon: "arrow-from-bottom" },
|
||||
!isHoisted || !isNotRoot ? null : { title: 'Unhoist note <kbd data-command="toggleNoteHoisting"></kbd>', command: "toggleNoteHoisting", uiIcon: "arrow-from-bottom" },
|
||||
{ title: 'Edit branch prefix <kbd data-command="editBranchPrefix"></kbd>', command: "editBranchPrefix", uiIcon: "empty",
|
||||
enabled: isNotRoot && parentNotSearch && noSelectedNotes},
|
||||
{ title: "Advanced", uiIcon: "empty", enabled: true, items: [
|
||||
|
@ -263,8 +263,10 @@ export default class NoteDetailWidget extends TabAwareWidget {
|
||||
});
|
||||
}
|
||||
|
||||
hoistedNoteChangedEvent() {
|
||||
this.refresh();
|
||||
hoistedNoteChangedEvent({tabId}) {
|
||||
if (this.isTab(tabId)) {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
async entitiesReloadedEvent({loadResults}) {
|
||||
|
@ -290,7 +290,7 @@ export default class NoteTreeWidget extends TabAwareWidget {
|
||||
this.$tree.fancytree({
|
||||
titlesTabbable: true,
|
||||
keyboard: true,
|
||||
extensions: ["dnd5", "clones"],
|
||||
extensions: ["dnd5", "clones", "filter"],
|
||||
source: treeData,
|
||||
scrollOfs: {
|
||||
top: 100,
|
||||
@ -341,6 +341,11 @@ export default class NoteTreeWidget extends TabAwareWidget {
|
||||
},
|
||||
expand: (event, data) => this.setExpanded(data.node.data.branchId, true),
|
||||
collapse: (event, data) => this.setExpanded(data.node.data.branchId, false),
|
||||
filter: {
|
||||
counter: false,
|
||||
mode: "hide",
|
||||
autoExpand: true
|
||||
},
|
||||
dnd5: {
|
||||
autoExpandMS: 600,
|
||||
dragStart: (node, data) => {
|
||||
@ -446,21 +451,6 @@ export default class NoteTreeWidget extends TabAwareWidget {
|
||||
const node = data.node;
|
||||
const $span = $(node.span);
|
||||
|
||||
if (node.data.noteId !== 'root'
|
||||
&& node.data.noteId === hoistedNoteService.getHoistedNoteId()
|
||||
&& $span.find('.unhoist-button').length === 0) {
|
||||
|
||||
const action = await keyboardActionsService.getAction('unhoist');
|
||||
let shortcuts = action.effectiveShortcuts.join(',');
|
||||
shortcuts = shortcuts ? `(${shortcuts})` : '';
|
||||
|
||||
const unhoistButton = $(`<span class="unhoist-button-wrapper" title="Unhoist current note to show the whole note tree ${shortcuts}">[<a class="unhoist-button">unhoist</a>]</span>`);
|
||||
|
||||
// prepending since appending could push out (when note title is too long)
|
||||
// the button too much to the right so that it's not visible
|
||||
$span.prepend(unhoistButton);
|
||||
}
|
||||
|
||||
const note = await treeCache.getNote(node.data.noteId);
|
||||
|
||||
if (note.type === 'search' && $span.find('.refresh-search-button').length === 0) {
|
||||
@ -512,17 +502,7 @@ export default class NoteTreeWidget extends TabAwareWidget {
|
||||
prepareRootNode() {
|
||||
const hoistedNoteId = hoistedNoteService.getHoistedNoteId();
|
||||
|
||||
let hoistedBranch;
|
||||
|
||||
if (hoistedNoteId === 'root') {
|
||||
hoistedBranch = treeCache.getBranch('root');
|
||||
}
|
||||
else {
|
||||
const hoistedNote = treeCache.getNoteFromCache(hoistedNoteId);
|
||||
hoistedBranch = hoistedNote.getBranches()[0];
|
||||
}
|
||||
|
||||
return this.prepareNode(hoistedBranch);
|
||||
return this.prepareNode(treeCache.getBranch('root'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -897,6 +877,8 @@ export default class NoteTreeWidget extends TabAwareWidget {
|
||||
newActiveNode.makeVisible({scrollIntoView: true});
|
||||
}
|
||||
}
|
||||
|
||||
this.filterHoistedBranch();
|
||||
}
|
||||
|
||||
async refreshSearch() {
|
||||
@ -1156,8 +1138,16 @@ export default class NoteTreeWidget extends TabAwareWidget {
|
||||
}
|
||||
}
|
||||
|
||||
hoistedNoteChangedEvent() {
|
||||
this.reloadTreeFromCache();
|
||||
async hoistedNoteChangedEvent({tabId}) {
|
||||
if (this.isTab(tabId)) {
|
||||
this.filterHoistedBranch();
|
||||
}
|
||||
}
|
||||
|
||||
filterHoistedBranch() {
|
||||
if (this.tabContext) {
|
||||
this.tree.filterBranches(node => node.data.noteId === this.tabContext.hoistedNoteId);
|
||||
}
|
||||
}
|
||||
|
||||
treeCacheReloadedEvent() {
|
||||
|
@ -60,7 +60,7 @@ export default class BookTypeWidget extends TypeWidget {
|
||||
.append(' if you want to add some text.'));
|
||||
}
|
||||
|
||||
const noteListRenderer = new NoteListRenderer(note, await note.getChildNotes());
|
||||
const noteListRenderer = new NoteListRenderer(note, note.getChildNoteIds());
|
||||
|
||||
this.$content.append(await noteListRenderer.renderList());
|
||||
}
|
||||
|
@ -81,6 +81,16 @@ span.fancytree-node.dotted .fancytree-title { text-decoration: dotted; }
|
||||
span.fancytree-node.bold .fancytree-title { font-weight: bold; }
|
||||
span.fancytree-node.muted { opacity: 0.6; }
|
||||
|
||||
/** following will hide ancestors of hoisted (filtered) note */
|
||||
.fancytree-submatch:not(.fancytree-match) {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/** resets indent of hoisted note */
|
||||
.fancytree-submatch:not(.fancytree-match) + ul {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.note-title[readonly] {
|
||||
background: inherit;
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ function getNotesAndBranchesAndAttributes(noteIds) {
|
||||
}
|
||||
|
||||
function getTree(req) {
|
||||
const subTreeNoteId = req.query.subTreeNoteId || optionService.getOption('hoistedNoteId');
|
||||
const subTreeNoteId = req.query.subTreeNoteId || 'root';
|
||||
|
||||
// FIXME: this query does not return ascendants of template notes
|
||||
const noteIds = sql.getColumn(`
|
||||
|
Loading…
x
Reference in New Issue
Block a user