mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-08-18 08:13:40 +08:00
client-ts: Port services/app/app_context
This commit is contained in:
parent
cd5ea28e14
commit
b7754bcea0
@ -14,8 +14,32 @@ import MainTreeExecutors from "./main_tree_executors.js";
|
|||||||
import toast from "../services/toast.js";
|
import toast from "../services/toast.js";
|
||||||
import ShortcutComponent from "./shortcut_component.js";
|
import ShortcutComponent from "./shortcut_component.js";
|
||||||
|
|
||||||
|
interface Layout {
|
||||||
|
getRootWidget: (appContext: AppContext) => RootWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RootWidget extends Component {
|
||||||
|
render: () => JQuery<HTMLElement>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BeforeUploadListener extends Component {
|
||||||
|
beforeUnloadEvent(): boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TriggerData {
|
||||||
|
noteIds?: string[];
|
||||||
|
callback?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
class AppContext extends Component {
|
class AppContext extends Component {
|
||||||
constructor(isMainWindow) {
|
|
||||||
|
isMainWindow: boolean;
|
||||||
|
components: Component[];
|
||||||
|
beforeUnloadListeners: WeakRef<BeforeUploadListener>[];
|
||||||
|
tabManager!: TabManager;
|
||||||
|
layout?: Layout;
|
||||||
|
|
||||||
|
constructor(isMainWindow: boolean) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.isMainWindow = isMainWindow;
|
this.isMainWindow = isMainWindow;
|
||||||
@ -24,7 +48,7 @@ class AppContext extends Component {
|
|||||||
this.beforeUnloadListeners = [];
|
this.beforeUnloadListeners = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
setLayout(layout) {
|
setLayout(layout: Layout) {
|
||||||
this.layout = layout;
|
this.layout = layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,6 +92,10 @@ class AppContext extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderWidgets() {
|
renderWidgets() {
|
||||||
|
if (!this.layout) {
|
||||||
|
throw new Error("Missing layout.");
|
||||||
|
}
|
||||||
|
|
||||||
const rootWidget = this.layout.getRootWidget(this);
|
const rootWidget = this.layout.getRootWidget(this);
|
||||||
const $renderedWidget = rootWidget.render();
|
const $renderedWidget = rootWidget.render();
|
||||||
|
|
||||||
@ -92,15 +120,13 @@ class AppContext extends Component {
|
|||||||
this.triggerEvent('initialRenderComplete');
|
this.triggerEvent('initialRenderComplete');
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {Promise<void>} */
|
triggerEvent(name: string, data: TriggerData = {}) {
|
||||||
triggerEvent(name, data = {}) {
|
|
||||||
return this.handleEvent(name, data);
|
return this.handleEvent(name, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {Promise<*>} */
|
triggerCommand(name: string, data: TriggerData = {}) {
|
||||||
triggerCommand(name, data = {}) {
|
|
||||||
for (const executor of this.components) {
|
for (const executor of this.components) {
|
||||||
const fun = executor[`${name}Command`];
|
const fun = (executor as any)[`${name}Command`];
|
||||||
|
|
||||||
if (fun) {
|
if (fun) {
|
||||||
return executor.callMethod(fun, data);
|
return executor.callMethod(fun, data);
|
||||||
@ -114,17 +140,17 @@ class AppContext extends Component {
|
|||||||
return this.triggerEvent(name, data);
|
return this.triggerEvent(name, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
getComponentByEl(el) {
|
getComponentByEl(el: HTMLElement) {
|
||||||
return $(el).closest(".component").prop('component');
|
return $(el).closest(".component").prop('component');
|
||||||
}
|
}
|
||||||
|
|
||||||
addBeforeUnloadListener(obj) {
|
addBeforeUnloadListener(obj: BeforeUploadListener) {
|
||||||
if (typeof WeakRef !== "function") {
|
if (typeof WeakRef !== "function") {
|
||||||
// older browsers don't support WeakRef
|
// older browsers don't support WeakRef
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.beforeUnloadListeners.push(new WeakRef(obj));
|
this.beforeUnloadListeners.push(new WeakRef<BeforeUploadListener>(obj));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -12,10 +12,10 @@ import utils from '../services/utils.js';
|
|||||||
* event / command is executed in all components - by simply awaiting the `triggerEvent()`.
|
* event / command is executed in all components - by simply awaiting the `triggerEvent()`.
|
||||||
*/
|
*/
|
||||||
export default class Component {
|
export default class Component {
|
||||||
private componentId: string;
|
componentId: string;
|
||||||
private children: Component[];
|
children: Component[];
|
||||||
private initialized: Promise<void> | null;
|
initialized: Promise<void> | null;
|
||||||
private parent?: Component;
|
parent?: Component;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.componentId = `${this.sanitizedClassName}-${utils.randomString(8)}`;
|
this.componentId = `${this.sanitizedClassName}-${utils.randomString(8)}`;
|
||||||
@ -64,7 +64,7 @@ export default class Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
triggerEvent(name: string, data = {}): Promise<unknown> | undefined {
|
triggerEvent(name: string, data = {}): Promise<unknown> | undefined | null {
|
||||||
return this.parent?.triggerEvent(name, data);
|
return this.parent?.triggerEvent(name, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ export default class Component {
|
|||||||
return promises.length > 0 ? Promise.all(promises) : null;
|
return promises.length > 0 ? Promise.all(promises) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
triggerCommand(name: string, data = {}): Promise<unknown> | undefined {
|
triggerCommand(name: string, data = {}): Promise<unknown> | undefined | null {
|
||||||
const fun = (this as any)[`${name}Command`];
|
const fun = (this as any)[`${name}Command`];
|
||||||
|
|
||||||
if (fun) {
|
if (fun) {
|
||||||
|
@ -31,7 +31,7 @@ interface SearchNoteResponse {
|
|||||||
* Backend has a similar cache called Becca
|
* Backend has a similar cache called Becca
|
||||||
*/
|
*/
|
||||||
class FrocaImpl implements Froca {
|
class FrocaImpl implements Froca {
|
||||||
private initializedPromise: Promise<void>;
|
initializedPromise: Promise<void>;
|
||||||
|
|
||||||
notes!: Record<string, FNote>;
|
notes!: Record<string, FNote>;
|
||||||
branches!: Record<string, FBranch>;
|
branches!: Record<string, FBranch>;
|
||||||
|
@ -100,10 +100,10 @@ function isCtrlKey(evt: KeyboardEvent) {
|
|||||||
|| (isMac() && evt.metaKey);
|
|| (isMac() && evt.metaKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
function assertArguments() {
|
function assertArguments(...args: string[]) {
|
||||||
for (const i in arguments) {
|
for (const i in args) {
|
||||||
if (!arguments[i]) {
|
if (!args[i]) {
|
||||||
console.trace(`Argument idx#${i} should not be falsy: ${arguments[i]}`);
|
console.trace(`Argument idx#${i} should not be falsy: ${args[i]}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
1
src/public/app/types.d.ts
vendored
1
src/public/app/types.d.ts
vendored
@ -26,6 +26,7 @@ interface CustomGlobals {
|
|||||||
baseApiUrl: string;
|
baseApiUrl: string;
|
||||||
isProtectedSessionAvailable: boolean;
|
isProtectedSessionAvailable: boolean;
|
||||||
isDev: boolean;
|
isDev: boolean;
|
||||||
|
isMainWindow: boolean;
|
||||||
maxEntityChangeIdAtLoad: number;
|
maxEntityChangeIdAtLoad: number;
|
||||||
maxEntityChangeSyncIdAtLoad: number;
|
maxEntityChangeSyncIdAtLoad: number;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user