mirror of
https://github.com/zadam/trilium.git
synced 2025-10-26 07:46:30 +01:00
chore(react): prototype for note context
This commit is contained in:
@@ -15,7 +15,7 @@ type EventHandler = ((data: any) => void);
|
||||
* event / command is executed in all components - by simply awaiting the `triggerEvent()`.
|
||||
*/
|
||||
export class TypedComponent<ChildT extends TypedComponent<ChildT>> {
|
||||
$widget!: JQuery<HTMLElement>;
|
||||
$widget!: JQuery<HTMLElement | DocumentFragment>;
|
||||
componentId: string;
|
||||
children: ChildT[];
|
||||
initialized: Promise<void> | null;
|
||||
|
||||
@@ -3,9 +3,9 @@ import Component, { TypedComponent } from "../components/component.js";
|
||||
import froca from "../services/froca.js";
|
||||
import { t } from "../services/i18n.js";
|
||||
import toastService from "../services/toast.js";
|
||||
import { renderReactWidget } from "./react/react_utils.jsx";
|
||||
import { EventNames, EventData } from "../components/app_context.js";
|
||||
import { Handler } from "leaflet";
|
||||
import { renderReactWidgetAtElement } from "./react/react_utils.jsx";
|
||||
import { type default as NoteContextType } from "../../components/note_context";
|
||||
import { EventData } from "../components/app_context.js";
|
||||
|
||||
export class TypedBasicWidget<T extends TypedComponent<any>> extends TypedComponent<T> {
|
||||
protected attrs: Record<string, string>;
|
||||
@@ -281,6 +281,8 @@ export function wrapReactWidgets<T extends TypedComponent<any>>(components: (T |
|
||||
export class ReactWrappedWidget extends BasicWidget {
|
||||
|
||||
private el: VNode;
|
||||
private noteContext: NoteContextType | null;
|
||||
private fragment: DocumentFragment = new DocumentFragment();
|
||||
|
||||
constructor(el: VNode) {
|
||||
super();
|
||||
@@ -288,7 +290,30 @@ export class ReactWrappedWidget extends BasicWidget {
|
||||
}
|
||||
|
||||
doRender() {
|
||||
this.$widget = renderReactWidget(this, this.el);
|
||||
renderReactWidgetAtElement({
|
||||
parentComponent: this,
|
||||
noteContext: this.noteContext
|
||||
}, this.el, this.fragment);
|
||||
this.$widget = $(this.fragment);
|
||||
}
|
||||
|
||||
activeContextChangedEvent({ noteContext }: EventData<"activeContextChanged">) {
|
||||
this.noteContext = noteContext;
|
||||
this.doRender();
|
||||
}
|
||||
|
||||
setNoteContextEvent({ noteContext }: EventData<"setNoteContext">) {
|
||||
this.noteContext = noteContext;
|
||||
this.doRender();
|
||||
}
|
||||
|
||||
noteSwitchedAndActivatedEvent({ noteContext }: EventData<"noteSwitchedAndActivated">) {
|
||||
this.noteContext = noteContext;
|
||||
this.doRender();
|
||||
}
|
||||
|
||||
noteSwitchedEvent({ noteContext }: EventData<"noteSwitched">) {
|
||||
this.doRender();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useRef, useState } from "preact/hooks";
|
||||
import { useContext, useEffect, useRef, useState } from "preact/hooks";
|
||||
import { t } from "../services/i18n";
|
||||
import FormTextBox from "./react/FormTextBox";
|
||||
import { useNoteContext, useNoteProperty, useSpacedUpdate, useTriliumEvent } from "./react/hooks";
|
||||
@@ -8,9 +8,13 @@ import "./note_title.css";
|
||||
import { isLaunchBarConfig } from "../services/utils";
|
||||
import appContext from "../components/app_context";
|
||||
import branches from "../services/branches";
|
||||
import { NoteContext, ParentComponent } from "./react/react_utils";
|
||||
|
||||
export default function NoteTitleWidget() {
|
||||
const { note, noteId, componentId, viewScope, noteContext, parentComponent } = useNoteContext();
|
||||
const parentComponent = useContext(ParentComponent);
|
||||
const noteContext = useContext(NoteContext);
|
||||
const { noteId, note, componentId, viewScope } = noteContext ?? {};
|
||||
|
||||
const title = useNoteProperty(note, "title", componentId);
|
||||
const isProtected = useNoteProperty(note, "isProtected");
|
||||
const newTitle = useRef("");
|
||||
@@ -31,7 +35,7 @@ export default function NoteTitleWidget() {
|
||||
// Manage the title for read-only notes
|
||||
useEffect(() => {
|
||||
if (isReadOnly) {
|
||||
noteContext?.getNavigationTitle().then(setNavigationTitle);
|
||||
noteContext?.getNavigationTitle?.().then(setNavigationTitle);
|
||||
}
|
||||
}, [isReadOnly]);
|
||||
|
||||
@@ -78,7 +82,7 @@ export default function NoteTitleWidget() {
|
||||
// Focus on the note content when pressing enter.
|
||||
if (e.key === "Enter") {
|
||||
e.preventDefault();
|
||||
parentComponent.triggerCommand("focusOnDetail", { ntxId: noteContext?.ntxId });
|
||||
parentComponent?.triggerCommand("focusOnDetail", { ntxId: noteContext?.ntxId });
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,10 @@ export default abstract class ReactBasicWidget extends BasicWidget {
|
||||
abstract get component(): JSX.Element;
|
||||
|
||||
doRender() {
|
||||
this.$widget = renderReactWidget(this, this.component);
|
||||
this.$widget = renderReactWidget({
|
||||
parentComponent: this,
|
||||
noteContext: null
|
||||
}, this.component);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,9 +17,13 @@ import { CSSProperties } from "preact/compat";
|
||||
|
||||
export function useTriliumEvent<T extends EventNames>(eventName: T, handler: (data: EventData<T>) => void) {
|
||||
const parentComponent = useContext(ParentComponent)!;
|
||||
parentComponent.registerHandler(eventName, handler);
|
||||
|
||||
useEffect(() => {
|
||||
parentComponent.registerHandler(eventName, handler);
|
||||
return (() => parentComponent.removeHandler(eventName, handler));
|
||||
}, [eventName, handler]);
|
||||
|
||||
useDebugValue(eventName);
|
||||
return (() => parentComponent.removeHandler(eventName, handler));
|
||||
}
|
||||
|
||||
export function useTriliumEvents<T extends EventNames>(eventNames: T[], handler: (data: EventData<T>, eventName: T) => void) {
|
||||
@@ -199,7 +203,6 @@ export function useNoteContext() {
|
||||
}, [ notePath ]);
|
||||
|
||||
useTriliumEvent("activeContextChanged", ({ noteContext }) => {
|
||||
setNoteContext(noteContext);
|
||||
setNotePath(noteContext.notePath);
|
||||
});
|
||||
useTriliumEvent("setNoteContext", ({ noteContext }) => {
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
import { ComponentChild, createContext, render, type JSX, type RefObject } from "preact";
|
||||
import Component from "../../components/component";
|
||||
import { EventData, EventNames } from "../../components/app_context";
|
||||
import { useContext } from "preact/hooks";
|
||||
import { type default as NoteContextType } from "../../components/note_context";
|
||||
|
||||
export const ParentComponent = createContext<Component | null>(null);
|
||||
export const NoteContext = createContext<NoteContextType | null>(null);
|
||||
|
||||
interface ComponentContext {
|
||||
parentComponent: Component | null;
|
||||
noteContext: NoteContextType | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes in a React ref and returns a corresponding JQuery selector.
|
||||
@@ -26,14 +31,16 @@ export function refToJQuerySelector<T extends HTMLElement>(ref: RefObject<T> | n
|
||||
* @param el the JSX element to render.
|
||||
* @returns the rendered wrapped DOM element.
|
||||
*/
|
||||
export function renderReactWidget(parentComponent: Component, el: JSX.Element) {
|
||||
return renderReactWidgetAtElement(parentComponent, el, new DocumentFragment()).children();
|
||||
export function renderReactWidget(context: ComponentContext, el: JSX.Element) {
|
||||
return renderReactWidgetAtElement(context, el, new DocumentFragment()).children();
|
||||
}
|
||||
|
||||
export function renderReactWidgetAtElement(parentComponent: Component, el: JSX.Element, container: Element | DocumentFragment) {
|
||||
export function renderReactWidgetAtElement({ parentComponent, noteContext }: ComponentContext, el: JSX.Element, container: Element | DocumentFragment) {
|
||||
render((
|
||||
<ParentComponent.Provider value={parentComponent}>
|
||||
{el}
|
||||
<NoteContext.Provider value={noteContext}>
|
||||
{el}
|
||||
</NoteContext.Provider>
|
||||
</ParentComponent.Provider>
|
||||
), container);
|
||||
return $(container) as JQuery<HTMLElement>;
|
||||
|
||||
Reference in New Issue
Block a user