mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 18:08:33 +02:00
refactoring of note detail API
This commit is contained in:
parent
4b66765cc1
commit
606d5afcab
@ -174,8 +174,7 @@ function AttributesModel() {
|
|||||||
|
|
||||||
appContext.getActiveTabContext().attributes.refreshAttributes();
|
appContext.getActiveTabContext().attributes.refreshAttributes();
|
||||||
|
|
||||||
// reload
|
// FIXME detail should be also reloaded
|
||||||
noteDetailService.reload();
|
|
||||||
appContext.trigger('reloadTree');
|
appContext.trigger('reloadTree');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -62,7 +62,6 @@ async function showTree() {
|
|||||||
|
|
||||||
const notePath = await treeUtils.getNotePath(node);
|
const notePath = await treeUtils.getNotePath(node);
|
||||||
|
|
||||||
noteDetailService.switchToNote(notePath);
|
|
||||||
},
|
},
|
||||||
expand: (event, data) => treeService.setExpandedToServer(data.node.data.branchId, true),
|
expand: (event, data) => treeService.setExpandedToServer(data.node.data.branchId, true),
|
||||||
collapse: (event, data) => treeService.setExpandedToServer(data.node.data.branchId, false),
|
collapse: (event, data) => treeService.setExpandedToServer(data.node.data.branchId, false),
|
||||||
|
@ -216,20 +216,11 @@ class AppContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async switchToTab(tabId, notePath) {
|
async switchToTab(tabId, notePath) {
|
||||||
const tabContext = this.tabContexts.find(tc => tc.tabId === tabId);
|
const tabContext = this.tabContexts.find(tc => tc.tabId === tabId)
|
||||||
|
|| this.openEmptyTab();
|
||||||
|
|
||||||
if (!tabContext) {
|
this.activateTab(tabContext.tabId);
|
||||||
await noteDetailService.loadNoteDetail(notePath, {
|
await tabContext.setNote(notePath);
|
||||||
newTab: true,
|
|
||||||
activate: true
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
await this.activateTab(tabContext.tabId);
|
|
||||||
|
|
||||||
if (notePath && tabContext.notePath !== notePath) {
|
|
||||||
await tabContext.setNote(notePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -252,18 +243,6 @@ class AppContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async reloadAllTabs() {
|
|
||||||
for (const tabContext of this.tabContexts) {
|
|
||||||
await this.reloadTab(tabContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async reloadTab(tc) {
|
|
||||||
if (tc.note) {
|
|
||||||
noteDetailService.reloadNote(tc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async openAndActivateEmptyTab() {
|
async openAndActivateEmptyTab() {
|
||||||
const tabContext = this.openEmptyTab();
|
const tabContext = this.openEmptyTab();
|
||||||
|
|
||||||
@ -278,6 +257,20 @@ class AppContext {
|
|||||||
return tabContext;
|
return tabContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async activateOrOpenNote(noteId) {
|
||||||
|
for (const tabContext of this.getTabContexts()) {
|
||||||
|
if (tabContext.note && tabContext.note.noteId === noteId) {
|
||||||
|
await tabContext.activate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no tab with this note has been found we'll create new tab
|
||||||
|
|
||||||
|
const tabContext = this.openEmptyTab();
|
||||||
|
await tabContext.setNote(noteId);
|
||||||
|
}
|
||||||
|
|
||||||
async filterTabs(noteId) {
|
async filterTabs(noteId) {
|
||||||
for (const tc of this.tabContexts) {
|
for (const tc of this.tabContexts) {
|
||||||
if (tc.notePath && !tc.notePath.split("/").includes(noteId)) {
|
if (tc.notePath && !tc.notePath.split("/").includes(noteId)) {
|
||||||
@ -318,7 +311,7 @@ class AppContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
openTabsChanged() {
|
openTabsChangedListener() {
|
||||||
// we don't want to send too many requests with tab changes so we always schedule task to do this in 1 seconds,
|
// we don't want to send too many requests with tab changes so we always schedule task to do this in 1 seconds,
|
||||||
// but if there's any change in between, we cancel the old one and schedule new one
|
// but if there's any change in between, we cancel the old one and schedule new one
|
||||||
// so effectively we kind of wait until user stopped e.g. quickly switching tabs
|
// so effectively we kind of wait until user stopped e.g. quickly switching tabs
|
||||||
@ -327,7 +320,7 @@ class AppContext {
|
|||||||
this.tabsChangedTaskId = setTimeout(() => this.saveOpenTabs(), 1000);
|
this.tabsChangedTaskId = setTimeout(() => this.saveOpenTabs(), 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
async activateTab(tabId) {
|
activateTab(tabId) {
|
||||||
this.activeTabId = tabId;
|
this.activeTabId = tabId;
|
||||||
|
|
||||||
this.trigger('activeTabChanged', { tabId: this.activeTabId });
|
this.trigger('activeTabChanged', { tabId: this.activeTabId });
|
||||||
@ -364,11 +357,11 @@ class AppContext {
|
|||||||
|
|
||||||
this.tabContexts = this.tabContexts.filter(tc => tc.tabId === tabId);
|
this.tabContexts = this.tabContexts.filter(tc => tc.tabId === tabId);
|
||||||
|
|
||||||
this.openTabsChanged();
|
this.openTabsChangedListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
tabReorderListener() {
|
tabReorderListener() {
|
||||||
this.openTabsChanged();
|
this.openTabsChangedListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
noteChangesSavedListener() {
|
noteChangesSavedListener() {
|
||||||
|
@ -78,7 +78,9 @@ export default class Entrypoints extends Component {
|
|||||||
|
|
||||||
await treeService.expandToNote(note.noteId);
|
await treeService.expandToNote(note.noteId);
|
||||||
|
|
||||||
await noteDetailService.openInTab(note.noteId, true);
|
const tabContext = appContext.openEmptyTab();
|
||||||
|
appContext.activateTab(tabContext.tabId);
|
||||||
|
await tabContext.setNote(note.noteId);
|
||||||
|
|
||||||
noteDetailService.focusAndSelectTitle();
|
noteDetailService.focusAndSelectTitle();
|
||||||
}
|
}
|
||||||
|
@ -272,22 +272,6 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
|
|||||||
*/
|
*/
|
||||||
this.refreshTree = treeService.reload;
|
this.refreshTree = treeService.reload;
|
||||||
|
|
||||||
/**
|
|
||||||
* Refresh active tab
|
|
||||||
*
|
|
||||||
* @method
|
|
||||||
* @returns {Promise<void>}
|
|
||||||
*/
|
|
||||||
this.refreshActiveTab = noteDetailService.reload;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Refresh current tab
|
|
||||||
*
|
|
||||||
* @method
|
|
||||||
* @returns {Promise<void>}
|
|
||||||
*/
|
|
||||||
this.refreshAllTabs = appContext.reloadAllTabs;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create note link (jQuery object) for given note.
|
* Create note link (jQuery object) for given note.
|
||||||
*
|
*
|
||||||
|
@ -79,10 +79,13 @@ function goToLink(e) {
|
|||||||
|
|
||||||
if (notePath) {
|
if (notePath) {
|
||||||
if ((e.which === 1 && e.ctrlKey) || e.which === 2) {
|
if ((e.which === 1 && e.ctrlKey) || e.which === 2) {
|
||||||
noteDetailService.openInTab(notePath, false);
|
const tabContext = appContext.openEmptyTab();
|
||||||
|
appContext.activateTab(tabContext.tabId);
|
||||||
|
tabContext.setNote(notePath);
|
||||||
}
|
}
|
||||||
else if (e.which === 1) {
|
else if (e.which === 1) {
|
||||||
treeService.activateNote(notePath);
|
const activeTabContext = appContext.getActiveTabContext();
|
||||||
|
activeTabContext.setNote(notePath)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return false;
|
return false;
|
||||||
@ -118,7 +121,9 @@ function newTabContextMenu(e) {
|
|||||||
},
|
},
|
||||||
selectContextMenuItem: (e, cmd) => {
|
selectContextMenuItem: (e, cmd) => {
|
||||||
if (cmd === 'openNoteInNewTab') {
|
if (cmd === 'openNoteInNewTab') {
|
||||||
noteDetailService.loadNoteDetail(notePath.split("/").pop(), { newTab: true });
|
const tabContext = appContext.openEmptyTab();
|
||||||
|
tabContext.setNote(notePath);
|
||||||
|
appContext.activateTab(tabContext.tabId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -138,7 +143,9 @@ $(document).on('mousedown', '.note-detail-text a', function (e) {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
if (notePath) {
|
if (notePath) {
|
||||||
noteDetailService.loadNoteDetail(notePath, {newTab: true});
|
const tabContext = appContext.openEmptyTab();
|
||||||
|
tabContext.setNote(notePath);
|
||||||
|
appContext.activateTab(tabContext.tabId);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const address = $link.attr('href');
|
const address = $link.attr('href');
|
||||||
|
@ -1,35 +1,9 @@
|
|||||||
import treeService from './tree.js';
|
|
||||||
import TabContext from './tab_context.js';
|
|
||||||
import server from './server.js';
|
import server from './server.js';
|
||||||
import ws from "./ws.js";
|
import ws from "./ws.js";
|
||||||
import treeCache from "./tree_cache.js";
|
import treeCache from "./tree_cache.js";
|
||||||
import NoteFull from "../entities/note_full.js";
|
import NoteFull from "../entities/note_full.js";
|
||||||
import treeUtils from "./tree_utils.js";
|
|
||||||
import tabRow from "../widgets/tab_row.js";
|
|
||||||
import appContext from "./app_context.js";
|
import appContext from "./app_context.js";
|
||||||
|
|
||||||
let detailLoadedListeners = [];
|
|
||||||
|
|
||||||
async function reload() {
|
|
||||||
// no saving here
|
|
||||||
|
|
||||||
await loadNoteDetail(appContext.getActiveTabNotePath());
|
|
||||||
}
|
|
||||||
|
|
||||||
async function reloadNote(tabContext) {
|
|
||||||
await loadNoteDetailToContext(tabContext, tabContext.notePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function openInTab(notePath, activate) {
|
|
||||||
await loadNoteDetail(notePath, { newTab: true, activate });
|
|
||||||
}
|
|
||||||
|
|
||||||
async function switchToNote(notePath) {
|
|
||||||
await loadNoteDetail(notePath);
|
|
||||||
|
|
||||||
appContext.openTabsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getActiveEditor() {
|
function getActiveEditor() {
|
||||||
const activeTabContext = appContext.getActiveTabContext();
|
const activeTabContext = appContext.getActiveTabContext();
|
||||||
|
|
||||||
@ -41,73 +15,6 @@ function getActiveEditor() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function activateOrOpenNote(noteId) {
|
|
||||||
for (const tabContext of appContext.getTabContexts()) {
|
|
||||||
if (tabContext.note && tabContext.note.noteId === noteId) {
|
|
||||||
await tabContext.activate();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if no tab with this note has been found we'll create new tab
|
|
||||||
|
|
||||||
await loadNoteDetail(noteId, {
|
|
||||||
newTab: true,
|
|
||||||
activate: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {TabContext} ctx
|
|
||||||
* @param {string} notePath
|
|
||||||
*/
|
|
||||||
async function loadNoteDetailToContext(ctx, notePath) {
|
|
||||||
await ctx.setNote(notePath);
|
|
||||||
|
|
||||||
appContext.openTabsChanged();
|
|
||||||
|
|
||||||
fireDetailLoaded();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loadNoteDetail(origNotePath, options = {}) {
|
|
||||||
const newTab = !!options.newTab;
|
|
||||||
const activate = !!options.activate;
|
|
||||||
|
|
||||||
let notePath = await treeService.resolveNotePath(origNotePath);
|
|
||||||
|
|
||||||
if (!notePath) {
|
|
||||||
console.error(`Cannot resolve note path ${origNotePath}`);
|
|
||||||
|
|
||||||
// fallback to display something
|
|
||||||
notePath = 'root';
|
|
||||||
}
|
|
||||||
|
|
||||||
const noteId = treeUtils.getNoteIdFromNotePath(notePath);
|
|
||||||
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
|
|
||||||
// try to render all those loaded notes one after each other. This only guarantees that correct note
|
|
||||||
// will be displayed independent of timing
|
|
||||||
const currentTreeNode = appContext.getMainNoteTree().getActiveNode();
|
|
||||||
if (!newTab && currentTreeNode && currentTreeNode.data.noteId !== noteId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const loadPromise = loadNoteDetailToContext(ctx, notePath).then(() => {
|
|
||||||
if (activate) {
|
|
||||||
return appContext.activateTab(ctx.tabId);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!options.async) {
|
|
||||||
await loadPromise;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loadNote(noteId) {
|
async function loadNote(noteId) {
|
||||||
const row = await server.get('notes/' + noteId);
|
const row = await server.get('notes/' + noteId);
|
||||||
|
|
||||||
@ -116,49 +23,12 @@ async function loadNote(noteId) {
|
|||||||
return new NoteFull(treeCache, row, noteShort);
|
return new NoteFull(treeCache, row, noteShort);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function noteDeleted(noteId) {
|
|
||||||
for (const tc of appContext.getTabContexts()) {
|
|
||||||
// not removing active even if it contains deleted note since that one will move to another note (handled by deletion logic)
|
|
||||||
// and we would lose tab context state (e.g. sidebar visibility)
|
|
||||||
if (!tc.isActive() && tc.notePath && tc.notePath.split("/").includes(noteId)) {
|
|
||||||
tabRow.removeTab(tc.tabId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function focusOnTitle() {
|
function focusOnTitle() {
|
||||||
appContext.getActiveTabContext().$noteTitle.trigger('focus');
|
appContext.trigger('focusOnTitle');
|
||||||
}
|
}
|
||||||
|
|
||||||
function focusAndSelectTitle() {
|
function focusAndSelectTitle() {
|
||||||
appContext.getActiveTabContext()
|
appContext.trigger('focusAndSelectTitle');
|
||||||
.$noteTitle
|
|
||||||
.trigger('focus')
|
|
||||||
.trigger('select');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Since detail loading may take some time and user might just browse through the notes using UP-DOWN keys,
|
|
||||||
* we intentionally decouple activation of the note in the tree and full load of the note so just avaiting on
|
|
||||||
* fancytree's activate() won't wait for the full load.
|
|
||||||
*
|
|
||||||
* This causes an issue where in some cases you want to do some action after detail is loaded. For this reason
|
|
||||||
* we provide the listeners here which will be triggered after the detail is loaded and if the loaded note
|
|
||||||
* is the one registered in the listener.
|
|
||||||
*/
|
|
||||||
function addDetailLoadedListener(noteId, callback) {
|
|
||||||
detailLoadedListeners.push({ noteId, callback });
|
|
||||||
}
|
|
||||||
|
|
||||||
function fireDetailLoaded() {
|
|
||||||
for (const {noteId, callback} of detailLoadedListeners) {
|
|
||||||
if (noteId === appContext.getActiveTabNoteId()) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// all the listeners are one time only
|
|
||||||
detailLoadedListeners = [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ws.subscribeToOutsideSyncMessages(syncData => {
|
ws.subscribeToOutsideSyncMessages(syncData => {
|
||||||
@ -199,17 +69,9 @@ $(window).on('beforeunload', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
reload,
|
|
||||||
openInTab,
|
|
||||||
switchToNote,
|
|
||||||
loadNote,
|
loadNote,
|
||||||
loadNoteDetail,
|
|
||||||
focusOnTitle,
|
focusOnTitle,
|
||||||
focusAndSelectTitle,
|
focusAndSelectTitle,
|
||||||
addDetailLoadedListener,
|
|
||||||
getActiveEditor,
|
getActiveEditor,
|
||||||
activateOrOpenNote,
|
noteChanged
|
||||||
noteDeleted,
|
|
||||||
noteChanged,
|
|
||||||
reloadNote
|
|
||||||
};
|
};
|
@ -109,17 +109,12 @@ async function unprotectNoteAndSendToServer() {
|
|||||||
await appContext.getActiveTabContext().saveNote();
|
await appContext.getActiveTabContext().saveNote();
|
||||||
|
|
||||||
treeService.setProtected(activeNote.noteId, activeNote.isProtected);
|
treeService.setProtected(activeNote.noteId, activeNote.isProtected);
|
||||||
|
|
||||||
await noteDetailService.reload();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function protectSubtree(noteId, protect) {
|
async function protectSubtree(noteId, protect) {
|
||||||
await enterProtectedSession();
|
await enterProtectedSession();
|
||||||
|
|
||||||
await server.put('notes/' + noteId + "/protect/" + (protect ? 1 : 0));
|
await server.put('notes/' + noteId + "/protect/" + (protect ? 1 : 0));
|
||||||
|
|
||||||
treeService.reload();
|
|
||||||
noteDetailService.reload();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeToast(message, protectingLabel, text) {
|
function makeToast(message, protectingLabel, text) {
|
||||||
|
@ -8,6 +8,7 @@ import appContext from "./app_context.js";
|
|||||||
import treeUtils from "./tree_utils.js";
|
import treeUtils from "./tree_utils.js";
|
||||||
import noteDetailService from "./note_detail.js";
|
import noteDetailService from "./note_detail.js";
|
||||||
import Component from "../widgets/component.js";
|
import Component from "../widgets/component.js";
|
||||||
|
import treeService from "./tree.js";
|
||||||
|
|
||||||
let showSidebarInNewTab = true;
|
let showSidebarInNewTab = true;
|
||||||
|
|
||||||
@ -35,7 +36,19 @@ class TabContext extends Component {
|
|||||||
this.trigger('tabOpened', {tabId: this.tabId});
|
this.trigger('tabOpened', {tabId: this.tabId});
|
||||||
}
|
}
|
||||||
|
|
||||||
async setNote(notePath) {
|
async setNote(inputNotePath) {
|
||||||
|
const notePath = await treeService.resolveNotePath(inputNotePath);
|
||||||
|
|
||||||
|
if (!notePath) {
|
||||||
|
console.error(`Cannot resolve note path ${inputNotePath}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notePath === this.notePath) {
|
||||||
|
console.log(`Setting existing notePath ${notePath} so ignoring ...`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await this.trigger('beforeNoteSwitch', {tabId: this.tabId}, true);
|
await this.trigger('beforeNoteSwitch', {tabId: this.tabId}, true);
|
||||||
|
|
||||||
this.notePath = notePath;
|
this.notePath = notePath;
|
||||||
@ -64,6 +77,7 @@ class TabContext extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.trigger('tabNoteSwitched', {tabId: this.tabId});
|
this.trigger('tabNoteSwitched', {tabId: this.tabId});
|
||||||
|
this.trigger('openTabsChanged');
|
||||||
}
|
}
|
||||||
|
|
||||||
async remove() {
|
async remove() {
|
||||||
@ -113,7 +127,16 @@ class TabContext extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
stateChanged() {
|
stateChanged() {
|
||||||
appContext.openTabsChanged();
|
appContext.openTabsChangedListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
noteDeletedListener({noteId}) {
|
||||||
|
if (this.note && noteId === this.note.noteId) {
|
||||||
|
this.note = null;
|
||||||
|
this.notePath = null;
|
||||||
|
|
||||||
|
this.trigger('tabNoteSwitched', {tabId: this.tabId});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,12 +263,12 @@ async function treeInitialized() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const tab of filteredTabs) {
|
for (const tab of filteredTabs) {
|
||||||
await noteDetailService.loadNoteDetail(tab.notePath, {
|
const tabContext = appContext.openEmptyTab();
|
||||||
state: tab,
|
tabContext.setNote(tab.notePath);
|
||||||
newTab: true,
|
|
||||||
activate: tab.active,
|
if (tab.active) {
|
||||||
async: true // faster initial load
|
appContext.activateTab(tabContext.tabId);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// previous opening triggered task to save tab changes but these are bogus changes (this is init)
|
// previous opening triggered task to save tab changes but these are bogus changes (this is init)
|
||||||
@ -446,7 +446,7 @@ ws.subscribeToMessages(message => {
|
|||||||
reload();
|
reload();
|
||||||
}
|
}
|
||||||
else if (message.type === 'open-note') {
|
else if (message.type === 'open-note') {
|
||||||
noteDetailService.activateOrOpenNote(message.noteId);
|
appContext.activateOrOpenNote(message.noteId);
|
||||||
|
|
||||||
if (utils.isElectron()) {
|
if (utils.isElectron()) {
|
||||||
const currentWindow = require("electron").remote.getCurrentWindow();
|
const currentWindow = require("electron").remote.getCurrentWindow();
|
||||||
|
@ -104,7 +104,9 @@ class TreeContextMenu {
|
|||||||
const notePath = await treeUtils.getNotePath(this.node);
|
const notePath = await treeUtils.getNotePath(this.node);
|
||||||
|
|
||||||
if (cmd === 'openInTab') {
|
if (cmd === 'openInTab') {
|
||||||
noteDetailService.openInTab(notePath, false);
|
const tabContext = appContext.openEmptyTab();
|
||||||
|
appContext.activateTab(tabContext.tabId);
|
||||||
|
tabContext.setNote(notePath);
|
||||||
}
|
}
|
||||||
else if (cmd.startsWith("insertNoteAfter")) {
|
else if (cmd.startsWith("insertNoteAfter")) {
|
||||||
const parentNoteId = this.node.data.parentNoteId;
|
const parentNoteId = this.node.data.parentNoteId;
|
||||||
|
@ -4,6 +4,7 @@ import protectedSessionHolder from "../services/protected_session_holder.js";
|
|||||||
import treeCache from "../services/tree_cache.js";
|
import treeCache from "../services/tree_cache.js";
|
||||||
import server from "../services/server.js";
|
import server from "../services/server.js";
|
||||||
import SpacedUpdate from "../services/spaced_update.js";
|
import SpacedUpdate from "../services/spaced_update.js";
|
||||||
|
import appContext from "../services/app_context.js";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<div class="note-title-container">
|
<div class="note-title-container">
|
||||||
@ -107,4 +108,18 @@ export default class NoteTitleWidget extends TabAwareWidget {
|
|||||||
await this.spacedUpdate.updateNowIfNecessary();
|
await this.spacedUpdate.updateNowIfNecessary();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
focusOnTitleListener() {
|
||||||
|
if (this.tabContext && this.tabContext.isActive()) {
|
||||||
|
this.$noteTitle.trigger('focus');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
focusAndSelectTitleListener() {
|
||||||
|
if (this.tabContext && this.tabContext.isActive()) {
|
||||||
|
this.$noteTitle
|
||||||
|
.trigger('focus')
|
||||||
|
.trigger('select');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -53,7 +53,8 @@ export default class NoteTreeWidget extends TabAwareWidget {
|
|||||||
|
|
||||||
treeUtils.getNotePath(node).then(notePath => {
|
treeUtils.getNotePath(node).then(notePath => {
|
||||||
if (notePath) {
|
if (notePath) {
|
||||||
noteDetailService.openInTab(notePath, false);
|
const tabContext = appContext.openEmptyTab();
|
||||||
|
tabContext.setNote(notePath);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -87,7 +88,9 @@ export default class NoteTreeWidget extends TabAwareWidget {
|
|||||||
node.setFocus(true);
|
node.setFocus(true);
|
||||||
}
|
}
|
||||||
else if (event.ctrlKey) {
|
else if (event.ctrlKey) {
|
||||||
noteDetailService.loadNoteDetail(node.data.noteId, { newTab: true });
|
const tabContext = appContext.openEmptyTab();
|
||||||
|
treeUtils.getNotePath(node).then(notePath => tabContext.setNote(notePath));
|
||||||
|
appContext.activateTab(tabContext.tabId);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
node.setActive();
|
node.setActive();
|
||||||
|
@ -130,9 +130,6 @@ export default class NoteTypeWidget extends TabAwareWidget {
|
|||||||
|
|
||||||
await noteDetailService.reload();
|
await noteDetailService.reload();
|
||||||
|
|
||||||
// for the note icon to be updated in the tree
|
|
||||||
await treeService.reload();
|
|
||||||
|
|
||||||
this.update();
|
this.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ export default class SearchBoxWidget extends BasicWidget {
|
|||||||
|
|
||||||
this.$saveSearchButton.on('click', () => this.saveSearch());
|
this.$saveSearchButton.on('click', () => this.saveSearch());
|
||||||
|
|
||||||
this.$closeSearchButton.on('click', () => this.hideSearchListener());
|
this.$closeSearchButton.on('click', () => this.trigger('hideSearch'));
|
||||||
|
|
||||||
return this.$widget;
|
return this.$widget;
|
||||||
}
|
}
|
||||||
@ -159,6 +159,8 @@ export default class SearchBoxWidget extends BasicWidget {
|
|||||||
this.resetSearchListener();
|
this.resetSearchListener();
|
||||||
|
|
||||||
this.$searchBox.slideUp();
|
this.$searchBox.slideUp();
|
||||||
|
|
||||||
|
this.trigger('hideSearchResults');
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleSearchListener() {
|
toggleSearchListener() {
|
||||||
@ -167,7 +169,6 @@ export default class SearchBoxWidget extends BasicWidget {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.hideSearchListener();
|
this.hideSearchListener();
|
||||||
this.trigger('hideSearchResults');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,8 @@ export default class SearchResultsWidget extends BasicWidget {
|
|||||||
this.$searchResults = this.$widget;
|
this.$searchResults = this.$widget;
|
||||||
this.$searchResultsInner = this.$widget.find(".search-results-inner");
|
this.$searchResultsInner = this.$widget.find(".search-results-inner");
|
||||||
|
|
||||||
|
this.toggle(false);
|
||||||
|
|
||||||
return this.$widget;
|
return this.$widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,10 @@ export default class TabCachingWidget extends TabAwareWidget {
|
|||||||
widget.toggle(false);
|
widget.toggle(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.tabContext) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let widget = this.widgets[this.tabContext.tabId];
|
let widget = this.widgets[this.tabContext.tabId];
|
||||||
|
|
||||||
if (!widget) {
|
if (!widget) {
|
||||||
@ -31,8 +35,6 @@ export default class TabCachingWidget extends TabAwareWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
widget.toggle(true);
|
widget.toggle(true);
|
||||||
|
|
||||||
return false; // stop propagation to children
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tabRemovedListener({tabId}) {
|
tabRemovedListener({tabId}) {
|
||||||
|
@ -7,6 +7,7 @@ import contextMenuWidget from "../../services/context_menu.js";
|
|||||||
import toastService from "../../services/toast.js";
|
import toastService from "../../services/toast.js";
|
||||||
import attributeAutocompleteService from "../../services/attribute_autocomplete.js";
|
import attributeAutocompleteService from "../../services/attribute_autocomplete.js";
|
||||||
import TypeWidget from "./type_widget.js";
|
import TypeWidget from "./type_widget.js";
|
||||||
|
import appContext from "../../services/app_context.js";
|
||||||
|
|
||||||
const uniDirectionalOverlays = [
|
const uniDirectionalOverlays = [
|
||||||
[ "Arrow", {
|
[ "Arrow", {
|
||||||
@ -196,7 +197,8 @@ export default class RelationMapTypeWidget extends TypeWidget {
|
|||||||
const noteId = this.idToNoteId($noteBox.prop("id"));
|
const noteId = this.idToNoteId($noteBox.prop("id"));
|
||||||
|
|
||||||
if (cmd === "open-in-new-tab") {
|
if (cmd === "open-in-new-tab") {
|
||||||
noteDetailService.openInTab(noteId, false);
|
const tabContext = appContext.openEmptyTab();
|
||||||
|
tabContext.setNote(noteId);
|
||||||
}
|
}
|
||||||
else if (cmd === "remove") {
|
else if (cmd === "remove") {
|
||||||
const confirmDialog = await import('../../dialogs/confirm.js');
|
const confirmDialog = await import('../../dialogs/confirm.js');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user