diff --git a/apps/client/src/widgets/dialogs/PopupEditor.tsx b/apps/client/src/widgets/dialogs/PopupEditor.tsx index 070244b56..583b13abd 100644 --- a/apps/client/src/widgets/dialogs/PopupEditor.tsx +++ b/apps/client/src/widgets/dialogs/PopupEditor.tsx @@ -1,47 +1,71 @@ -import { useContext, useEffect, useState } from "preact/hooks"; +import { useContext, useEffect, useRef, useState } from "preact/hooks"; import Modal from "../react/Modal"; import "./PopupEditor.css"; -import { useTriliumEvent } from "../react/hooks"; +import { useNoteContext, useNoteLabel, useTriliumEvent } from "../react/hooks"; import NoteTitleWidget from "../note_title"; import NoteIcon from "../note_icon"; import NoteContext from "../../components/note_context"; import { NoteContextContext, ParentComponent } from "../react/react_utils"; import NoteDetail from "../NoteDetail"; - -const noteContext = new NoteContext("_popup-editor"); +import { ComponentChildren } from "preact"; export default function PopupEditor() { const [ shown, setShown ] = useState(false); const parentComponent = useContext(ParentComponent); + const [ noteContext, setNoteContext ] = useState(new NoteContext("_popup-editor")); useTriliumEvent("openInPopup", async ({ noteIdOrPath }) => { + const noteContext = new NoteContext("_popup-editor"); await noteContext.setNote(noteIdOrPath, { viewScope: { readOnlyTemporarilyDisabled: true } }); + setNoteContext(noteContext); setShown(true); }); return ( - } - className="popup-editor-dialog" - size="lg" - show={shown} - onShown={() => { - parentComponent?.handleEvent("focusOnDetail", { ntxId: noteContext.ntxId }); - }} - onHidden={() => setShown(false)} - > - - + + } + className="popup-editor-dialog" + size="lg" + show={shown} + onShown={() => { + parentComponent?.handleEvent("focusOnDetail", { ntxId: noteContext.ntxId }); + }} + onHidden={() => setShown(false)} + > + + + ) } +export function DialogWrapper({ children }: { children: ComponentChildren }) { + const { note, ntxId } = useNoteContext(); + const wrapperRef = useRef(null); + const colorClass = note?.getColorClass(); + const [ hasTint, setHasTint ] = useState(false); + + // Apply the tinted-dialog class only if the custom color CSS class specifies a hue + useEffect(() => { + if (!wrapperRef.current) return; + const customHue = getComputedStyle(wrapperRef.current).getPropertyValue("--custom-color-hue"); + setHasTint(!!customHue); + }, [ note, colorClass ]); + + return ( +
+ {children} +
+ ) +} + export function TitleRow() { return (
diff --git a/apps/client/src/widgets/dialogs/popup_editor.ts b/apps/client/src/widgets/dialogs/popup_editor.ts deleted file mode 100644 index 1cadb3ab6..000000000 --- a/apps/client/src/widgets/dialogs/popup_editor.ts +++ /dev/null @@ -1,101 +0,0 @@ -import type { EventNames, EventData } from "../../components/app_context.js"; -import NoteContext from "../../components/note_context.js"; -import { openDialog } from "../../services/dialog.js"; -import BasicWidget, { ReactWrappedWidget } from "../basic_widget.js"; -import Container from "../containers/container.js"; - -export default class PopupEditorDialog extends Container { - - private noteContext: NoteContext; - private $modalHeader!: JQuery; - private $modalBody!: JQuery; - private $wrapper!: JQuery; - - constructor() { - super(); - this.noteContext = - } - - doRender() { - // This will populate this.$widget with the content of the children. - super.doRender(); - - // Now we wrap it in the modal. - const $newWidget = $(TPL); - this.$modalHeader = $newWidget.find(".modal-title"); - this.$modalBody = $newWidget.find(".modal-body"); - this.$wrapper = $newWidget.find(".quick-edit-dialog-wrapper"); - - const children = this.$widget.children(); - this.$modalHeader.append(children[0]); - this.$modalBody.append(children.slice(1)); - this.$widget = $newWidget; - this.setVisibility(false); - } - - async openInPopupEvent({ noteIdOrPath }: EventData<"openInPopup">) { - - - const colorClass = this.noteContext.note?.getColorClass(); - const wrapperElement = this.$wrapper.get(0)!; - - if (colorClass) { - wrapperElement.className = "quick-edit-dialog-wrapper " + colorClass; - } else { - wrapperElement.className = "quick-edit-dialog-wrapper"; - } - - const customHue = getComputedStyle(wrapperElement).getPropertyValue("--custom-color-hue"); - if (customHue) { - /* Apply the tinted-dialog class only if the custom color CSS class specifies a hue */ - wrapperElement.classList.add("tinted-quick-edit-dialog"); - } - - const activeEl = document.activeElement; - if (activeEl && "blur" in activeEl) { - (activeEl as HTMLElement).blur(); - } - - $dialog.on("shown.bs.modal", async () => { - this.setVisibility(true); - }); - $dialog.on("hidden.bs.modal", () => { - const $typeWidgetEl = $dialog.find(".note-detail-printable"); - if ($typeWidgetEl.length) { - const typeWidget = glob.getComponentByEl($typeWidgetEl[0]) as ReactWrappedWidget; - typeWidget.cleanup(); - } - - this.setVisibility(false); - }); - } - - setVisibility(visible: boolean) { - const $bodyItems = this.$modalBody.find("> div"); - if (visible) { - $bodyItems.fadeIn(); - this.$modalHeader.children().show(); - document.body.classList.add("popup-editor-open"); - - } else { - $bodyItems.hide(); - this.$modalHeader.children().hide(); - document.body.classList.remove("popup-editor-open"); - } - } - - handleEventInChildren(name: T, data: EventData): Promise | null { - // Avoid events related to the current tab interfere with our popup. - if (["noteSwitched", "noteSwitchedAndActivated", "exportAsPdf", "printActiveNote"].includes(name)) { - return Promise.resolve(); - } - - // Avoid not showing recent notes when creating a new empty tab. - if ("noteContext" in data && data.noteContext.ntxId !== "_popup-editor") { - return Promise.resolve(); - } - - return super.handleEventInChildren(name, data); - } - -} diff --git a/apps/client/src/widgets/react/hooks.tsx b/apps/client/src/widgets/react/hooks.tsx index 63fa4fff1..82d01750c 100644 --- a/apps/client/src/widgets/react/hooks.tsx +++ b/apps/client/src/widgets/react/hooks.tsx @@ -265,11 +265,20 @@ export function useNoteContext() { const [ isReadOnlyTemporarilyDisabled, setIsReadOnlyTemporarilyDisabled ] = useState(noteContext?.viewScope?.isReadOnly); const [ refreshCounter, setRefreshCounter ] = useState(0); + useEffect(() => { + if (!noteContextContext) return; + setNoteContext(noteContextContext); + setNote(noteContextContext.note); + setNotePath(noteContextContext.notePath); + setViewScope(noteContextContext.viewScope); + }, [ noteContextContext ]); + useEffect(() => { setNote(noteContext?.note); }, [ notePath ]); useTriliumEvents([ "setNoteContext", "activeContextChanged", "noteSwitchedAndActivated", "noteSwitched" ], ({ noteContext }) => { + if (noteContextContext) return; setNoteContext(noteContext); setNotePath(noteContext.notePath); setViewScope(noteContext.viewScope);