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