mirror of
https://github.com/zadam/trilium.git
synced 2025-11-01 02:45:54 +01:00
moved tab related stuff to tab manager from app context
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import TabContext from "./tab_context.js";
|
||||
import server from "./server.js";
|
||||
import treeCache from "./tree_cache.js";
|
||||
import bundleService from "./bundle.js";
|
||||
@@ -6,28 +5,15 @@ import DialogEventComponent from "./dialog_events.js";
|
||||
import Entrypoints from "./entrypoints.js";
|
||||
import options from "./options.js";
|
||||
import utils from "./utils.js";
|
||||
import treeService from "./tree.js";
|
||||
import ZoomService from "./zoom.js";
|
||||
import Layout from "../widgets/layout.js";
|
||||
import SpacedUpdate from "./spaced_update.js";
|
||||
import TabManager from "./tab_manager.js";
|
||||
|
||||
class AppContext {
|
||||
constructor(layout) {
|
||||
this.layout = layout;
|
||||
this.components = [];
|
||||
/** @type {TabContext[]} */
|
||||
this.tabContexts = [];
|
||||
this.activeTabId = null;
|
||||
|
||||
this.tabsUpdate = new SpacedUpdate(async () => {
|
||||
const openTabs = this.tabContexts
|
||||
.map(tc => tc.getTabState())
|
||||
.filter(t => !!t);
|
||||
|
||||
await server.put('options', {
|
||||
openTabs: JSON.stringify(openTabs)
|
||||
});
|
||||
});
|
||||
this.tabManager = new TabManager(this);
|
||||
this.components = [this.tabManager];
|
||||
}
|
||||
|
||||
async start() {
|
||||
@@ -35,80 +21,11 @@ class AppContext {
|
||||
|
||||
this.showWidgets();
|
||||
|
||||
this.loadTabs();
|
||||
this.tabManager.loadTabs();
|
||||
|
||||
bundleService.executeStartupBundles();
|
||||
}
|
||||
|
||||
async loadTabs() {
|
||||
const openTabs = options.getJson('openTabs') || [];
|
||||
|
||||
await treeCache.initializedPromise;
|
||||
|
||||
// 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 treeCache.noteExists(noteId)) {
|
||||
for (const tab of openTabs) {
|
||||
tab.active = false;
|
||||
}
|
||||
|
||||
const foundTab = openTabs.find(tab => noteId === treeService.getNoteIdFromNotePath(tab.notePath));
|
||||
|
||||
if (foundTab) {
|
||||
foundTab.active = true;
|
||||
}
|
||||
else {
|
||||
openTabs.push({
|
||||
notePath: notePath,
|
||||
active: true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let filteredTabs = [];
|
||||
|
||||
for (const openTab of openTabs) {
|
||||
const noteId = treeService.getNoteIdFromNotePath(openTab.notePath);
|
||||
|
||||
if (await treeCache.noteExists(noteId)) {
|
||||
// note doesn't exist so don't try to open tab for it
|
||||
filteredTabs.push(openTab);
|
||||
}
|
||||
}
|
||||
|
||||
if (utils.isMobile()) {
|
||||
// mobile frontend doesn't have tabs so show only the active tab
|
||||
filteredTabs = filteredTabs.filter(tab => tab.active);
|
||||
}
|
||||
|
||||
if (filteredTabs.length === 0) {
|
||||
filteredTabs.push({
|
||||
notePath: 'root',
|
||||
active: true
|
||||
});
|
||||
}
|
||||
|
||||
if (!filteredTabs.find(tab => tab.active)) {
|
||||
filteredTabs[0].active = true;
|
||||
}
|
||||
|
||||
this.tabsUpdate.allowUpdateWithoutChange(() => {
|
||||
for (const tab of filteredTabs) {
|
||||
const tabContext = this.openEmptyTab();
|
||||
tabContext.setNote(tab.notePath);
|
||||
|
||||
if (tab.active) {
|
||||
this.activateTab(tabContext.tabId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
showWidgets() {
|
||||
const rootContainer = this.layout.getRootWidget(this);
|
||||
|
||||
@@ -145,210 +62,20 @@ class AppContext {
|
||||
}
|
||||
}
|
||||
|
||||
tabNoteSwitchedListener({tabId}) {
|
||||
if (tabId === this.activeTabId) {
|
||||
this._setCurrentNotePathToHash();
|
||||
}
|
||||
}
|
||||
|
||||
_setCurrentNotePathToHash() {
|
||||
const activeTabContext = this.getActiveTabContext();
|
||||
|
||||
if (activeTabContext && activeTabContext.notePath) {
|
||||
document.location.hash = (activeTabContext.notePath || "") + "-" + activeTabContext.tabId;
|
||||
}
|
||||
}
|
||||
|
||||
/** @return {TabContext[]} */
|
||||
getTabContexts() {
|
||||
return this.tabContexts;
|
||||
}
|
||||
|
||||
/** @returns {TabContext} */
|
||||
getTabContextById(tabId) {
|
||||
return this.tabContexts.find(tc => tc.tabId === tabId);
|
||||
}
|
||||
|
||||
/** @returns {TabContext} */
|
||||
getActiveTabContext() {
|
||||
return this.getTabContextById(this.activeTabId);
|
||||
}
|
||||
|
||||
/** @returns {string|null} */
|
||||
getActiveTabNotePath() {
|
||||
const activeContext = this.getActiveTabContext();
|
||||
return activeContext ? activeContext.notePath : null;
|
||||
}
|
||||
|
||||
/** @return {NoteShort} */
|
||||
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)
|
||||
|| this.openEmptyTab();
|
||||
|
||||
this.activateTab(tabContext.tabId);
|
||||
await tabContext.setNote(notePath);
|
||||
}
|
||||
|
||||
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(this, state);
|
||||
this.tabContexts.push(ctx);
|
||||
this.components.push(ctx);
|
||||
|
||||
return ctx;
|
||||
} else {
|
||||
return this.getActiveTabContext();
|
||||
}
|
||||
}
|
||||
|
||||
async openAndActivateEmptyTab() {
|
||||
const tabContext = this.openEmptyTab();
|
||||
|
||||
await this.activateTab(tabContext.tabId);
|
||||
}
|
||||
|
||||
openEmptyTab() {
|
||||
const tabContext = new TabContext(this);
|
||||
this.tabContexts.push(tabContext);
|
||||
this.components.push(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);
|
||||
}
|
||||
|
||||
hoistedNoteChangedListener({hoistedNoteId}) {
|
||||
if (hoistedNoteId === 'root') {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const tc of this.tabContexts) {
|
||||
for (const tc of this.tabManager.getTabContexts()) {
|
||||
if (tc.notePath && !tc.notePath.split("/").includes(hoistedNoteId)) {
|
||||
this.removeTab(tc.tabId);
|
||||
this.tabManager.removeTab(tc.tabId);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.tabContexts.length === 0) {
|
||||
this.openAndActivateEmptyTab();
|
||||
if (this.tabManager.getTabContexts().length === 0) {
|
||||
this.tabManager.openAndActivateEmptyTab();
|
||||
}
|
||||
|
||||
this.saveOpenTabs();
|
||||
}
|
||||
|
||||
openTabsChangedListener() {
|
||||
this.tabsUpdate.scheduleUpdate();
|
||||
}
|
||||
|
||||
activateTab(tabId) {
|
||||
if (tabId === this.activeTabId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const oldActiveTabId = this.activeTabId;
|
||||
|
||||
this.activeTabId = tabId;
|
||||
|
||||
this.trigger('activeTabChanged', { oldActiveTabId, newActiveTabId: tabId });
|
||||
}
|
||||
|
||||
newTabListener() {
|
||||
this.openAndActivateEmptyTab();
|
||||
}
|
||||
|
||||
async removeTab(tabId) {
|
||||
const tabContextToRemove = this.tabContexts.find(tc => tc.tabId === tabId);
|
||||
|
||||
if (!tabContextToRemove) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.trigger('beforeTabRemove', {tabId}, true);
|
||||
|
||||
if (this.tabContexts.length === 1) {
|
||||
this.openAndActivateEmptyTab();
|
||||
}
|
||||
else {
|
||||
this.activateNextTabListener();
|
||||
}
|
||||
|
||||
this.tabContexts = this.tabContexts.filter(tc => tc.tabId === tabId);
|
||||
|
||||
this.trigger('tabRemoved', {tabId});
|
||||
|
||||
this.openTabsChangedListener();
|
||||
}
|
||||
|
||||
tabReorderListener({tabIdsInOrder}) {
|
||||
const order = {};
|
||||
|
||||
for (const i in tabIdsInOrder) {
|
||||
order[tabIdsInOrder[i]] = i;
|
||||
}
|
||||
|
||||
this.tabContexts.sort((a, b) => order[a.tabId] < order[b.tabId] ? -1 : 1);
|
||||
|
||||
this.openTabsChangedListener();
|
||||
}
|
||||
|
||||
activateNextTabListener() {
|
||||
const oldIdx = this.tabContexts.findIndex(tc => tc.tabId === this.activeTabId);
|
||||
const newActiveTabId = this.tabContexts[oldIdx === this.tabContexts.length - 1 ? 0 : oldIdx + 1].tabId;
|
||||
|
||||
this.activateTab(newActiveTabId);
|
||||
}
|
||||
|
||||
activatePreviousTabListener() {
|
||||
const oldIdx = this.tabContexts.findIndex(tc => tc.tabId === this.activeTabId);
|
||||
const newActiveTabId = this.tabContexts[oldIdx === 0 ? this.tabContexts.length - 1 : oldIdx - 1].tabId;
|
||||
|
||||
this.activateTab(newActiveTabId);
|
||||
}
|
||||
|
||||
closeActiveTabListener() {
|
||||
this.removeTab(this.activeTabId);
|
||||
}
|
||||
|
||||
openNewTabListener() {
|
||||
this.openAndActivateEmptyTab();
|
||||
}
|
||||
|
||||
removeAllTabsListener() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
removeAllTabsExceptForThis() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
async protectedSessionStartedListener() {
|
||||
|
||||
Reference in New Issue
Block a user