import React from "react"; import { observable, computed, action, runInAction, autorun, makeObservable, IReactionDisposer } from "mobx"; import type { InstrumentAppStore } from "instrument/window/app-store"; import type * as ScriptsModule from "instrument/window/scripts"; import type * as ShortcutsModule from "instrument/window/shortcuts"; import type * as TerminalModule from "instrument/window/terminal/terminal"; import type * as DeletedHistoryItemsModule from "instrument/window/history/deleted-history-items-view"; import { HistoryViewComponent, showSessionsList } from "instrument/window/history/history-view"; import type * as ListsModule from "instrument/window/lists/lists"; import type { INavigationItem } from "instrument/window/navigation"; import type * as Bb3Module from "instrument/bb3"; import type * as DashboardModule from "instrument/window/dashboard"; //////////////////////////////////////////////////////////////////////////////// export class NavigationStore { terminalNavigationItem: INavigationItem; deletedHistoryItemsNavigationItem: INavigationItem; scriptsNavigationItem: INavigationItem; shortcutsAndGroupsNavigationItem: INavigationItem; listsNavigationItem: INavigationItem; private _mainNavigationSelectedItem: INavigationItem; mainHistoryView: HistoryViewComponent | undefined; autorunDispose: IReactionDisposer | undefined; constructor(public appStore: InstrumentAppStore) { makeObservable< NavigationStore, | "_mainNavigationSelectedItem" | "_selectedListId" | "_selectedScriptId" >(this, { _mainNavigationSelectedItem: observable.ref, startPageNavigationItem: computed({ keepAlive: true }), navigationItems: computed, mainNavigationSelectedItem: computed, navigateToHistory: action.bound, navigateToDeletedHistoryItems: action.bound, navigateToSessionsList: action.bound, navigateToScripts: action.bound, _selectedListId: observable, _selectedScriptId: observable, dashboardNavigationItems: computed }); this.terminalNavigationItem = { id: "terminal", icon: "material:navigate_next", title: "Terminal", renderContent: () => { const { render } = require("instrument/window/terminal/terminal") as typeof TerminalModule; return appStore.instrument ? render(this.appStore) :
; }, renderToolbarButtons: () => { const { renderToolbarButtons } = require("instrument/window/terminal/terminal") as typeof TerminalModule; return appStore.instrument ? ( renderToolbarButtons(this.appStore) ) : (
); } }; this.deletedHistoryItemsNavigationItem = { id: "deletedHistoryItems", position: "hidden", icon: "", title: "", renderContent: () => { const { DeletedHistoryItemsView } = require("instrument/window/history/deleted-history-items-view") as typeof DeletedHistoryItemsModule; return ( ); }, renderToolbarButtons: () => { const { DeletedHistoryItemsTools } = require("instrument/window/history/deleted-history-items-view") as typeof DeletedHistoryItemsModule; return ; } }; this.scriptsNavigationItem = { id: "scripts", icon: "material:slideshow", title: "Scripts", renderContent: () => { const { render } = require("instrument/window/scripts") as typeof ScriptsModule; return render(this.appStore); }, renderToolbarButtons: () => { const { toolbarButtonsRender } = require("instrument/window/scripts") as typeof ScriptsModule; return toolbarButtonsRender(this.appStore); } }; this.shortcutsAndGroupsNavigationItem = { id: "shortcutsAndGroups", icon: "material:playlist_play", title: "Shortcuts", renderContent: () => { const { render } = require("instrument/window/shortcuts") as typeof ShortcutsModule; return render(this.appStore); }, renderToolbarButtons: () => { const { toolbarButtonsRender } = require("instrument/window/shortcuts") as typeof ShortcutsModule; return toolbarButtonsRender(this.appStore); } }; this.listsNavigationItem = { id: "lists", icon: "material:timeline", title: "Lists", renderContent: () => { const { render } = require("instrument/window/lists/lists") as typeof ListsModule; return appStore.instrument ? render(this.appStore) :
; }, renderToolbarButtons: () => { const { toolbarButtonsRender } = require("instrument/window/lists/lists") as typeof ListsModule; return toolbarButtonsRender(this.appStore); } }; this.autorunDispose = autorun(() => { if ( this.mainNavigationSelectedItem === this.deletedHistoryItemsNavigationItem && this.appStore.deletedItemsHistory.deletedCount === 0 ) { this.navigateToHistory(); } }); } get startPageNavigationItem() { if (this.appStore.instrument.isBB3) { return { id: "start-page", icon: "material:dashboard", title: "Start Page", renderContent: () => { const { render } = require("instrument/bb3") as typeof Bb3Module; return render(this.appStore); }, renderToolbarButtons: () => { const { toolbarButtonsRender } = require("instrument/bb3") as typeof Bb3Module; return toolbarButtonsRender(this.appStore); } }; } return undefined; } get dashboardNavigationItems() { const dashboards = this.appStore.instrument.extension?.properties?.dashboards; if (!dashboards) { return []; } return dashboards.map((dashboard, i) => ({ id: "dashboard-" + i, icon: dashboard.icon || "material:dashboard", title: dashboard.title, renderContent: () => { const { Dashboard } = require("instrument/window/dashboard") as typeof DashboardModule; return ( ); }, renderToolbarButtons: () => { return
; } })); } get navigationItems() { let navigationItems: INavigationItem[] = []; if (this.startPageNavigationItem) { navigationItems.push(this.startPageNavigationItem); } navigationItems.push(...this.dashboardNavigationItems); navigationItems.push(this.terminalNavigationItem); navigationItems.push(this.deletedHistoryItemsNavigationItem); navigationItems.push(this.scriptsNavigationItem); navigationItems.push(this.shortcutsAndGroupsNavigationItem); if ( this.appStore.instrument && this.appStore.instrument.listsProperty ) { navigationItems.push(this.listsNavigationItem); } return navigationItems; } get mainNavigationSelectedItem() { if ( this._mainNavigationSelectedItem && this.navigationItems.indexOf(this._mainNavigationSelectedItem) != -1 ) { return this._mainNavigationSelectedItem; } if (this.startPageNavigationItem) { return this.startPageNavigationItem; } return this.terminalNavigationItem; } async changeMainNavigationSelectedItem(value: INavigationItem) { if (await this.appStore.undoManager.confirmSave()) { runInAction(() => { this._mainNavigationSelectedItem = value; }); return true; } else { return false; } } navigateToHistory() { this.changeMainNavigationSelectedItem(this.terminalNavigationItem); } navigateToDeletedHistoryItems() { this.changeMainNavigationSelectedItem( this.deletedHistoryItemsNavigationItem ); } async navigateToSessionsList() { if ( await this.changeMainNavigationSelectedItem( this.terminalNavigationItem ) ) { showSessionsList(this); } } navigateToScripts() { this.changeMainNavigationSelectedItem(this.scriptsNavigationItem); } // private _selectedListId: string | undefined; get selectedListId() { return this._selectedListId; } async changeSelectedListId(value: string | undefined) { if (!(await this.appStore.undoManager.confirmSave())) { return; } runInAction(() => { if (this._mainNavigationSelectedItem !== this.listsNavigationItem) { // First switch to lists section ... this._selectedListId = undefined; this._mainNavigationSelectedItem = this.listsNavigationItem; window.requestAnimationFrame( action(() => { // ... and than select the list. // This way list chart view will be automatically in focus, // so keyboard shortcuts will work immediatelly (no need to // manually click on chart view). this._selectedListId = value; }) ); } else { this._selectedListId = value; } }); } // private _selectedScriptId: string | undefined; get selectedScriptId() { return this._selectedScriptId; } async changeSelectedScriptId(value: string | undefined) { if (!(await this.appStore.undoManager.confirmSave())) { return; } runInAction(() => { this._mainNavigationSelectedItem = this.scriptsNavigationItem; this._selectedScriptId = value; }); } onTerminate() { if (this.autorunDispose) { this.autorunDispose(); this.autorunDispose = undefined; } this.mainHistoryView = undefined; // WORKAROUND: for some reason garbage collector doesn't collect this object unless we delete all the properties here for (const propertyName in this) { try { delete this[propertyName]; } catch (err) {} } } }