feat(react): set up hook for reacting to events

This commit is contained in:
Elian Doran 2025-08-08 20:08:06 +03:00
parent bd6c690160
commit 3975041798
No known key found for this signature in database
4 changed files with 58 additions and 24 deletions

View File

@ -15,6 +15,7 @@ import RenameNoteBulkAction from "../bulk_actions/note/rename_note";
import { RawHtmlBlock } from "../react/RawHtml"; import { RawHtmlBlock } from "../react/RawHtml";
import FNote from "../../entities/fnote"; import FNote from "../../entities/fnote";
import froca from "../../services/froca"; import froca from "../../services/froca";
import useTriliumEvent from "../react/hooks";
interface BulkActionProps { interface BulkActionProps {
bulkActionNote?: FNote | null; bulkActionNote?: FNote | null;
@ -42,6 +43,10 @@ function BulkActionComponent({ selectedOrActiveNoteIds, bulkActionNote }: BulkAc
setExistingActions(bulk_action.parseActions(bulkActionNote)); setExistingActions(bulk_action.parseActions(bulkActionNote));
}, []); }, []);
useTriliumEvent("entitiesReloaded", () => {
console.log("Got entities reloaded.");
});
return ( selectedOrActiveNoteIds && return ( selectedOrActiveNoteIds &&
<Modal <Modal
className="bulk-actions-dialog" className="bulk-actions-dialog"
@ -130,14 +135,4 @@ export default class BulkActionsDialog extends ReactBasicWidget {
openDialog(this.$widget); openDialog(this.$widget);
} }
entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) {
// only refreshing deleted attrs, otherwise components update themselves
if (loadResults.getAttributeRows().find((row) => row.type === "label" && row.name === "action" && row.noteId === "_bulkAction" && row.isDeleted)) {
// this may be triggered from e.g., sync without open widget, then no need to refresh the widget
if (this.props.selectedOrActiveNoteIds && this.$widget.is(":visible")) {
this.doRender();
}
}
}
} }

View File

@ -1,14 +0,0 @@
import { JSX, render } from "preact";
import BasicWidget from "../basic_widget.js";
export default abstract class ReactBasicWidget extends BasicWidget {
abstract get component(): JSX.Element;
doRender() {
const renderContainer = new DocumentFragment();
render(this.component, renderContainer);
this.$widget = $(renderContainer.firstChild as HTMLElement);
}
}

View File

@ -0,0 +1,21 @@
import { createContext, JSX, render } from "preact";
import BasicWidget from "../basic_widget.js";
import Component from "../../components/component.js";
export const ParentComponent = createContext<Component | null>(null);
export default abstract class ReactBasicWidget extends BasicWidget {
abstract get component(): JSX.Element;
doRender() {
const renderContainer = new DocumentFragment();
render((
<ParentComponent.Provider value={this}>
{this.component}
</ParentComponent.Provider>
), renderContainer);
this.$widget = $(renderContainer.firstChild as HTMLElement);
}
}

View File

@ -0,0 +1,32 @@
import { useContext, useEffect, useState } from "preact/hooks";
import { EventData, EventNames } from "../../components/app_context";
import { ParentComponent } from "./ReactBasicWidget";
export default function useTriliumEvent<T extends EventNames>(eventName: T, handler: (data: EventData<T>) => void) {
const parentWidget = useContext(ParentComponent);
useEffect(() => {
if (!parentWidget) {
console.warn("useTriliumEvent: No widget context found");
return;
}
// Create a unique handler name for this specific event listener
const handlerName = `${eventName}Event`;
const originalHandler = parentWidget[handlerName];
// Override the event handler to call our handler
parentWidget[handlerName] = async function(data: EventData<T>) {
// Call original handler if it exists
if (originalHandler) {
await originalHandler.call(parentWidget, data);
}
// Call our React component's handler
handler(data);
};
// Cleanup: restore original handler on unmount
return () => {
parentWidget[handlerName] = originalHandler;
};
}, [parentWidget]);
}