mirror of
https://github.com/zadam/trilium.git
synced 2025-06-05 17:38:47 +02:00
moved tab management to app context
This commit is contained in:
parent
61474defff
commit
5e11840137
@ -61,7 +61,7 @@ window.glob.noteChanged = noteDetailService.noteChanged;
|
||||
window.glob.refreshTree = treeService.reload;
|
||||
|
||||
// required for ESLint plugin
|
||||
window.glob.getActiveTabNote = noteDetailService.getActiveTabNote;
|
||||
window.glob.getActiveTabNote = appContext.getActiveTabNote;
|
||||
window.glob.requireLibrary = libraryLoader.requireLibrary;
|
||||
window.glob.ESLINT = libraryLoader.ESLINT;
|
||||
|
||||
@ -145,7 +145,7 @@ async function printActiveNote() {
|
||||
return;
|
||||
}
|
||||
|
||||
const $tabContext = noteDetailService.getActiveTabContext();
|
||||
const $tabContext = appContext.getActiveTabContext();
|
||||
if (!$tabContext) {
|
||||
return;
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ function AttributesModel() {
|
||||
}
|
||||
|
||||
this.loadAttributes = async function() {
|
||||
const noteId = noteDetailService.getActiveTabNoteId();
|
||||
const noteId = appContext.getActiveTabNoteId();
|
||||
|
||||
const attributes = await server.get('notes/' + noteId + '/attributes');
|
||||
|
||||
@ -139,7 +139,7 @@ function AttributesModel() {
|
||||
|
||||
self.updateAttributePositions();
|
||||
|
||||
const noteId = noteDetailService.getActiveTabNoteId();
|
||||
const noteId = appContext.getActiveTabNoteId();
|
||||
|
||||
const attributesToSave = self.ownedAttributes()
|
||||
.map(attribute => attribute())
|
||||
@ -171,7 +171,7 @@ function AttributesModel() {
|
||||
|
||||
toastService.showMessage("Attributes have been saved.");
|
||||
|
||||
const ctx = noteDetailService.getActiveTabContext();
|
||||
const ctx = appContext.getActiveTabContext();
|
||||
|
||||
ctx.attributes.refreshAttributes();
|
||||
|
||||
|
@ -31,7 +31,7 @@ export async function showDialog() {
|
||||
}
|
||||
|
||||
$dialog.on('shown.bs.modal', () => {
|
||||
const note = noteDetailService.getActiveTabNote();
|
||||
const note = appContext.getActiveTabNote();
|
||||
|
||||
linkMapService = new LinkMapService(note, $linkMapContainer, getOptions());
|
||||
linkMapService.render();
|
||||
|
@ -26,7 +26,7 @@ async function convertMarkdownToHtml(text) {
|
||||
}
|
||||
|
||||
export async function importMarkdownInline() {
|
||||
if (noteDetailService.getActiveTabNoteType() !== 'text') {
|
||||
if (appContext.getActiveTabNoteType() !== 'text') {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ export function showDialog() {
|
||||
|
||||
$dialog.modal();
|
||||
|
||||
const activeNote = noteDetailService.getActiveTabNote();
|
||||
const activeNote = appContext.getActiveTabNote();
|
||||
|
||||
$noteId.text(activeNote.noteId);
|
||||
$dateCreated.text(activeNote.dateCreated);
|
||||
|
@ -25,7 +25,7 @@ let note;
|
||||
let noteRevisionId;
|
||||
|
||||
export async function showCurrentNoteRevisions() {
|
||||
await showNoteRevisionsDialog(noteDetailService.getActiveTabNoteId());
|
||||
await showNoteRevisionsDialog(appContext.getActiveTabNoteId());
|
||||
}
|
||||
|
||||
export async function showNoteRevisionsDialog(noteId, noteRevisionId) {
|
||||
@ -42,7 +42,7 @@ async function loadNoteRevisions(noteId, noteRevId) {
|
||||
$list.empty();
|
||||
$content.empty();
|
||||
|
||||
note = noteDetailService.getActiveTabNote();
|
||||
note = appContext.getActiveTabNote();
|
||||
revisionItems = await server.get(`notes/${noteId}/revisions`);
|
||||
|
||||
for (const item of revisionItems) {
|
||||
|
@ -11,7 +11,7 @@ export function showDialog() {
|
||||
|
||||
$dialog.modal();
|
||||
|
||||
const noteText = noteDetailService.getActiveTabNote().content;
|
||||
const noteText = appContext.getActiveTabNote().content;
|
||||
|
||||
$noteSource.text(formatHtml(noteText));
|
||||
}
|
||||
|
@ -2,10 +2,16 @@ import GlobalButtonsWidget from "../widgets/global_buttons.js";
|
||||
import SearchBoxWidget from "../widgets/search_box.js";
|
||||
import SearchResultsWidget from "../widgets/search_results.js";
|
||||
import NoteTreeWidget from "../widgets/note_tree.js";
|
||||
import tabRow from "./tab_row.js";
|
||||
import treeService from "./tree.js";
|
||||
import noteDetailService from "./note_detail.js";
|
||||
import TabContext from "./tab_context.js";
|
||||
|
||||
class AppContext {
|
||||
constructor() {
|
||||
this.widgets = [];
|
||||
/** @type {TabContext[]} */
|
||||
this.tabContexts = [];
|
||||
}
|
||||
|
||||
trigger(name, data) {
|
||||
@ -14,6 +20,97 @@ class AppContext {
|
||||
}
|
||||
}
|
||||
|
||||
/** @return {TabContext[]} */
|
||||
getTabContexts() {
|
||||
return this.tabContexts;
|
||||
}
|
||||
|
||||
/** @returns {TabContext} */
|
||||
getActiveTabContext() {
|
||||
const activeTabEl = tabRow.activeTabEl;
|
||||
|
||||
if (!activeTabEl) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const tabId = activeTabEl.getAttribute('data-tab-id');
|
||||
|
||||
return this.tabContexts.find(tc => tc.tabId === tabId);
|
||||
}
|
||||
|
||||
/** @returns {string|null} */
|
||||
getActiveTabNotePath() {
|
||||
const activeContext = this.getActiveTabContext();
|
||||
return activeContext ? activeContext.notePath : null;
|
||||
}
|
||||
|
||||
/** @return {NoteFull} */
|
||||
getActiveTabNote() {
|
||||
const activeContext = this.getActiveTabContext();
|
||||
return activeContext ? activeContext.note : null;
|
||||
}
|
||||
|
||||
/** @return {string|null} */
|
||||
getActiveTabNoteId() {
|
||||
const activeNote = this.getActiveTabNote();
|
||||
|
||||
return activeNote ? activeNote.noteId : null;
|
||||
}
|
||||
|
||||
/** @return {string|null} */
|
||||
getActiveTabNoteType() {
|
||||
const activeNote = this.getActiveTabNote();
|
||||
|
||||
return activeNote ? activeNote.type : null;
|
||||
}
|
||||
|
||||
async switchToTab(tabId, notePath) {
|
||||
const tabContext = this.tabContexts.find(tc => tc.tabId === tabId);
|
||||
|
||||
if (!tabContext) {
|
||||
await noteDetailService.loadNoteDetail(notePath, {
|
||||
newTab: true,
|
||||
activate: true
|
||||
});
|
||||
} else {
|
||||
await tabContext.activate();
|
||||
|
||||
if (notePath && tabContext.notePath !== notePath) {
|
||||
await treeService.activateNote(notePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async showTab(tabId) {
|
||||
for (const ctx of this.tabContexts) {
|
||||
if (ctx.tabId === tabId) {
|
||||
await ctx.show();
|
||||
} else {
|
||||
ctx.hide();
|
||||
}
|
||||
}
|
||||
|
||||
const oldActiveNode = this.getMainNoteTree().getActiveNode();
|
||||
|
||||
if (oldActiveNode) {
|
||||
oldActiveNode.setActive(false);
|
||||
}
|
||||
|
||||
const newActiveTabContext = this.getActiveTabContext();
|
||||
|
||||
if (newActiveTabContext && newActiveTabContext.notePath) {
|
||||
const newActiveNode = await this.getMainNoteTree().getNodeFromPath(newActiveTabContext.notePath);
|
||||
|
||||
if (newActiveNode) {
|
||||
if (!newActiveNode.isVisible()) {
|
||||
await this.getMainNoteTree().expandToNote(newActiveTabContext.notePath);
|
||||
}
|
||||
|
||||
newActiveNode.setActive(true, {noEvents: true});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
showWidgets() {
|
||||
const $leftPane = $("#left-pane");
|
||||
|
||||
@ -39,8 +136,68 @@ class AppContext {
|
||||
getMainNoteTree() {
|
||||
return this.noteTreeWidget;
|
||||
}
|
||||
|
||||
getTab(newTab, state) {
|
||||
if (!this.getActiveTabContext() || newTab) {
|
||||
// if it's a new tab explicitly by user then it's in background
|
||||
const ctx = new TabContext(tabRow, state);
|
||||
this.tabContexts.push(ctx);
|
||||
|
||||
return ctx;
|
||||
} else {
|
||||
return this.getActiveTabContext();
|
||||
}
|
||||
}
|
||||
|
||||
async reloadAllTabs() {
|
||||
for (const tabContext of this.tabContexts) {
|
||||
await this.reloadTab(tabContext);
|
||||
}
|
||||
}
|
||||
|
||||
async refreshTabs(sourceTabId, noteId) {
|
||||
for (const tc of this.tabContexts) {
|
||||
if (tc.noteId === noteId && tc.tabId !== sourceTabId) {
|
||||
await this.reloadTab(tc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async reloadTab(tc) {
|
||||
if (tc.note) {
|
||||
noteDetailService.reloadNote(tc);
|
||||
}
|
||||
}
|
||||
|
||||
async openEmptyTab() {
|
||||
const ctx = new TabContext(tabRow);
|
||||
this.tabContexts.push(ctx);
|
||||
|
||||
await tabRow.activateTab(ctx.$tab[0]);
|
||||
}
|
||||
}
|
||||
|
||||
const appContext = new AppContext();
|
||||
|
||||
tabRow.addListener('newTab', () => appContext.openEmptyTab());
|
||||
|
||||
tabRow.addListener('activeTabChange', async ({ detail }) => {
|
||||
const tabId = detail.tabEl.getAttribute('data-tab-id');
|
||||
|
||||
await appContext.showTab(tabId);
|
||||
});
|
||||
|
||||
tabRow.addListener('tabRemove', async ({ detail }) => {
|
||||
const tabId = detail.tabEl.getAttribute('data-tab-id');
|
||||
|
||||
appContext.tabContexts.filter(nc => nc.tabId === tabId)
|
||||
.forEach(tc => tc.remove());
|
||||
|
||||
appContext.tabContexts = appContext.tabContexts.filter(nc => nc.tabId !== tabId);
|
||||
|
||||
if (appContext.tabContexts.length === 0) {
|
||||
appContext.openEmptyTab();
|
||||
}
|
||||
});
|
||||
|
||||
export default appContext;
|
@ -284,6 +284,8 @@ function registerEntrypoints() {
|
||||
|
||||
searchNotesService.searchInSubtree(node.data.noteId);
|
||||
});
|
||||
|
||||
keyboardActionService.setGlobalActionHandler('CollapseTree', () => appContext.getMainNoteTree().collapseTree());
|
||||
}
|
||||
|
||||
export default {
|
||||
|
@ -286,7 +286,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
|
||||
* @method
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
this.refreshAllTabs = noteDetailService.reloadAllTabs;
|
||||
this.refreshAllTabs = appContext.reloadAllTabs;
|
||||
|
||||
/**
|
||||
* Create note link (jQuery object) for given note.
|
||||
@ -309,7 +309,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
|
||||
* @method
|
||||
* @returns {NoteFull} active note (loaded into right pane)
|
||||
*/
|
||||
this.getActiveTabNote = noteDetailService.getActiveTabNote;
|
||||
this.getActiveTabNote = appContext.getActiveTabNote;
|
||||
|
||||
/**
|
||||
* See https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editor-Editor.html for a documentation on the returned instance.
|
||||
@ -323,7 +323,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
|
||||
* @method
|
||||
* @returns {Promise<string|null>} returns note path of active note or null if there isn't active note
|
||||
*/
|
||||
this.getActiveTabNotePath = noteDetailService.getActiveTabNotePath;
|
||||
this.getActiveTabNotePath = appContext.getActiveTabNotePath;
|
||||
|
||||
/**
|
||||
* This method checks whether user navigated away from the note from which the scripts has been started.
|
||||
|
@ -30,7 +30,7 @@ async function setHoistedNoteId(noteId) {
|
||||
|
||||
await tree.reload();
|
||||
|
||||
const activeTabContext = noteDetailService.getActiveTabContext();
|
||||
const activeTabContext = appContext.getActiveTabContext();
|
||||
|
||||
if (activeTabContext) {
|
||||
await tree.activateNote(activeTabContext.notePath);
|
||||
|
@ -8,7 +8,7 @@ const SELECTED_PATH_KEY = "data-note-path";
|
||||
async function autocompleteSource(term, cb) {
|
||||
const result = await server.get('autocomplete'
|
||||
+ '?query=' + encodeURIComponent(term)
|
||||
+ '&activeNoteId=' + noteDetailService.getActiveTabNoteId());
|
||||
+ '&activeNoteId=' + appContext.getActiveTabNoteId());
|
||||
|
||||
if (result.length === 0) {
|
||||
result.push({
|
||||
|
@ -4,7 +4,6 @@ import server from './server.js';
|
||||
import ws from "./ws.js";
|
||||
import treeCache from "./tree_cache.js";
|
||||
import NoteFull from "../entities/note_full.js";
|
||||
import utils from "./utils.js";
|
||||
import contextMenuService from "./context_menu.js";
|
||||
import treeUtils from "./tree_utils.js";
|
||||
import tabRow from "./tab_row.js";
|
||||
@ -19,21 +18,13 @@ let detailLoadedListeners = [];
|
||||
async function reload() {
|
||||
// no saving here
|
||||
|
||||
await loadNoteDetail(getActiveTabContext().notePath);
|
||||
await loadNoteDetail(appContext.getActiveTabNotePath());
|
||||
}
|
||||
|
||||
async function reloadTab(tabContext) {
|
||||
if (tabContext.note) {
|
||||
const note = await loadNote(tabContext.note.noteId);
|
||||
async function reloadNote(tabContext) {
|
||||
const note = await loadNote(tabContext.note.noteId);
|
||||
|
||||
await loadNoteDetailToContext(tabContext, note, tabContext.notePath);
|
||||
}
|
||||
}
|
||||
|
||||
async function reloadAllTabs() {
|
||||
for (const tabContext of tabContexts) {
|
||||
await reloadTab(tabContext);
|
||||
}
|
||||
await loadNoteDetailToContext(tabContext, note, tabContext.notePath);
|
||||
}
|
||||
|
||||
async function openInTab(notePath, activate) {
|
||||
@ -53,7 +44,7 @@ function onNoteChange(func) {
|
||||
}
|
||||
|
||||
async function saveNotesIfChanged() {
|
||||
for (const ctx of tabContexts) {
|
||||
for (const ctx of appContext.getTabContexts()) {
|
||||
await ctx.saveNoteIfChanged();
|
||||
}
|
||||
|
||||
@ -61,9 +52,6 @@ async function saveNotesIfChanged() {
|
||||
$savedIndicator.fadeIn();
|
||||
}
|
||||
|
||||
/** @type {TabContext[]} */
|
||||
let tabContexts = [];
|
||||
|
||||
function getActiveEditor() {
|
||||
const activeTabContext = getActiveTabContext();
|
||||
|
||||
@ -91,98 +79,6 @@ async function activateOrOpenNote(noteId) {
|
||||
});
|
||||
}
|
||||
|
||||
/** @return {TabContext[]} */
|
||||
function getTabContexts() {
|
||||
return tabContexts;
|
||||
}
|
||||
|
||||
/** @returns {TabContext} */
|
||||
function getActiveTabContext() {
|
||||
const activeTabEl = tabRow.activeTabEl;
|
||||
|
||||
if (!activeTabEl) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const tabId = activeTabEl.getAttribute('data-tab-id');
|
||||
|
||||
return tabContexts.find(tc => tc.tabId === tabId);
|
||||
}
|
||||
|
||||
/** @returns {string|null} */
|
||||
function getActiveTabNotePath() {
|
||||
const activeContext = getActiveTabContext();
|
||||
return activeContext ? activeContext.notePath : null;
|
||||
}
|
||||
|
||||
/** @return {NoteFull} */
|
||||
function getActiveTabNote() {
|
||||
const activeContext = getActiveTabContext();
|
||||
return activeContext ? activeContext.note : null;
|
||||
}
|
||||
|
||||
/** @return {string|null} */
|
||||
function getActiveTabNoteId() {
|
||||
const activeNote = getActiveTabNote();
|
||||
|
||||
return activeNote ? activeNote.noteId : null;
|
||||
}
|
||||
|
||||
/** @return {string|null} */
|
||||
function getActiveTabNoteType() {
|
||||
const activeNote = getActiveTabNote();
|
||||
|
||||
return activeNote ? activeNote.type : null;
|
||||
}
|
||||
|
||||
async function switchToTab(tabId, notePath) {
|
||||
const tabContext = tabContexts.find(tc => tc.tabId === tabId);
|
||||
|
||||
if (!tabContext) {
|
||||
await loadNoteDetail(notePath, {
|
||||
newTab: true,
|
||||
activate: true
|
||||
});
|
||||
} else {
|
||||
await tabContext.activate();
|
||||
|
||||
if (notePath && tabContext.notePath !== notePath) {
|
||||
await treeService.activateNote(notePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function showTab(tabId) {
|
||||
for (const ctx of tabContexts) {
|
||||
if (ctx.tabId === tabId) {
|
||||
await ctx.show();
|
||||
}
|
||||
else {
|
||||
ctx.hide();
|
||||
}
|
||||
}
|
||||
|
||||
const oldActiveNode = appContext.getMainNoteTree().getActiveNode();
|
||||
|
||||
if (oldActiveNode) {
|
||||
oldActiveNode.setActive(false);
|
||||
}
|
||||
|
||||
const newActiveTabContext = getActiveTabContext();
|
||||
|
||||
if (newActiveTabContext && newActiveTabContext.notePath) {
|
||||
const newActiveNode = await appContext.getMainNoteTree().getNodeFromPath(newActiveTabContext.notePath);
|
||||
|
||||
if (newActiveNode) {
|
||||
if (!newActiveNode.isVisible()) {
|
||||
await appContext.getMainNoteTree().expandToNote(newActiveTabContext.notePath);
|
||||
}
|
||||
|
||||
newActiveNode.setActive(true, {noEvents: true});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TabContext} ctx
|
||||
* @param {NoteFull} note
|
||||
@ -211,16 +107,7 @@ async function loadNoteDetail(origNotePath, options = {}) {
|
||||
|
||||
const noteId = treeUtils.getNoteIdFromNotePath(notePath);
|
||||
const loadedNote = await loadNote(noteId);
|
||||
let ctx;
|
||||
|
||||
if (!getActiveTabContext() || newTab) {
|
||||
// if it's a new tab explicitly by user then it's in background
|
||||
ctx = new TabContext(tabRow, options.state);
|
||||
tabContexts.push(ctx);
|
||||
}
|
||||
else {
|
||||
ctx = getActiveTabContext();
|
||||
}
|
||||
const ctx = appContext.getTab(newTab, options.state);
|
||||
|
||||
// we will try to render the new note only if it's still the active one in the tree
|
||||
// this is useful when user quickly switches notes (by e.g. holding down arrow) so that we don't
|
||||
@ -281,14 +168,6 @@ async function noteDeleted(noteId) {
|
||||
}
|
||||
}
|
||||
|
||||
async function refreshTabs(sourceTabId, noteId) {
|
||||
for (const tc of tabContexts) {
|
||||
if (tc.noteId === noteId && tc.tabId !== sourceTabId) {
|
||||
await reloadTab(tc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function focusOnTitle() {
|
||||
getActiveTabContext().$noteTitle.trigger('focus');
|
||||
}
|
||||
@ -337,12 +216,12 @@ ws.subscribeToOutsideSyncMessages(syncData => {
|
||||
.forEach(sync => noteIdsToRefresh.add(sync.noteId));
|
||||
|
||||
for (const noteId of noteIdsToRefresh) {
|
||||
refreshTabs(null, noteId);
|
||||
appContext.refreshTabs(null, noteId);
|
||||
}
|
||||
});
|
||||
|
||||
ws.subscribeToAllSyncMessages(syncData => {
|
||||
for (const tc of tabContexts) {
|
||||
for (const tc of appContext.tabContexts) {
|
||||
tc.eventReceived('syncData', syncData);
|
||||
}
|
||||
});
|
||||
@ -371,34 +250,6 @@ $tabContentsContainer.on("drop", async e => {
|
||||
});
|
||||
});
|
||||
|
||||
async function openEmptyTab() {
|
||||
const ctx = new TabContext(tabRow);
|
||||
tabContexts.push(ctx);
|
||||
|
||||
await tabRow.activateTab(ctx.$tab[0]);
|
||||
}
|
||||
|
||||
tabRow.addListener('newTab', openEmptyTab);
|
||||
|
||||
tabRow.addListener('activeTabChange', async ({ detail }) => {
|
||||
const tabId = detail.tabEl.getAttribute('data-tab-id');
|
||||
|
||||
await showTab(tabId);
|
||||
});
|
||||
|
||||
tabRow.addListener('tabRemove', async ({ detail }) => {
|
||||
const tabId = detail.tabEl.getAttribute('data-tab-id');
|
||||
|
||||
tabContexts.filter(nc => nc.tabId === tabId)
|
||||
.forEach(tc => tc.remove());
|
||||
|
||||
tabContexts = tabContexts.filter(nc => nc.tabId !== tabId);
|
||||
|
||||
if (tabContexts.length === 0) {
|
||||
openEmptyTab();
|
||||
}
|
||||
});
|
||||
|
||||
$(tabRow.el).on('contextmenu', '.note-tab', e => {
|
||||
e.preventDefault();
|
||||
|
||||
@ -473,7 +324,7 @@ async function saveOpenTabs() {
|
||||
|
||||
for (const tabEl of tabRow.tabEls) {
|
||||
const tabId = tabEl.getAttribute('data-tab-id');
|
||||
const tabContext = tabContexts.find(tc => tc.tabId === tabId);
|
||||
const tabContext = appContext.getTabContexts().find(tc => tc.tabId === tabId);
|
||||
|
||||
if (tabContext) {
|
||||
const tabState = tabContext.getTabState();
|
||||
@ -505,7 +356,6 @@ setInterval(saveNotesIfChanged, 3000);
|
||||
|
||||
export default {
|
||||
reload,
|
||||
reloadAllTabs,
|
||||
openInTab,
|
||||
switchToNote,
|
||||
loadNote,
|
||||
@ -515,20 +365,12 @@ export default {
|
||||
saveNotesIfChanged,
|
||||
onNoteChange,
|
||||
addDetailLoadedListener,
|
||||
switchToTab,
|
||||
getTabContexts,
|
||||
getActiveTabContext,
|
||||
getActiveTabNotePath,
|
||||
getActiveTabNote,
|
||||
getActiveTabNoteType,
|
||||
getActiveTabNoteId,
|
||||
getActiveEditor,
|
||||
activateOrOpenNote,
|
||||
clearOpenTabsTask,
|
||||
filterTabs,
|
||||
openEmptyTab,
|
||||
noteDeleted,
|
||||
refreshTabs,
|
||||
noteChanged,
|
||||
openTabsChanged
|
||||
openTabsChanged,
|
||||
reloadNote
|
||||
};
|
@ -5,6 +5,7 @@ import server from './server.js';
|
||||
import protectedSessionHolder from './protected_session_holder.js';
|
||||
import toastService from "./toast.js";
|
||||
import ws from "./ws.js";
|
||||
import appContext from "./app_context.js";
|
||||
|
||||
const $enterProtectedSessionButton = $("#enter-protected-session-button");
|
||||
const $leaveProtectedSessionButton = $("#leave-protected-session-button");
|
||||
@ -50,7 +51,7 @@ async function setupProtectedSession(password) {
|
||||
await treeService.reload();
|
||||
|
||||
// it's important that tree has been already reloaded at this point since detail also uses tree cache (for book)
|
||||
await noteDetailService.reloadAllTabs();
|
||||
await appContext.reloadAllTabs();
|
||||
|
||||
if (protectedSessionDeferred !== null) {
|
||||
import("../dialogs/protected_session.js").then(dialog => dialog.close());
|
||||
@ -72,16 +73,16 @@ async function enterProtectedSessionOnServer(password) {
|
||||
}
|
||||
|
||||
async function protectNoteAndSendToServer() {
|
||||
if (!noteDetailService.getActiveTabNote() || noteDetailService.getActiveTabNote().isProtected) {
|
||||
if (!appContext.getActiveTabNote() || appContext.getActiveTabNote().isProtected) {
|
||||
return;
|
||||
}
|
||||
|
||||
await enterProtectedSession();
|
||||
|
||||
const note = noteDetailService.getActiveTabNote();
|
||||
const note = appContext.getActiveTabNote();
|
||||
note.isProtected = true;
|
||||
|
||||
await noteDetailService.getActiveTabContext().saveNote();
|
||||
await appContext.getActiveTabContext().saveNote();
|
||||
|
||||
treeService.setProtected(note.noteId, note.isProtected);
|
||||
|
||||
@ -89,7 +90,7 @@ async function protectNoteAndSendToServer() {
|
||||
}
|
||||
|
||||
async function unprotectNoteAndSendToServer() {
|
||||
const activeNote = noteDetailService.getActiveTabNote();
|
||||
const activeNote = appContext.getActiveTabNote();
|
||||
|
||||
if (!activeNote.isProtected) {
|
||||
toastService.showAndLogError(`Note ${activeNote.noteId} is not protected`);
|
||||
@ -108,7 +109,7 @@ async function unprotectNoteAndSendToServer() {
|
||||
|
||||
activeNote.isProtected = false;
|
||||
|
||||
await noteDetailService.getActiveTabContext().saveNote();
|
||||
await appContext.getActiveTabContext().saveNote();
|
||||
|
||||
treeService.setProtected(activeNote.noteId, activeNote.isProtected);
|
||||
|
||||
|
@ -38,7 +38,7 @@ $showSidebarButton.on('click', async () => {
|
||||
|
||||
await server.put('options/rightPaneVisible/true');
|
||||
|
||||
const {sidebar} = noteDetailService.getActiveTabContext();
|
||||
const {sidebar} = appContext.getActiveTabContext();
|
||||
await sidebar.noteLoaded();
|
||||
sidebar.show();
|
||||
});
|
||||
|
@ -11,6 +11,7 @@ import protectedSessionService from "./protected_session.js";
|
||||
import optionsService from "./options.js";
|
||||
import linkService from "./link.js";
|
||||
import Sidebar from "./sidebar.js";
|
||||
import appContext from "./app_context.js";
|
||||
|
||||
const $tabContentsContainer = $("#note-tab-container");
|
||||
|
||||
@ -360,7 +361,7 @@ class TabContext {
|
||||
if (this.isNoteChanged) {
|
||||
await this.saveNote();
|
||||
|
||||
noteDetailService.refreshTabs(this.tabId, this.note.noteId);
|
||||
appContext.refreshTabs(this.tabId, this.note.noteId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -215,7 +215,7 @@ function getSelectedNodes(stopOnParents = false) {
|
||||
}
|
||||
|
||||
async function treeInitialized() {
|
||||
if (noteDetailService.getTabContexts().length > 0) {
|
||||
if (appContext.getTabContexts().length > 0) {
|
||||
// this is just tree reload - tabs are already in place
|
||||
return;
|
||||
}
|
||||
@ -369,7 +369,7 @@ async function createNote(node, parentNoteId, target, extraOptions = {}) {
|
||||
extraOptions.isProtected = false;
|
||||
}
|
||||
|
||||
if (noteDetailService.getActiveTabNoteType() !== 'text') {
|
||||
if (appContext.getActiveTabNoteType() !== 'text') {
|
||||
extraOptions.saveSelection = false;
|
||||
}
|
||||
|
||||
@ -560,31 +560,10 @@ async function reloadNotes(noteIds, activateNotePath = null) {
|
||||
await treeCache.reloadNotes(noteIds);
|
||||
|
||||
if (!activateNotePath) {
|
||||
activateNotePath = noteDetailService.getActiveTabNotePath();
|
||||
activateNotePath = appContext.getActiveTabNotePath();
|
||||
}
|
||||
|
||||
for (const noteId of noteIds) {
|
||||
for (const node of appContext.getMainNoteTree().getNodesByNoteId(noteId)) {
|
||||
const branch = treeCache.getBranch(node.data.branchId, true);
|
||||
|
||||
if (!branch) {
|
||||
node.remove();
|
||||
}
|
||||
else {
|
||||
await node.load(true);
|
||||
|
||||
await appContext.getMainNoteTree().checkFolderStatus(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (activateNotePath) {
|
||||
const node = await appContext.getMainNoteTree().getNodeFromPath(activateNotePath);
|
||||
|
||||
if (node && !node.isActive()) {
|
||||
await node.setActive(true);
|
||||
}
|
||||
}
|
||||
appContext.trigger('notesReloaded', { noteIds, activateNotePath });
|
||||
}
|
||||
|
||||
window.glob.cutIntoNote = () => createNoteInto(true);
|
||||
@ -599,7 +578,7 @@ $(window).bind('hashchange', async function() {
|
||||
if (isNotePathInAddress()) {
|
||||
const [notePath, tabId] = getHashValueFromAddress();
|
||||
|
||||
noteDetailService.switchToTab(tabId, notePath);
|
||||
appContext.switchToTab(tabId, notePath);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import BasicWidget from "./basic_widget.js";
|
||||
import hoistedNoteService from "../services/hoisted_note.js";
|
||||
import searchNotesService from "../services/search_notes.js";
|
||||
import keyboardActionService from "../services/keyboard_actions.js";
|
||||
import treeService from "../services/tree.js";
|
||||
import treeUtils from "../services/tree_utils.js";
|
||||
import noteDetailService from "../services/note_detail.js";
|
||||
@ -13,10 +12,11 @@ import treeBuilder from "../services/tree_builder.js";
|
||||
import TreeContextMenu from "../services/tree_context_menu.js";
|
||||
import treeChangesService from "../services/branches.js";
|
||||
import ws from "../services/ws.js";
|
||||
import appContext from "../services/app_context.js";
|
||||
|
||||
const TPL = `
|
||||
<style>
|
||||
#tree {
|
||||
.tree {
|
||||
overflow: auto;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
@ -26,7 +26,7 @@ const TPL = `
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="tree"></div>
|
||||
<div class="tree"></div>
|
||||
`;
|
||||
|
||||
export default class NoteTreeWidget extends BasicWidget {
|
||||
@ -39,7 +39,7 @@ export default class NoteTreeWidget extends BasicWidget {
|
||||
async doRender($widget) {
|
||||
$widget.append($(TPL));
|
||||
|
||||
const $tree = $widget.find('#tree');
|
||||
const $tree = $widget.find('.tree');
|
||||
|
||||
const treeData = await treeService.loadTreeData();
|
||||
|
||||
@ -48,9 +48,6 @@ export default class NoteTreeWidget extends BasicWidget {
|
||||
$tree.on("click", ".unhoist-button", hoistedNoteService.unhoist);
|
||||
$tree.on("click", ".refresh-search-button", searchNotesService.refreshSearch);
|
||||
|
||||
// FIXME this does not belong here ...
|
||||
keyboardActionService.setGlobalActionHandler('CollapseTree', () => this.collapseTree()); // don't use shortened form since collapseTree() accepts argument
|
||||
|
||||
// fancytree doesn't support middle click so this is a way to support it
|
||||
$widget.on('mousedown', '.fancytree-title', e => {
|
||||
if (e.which === 2) {
|
||||
@ -154,7 +151,7 @@ export default class NoteTreeWidget extends BasicWidget {
|
||||
if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
|
||||
const files = [...dataTransfer.files]; // chrome has issue that dataTransfer.files empties after async operation
|
||||
|
||||
const importService = await import('./import.js');
|
||||
const importService = await import('../services/import.js');
|
||||
|
||||
importService.uploadFiles(node.data.noteId, files, {
|
||||
safeImport: true,
|
||||
@ -231,7 +228,7 @@ export default class NoteTreeWidget extends BasicWidget {
|
||||
return false; // blocks default browser right click menu
|
||||
});
|
||||
|
||||
this.tree = $.ui.fancytree.getTree("#tree");
|
||||
this.tree = $.ui.fancytree.getTree($tree);
|
||||
}
|
||||
|
||||
/** @return {FancytreeNode[]} */
|
||||
@ -286,7 +283,7 @@ export default class NoteTreeWidget extends BasicWidget {
|
||||
|
||||
// FIXME since this operates on note details tab context it seems it does not really belong here
|
||||
async scrollToActiveNote() {
|
||||
const activeContext = noteDetailService.getActiveTabContext();
|
||||
const activeContext = appContext.getActiveTabContext();
|
||||
|
||||
if (activeContext && activeContext.notePath) {
|
||||
this.tree.setFocus();
|
||||
@ -405,4 +402,29 @@ export default class NoteTreeWidget extends BasicWidget {
|
||||
createTopLevelNoteListener() { treeService.createNewTopLevelNote(); }
|
||||
|
||||
collapseTreeListener() { this.collapseTree(); }
|
||||
|
||||
async notesReloadedListener({ noteIds, activateNotePath }) {
|
||||
for (const noteId of noteIds) {
|
||||
for (const node of this.getNodesByNoteId(noteId)) {
|
||||
const branch = treeCache.getBranch(node.data.branchId, true);
|
||||
|
||||
if (!branch) {
|
||||
node.remove();
|
||||
}
|
||||
else {
|
||||
await node.load(true);
|
||||
|
||||
await this.checkFolderStatus(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (activateNotePath) {
|
||||
const node = await this.getNodeFromPath(activateNotePath);
|
||||
|
||||
if (node && !node.isActive()) {
|
||||
await node.setActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -23,12 +23,12 @@ html, body {
|
||||
margin: 0 10px 0 16px;
|
||||
}
|
||||
|
||||
#tree {
|
||||
.tree {
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#tree .action-button {
|
||||
.tree .action-button {
|
||||
position: relative;
|
||||
top: -5px;
|
||||
margin-left: 10px;
|
||||
|
Loading…
x
Reference in New Issue
Block a user