mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-04 05:28:59 +01:00 
			
		
		
		
	refactor(react): use beta approach for handling events everywhere
This commit is contained in:
		
							parent
							
								
									a507991808
								
							
						
					
					
						commit
						f2db7baeba
					
				@ -1,6 +1,8 @@
 | 
				
			|||||||
import utils from "../services/utils.js";
 | 
					import utils from "../services/utils.js";
 | 
				
			||||||
import type { CommandMappings, CommandNames, EventData, EventNames } from "./app_context.js";
 | 
					import type { CommandMappings, CommandNames, EventData, EventNames } from "./app_context.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type EventHandler = ((data: any) => void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Abstract class for all components in the Trilium's frontend.
 | 
					 * Abstract class for all components in the Trilium's frontend.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@ -19,6 +21,7 @@ export class TypedComponent<ChildT extends TypedComponent<ChildT>> {
 | 
				
			|||||||
    initialized: Promise<void> | null;
 | 
					    initialized: Promise<void> | null;
 | 
				
			||||||
    parent?: TypedComponent<any>;
 | 
					    parent?: TypedComponent<any>;
 | 
				
			||||||
    _position!: number;
 | 
					    _position!: number;
 | 
				
			||||||
 | 
					    private listeners: Record<string, EventHandler[]> | null = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor() {
 | 
					    constructor() {
 | 
				
			||||||
        this.componentId = `${this.sanitizedClassName}-${utils.randomString(8)}`;
 | 
					        this.componentId = `${this.sanitizedClassName}-${utils.randomString(8)}`;
 | 
				
			||||||
@ -76,6 +79,14 @@ export class TypedComponent<ChildT extends TypedComponent<ChildT>> {
 | 
				
			|||||||
    handleEventInChildren<T extends EventNames>(name: T, data: EventData<T>): Promise<unknown[] | unknown> | null {
 | 
					    handleEventInChildren<T extends EventNames>(name: T, data: EventData<T>): Promise<unknown[] | unknown> | null {
 | 
				
			||||||
        const promises: Promise<unknown>[] = [];
 | 
					        const promises: Promise<unknown>[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Handle React children.
 | 
				
			||||||
 | 
					        if (this.listeners?.[name]) {
 | 
				
			||||||
 | 
					            for (const listener of this.listeners[name]) {
 | 
				
			||||||
 | 
					                listener(data);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Handle legacy children.
 | 
				
			||||||
        for (const child of this.children) {
 | 
					        for (const child of this.children) {
 | 
				
			||||||
            const ret = child.handleEvent(name, data) as Promise<void>;
 | 
					            const ret = child.handleEvent(name, data) as Promise<void>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -120,6 +131,35 @@ export class TypedComponent<ChildT extends TypedComponent<ChildT>> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return promise;
 | 
					        return promise;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    registerHandler<T extends EventNames>(name: T, handler: EventHandler) {
 | 
				
			||||||
 | 
					        if (!this.listeners) {
 | 
				
			||||||
 | 
					            this.listeners = {};
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!this.listeners[name]) {
 | 
				
			||||||
 | 
					            this.listeners[name] = [];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (this.listeners[name].includes(handler)) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.listeners[name].push(handler);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    removeHandler<T extends EventNames>(name: T, handler: EventHandler) {
 | 
				
			||||||
 | 
					        if (!this.listeners?.[name]?.includes(handler)) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.listeners[name] = this.listeners[name]
 | 
				
			||||||
 | 
					            .filter(listener => listener !== handler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!this.listeners[name].length) {
 | 
				
			||||||
 | 
					            delete this.listeners[name];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class Component extends TypedComponent<Component> {}
 | 
					export default class Component extends TypedComponent<Component> {}
 | 
				
			||||||
 | 
				
			|||||||
@ -278,12 +278,9 @@ export function wrapReactWidgets<T extends TypedComponent<any>>(components: (T |
 | 
				
			|||||||
    return wrappedResult;
 | 
					    return wrappedResult;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type EventHandler = ((data: any) => void);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export class ReactWrappedWidget extends BasicWidget {
 | 
					export class ReactWrappedWidget extends BasicWidget {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private el: VNode;
 | 
					    private el: VNode;
 | 
				
			||||||
    private listeners: Record<string, EventHandler[]> = {};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(el: VNode) {
 | 
					    constructor(el: VNode) {
 | 
				
			||||||
        super();
 | 
					        super();
 | 
				
			||||||
@ -294,41 +291,4 @@ export class ReactWrappedWidget extends BasicWidget {
 | 
				
			|||||||
        this.$widget = renderReactWidget(this, this.el);
 | 
					        this.$widget = renderReactWidget(this, this.el);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    handleEvent<T extends EventNames>(name: T, data: EventData<T>): Promise<unknown[] | unknown> | null | undefined {
 | 
					 | 
				
			||||||
        if (!this.listeners[name]) {
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (const listener of this.listeners[name]) {
 | 
					 | 
				
			||||||
            listener(data);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        super.handleEvent(name, data);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    registerHandler<T extends EventNames>(name: T, handler: EventHandler) {
 | 
					 | 
				
			||||||
        if (!this.listeners[name]) {
 | 
					 | 
				
			||||||
            this.listeners[name] = [];
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (this.listeners[name].includes(handler)) {
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.listeners[name].push(handler);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    removeHandler<T extends EventNames>(name: T, handler: EventHandler) {
 | 
					 | 
				
			||||||
        if (!this.listeners[name]?.includes(handler)) {
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.listeners[name] = this.listeners[name]
 | 
					 | 
				
			||||||
            .filter(listener => listener !== handler);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!this.listeners[name].length) {
 | 
					 | 
				
			||||||
            delete this.listeners[name];
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -7,14 +7,14 @@ import openService from "../../services/open.js";
 | 
				
			|||||||
import { useState } from "preact/hooks";
 | 
					import { useState } from "preact/hooks";
 | 
				
			||||||
import type { CSSProperties } from "preact/compat";
 | 
					import type { CSSProperties } from "preact/compat";
 | 
				
			||||||
import type { AppInfo } from "@triliumnext/commons";
 | 
					import type { AppInfo } from "@triliumnext/commons";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks.jsx";
 | 
					import { useTriliumEvent } from "../react/hooks.jsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function AboutDialog() {
 | 
					export default function AboutDialog() {
 | 
				
			||||||
    let [appInfo, setAppInfo] = useState<AppInfo | null>(null);
 | 
					    let [appInfo, setAppInfo] = useState<AppInfo | null>(null);
 | 
				
			||||||
    let [shown, setShown] = useState(false);
 | 
					    let [shown, setShown] = useState(false);
 | 
				
			||||||
    const forceWordBreak: CSSProperties = { wordBreak: "break-all" };
 | 
					    const forceWordBreak: CSSProperties = { wordBreak: "break-all" };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useTriliumEventBeta("openAboutDialog", () => setShown(true));
 | 
					    useTriliumEvent("openAboutDialog", () => setShown(true));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <Modal className="about-dialog"
 | 
					        <Modal className="about-dialog"
 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,7 @@ import { default as TextTypeWidget } from "../type_widgets/editable_text.js";
 | 
				
			|||||||
import { logError } from "../../services/ws";
 | 
					import { logError } from "../../services/ws";
 | 
				
			||||||
import FormGroup from "../react/FormGroup.js";
 | 
					import FormGroup from "../react/FormGroup.js";
 | 
				
			||||||
import { refToJQuerySelector } from "../react/react_utils";
 | 
					import { refToJQuerySelector } from "../react/react_utils";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks";
 | 
					import { useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type LinkType = "reference-link" | "external-link" | "hyper-link";
 | 
					type LinkType = "reference-link" | "external-link" | "hyper-link";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -24,7 +24,7 @@ export default function AddLinkDialog() {
 | 
				
			|||||||
    const [ suggestion, setSuggestion ] = useState<Suggestion | null>(null);
 | 
					    const [ suggestion, setSuggestion ] = useState<Suggestion | null>(null);
 | 
				
			||||||
    const [ shown, setShown ] = useState(false);
 | 
					    const [ shown, setShown ] = useState(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useTriliumEventBeta("showAddLinkDialog", ( { textTypeWidget, text }) => {
 | 
					    useTriliumEvent("showAddLinkDialog", ( { textTypeWidget, text }) => {
 | 
				
			||||||
        setTextTypeWidget(textTypeWidget);
 | 
					        setTextTypeWidget(textTypeWidget);
 | 
				
			||||||
        initialText.current = text;
 | 
					        initialText.current = text;
 | 
				
			||||||
        setShown(true);
 | 
					        setShown(true);
 | 
				
			||||||
 | 
				
			|||||||
@ -8,7 +8,7 @@ import froca from "../../services/froca.js";
 | 
				
			|||||||
import tree from "../../services/tree.js";
 | 
					import tree from "../../services/tree.js";
 | 
				
			||||||
import Button from "../react/Button.jsx";
 | 
					import Button from "../react/Button.jsx";
 | 
				
			||||||
import FormGroup from "../react/FormGroup.js";
 | 
					import FormGroup from "../react/FormGroup.js";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks.jsx";
 | 
					import { useTriliumEvent } from "../react/hooks.jsx";
 | 
				
			||||||
import FBranch from "../../entities/fbranch.js";
 | 
					import FBranch from "../../entities/fbranch.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function BranchPrefixDialog() {
 | 
					export default function BranchPrefixDialog() {
 | 
				
			||||||
@ -17,7 +17,7 @@ export default function BranchPrefixDialog() {
 | 
				
			|||||||
    const [ prefix, setPrefix ] = useState(branch?.prefix ?? "");
 | 
					    const [ prefix, setPrefix ] = useState(branch?.prefix ?? "");
 | 
				
			||||||
    const branchInput = useRef<HTMLInputElement>(null);
 | 
					    const branchInput = useRef<HTMLInputElement>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useTriliumEventBeta("editBranchPrefix", async () => {
 | 
					    useTriliumEvent("editBranchPrefix", async () => {
 | 
				
			||||||
        const notePath = appContext.tabManager.getActiveContextNotePath();
 | 
					        const notePath = appContext.tabManager.getActiveContextNotePath();
 | 
				
			||||||
        if (!notePath) {
 | 
					        if (!notePath) {
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@ import toast from "../../services/toast";
 | 
				
			|||||||
import RenameNoteBulkAction from "../bulk_actions/note/rename_note";
 | 
					import RenameNoteBulkAction from "../bulk_actions/note/rename_note";
 | 
				
			||||||
import FNote from "../../entities/fnote";
 | 
					import FNote from "../../entities/fnote";
 | 
				
			||||||
import froca from "../../services/froca";
 | 
					import froca from "../../services/froca";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks";
 | 
					import { useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function BulkActionsDialog() {
 | 
					export default function BulkActionsDialog() {
 | 
				
			||||||
    const [ selectedOrActiveNoteIds, setSelectedOrActiveNoteIds ] = useState<string[]>();
 | 
					    const [ selectedOrActiveNoteIds, setSelectedOrActiveNoteIds ] = useState<string[]>();
 | 
				
			||||||
@ -22,7 +22,7 @@ export default function BulkActionsDialog() {
 | 
				
			|||||||
    const [ existingActions, setExistingActions ] = useState<RenameNoteBulkAction[]>([]);
 | 
					    const [ existingActions, setExistingActions ] = useState<RenameNoteBulkAction[]>([]);
 | 
				
			||||||
    const [ shown, setShown ] = useState(false);
 | 
					    const [ shown, setShown ] = useState(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useTriliumEventBeta("openBulkActionsDialog", async ({ selectedOrActiveNoteIds }) => {
 | 
					    useTriliumEvent("openBulkActionsDialog", async ({ selectedOrActiveNoteIds }) => {
 | 
				
			||||||
        setSelectedOrActiveNoteIds(selectedOrActiveNoteIds);
 | 
					        setSelectedOrActiveNoteIds(selectedOrActiveNoteIds);
 | 
				
			||||||
        setBulkActionNote(await froca.getNote("_bulkAction"));
 | 
					        setBulkActionNote(await froca.getNote("_bulkAction"));
 | 
				
			||||||
        setShown(true);
 | 
					        setShown(true);
 | 
				
			||||||
@ -46,7 +46,7 @@ export default function BulkActionsDialog() {
 | 
				
			|||||||
        refreshExistingActions();
 | 
					        refreshExistingActions();
 | 
				
			||||||
    }, [refreshExistingActions]);
 | 
					    }, [refreshExistingActions]);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    useTriliumEventBeta("entitiesReloaded", ({ loadResults }) => {
 | 
					    useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
 | 
				
			||||||
        if (loadResults.getAttributeRows().find((row) =>
 | 
					        if (loadResults.getAttributeRows().find((row) =>
 | 
				
			||||||
            row.type === "label" && row.name === "action" && row.noteId === "_bulkAction")) {
 | 
					            row.type === "label" && row.name === "action" && row.noteId === "_bulkAction")) {
 | 
				
			||||||
                refreshExistingActions();
 | 
					                refreshExistingActions();
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@ import tree from "../../services/tree";
 | 
				
			|||||||
import branches from "../../services/branches";
 | 
					import branches from "../../services/branches";
 | 
				
			||||||
import toast from "../../services/toast";
 | 
					import toast from "../../services/toast";
 | 
				
			||||||
import NoteList from "../react/NoteList";
 | 
					import NoteList from "../react/NoteList";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks";
 | 
					import { useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function CloneToDialog() {
 | 
					export default function CloneToDialog() {
 | 
				
			||||||
    const [ clonedNoteIds, setClonedNoteIds ] = useState<string[]>();
 | 
					    const [ clonedNoteIds, setClonedNoteIds ] = useState<string[]>();
 | 
				
			||||||
@ -22,7 +22,7 @@ export default function CloneToDialog() {
 | 
				
			|||||||
    const [ shown, setShown ] = useState(false);
 | 
					    const [ shown, setShown ] = useState(false);
 | 
				
			||||||
    const autoCompleteRef = useRef<HTMLInputElement>(null);
 | 
					    const autoCompleteRef = useRef<HTMLInputElement>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useTriliumEventBeta("cloneNoteIdsTo", ({ noteIds }) => {
 | 
					    useTriliumEvent("cloneNoteIdsTo", ({ noteIds }) => {
 | 
				
			||||||
        if (!noteIds || noteIds.length === 0) {
 | 
					        if (!noteIds || noteIds.length === 0) {
 | 
				
			||||||
            noteIds = [appContext.tabManager.getActiveContextNoteId() ?? ""];
 | 
					            noteIds = [appContext.tabManager.getActiveContextNoteId() ?? ""];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@ import Button from "../react/Button";
 | 
				
			|||||||
import { t } from "../../services/i18n";
 | 
					import { t } from "../../services/i18n";
 | 
				
			||||||
import { useState } from "preact/hooks";
 | 
					import { useState } from "preact/hooks";
 | 
				
			||||||
import FormCheckbox from "../react/FormCheckbox";
 | 
					import FormCheckbox from "../react/FormCheckbox";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks";
 | 
					import { useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface ConfirmDialogProps {
 | 
					interface ConfirmDialogProps {
 | 
				
			||||||
    title?: string;
 | 
					    title?: string;
 | 
				
			||||||
@ -27,8 +27,8 @@ export default function ConfirmDialog() {
 | 
				
			|||||||
        setShown(true);
 | 
					        setShown(true);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useTriliumEventBeta("showConfirmDialog", ({ message, callback }) => showDialog(null, message, callback, false));
 | 
					    useTriliumEvent("showConfirmDialog", ({ message, callback }) => showDialog(null, message, callback, false));
 | 
				
			||||||
    useTriliumEventBeta("showConfirmDeleteNoteBoxWithNoteDialog", ({ title, callback }) => showDialog(title, t("confirm.are_you_sure_remove_note", { title: title }), callback, true));
 | 
					    useTriliumEvent("showConfirmDeleteNoteBoxWithNoteDialog", ({ title, callback }) => showDialog(title, t("confirm.are_you_sure_remove_note", { title: title }), callback, true));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return ( 
 | 
					    return ( 
 | 
				
			||||||
        <Modal
 | 
					        <Modal
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,6 @@ import { useRef, useState, useEffect } from "preact/hooks";
 | 
				
			|||||||
import { t } from "../../services/i18n.js";
 | 
					import { t } from "../../services/i18n.js";
 | 
				
			||||||
import FormCheckbox from "../react/FormCheckbox.js";
 | 
					import FormCheckbox from "../react/FormCheckbox.js";
 | 
				
			||||||
import Modal from "../react/Modal.js";
 | 
					import Modal from "../react/Modal.js";
 | 
				
			||||||
import ReactBasicWidget from "../react/ReactBasicWidget.js";
 | 
					 | 
				
			||||||
import type { DeleteNotesPreview } from "@triliumnext/commons";
 | 
					import type { DeleteNotesPreview } from "@triliumnext/commons";
 | 
				
			||||||
import server from "../../services/server.js";
 | 
					import server from "../../services/server.js";
 | 
				
			||||||
import froca from "../../services/froca.js";
 | 
					import froca from "../../services/froca.js";
 | 
				
			||||||
@ -10,7 +9,7 @@ import FNote from "../../entities/fnote.js";
 | 
				
			|||||||
import link from "../../services/link.js";
 | 
					import link from "../../services/link.js";
 | 
				
			||||||
import Button from "../react/Button.jsx";
 | 
					import Button from "../react/Button.jsx";
 | 
				
			||||||
import Alert from "../react/Alert.jsx";
 | 
					import Alert from "../react/Alert.jsx";
 | 
				
			||||||
import useTriliumEvent, { useTriliumEventBeta } from "../react/hooks.jsx";
 | 
					import { useTriliumEvent } from "../react/hooks.jsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface ResolveOptions {
 | 
					export interface ResolveOptions {
 | 
				
			||||||
    proceed: boolean;
 | 
					    proceed: boolean;
 | 
				
			||||||
@ -39,7 +38,7 @@ export default function DeleteNotesDialog() {
 | 
				
			|||||||
    const [ shown, setShown ] = useState(false);
 | 
					    const [ shown, setShown ] = useState(false);
 | 
				
			||||||
    const okButtonRef = useRef<HTMLButtonElement>(null);
 | 
					    const okButtonRef = useRef<HTMLButtonElement>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useTriliumEventBeta("showDeleteNotesDialog", (opts) => {
 | 
					    useTriliumEvent("showDeleteNotesDialog", (opts) => {
 | 
				
			||||||
        setOpts(opts);
 | 
					        setOpts(opts);
 | 
				
			||||||
        setShown(true);
 | 
					        setShown(true);
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,7 @@ import toastService, { ToastOptions } from "../../services/toast";
 | 
				
			|||||||
import utils from "../../services/utils";
 | 
					import utils from "../../services/utils";
 | 
				
			||||||
import open from "../../services/open";
 | 
					import open from "../../services/open";
 | 
				
			||||||
import froca from "../../services/froca";
 | 
					import froca from "../../services/froca";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks";
 | 
					import { useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface ExportDialogProps {
 | 
					interface ExportDialogProps {
 | 
				
			||||||
    branchId?: string | null;
 | 
					    branchId?: string | null;
 | 
				
			||||||
@ -27,7 +27,7 @@ export default function ExportDialog() {
 | 
				
			|||||||
    const [ opmlVersion, setOpmlVersion ] = useState("2.0");
 | 
					    const [ opmlVersion, setOpmlVersion ] = useState("2.0");
 | 
				
			||||||
    const [ shown, setShown ] = useState(false);
 | 
					    const [ shown, setShown ] = useState(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useTriliumEventBeta("showExportDialog", async ({ notePath, defaultType }) => {
 | 
					    useTriliumEvent("showExportDialog", async ({ notePath, defaultType }) => {
 | 
				
			||||||
        const { noteId, parentNoteId } = tree.getNoteIdAndParentIdFromUrl(notePath);
 | 
					        const { noteId, parentNoteId } = tree.getNoteIdAndParentIdFromUrl(notePath);
 | 
				
			||||||
        if (!parentNoteId) {
 | 
					        if (!parentNoteId) {
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
 | 
				
			|||||||
@ -5,11 +5,11 @@ import { CommandNames } from "../../components/app_context.js";
 | 
				
			|||||||
import RawHtml from "../react/RawHtml.jsx";
 | 
					import RawHtml from "../react/RawHtml.jsx";
 | 
				
			||||||
import { useEffect, useState } from "preact/hooks";
 | 
					import { useEffect, useState } from "preact/hooks";
 | 
				
			||||||
import keyboard_actions from "../../services/keyboard_actions.js";
 | 
					import keyboard_actions from "../../services/keyboard_actions.js";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks.jsx";
 | 
					import { useTriliumEvent } from "../react/hooks.jsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function HelpDialog() {
 | 
					export default function HelpDialog() {
 | 
				
			||||||
    const [ shown, setShown ] = useState(false);
 | 
					    const [ shown, setShown ] = useState(false);
 | 
				
			||||||
    useTriliumEventBeta("showCheatsheet", () => setShown(true));
 | 
					    useTriliumEvent("showCheatsheet", () => setShown(true));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <Modal
 | 
					        <Modal
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@ import Modal from "../react/Modal";
 | 
				
			|||||||
import RawHtml from "../react/RawHtml";
 | 
					import RawHtml from "../react/RawHtml";
 | 
				
			||||||
import ReactBasicWidget from "../react/ReactBasicWidget";
 | 
					import ReactBasicWidget from "../react/ReactBasicWidget";
 | 
				
			||||||
import importService, { UploadFilesOptions } from "../../services/import";
 | 
					import importService, { UploadFilesOptions } from "../../services/import";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks";
 | 
					import { useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function ImportDialog() {
 | 
					export default function ImportDialog() {
 | 
				
			||||||
    const [ parentNoteId, setParentNoteId ] = useState<string>();
 | 
					    const [ parentNoteId, setParentNoteId ] = useState<string>();
 | 
				
			||||||
@ -23,7 +23,7 @@ export default function ImportDialog() {
 | 
				
			|||||||
    const [ replaceUnderscoresWithSpaces, setReplaceUnderscoresWithSpaces ] = useState(true);
 | 
					    const [ replaceUnderscoresWithSpaces, setReplaceUnderscoresWithSpaces ] = useState(true);
 | 
				
			||||||
    const [ shown, setShown ] = useState(false);
 | 
					    const [ shown, setShown ] = useState(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useTriliumEventBeta("showImportDialog", ({ noteId }) => {
 | 
					    useTriliumEvent("showImportDialog", ({ noteId }) => {
 | 
				
			||||||
        setParentNoteId(noteId);
 | 
					        setParentNoteId(noteId);
 | 
				
			||||||
        tree.getNoteTitle(noteId).then(setNoteTitle);
 | 
					        tree.getNoteTitle(noteId).then(setNoteTitle);
 | 
				
			||||||
        setShown(true);
 | 
					        setShown(true);
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@ import { Suggestion, triggerRecentNotes } from "../../services/note_autocomplete
 | 
				
			|||||||
import tree from "../../services/tree";
 | 
					import tree from "../../services/tree";
 | 
				
			||||||
import froca from "../../services/froca";
 | 
					import froca from "../../services/froca";
 | 
				
			||||||
import EditableTextTypeWidget from "../type_widgets/editable_text";
 | 
					import EditableTextTypeWidget from "../type_widgets/editable_text";
 | 
				
			||||||
import useTriliumEvent from "../react/hooks";
 | 
					import { useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function IncludeNoteDialog() {
 | 
					export default function IncludeNoteDialog() {
 | 
				
			||||||
    const [textTypeWidget, setTextTypeWidget] = useState<EditableTextTypeWidget>();
 | 
					    const [textTypeWidget, setTextTypeWidget] = useState<EditableTextTypeWidget>();
 | 
				
			||||||
 | 
				
			|||||||
@ -4,12 +4,12 @@ import utils from "../../services/utils.js";
 | 
				
			|||||||
import Button from "../react/Button.js";
 | 
					import Button from "../react/Button.js";
 | 
				
			||||||
import Modal from "../react/Modal.js";
 | 
					import Modal from "../react/Modal.js";
 | 
				
			||||||
import { useState } from "preact/hooks";
 | 
					import { useState } from "preact/hooks";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks.jsx";
 | 
					import { useTriliumEvent } from "../react/hooks.jsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function IncorrectCpuArchDialogComponent() {
 | 
					export default function IncorrectCpuArchDialogComponent() {
 | 
				
			||||||
    const [ shown, setShown ] = useState(false);
 | 
					    const [ shown, setShown ] = useState(false);
 | 
				
			||||||
    const downloadButtonRef = useRef<HTMLButtonElement>(null);
 | 
					    const downloadButtonRef = useRef<HTMLButtonElement>(null);
 | 
				
			||||||
    useTriliumEventBeta("showCpuArchWarning", () => setShown(true));
 | 
					    useTriliumEvent("showCpuArchWarning", () => setShown(true));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <Modal
 | 
					        <Modal
 | 
				
			||||||
 | 
				
			|||||||
@ -4,14 +4,14 @@ import { t } from "../../services/i18n";
 | 
				
			|||||||
import Button from "../react/Button";
 | 
					import Button from "../react/Button";
 | 
				
			||||||
import { useRef, useState } from "preact/hooks";
 | 
					import { useRef, useState } from "preact/hooks";
 | 
				
			||||||
import { RawHtmlBlock } from "../react/RawHtml";
 | 
					import { RawHtmlBlock } from "../react/RawHtml";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks";
 | 
					import { useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function InfoDialog() {
 | 
					export default function InfoDialog() {
 | 
				
			||||||
    const [ opts, setOpts ] = useState<EventData<"showInfoDialog">>();
 | 
					    const [ opts, setOpts ] = useState<EventData<"showInfoDialog">>();
 | 
				
			||||||
    const [ shown, setShown ] = useState(false);
 | 
					    const [ shown, setShown ] = useState(false);
 | 
				
			||||||
    const okButtonRef = useRef<HTMLButtonElement>(null);
 | 
					    const okButtonRef = useRef<HTMLButtonElement>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useTriliumEventBeta("showInfoDialog", (opts) => {
 | 
					    useTriliumEvent("showInfoDialog", (opts) => {
 | 
				
			||||||
        setOpts(opts);
 | 
					        setOpts(opts);
 | 
				
			||||||
        setShown(true);
 | 
					        setShown(true);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
				
			|||||||
@ -7,7 +7,7 @@ import note_autocomplete, { Suggestion } from "../../services/note_autocomplete"
 | 
				
			|||||||
import appContext from "../../components/app_context";
 | 
					import appContext from "../../components/app_context";
 | 
				
			||||||
import commandRegistry from "../../services/command_registry";
 | 
					import commandRegistry from "../../services/command_registry";
 | 
				
			||||||
import { refToJQuerySelector } from "../react/react_utils";
 | 
					import { refToJQuerySelector } from "../react/react_utils";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks";
 | 
					import { useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const KEEP_LAST_SEARCH_FOR_X_SECONDS = 120;
 | 
					const KEEP_LAST_SEARCH_FOR_X_SECONDS = 120;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -50,8 +50,8 @@ export default function JumpToNoteDialogComponent() {
 | 
				
			|||||||
        setLastOpenedTs(Date.now());
 | 
					        setLastOpenedTs(Date.now());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useTriliumEventBeta("jumpToNote", () => openDialog(false));
 | 
					    useTriliumEvent("jumpToNote", () => openDialog(false));
 | 
				
			||||||
    useTriliumEventBeta("commandPalette", () => openDialog(true));
 | 
					    useTriliumEvent("commandPalette", () => openDialog(true));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async function onItemSelected(suggestion?: Suggestion | null) {
 | 
					    async function onItemSelected(suggestion?: Suggestion | null) {
 | 
				
			||||||
        if (!suggestion) {
 | 
					        if (!suggestion) {
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,7 @@ import toast from "../../services/toast";
 | 
				
			|||||||
import utils from "../../services/utils";
 | 
					import utils from "../../services/utils";
 | 
				
			||||||
import Modal from "../react/Modal";
 | 
					import Modal from "../react/Modal";
 | 
				
			||||||
import Button from "../react/Button";
 | 
					import Button from "../react/Button";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks";
 | 
					import { useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface RenderMarkdownResponse {
 | 
					interface RenderMarkdownResponse {
 | 
				
			||||||
    htmlContent: string;
 | 
					    htmlContent: string;
 | 
				
			||||||
@ -32,8 +32,8 @@ export default function MarkdownImportDialog() {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }, []);
 | 
					    }, []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useTriliumEventBeta("importMarkdownInline", triggerImport);
 | 
					    useTriliumEvent("importMarkdownInline", triggerImport);
 | 
				
			||||||
    useTriliumEventBeta("pasteMarkdownIntoText", triggerImport);
 | 
					    useTriliumEvent("pasteMarkdownIntoText", triggerImport);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async function sendForm() {
 | 
					    async function sendForm() {
 | 
				
			||||||
        await convertMarkdownToHtml(text);
 | 
					        await convertMarkdownToHtml(text);
 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,7 @@ import tree from "../../services/tree";
 | 
				
			|||||||
import froca from "../../services/froca";
 | 
					import froca from "../../services/froca";
 | 
				
			||||||
import branches from "../../services/branches";
 | 
					import branches from "../../services/branches";
 | 
				
			||||||
import toast from "../../services/toast";
 | 
					import toast from "../../services/toast";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks";
 | 
					import { useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function MoveToDialog() {
 | 
					export default function MoveToDialog() {
 | 
				
			||||||
    const [ movedBranchIds, setMovedBranchIds ] = useState<string[]>();
 | 
					    const [ movedBranchIds, setMovedBranchIds ] = useState<string[]>();
 | 
				
			||||||
@ -19,7 +19,7 @@ export default function MoveToDialog() {
 | 
				
			|||||||
    const [ shown, setShown ] = useState(false);
 | 
					    const [ shown, setShown ] = useState(false);
 | 
				
			||||||
    const autoCompleteRef = useRef<HTMLInputElement>(null);
 | 
					    const autoCompleteRef = useRef<HTMLInputElement>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useTriliumEventBeta("moveBranchIdsTo", ({ branchIds }) => {
 | 
					    useTriliumEvent("moveBranchIdsTo", ({ branchIds }) => {
 | 
				
			||||||
        setMovedBranchIds(branchIds);
 | 
					        setMovedBranchIds(branchIds);
 | 
				
			||||||
        setShown(true);
 | 
					        setShown(true);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@ import { MenuCommandItem, MenuItem } from "../../menus/context_menu";
 | 
				
			|||||||
import { TreeCommandNames } from "../../menus/tree_context_menu";
 | 
					import { TreeCommandNames } from "../../menus/tree_context_menu";
 | 
				
			||||||
import { Suggestion } from "../../services/note_autocomplete";
 | 
					import { Suggestion } from "../../services/note_autocomplete";
 | 
				
			||||||
import Badge from "../react/Badge";
 | 
					import Badge from "../react/Badge";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks";
 | 
					import { useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface ChooseNoteTypeResponse {
 | 
					export interface ChooseNoteTypeResponse {
 | 
				
			||||||
    success: boolean;
 | 
					    success: boolean;
 | 
				
			||||||
@ -31,7 +31,7 @@ export default function NoteTypeChooserDialogComponent() {
 | 
				
			|||||||
    const [ parentNote, setParentNote ] = useState<Suggestion | null>(); 
 | 
					    const [ parentNote, setParentNote ] = useState<Suggestion | null>(); 
 | 
				
			||||||
    const [ noteTypes, setNoteTypes ] = useState<MenuItem<TreeCommandNames>[]>([]);    
 | 
					    const [ noteTypes, setNoteTypes ] = useState<MenuItem<TreeCommandNames>[]>([]);    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useTriliumEventBeta("chooseNoteType", ({ callback }) => {
 | 
					    useTriliumEvent("chooseNoteType", ({ callback }) => {
 | 
				
			||||||
        setCallback(() => callback);
 | 
					        setCallback(() => callback);
 | 
				
			||||||
        setShown(true);
 | 
					        setShown(true);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
				
			|||||||
@ -3,11 +3,11 @@ import { t } from "../../services/i18n";
 | 
				
			|||||||
import Button from "../react/Button";
 | 
					import Button from "../react/Button";
 | 
				
			||||||
import appContext from "../../components/app_context";
 | 
					import appContext from "../../components/app_context";
 | 
				
			||||||
import { useState } from "preact/hooks";
 | 
					import { useState } from "preact/hooks";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks";
 | 
					import { useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function PasswordNotSetDialog() {
 | 
					export default function PasswordNotSetDialog() {
 | 
				
			||||||
    const [ shown, setShown ] = useState(false);
 | 
					    const [ shown, setShown ] = useState(false);
 | 
				
			||||||
    useTriliumEventBeta("showPasswordNotSet", () => setShown(true));
 | 
					    useTriliumEvent("showPasswordNotSet", () => setShown(true));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <Modal
 | 
					        <Modal
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,7 @@ import Modal from "../react/Modal";
 | 
				
			|||||||
import FormTextBox from "../react/FormTextBox";
 | 
					import FormTextBox from "../react/FormTextBox";
 | 
				
			||||||
import FormGroup from "../react/FormGroup";
 | 
					import FormGroup from "../react/FormGroup";
 | 
				
			||||||
import { refToJQuerySelector } from "../react/react_utils";
 | 
					import { refToJQuerySelector } from "../react/react_utils";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks";
 | 
					import { useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// JQuery here is maintained for compatibility with existing code.
 | 
					// JQuery here is maintained for compatibility with existing code.
 | 
				
			||||||
interface ShownCallbackData {
 | 
					interface ShownCallbackData {
 | 
				
			||||||
@ -36,7 +36,7 @@ export default function PromptDialog() {
 | 
				
			|||||||
    const [ shown, setShown ] = useState(false);
 | 
					    const [ shown, setShown ] = useState(false);
 | 
				
			||||||
    const submitValue = useRef<string>(null);
 | 
					    const submitValue = useRef<string>(null);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    useTriliumEventBeta("showPromptDialog", (newOpts) => {
 | 
					    useTriliumEvent("showPromptDialog", (newOpts) => {
 | 
				
			||||||
        opts.current = newOpts;
 | 
					        opts.current = newOpts;
 | 
				
			||||||
        setValue(newOpts.defaultValue ?? "");
 | 
					        setValue(newOpts.defaultValue ?? "");
 | 
				
			||||||
        setShown(true);
 | 
					        setShown(true);
 | 
				
			||||||
 | 
				
			|||||||
@ -4,15 +4,15 @@ import Button from "../react/Button";
 | 
				
			|||||||
import FormTextBox from "../react/FormTextBox";
 | 
					import FormTextBox from "../react/FormTextBox";
 | 
				
			||||||
import Modal from "../react/Modal";
 | 
					import Modal from "../react/Modal";
 | 
				
			||||||
import protected_session from "../../services/protected_session";
 | 
					import protected_session from "../../services/protected_session";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks";
 | 
					import { useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function ProtectedSessionPasswordDialog() {
 | 
					export default function ProtectedSessionPasswordDialog() {
 | 
				
			||||||
    const [ shown, setShown ] = useState(false);
 | 
					    const [ shown, setShown ] = useState(false);
 | 
				
			||||||
    const [ password, setPassword ] = useState("");
 | 
					    const [ password, setPassword ] = useState("");
 | 
				
			||||||
    const inputRef = useRef<HTMLInputElement>(null);
 | 
					    const inputRef = useRef<HTMLInputElement>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useTriliumEventBeta("showProtectedSessionPasswordDialog", () => setShown(true));
 | 
					    useTriliumEvent("showProtectedSessionPasswordDialog", () => setShown(true));
 | 
				
			||||||
    useTriliumEventBeta("closeProtectedSessionPasswordDialog", () => setShown(false));
 | 
					    useTriliumEvent("closeProtectedSessionPasswordDialog", () => setShown(false));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <Modal
 | 
					        <Modal
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@ import { formatDateTime } from "../../utils/formatters";
 | 
				
			|||||||
import link from "../../services/link";
 | 
					import link from "../../services/link";
 | 
				
			||||||
import RawHtml from "../react/RawHtml";
 | 
					import RawHtml from "../react/RawHtml";
 | 
				
			||||||
import ws from "../../services/ws";
 | 
					import ws from "../../services/ws";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks";
 | 
					import { useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function RecentChangesDialog() {
 | 
					export default function RecentChangesDialog() {
 | 
				
			||||||
    const [ ancestorNoteId, setAncestorNoteId ] = useState<string>();
 | 
					    const [ ancestorNoteId, setAncestorNoteId ] = useState<string>();
 | 
				
			||||||
@ -21,7 +21,7 @@ export default function RecentChangesDialog() {
 | 
				
			|||||||
    const [ needsRefresh, setNeedsRefresh ] = useState(false);
 | 
					    const [ needsRefresh, setNeedsRefresh ] = useState(false);
 | 
				
			||||||
    const [ shown, setShown ] = useState(false);
 | 
					    const [ shown, setShown ] = useState(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useTriliumEventBeta("showRecentChanges", ({ ancestorNoteId }) => {
 | 
					    useTriliumEvent("showRecentChanges", ({ ancestorNoteId }) => {
 | 
				
			||||||
        setNeedsRefresh(true);
 | 
					        setNeedsRefresh(true);
 | 
				
			||||||
        setAncestorNoteId(ancestorNoteId ?? hoisted_note.getHoistedNoteId());
 | 
					        setAncestorNoteId(ancestorNoteId ?? hoisted_note.getHoistedNoteId());
 | 
				
			||||||
        setShown(true);
 | 
					        setShown(true);
 | 
				
			||||||
 | 
				
			|||||||
@ -8,7 +8,6 @@ import server from "../../services/server";
 | 
				
			|||||||
import toast from "../../services/toast";
 | 
					import toast from "../../services/toast";
 | 
				
			||||||
import Button from "../react/Button";
 | 
					import Button from "../react/Button";
 | 
				
			||||||
import Modal from "../react/Modal";
 | 
					import Modal from "../react/Modal";
 | 
				
			||||||
import ReactBasicWidget from "../react/ReactBasicWidget";
 | 
					 | 
				
			||||||
import FormList, { FormListItem } from "../react/FormList";
 | 
					import FormList, { FormListItem } from "../react/FormList";
 | 
				
			||||||
import utils from "../../services/utils";
 | 
					import utils from "../../services/utils";
 | 
				
			||||||
import { Dispatch, StateUpdater, useEffect, useRef, useState } from "preact/hooks";
 | 
					import { Dispatch, StateUpdater, useEffect, useRef, useState } from "preact/hooks";
 | 
				
			||||||
@ -18,7 +17,7 @@ import type { CSSProperties } from "preact/compat";
 | 
				
			|||||||
import open from "../../services/open";
 | 
					import open from "../../services/open";
 | 
				
			||||||
import ActionButton from "../react/ActionButton";
 | 
					import ActionButton from "../react/ActionButton";
 | 
				
			||||||
import options from "../../services/options";
 | 
					import options from "../../services/options";
 | 
				
			||||||
import useTriliumEvent from "../react/hooks";
 | 
					import { useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function RevisionsDialog() {
 | 
					export default function RevisionsDialog() {
 | 
				
			||||||
    const [ note, setNote ] = useState<FNote>();
 | 
					    const [ note, setNote ] = useState<FNote>();
 | 
				
			||||||
 | 
				
			|||||||
@ -7,7 +7,7 @@ import FormTextBox from "../react/FormTextBox";
 | 
				
			|||||||
import Modal from "../react/Modal";
 | 
					import Modal from "../react/Modal";
 | 
				
			||||||
import server from "../../services/server";
 | 
					import server from "../../services/server";
 | 
				
			||||||
import FormGroup from "../react/FormGroup";
 | 
					import FormGroup from "../react/FormGroup";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks";
 | 
					import { useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function SortChildNotesDialog() {
 | 
					export default function SortChildNotesDialog() {
 | 
				
			||||||
    const [ parentNoteId, setParentNoteId ] = useState<string>();
 | 
					    const [ parentNoteId, setParentNoteId ] = useState<string>();
 | 
				
			||||||
@ -18,7 +18,7 @@ export default function SortChildNotesDialog() {
 | 
				
			|||||||
    const [ sortLocale, setSortLocale ] = useState("");
 | 
					    const [ sortLocale, setSortLocale ] = useState("");
 | 
				
			||||||
    const [ shown, setShown ] = useState(false);
 | 
					    const [ shown, setShown ] = useState(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useTriliumEventBeta("sortChildNotes", ({ node }) => {
 | 
					    useTriliumEvent("sortChildNotes", ({ node }) => {
 | 
				
			||||||
        setParentNoteId(node.data.noteId);
 | 
					        setParentNoteId(node.data.noteId);
 | 
				
			||||||
        setShown(true);
 | 
					        setShown(true);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@ import ReactBasicWidget from "../react/ReactBasicWidget";
 | 
				
			|||||||
import options from "../../services/options";
 | 
					import options from "../../services/options";
 | 
				
			||||||
import importService from "../../services/import.js";
 | 
					import importService from "../../services/import.js";
 | 
				
			||||||
import tree from "../../services/tree";
 | 
					import tree from "../../services/tree";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks";
 | 
					import { useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function UploadAttachmentsDialog() {
 | 
					export default function UploadAttachmentsDialog() {
 | 
				
			||||||
    const [ parentNoteId, setParentNoteId ] = useState<string>();
 | 
					    const [ parentNoteId, setParentNoteId ] = useState<string>();
 | 
				
			||||||
@ -19,7 +19,7 @@ export default function UploadAttachmentsDialog() {
 | 
				
			|||||||
    const [ description, setDescription ] = useState<string | undefined>(undefined);
 | 
					    const [ description, setDescription ] = useState<string | undefined>(undefined);
 | 
				
			||||||
    const [ shown, setShown ] = useState(false);
 | 
					    const [ shown, setShown ] = useState(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useTriliumEventBeta("showUploadAttachmentsDialog", ({ noteId }) => {
 | 
					    useTriliumEvent("showUploadAttachmentsDialog", ({ noteId }) => {
 | 
				
			||||||
        setParentNoteId(noteId);
 | 
					        setParentNoteId(noteId);
 | 
				
			||||||
        setShown(true);
 | 
					        setShown(true);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import { useEffect, useRef, useState } from "preact/hooks";
 | 
					import { useEffect, useRef, useState } from "preact/hooks";
 | 
				
			||||||
import { t } from "../services/i18n";
 | 
					import { t } from "../services/i18n";
 | 
				
			||||||
import FormTextBox from "./react/FormTextBox";
 | 
					import FormTextBox from "./react/FormTextBox";
 | 
				
			||||||
import { useNoteContext, useNoteProperty, useSpacedUpdate, useTriliumEventBeta } from "./react/hooks";
 | 
					import { useNoteContext, useNoteProperty, useSpacedUpdate, useTriliumEvent } from "./react/hooks";
 | 
				
			||||||
import protected_session_holder from "../services/protected_session_holder";
 | 
					import protected_session_holder from "../services/protected_session_holder";
 | 
				
			||||||
import server from "../services/server";
 | 
					import server from "../services/server";
 | 
				
			||||||
import "./note_title.css";
 | 
					import "./note_title.css";
 | 
				
			||||||
@ -48,12 +48,12 @@ export default function NoteTitleWidget() {
 | 
				
			|||||||
    useEffect(() => {
 | 
					    useEffect(() => {
 | 
				
			||||||
        appContext.addBeforeUnloadListener(() => spacedUpdate.isAllSavedAndTriggerUpdate());        
 | 
					        appContext.addBeforeUnloadListener(() => spacedUpdate.isAllSavedAndTriggerUpdate());        
 | 
				
			||||||
    }, []);
 | 
					    }, []);
 | 
				
			||||||
    useTriliumEventBeta([ "beforeNoteSwitch", "beforeNoteContextRemove" ], () => spacedUpdate.updateNowIfNecessary());
 | 
					    useTriliumEvent([ "beforeNoteSwitch", "beforeNoteContextRemove" ], () => spacedUpdate.updateNowIfNecessary());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Manage focus.
 | 
					    // Manage focus.
 | 
				
			||||||
    const textBoxRef = useRef<HTMLInputElement>(null);
 | 
					    const textBoxRef = useRef<HTMLInputElement>(null);
 | 
				
			||||||
    const isNewNote = useRef<boolean>();
 | 
					    const isNewNote = useRef<boolean>();
 | 
				
			||||||
    useTriliumEventBeta([ "focusOnTitle", "focusAndSelectTitle" ], (e) => {
 | 
					    useTriliumEvent([ "focusOnTitle", "focusAndSelectTitle" ], (e) => {
 | 
				
			||||||
        if (noteContext?.isActive() && textBoxRef.current) {
 | 
					        if (noteContext?.isActive() && textBoxRef.current) {
 | 
				
			||||||
            textBoxRef.current.focus();
 | 
					            textBoxRef.current.focus();
 | 
				
			||||||
            isNewNote.current = ("isNewNote" in e ? e.isNewNote : false);
 | 
					            isNewNote.current = ("isNewNote" in e ? e.isNewNote : false);
 | 
				
			||||||
 | 
				
			|||||||
@ -5,95 +5,26 @@ import SpacedUpdate from "../../services/spaced_update";
 | 
				
			|||||||
import { OptionNames } from "@triliumnext/commons";
 | 
					import { OptionNames } from "@triliumnext/commons";
 | 
				
			||||||
import options, { type OptionValue } from "../../services/options";
 | 
					import options, { type OptionValue } from "../../services/options";
 | 
				
			||||||
import utils, { reloadFrontendApp } from "../../services/utils";
 | 
					import utils, { reloadFrontendApp } from "../../services/utils";
 | 
				
			||||||
import Component from "../../components/component";
 | 
					 | 
				
			||||||
import NoteContext from "../../components/note_context";
 | 
					import NoteContext from "../../components/note_context";
 | 
				
			||||||
import BasicWidget, { ReactWrappedWidget } from "../basic_widget";
 | 
					import BasicWidget, { ReactWrappedWidget } from "../basic_widget";
 | 
				
			||||||
import FNote from "../../entities/fnote";
 | 
					import FNote from "../../entities/fnote";
 | 
				
			||||||
import attributes from "../../services/attributes";
 | 
					import attributes from "../../services/attributes";
 | 
				
			||||||
import FBlob from "../../entities/fblob";
 | 
					import FBlob from "../../entities/fblob";
 | 
				
			||||||
import NoteContextAwareWidget from "../note_context_aware_widget";
 | 
					import NoteContextAwareWidget from "../note_context_aware_widget";
 | 
				
			||||||
import { Ref, RefObject, VNode } from "preact";
 | 
					import { RefObject, VNode } from "preact";
 | 
				
			||||||
import { Tooltip } from "bootstrap";
 | 
					import { Tooltip } from "bootstrap";
 | 
				
			||||||
import { CSSProperties } from "preact/compat";
 | 
					import { CSSProperties } from "preact/compat";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type TriliumEventHandler<T extends EventNames> = (data: EventData<T>) => void;
 | 
					type TriliumEventHandler<T extends EventNames> = (data: EventData<T>) => void;
 | 
				
			||||||
const registeredHandlers: Map<Component, Map<EventNames, TriliumEventHandler<any>[]>> = new Map();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					export function useTriliumEvent<T extends EventNames>(eventName: T | T[], handler: TriliumEventHandler<T>) {
 | 
				
			||||||
 * Allows a React component to react to Trilium events (e.g. `entitiesReloaded`). When the desired event is triggered, the handler is invoked with the event parameters.
 | 
					    const parentComponent = useContext(ParentComponent);
 | 
				
			||||||
 * 
 | 
					
 | 
				
			||||||
 * Under the hood, it works by altering the parent (Trilium) component of the React element to introduce the corresponding event.
 | 
					    if (!parentComponent) {
 | 
				
			||||||
 * 
 | 
					        console.error("React widget has no legacy parent component. Event handling will not work.", new Error().stack);
 | 
				
			||||||
 * @param eventName the name of the Trilium event to listen for.
 | 
					 | 
				
			||||||
 * @param handler the handler to be invoked when the event is triggered.
 | 
					 | 
				
			||||||
 * @param enabled determines whether the event should be listened to or not. Useful to conditionally limit the listener based on a state (e.g. a modal being displayed).
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
export default function useTriliumEvent<T extends EventNames>(eventName: T, handler: TriliumEventHandler<T>, enabled = true) {
 | 
					 | 
				
			||||||
    const parentWidget = useContext(ParentComponent);
 | 
					 | 
				
			||||||
    if (!parentWidget) {
 | 
					 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const handlerName = `${eventName}Event`;
 | 
					 | 
				
			||||||
    const customHandler  = useMemo(() => {
 | 
					 | 
				
			||||||
        return async (data: EventData<T>) => {
 | 
					 | 
				
			||||||
            // Inform the attached event listeners.
 | 
					 | 
				
			||||||
            const eventHandlers = registeredHandlers.get(parentWidget)?.get(eventName) ?? [];
 | 
					 | 
				
			||||||
            for (const eventHandler of eventHandlers) {
 | 
					 | 
				
			||||||
                eventHandler(data);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }, [ eventName, parentWidget ]);    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    useEffect(() => {
 | 
					 | 
				
			||||||
        // Attach to the list of handlers.
 | 
					 | 
				
			||||||
        let handlersByWidget = registeredHandlers.get(parentWidget);
 | 
					 | 
				
			||||||
        if (!handlersByWidget) {
 | 
					 | 
				
			||||||
            handlersByWidget = new Map();
 | 
					 | 
				
			||||||
            registeredHandlers.set(parentWidget, handlersByWidget);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let handlersByWidgetAndEventName = handlersByWidget.get(eventName);
 | 
					 | 
				
			||||||
        if (!handlersByWidgetAndEventName) {
 | 
					 | 
				
			||||||
            handlersByWidgetAndEventName = [];
 | 
					 | 
				
			||||||
            handlersByWidget.set(eventName, handlersByWidgetAndEventName);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!handlersByWidgetAndEventName.includes(handler)) {
 | 
					 | 
				
			||||||
            handlersByWidgetAndEventName.push(handler);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Apply the custom event handler.
 | 
					 | 
				
			||||||
        if (parentWidget[handlerName] && parentWidget[handlerName] !== customHandler) {
 | 
					 | 
				
			||||||
            console.warn(`Widget ${parentWidget.componentId} already had an event listener and it was replaced by the React one.`);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        parentWidget[handlerName] = customHandler;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
        return () => {
 | 
					 | 
				
			||||||
            const eventHandlers = registeredHandlers.get(parentWidget)?.get(eventName);
 | 
					 | 
				
			||||||
            if (!eventHandlers || !eventHandlers.includes(handler)) {
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
            // Remove the event handler from the array.            
 | 
					 | 
				
			||||||
            const newEventHandlers = eventHandlers.filter(e => e !== handler);            
 | 
					 | 
				
			||||||
            if (newEventHandlers.length) {
 | 
					 | 
				
			||||||
                registeredHandlers.get(parentWidget)?.set(eventName, newEventHandlers);        
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                registeredHandlers.get(parentWidget)?.delete(eventName);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (!registeredHandlers.get(parentWidget)?.size) {
 | 
					 | 
				
			||||||
                registeredHandlers.delete(parentWidget);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
    }, [ eventName, parentWidget, handler ]);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function useTriliumEventBeta<T extends EventNames>(eventName: T | T[], handler: TriliumEventHandler<T>) {
 | 
					 | 
				
			||||||
    const parentComponent = useContext(ParentComponent) as ReactWrappedWidget;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (Array.isArray(eventName)) {
 | 
					    if (Array.isArray(eventName)) {
 | 
				
			||||||
        for (const eventSingleName of eventName) {
 | 
					        for (const eventSingleName of eventName) {
 | 
				
			||||||
            parentComponent.registerHandler(eventSingleName, handler);
 | 
					            parentComponent.registerHandler(eventSingleName, handler);
 | 
				
			||||||
@ -185,7 +116,7 @@ export function useTriliumOptionBeta(name: OptionNames, needsRefresh?: boolean):
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }, [ name, needsRefresh ]);
 | 
					    }, [ name, needsRefresh ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useTriliumEventBeta("entitiesReloaded", useCallback(({ loadResults }) => {
 | 
					    useTriliumEvent("entitiesReloaded", useCallback(({ loadResults }) => {
 | 
				
			||||||
        if (loadResults.getOptionNames().includes(name)) {
 | 
					        if (loadResults.getOptionNames().includes(name)) {
 | 
				
			||||||
            const newValue = options.get(name);
 | 
					            const newValue = options.get(name);
 | 
				
			||||||
            setValue(newValue);
 | 
					            setValue(newValue);
 | 
				
			||||||
@ -283,20 +214,20 @@ export function useNoteContext() {
 | 
				
			|||||||
        setNote(noteContext?.note);
 | 
					        setNote(noteContext?.note);
 | 
				
			||||||
    }, [ notePath ]);
 | 
					    }, [ notePath ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useTriliumEventBeta("activeContextChanged", ({ noteContext }) => {
 | 
					    useTriliumEvent("activeContextChanged", ({ noteContext }) => {
 | 
				
			||||||
        setNoteContext(noteContext);
 | 
					        setNoteContext(noteContext);
 | 
				
			||||||
        setNotePath(noteContext.notePath);        
 | 
					        setNotePath(noteContext.notePath);        
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    useTriliumEventBeta("setNoteContext", ({ noteContext }) => {
 | 
					    useTriliumEvent("setNoteContext", ({ noteContext }) => {
 | 
				
			||||||
        setNoteContext(noteContext);
 | 
					        setNoteContext(noteContext);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    useTriliumEventBeta("noteSwitchedAndActivated", ({ noteContext }) => {
 | 
					    useTriliumEvent("noteSwitchedAndActivated", ({ noteContext }) => {
 | 
				
			||||||
        setNoteContext(noteContext);
 | 
					        setNoteContext(noteContext);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    useTriliumEventBeta("noteSwitched", ({ noteContext, notePath }) => {
 | 
					    useTriliumEvent("noteSwitched", ({ noteContext, notePath }) => {
 | 
				
			||||||
        setNotePath(notePath);
 | 
					        setNotePath(notePath);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    useTriliumEventBeta("frocaReloaded", () => {
 | 
					    useTriliumEvent("frocaReloaded", () => {
 | 
				
			||||||
        setNote(noteContext?.note);
 | 
					        setNote(noteContext?.note);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -336,7 +267,7 @@ export function useNoteProperty<T extends keyof FNote>(note: FNote | null | unde
 | 
				
			|||||||
    useEffect(() => refreshValue(), [ note, note[property] ]);
 | 
					    useEffect(() => refreshValue(), [ note, note[property] ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Watch for external changes.
 | 
					    // Watch for external changes.
 | 
				
			||||||
    useTriliumEventBeta("entitiesReloaded", ({ loadResults }) => {
 | 
					    useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
 | 
				
			||||||
        if (loadResults.isNoteReloaded(note.noteId, componentId)) {
 | 
					        if (loadResults.isNoteReloaded(note.noteId, componentId)) {
 | 
				
			||||||
            refreshValue();
 | 
					            refreshValue();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -349,7 +280,7 @@ export function useNoteRelation(note: FNote | undefined | null, relationName: st
 | 
				
			|||||||
    const [ relationValue, setRelationValue ] = useState<string | null | undefined>(note?.getRelationValue(relationName));
 | 
					    const [ relationValue, setRelationValue ] = useState<string | null | undefined>(note?.getRelationValue(relationName));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useEffect(() => setRelationValue(note?.getRelationValue(relationName) ?? null), [ note ]);
 | 
					    useEffect(() => setRelationValue(note?.getRelationValue(relationName) ?? null), [ note ]);
 | 
				
			||||||
    useTriliumEventBeta("entitiesReloaded", ({ loadResults }) => {
 | 
					    useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
 | 
				
			||||||
        for (const attr of loadResults.getAttributeRows()) {
 | 
					        for (const attr of loadResults.getAttributeRows()) {
 | 
				
			||||||
            if (attr.type === "relation" && attr.name === relationName && attributes.isAffecting(attr, note)) {
 | 
					            if (attr.type === "relation" && attr.name === relationName && attributes.isAffecting(attr, note)) {
 | 
				
			||||||
                setRelationValue(attr.value ?? null);
 | 
					                setRelationValue(attr.value ?? null);
 | 
				
			||||||
@ -380,7 +311,7 @@ export function useNoteLabel(note: FNote | undefined | null, labelName: string):
 | 
				
			|||||||
    const [ labelValue, setLabelValue ] = useState<string | null | undefined>(note?.getLabelValue(labelName));
 | 
					    const [ labelValue, setLabelValue ] = useState<string | null | undefined>(note?.getLabelValue(labelName));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useEffect(() => setLabelValue(note?.getLabelValue(labelName) ?? null), [ note ]);
 | 
					    useEffect(() => setLabelValue(note?.getLabelValue(labelName) ?? null), [ note ]);
 | 
				
			||||||
    useTriliumEventBeta("entitiesReloaded", ({ loadResults }) => {
 | 
					    useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
 | 
				
			||||||
        for (const attr of loadResults.getAttributeRows()) {
 | 
					        for (const attr of loadResults.getAttributeRows()) {
 | 
				
			||||||
            if (attr.type === "label" && attr.name === labelName && attributes.isAffecting(attr, note)) {
 | 
					            if (attr.type === "label" && attr.name === labelName && attributes.isAffecting(attr, note)) {
 | 
				
			||||||
                setLabelValue(attr.value ?? null);
 | 
					                setLabelValue(attr.value ?? null);
 | 
				
			||||||
@ -409,7 +340,7 @@ export function useNoteLabelBoolean(note: FNote | undefined | null, labelName: s
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    useEffect(() => setLabelValue(!!note?.hasLabel(labelName)), [ note ]);
 | 
					    useEffect(() => setLabelValue(!!note?.hasLabel(labelName)), [ note ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useTriliumEventBeta("entitiesReloaded", ({ loadResults }) => {
 | 
					    useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
 | 
				
			||||||
        for (const attr of loadResults.getAttributeRows()) {
 | 
					        for (const attr of loadResults.getAttributeRows()) {
 | 
				
			||||||
            if (attr.type === "label" && attr.name === labelName && attributes.isAffecting(attr, note)) {
 | 
					            if (attr.type === "label" && attr.name === labelName && attributes.isAffecting(attr, note)) {
 | 
				
			||||||
                setLabelValue(!attr.isDeleted);
 | 
					                setLabelValue(!attr.isDeleted);
 | 
				
			||||||
@ -442,7 +373,7 @@ export function useNoteBlob(note: FNote | null | undefined): [ FBlob | null | un
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useEffect(refresh, [ note?.noteId ]);
 | 
					    useEffect(refresh, [ note?.noteId ]);
 | 
				
			||||||
    useTriliumEventBeta("entitiesReloaded", ({ loadResults }) => {
 | 
					    useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
 | 
				
			||||||
        if (note && loadResults.hasRevisionForNote(note.noteId)) {
 | 
					        if (note && loadResults.hasRevisionForNote(note.noteId)) {
 | 
				
			||||||
            refresh();
 | 
					            refresh();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@ import Dropdown from "../react/Dropdown";
 | 
				
			|||||||
import { NOTE_TYPES } from "../../services/note_types";
 | 
					import { NOTE_TYPES } from "../../services/note_types";
 | 
				
			||||||
import { FormDropdownDivider, FormListBadge, FormListItem } from "../react/FormList";
 | 
					import { FormDropdownDivider, FormListBadge, FormListItem } from "../react/FormList";
 | 
				
			||||||
import { getAvailableLocales, t } from "../../services/i18n";
 | 
					import { getAvailableLocales, t } from "../../services/i18n";
 | 
				
			||||||
import { useNoteLabel, useNoteLabelBoolean, useNoteProperty, useTriliumEventBeta, useTriliumOption, useTriliumOptionBeta, useTriliumOptionJson } from "../react/hooks";
 | 
					import { useNoteLabel, useNoteLabelBoolean, useNoteProperty, useTriliumEvent, useTriliumOption, useTriliumOptionBeta, useTriliumOptionJson } from "../react/hooks";
 | 
				
			||||||
import mime_types from "../../services/mime_types";
 | 
					import mime_types from "../../services/mime_types";
 | 
				
			||||||
import { Locale, NoteType, ToggleInParentResponse } from "@triliumnext/commons";
 | 
					import { Locale, NoteType, ToggleInParentResponse } from "@triliumnext/commons";
 | 
				
			||||||
import server from "../../services/server";
 | 
					import server from "../../services/server";
 | 
				
			||||||
@ -179,7 +179,7 @@ function BookmarkSwitch({ note }: { note?: FNote | null }) {
 | 
				
			|||||||
    }, [ note ]);
 | 
					    }, [ note ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useEffect(() => refreshState(), [ note ]);
 | 
					    useEffect(() => refreshState(), [ note ]);
 | 
				
			||||||
    useTriliumEventBeta("entitiesReloaded", ({ loadResults }) => {
 | 
					    useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
 | 
				
			||||||
        if (note && loadResults.getBranchRows().find((b) => b.noteId === note.noteId)) {
 | 
					        if (note && loadResults.getBranchRows().find((b) => b.noteId === note.noteId)) {
 | 
				
			||||||
            refreshState();
 | 
					            refreshState();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -228,7 +228,7 @@ function SharedSwitch({ note }: { note?: FNote | null }) {
 | 
				
			|||||||
    }, [ note ]);
 | 
					    }, [ note ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useEffect(() => refreshState(), [ note ]);
 | 
					    useEffect(() => refreshState(), [ note ]);
 | 
				
			||||||
    useTriliumEventBeta("entitiesReloaded", ({ loadResults }) => {
 | 
					    useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
 | 
				
			||||||
        if (note && loadResults.getBranchRows().find((b) => b.noteId === note.noteId)) {
 | 
					        if (note && loadResults.getBranchRows().find((b) => b.noteId === note.noteId)) {
 | 
				
			||||||
            refreshState();
 | 
					            refreshState();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import { useEffect, useState } from "preact/hooks";
 | 
					import { useEffect, useState } from "preact/hooks";
 | 
				
			||||||
import { TabContext } from "./ribbon-interface";
 | 
					import { TabContext } from "./ribbon-interface";
 | 
				
			||||||
import FAttribute from "../../entities/fattribute";
 | 
					import FAttribute from "../../entities/fattribute";
 | 
				
			||||||
import { useLegacyWidget, useTriliumEventBeta } from "../react/hooks";
 | 
					import { useLegacyWidget, useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
import attributes from "../../services/attributes";
 | 
					import attributes from "../../services/attributes";
 | 
				
			||||||
import { t } from "../../services/i18n";
 | 
					import { t } from "../../services/i18n";
 | 
				
			||||||
import attribute_renderer from "../../services/attribute_renderer";
 | 
					import attribute_renderer from "../../services/attribute_renderer";
 | 
				
			||||||
@ -29,7 +29,7 @@ export default function InheritedAttributesTab({ note, componentId }: TabContext
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useEffect(refresh, [ note ]);
 | 
					    useEffect(refresh, [ note ]);
 | 
				
			||||||
    useTriliumEventBeta("entitiesReloaded", ({ loadResults }) => {
 | 
					    useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
 | 
				
			||||||
        if (loadResults.getAttributeRows(componentId).find((attr) => attributes.isAffecting(attr, note))) {
 | 
					        if (loadResults.getAttributeRows(componentId).find((attr) => attributes.isAffecting(attr, note))) {
 | 
				
			||||||
            refresh();
 | 
					            refresh();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -7,7 +7,7 @@ import Button from "../react/Button";
 | 
				
			|||||||
import { formatDateTime } from "../../utils/formatters";
 | 
					import { formatDateTime } from "../../utils/formatters";
 | 
				
			||||||
import { formatSize } from "../../services/utils";
 | 
					import { formatSize } from "../../services/utils";
 | 
				
			||||||
import LoadingSpinner from "../react/LoadingSpinner";
 | 
					import LoadingSpinner from "../react/LoadingSpinner";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks";
 | 
					import { useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function NoteInfoTab({ note }: TabContext) {
 | 
					export default function NoteInfoTab({ note }: TabContext) {
 | 
				
			||||||
    const [ metadata, setMetadata ] = useState<MetadataResponse>();
 | 
					    const [ metadata, setMetadata ] = useState<MetadataResponse>();
 | 
				
			||||||
@ -26,7 +26,7 @@ export default function NoteInfoTab({ note }: TabContext) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useEffect(refresh, [ note?.noteId ]);
 | 
					    useEffect(refresh, [ note?.noteId ]);
 | 
				
			||||||
    useTriliumEventBeta("entitiesReloaded", ({ loadResults }) => {
 | 
					    useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
 | 
				
			||||||
        const noteId = note?.noteId;
 | 
					        const noteId = note?.noteId;
 | 
				
			||||||
        if (noteId && (loadResults.isNoteReloaded(noteId) || loadResults.isNoteContentReloaded(noteId))) {
 | 
					        if (noteId && (loadResults.isNoteReloaded(noteId) || loadResults.isNoteContentReloaded(noteId))) {
 | 
				
			||||||
            refresh();
 | 
					            refresh();
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import { TabContext } from "./ribbon-interface";
 | 
					import { TabContext } from "./ribbon-interface";
 | 
				
			||||||
import { t } from "../../services/i18n";
 | 
					import { t } from "../../services/i18n";
 | 
				
			||||||
import Button from "../react/Button";
 | 
					import Button from "../react/Button";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks";
 | 
					import { useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
import { useEffect, useMemo, useState } from "preact/hooks";
 | 
					import { useEffect, useMemo, useState } from "preact/hooks";
 | 
				
			||||||
import { NotePathRecord } from "../../entities/fnote";
 | 
					import { NotePathRecord } from "../../entities/fnote";
 | 
				
			||||||
import NoteLink from "../react/NoteLink";
 | 
					import NoteLink from "../react/NoteLink";
 | 
				
			||||||
@ -18,7 +18,7 @@ export default function NotePathsTab({ note, hoistedNoteId, notePath }: TabConte
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useEffect(refresh, [ note?.noteId ]);
 | 
					    useEffect(refresh, [ note?.noteId ]);
 | 
				
			||||||
    useTriliumEventBeta("entitiesReloaded", ({ loadResults }) => {
 | 
					    useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
 | 
				
			||||||
        const noteId = note?.noteId;
 | 
					        const noteId = note?.noteId;
 | 
				
			||||||
        if (!noteId) return;
 | 
					        if (!noteId) return;
 | 
				
			||||||
        if (loadResults.getBranchRows().find((branch) => branch.noteId === noteId)
 | 
					        if (loadResults.getBranchRows().find((branch) => branch.noteId === noteId)
 | 
				
			||||||
 | 
				
			|||||||
@ -8,7 +8,7 @@ import toast from "../../services/toast";
 | 
				
			|||||||
import froca from "../../services/froca";
 | 
					import froca from "../../services/froca";
 | 
				
			||||||
import { useContext, useEffect, useState } from "preact/hooks";
 | 
					import { useContext, useEffect, useState } from "preact/hooks";
 | 
				
			||||||
import { ParentComponent } from "../react/react_utils";
 | 
					import { ParentComponent } from "../react/react_utils";
 | 
				
			||||||
import { useTriliumEventBeta } from "../react/hooks";
 | 
					import { useTriliumEvent } from "../react/hooks";
 | 
				
			||||||
import appContext from "../../components/app_context";
 | 
					import appContext from "../../components/app_context";
 | 
				
			||||||
import server from "../../services/server";
 | 
					import server from "../../services/server";
 | 
				
			||||||
import ws from "../../services/ws";
 | 
					import ws from "../../services/ws";
 | 
				
			||||||
@ -65,7 +65,7 @@ export default function SearchDefinitionTab({ note, ntxId }: TabContext) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // Refresh the list of available and active options.
 | 
					  // Refresh the list of available and active options.
 | 
				
			||||||
  useEffect(refreshOptions, [ note ]);
 | 
					  useEffect(refreshOptions, [ note ]);
 | 
				
			||||||
  useTriliumEventBeta("entitiesReloaded", ({ loadResults }) => {
 | 
					  useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
 | 
				
			||||||
    if (loadResults.getAttributeRows().find((attrRow) => attributes.isAffecting(attrRow, note))) {
 | 
					    if (loadResults.getAttributeRows().find((attrRow) => attributes.isAffecting(attrRow, note))) {
 | 
				
			||||||
      refreshOptions();
 | 
					      refreshOptions();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -166,7 +166,7 @@ function BulkActionsList({ note }: { note: FNote }) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // React to changes.
 | 
					  // React to changes.
 | 
				
			||||||
  useEffect(refreshBulkActions, [ note ]);
 | 
					  useEffect(refreshBulkActions, [ note ]);
 | 
				
			||||||
  useTriliumEventBeta("entitiesReloaded", ({loadResults}) => {
 | 
					  useTriliumEvent("entitiesReloaded", ({loadResults}) => {
 | 
				
			||||||
    if (loadResults.getAttributeRows().find(attr => attr.type === "label" && attr.name === "action" && attributes.isAffecting(attr, note))) {
 | 
					    if (loadResults.getAttributeRows().find(attr => attr.type === "label" && attr.name === "action" && attributes.isAffecting(attr, note))) {
 | 
				
			||||||
      refreshBulkActions();
 | 
					      refreshBulkActions();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@ import { t } from "../../../services/i18n";
 | 
				
			|||||||
import server from "../../../services/server";
 | 
					import server from "../../../services/server";
 | 
				
			||||||
import note_autocomplete, { Suggestion } from "../../../services/note_autocomplete";
 | 
					import note_autocomplete, { Suggestion } from "../../../services/note_autocomplete";
 | 
				
			||||||
import CKEditor, { CKEditorApi } from "../../react/CKEditor";
 | 
					import CKEditor, { CKEditorApi } from "../../react/CKEditor";
 | 
				
			||||||
import { useLegacyImperativeHandlers, useLegacyWidget, useTooltip, useTriliumEventBeta } from "../../react/hooks";
 | 
					import { useLegacyImperativeHandlers, useLegacyWidget, useTooltip, useTriliumEvent } from "../../react/hooks";
 | 
				
			||||||
import FAttribute from "../../../entities/fattribute";
 | 
					import FAttribute from "../../../entities/fattribute";
 | 
				
			||||||
import attribute_renderer from "../../../services/attribute_renderer";
 | 
					import attribute_renderer from "../../../services/attribute_renderer";
 | 
				
			||||||
import FNote from "../../../entities/fnote";
 | 
					import FNote from "../../../entities/fnote";
 | 
				
			||||||
@ -215,7 +215,7 @@ export default function AttributeEditor({ note, componentId, notePath, ntxId }:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useEffect(() => refresh(), [ note ]);
 | 
					    useEffect(() => refresh(), [ note ]);
 | 
				
			||||||
    useTriliumEventBeta("entitiesReloaded", ({ loadResults }) => {
 | 
					    useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
 | 
				
			||||||
        if (loadResults.getAttributeRows(componentId).find((attr) => attributes.isAffecting(attr, note))) {
 | 
					        if (loadResults.getAttributeRows(componentId).find((attr) => attributes.isAffecting(attr, note))) {
 | 
				
			||||||
            console.log("Trigger due to entities reloaded");
 | 
					            console.log("Trigger due to entities reloaded");
 | 
				
			||||||
            refresh();
 | 
					            refresh();
 | 
				
			||||||
@ -257,11 +257,11 @@ export default function AttributeEditor({ note, componentId, notePath, ntxId }:
 | 
				
			|||||||
    }), []));
 | 
					    }), []));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Keyboard shortcuts
 | 
					    // Keyboard shortcuts
 | 
				
			||||||
    useTriliumEventBeta("addNewLabel", ({ ntxId: eventNtxId }) => {
 | 
					    useTriliumEvent("addNewLabel", ({ ntxId: eventNtxId }) => {
 | 
				
			||||||
        if (eventNtxId !== ntxId) return;
 | 
					        if (eventNtxId !== ntxId) return;
 | 
				
			||||||
        handleAddNewAttributeCommand("addNewLabel");
 | 
					        handleAddNewAttributeCommand("addNewLabel");
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    useTriliumEventBeta("addNewRelation", ({ ntxId: eventNtxId }) => {
 | 
					    useTriliumEvent("addNewRelation", ({ ntxId: eventNtxId }) => {
 | 
				
			||||||
        if (eventNtxId !== ntxId) return;
 | 
					        if (eventNtxId !== ntxId) return;
 | 
				
			||||||
        handleAddNewAttributeCommand("addNewRelation");
 | 
					        handleAddNewAttributeCommand("addNewRelation");
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
				
			|||||||
@ -76,7 +76,6 @@ const CONTENT_WIDGETS: Record<OptionPages | "_backendLog", ((typeof NoteContextA
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
export default class ContentWidgetTypeWidget extends TypeWidget {
 | 
					export default class ContentWidgetTypeWidget extends TypeWidget {
 | 
				
			||||||
    private $content!: JQuery<HTMLElement>;
 | 
					    private $content!: JQuery<HTMLElement>;
 | 
				
			||||||
    private widget?: BasicWidget;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static getType() {
 | 
					    static getType() {
 | 
				
			||||||
        return "contentWidget";
 | 
					        return "contentWidget";
 | 
				
			||||||
@ -113,7 +112,6 @@ export default class ContentWidgetTypeWidget extends TypeWidget {
 | 
				
			|||||||
                this.child(widget);
 | 
					                this.child(widget);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                this.$content.append(widget.render());
 | 
					                this.$content.append(widget.render());
 | 
				
			||||||
                this.widget = widget;
 | 
					 | 
				
			||||||
                await widget.refresh();
 | 
					                await widget.refresh();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
 | 
				
			|||||||
@ -10,7 +10,7 @@ import toast from "../../../services/toast";
 | 
				
			|||||||
import dialog from "../../../services/dialog";
 | 
					import dialog from "../../../services/dialog";
 | 
				
			||||||
import { formatDateTime } from "../../../utils/formatters";
 | 
					import { formatDateTime } from "../../../utils/formatters";
 | 
				
			||||||
import ActionButton from "../../react/ActionButton";
 | 
					import ActionButton from "../../react/ActionButton";
 | 
				
			||||||
import useTriliumEvent from "../../react/hooks";
 | 
					import { useTriliumEvent } from "../../react/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type RenameTokenCallback = (tokenId: string, oldName: string) => Promise<void>;
 | 
					type RenameTokenCallback = (tokenId: string, oldName: string) => Promise<void>;
 | 
				
			||||||
type DeleteTokenCallback = (tokenId: string, name: string ) => Promise<void>;
 | 
					type DeleteTokenCallback = (tokenId: string, name: string ) => Promise<void>;
 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,7 @@ import { useCallback, useEffect, useState } from "preact/hooks";
 | 
				
			|||||||
import server from "../../../services/server";
 | 
					import server from "../../../services/server";
 | 
				
			||||||
import options from "../../../services/options";
 | 
					import options from "../../../services/options";
 | 
				
			||||||
import dialog from "../../../services/dialog";
 | 
					import dialog from "../../../services/dialog";
 | 
				
			||||||
import useTriliumEvent from "../../react/hooks";
 | 
					import { useTriliumEvent } from "../../react/hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function ShortcutSettings() {
 | 
					export default function ShortcutSettings() {
 | 
				
			||||||
    const [ keyboardShortcuts, setKeyboardShortcuts ] = useState<KeyboardShortcut[]>([]);    
 | 
					    const [ keyboardShortcuts, setKeyboardShortcuts ] = useState<KeyboardShortcut[]>([]);    
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user