mirror of
https://github.com/zadam/trilium.git
synced 2025-11-26 10:34:25 +01:00
Port Quick edit popup to React (#7840)
Some checks are pending
Checks / main (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Dev / Test development (push) Waiting to run
Dev / Build Docker image (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile) (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile.alpine) (push) Blocked by required conditions
/ Check Docker build (Dockerfile) (push) Waiting to run
/ Check Docker build (Dockerfile.alpine) (push) Waiting to run
/ Build Docker images (Dockerfile, ubuntu-24.04-arm, linux/arm64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.alpine, ubuntu-latest, linux/amd64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v7) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v8) (push) Blocked by required conditions
/ Merge manifest lists (push) Blocked by required conditions
playwright / E2E tests on linux-arm64 (push) Waiting to run
playwright / E2E tests on linux-x64 (push) Waiting to run
Some checks are pending
Checks / main (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Dev / Test development (push) Waiting to run
Dev / Build Docker image (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile) (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile.alpine) (push) Blocked by required conditions
/ Check Docker build (Dockerfile) (push) Waiting to run
/ Check Docker build (Dockerfile.alpine) (push) Waiting to run
/ Build Docker images (Dockerfile, ubuntu-24.04-arm, linux/arm64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.alpine, ubuntu-latest, linux/amd64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v7) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v8) (push) Blocked by required conditions
/ Merge manifest lists (push) Blocked by required conditions
playwright / E2E tests on linux-arm64 (push) Waiting to run
playwright / E2E tests on linux-x64 (push) Waiting to run
This commit is contained in:
commit
2d8b1299b3
@ -22,16 +22,8 @@ import RevisionsDialog from "../widgets/dialogs/revisions.js";
|
|||||||
import DeleteNotesDialog from "../widgets/dialogs/delete_notes.js";
|
import DeleteNotesDialog from "../widgets/dialogs/delete_notes.js";
|
||||||
import InfoDialog from "../widgets/dialogs/info.js";
|
import InfoDialog from "../widgets/dialogs/info.js";
|
||||||
import IncorrectCpuArchDialog from "../widgets/dialogs/incorrect_cpu_arch.js";
|
import IncorrectCpuArchDialog from "../widgets/dialogs/incorrect_cpu_arch.js";
|
||||||
import PopupEditorDialog from "../widgets/dialogs/popup_editor.js";
|
|
||||||
import FlexContainer from "../widgets/containers/flex_container.js";
|
|
||||||
import NoteIconWidget from "../widgets/note_icon";
|
|
||||||
import PromotedAttributesWidget from "../widgets/promoted_attributes.js";
|
|
||||||
import CallToActionDialog from "../widgets/dialogs/call_to_action.jsx";
|
import CallToActionDialog from "../widgets/dialogs/call_to_action.jsx";
|
||||||
import NoteTitleWidget from "../widgets/note_title.jsx";
|
import PopupEditorDialog from "../widgets/dialogs/PopupEditor.jsx";
|
||||||
import FormattingToolbar from "../widgets/ribbon/FormattingToolbar.js";
|
|
||||||
import NoteList from "../widgets/collections/NoteList.jsx";
|
|
||||||
import NoteDetail from "../widgets/NoteDetail.jsx";
|
|
||||||
import StandaloneRibbonAdapter from "../widgets/ribbon/components/StandaloneRibbonAdapter.jsx";
|
|
||||||
|
|
||||||
export function applyModals(rootContainer: RootContainer) {
|
export function applyModals(rootContainer: RootContainer) {
|
||||||
rootContainer
|
rootContainer
|
||||||
@ -57,16 +49,6 @@ export function applyModals(rootContainer: RootContainer) {
|
|||||||
.child(<ConfirmDialog />)
|
.child(<ConfirmDialog />)
|
||||||
.child(<PromptDialog />)
|
.child(<PromptDialog />)
|
||||||
.child(<IncorrectCpuArchDialog />)
|
.child(<IncorrectCpuArchDialog />)
|
||||||
.child(new PopupEditorDialog()
|
.child(<PopupEditorDialog />)
|
||||||
.child(new FlexContainer("row")
|
|
||||||
.class("title-row")
|
|
||||||
.css("align-items", "center")
|
|
||||||
.cssBlock(".title-row > * { margin: 5px; }")
|
|
||||||
.child(<NoteIconWidget />)
|
|
||||||
.child(<NoteTitleWidget />))
|
|
||||||
.child(<StandaloneRibbonAdapter component={FormattingToolbar} />)
|
|
||||||
.child(new PromotedAttributesWidget())
|
|
||||||
.child(<NoteDetail />)
|
|
||||||
.child(<NoteList media="screen" displayOnlyCollections />))
|
|
||||||
.child(<CallToActionDialog />);
|
.child(<CallToActionDialog />);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2591,7 +2591,7 @@ iframe.print-iframe {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scrolling-container > .note-detail.full-height,
|
.note-detail.full-height,
|
||||||
.scrolling-container > .note-list-widget.full-height {
|
.scrolling-container > .note-list-widget.full-height {
|
||||||
position: relative;
|
position: relative;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
|||||||
64
apps/client/src/widgets/dialogs/PopupEditor.css
Normal file
64
apps/client/src/widgets/dialogs/PopupEditor.css
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/** Reduce the z-index of modals so that ckeditor popups are properly shown on top of it. */
|
||||||
|
body.popup-editor-open > .modal-backdrop { z-index: 998; }
|
||||||
|
body.popup-editor-open .popup-editor-dialog { z-index: 999; }
|
||||||
|
body.popup-editor-open .ck-clipboard-drop-target-line { z-index: 1000; }
|
||||||
|
|
||||||
|
body.desktop .modal.popup-editor-dialog .modal-dialog {
|
||||||
|
max-width: 75vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal.popup-editor-dialog .modal-header .modal-title {
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal.popup-editor-dialog .modal-header .title-row {
|
||||||
|
flex-grow: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal.popup-editor-dialog .modal-header .title-row > * {
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal.popup-editor-dialog .modal-body {
|
||||||
|
padding: 0;
|
||||||
|
height: 75vh;
|
||||||
|
overflow: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal.popup-editor-dialog .note-detail-editable-text {
|
||||||
|
padding: 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal.popup-editor-dialog .title-row,
|
||||||
|
.modal.popup-editor-dialog .modal-title,
|
||||||
|
.modal.popup-editor-dialog .note-icon-widget {
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal.popup-editor-dialog .note-icon-widget {
|
||||||
|
width: 32px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal.popup-editor-dialog .note-icon-widget button.note-icon,
|
||||||
|
.modal.popup-editor-dialog .note-title-widget input.note-title {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal.popup-editor-dialog .classic-toolbar-widget {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
inset-inline-start: 0;
|
||||||
|
inset-inline-end: 0;
|
||||||
|
background: var(--modal-background-color);
|
||||||
|
z-index: 998;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal.popup-editor-dialog .note-detail-file {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
85
apps/client/src/widgets/dialogs/PopupEditor.tsx
Normal file
85
apps/client/src/widgets/dialogs/PopupEditor.tsx
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import { useContext, useEffect, useRef, useState } from "preact/hooks";
|
||||||
|
import Modal from "../react/Modal";
|
||||||
|
import "./PopupEditor.css";
|
||||||
|
import { useNoteContext, 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";
|
||||||
|
import { ComponentChildren } from "preact";
|
||||||
|
import NoteList from "../collections/NoteList";
|
||||||
|
import StandaloneRibbonAdapter from "../ribbon/components/StandaloneRibbonAdapter";
|
||||||
|
import FormattingToolbar from "../ribbon/FormattingToolbar";
|
||||||
|
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add a global class to be able to handle issues with z-index due to rendering in a popup.
|
||||||
|
useEffect(() => {
|
||||||
|
document.body.classList.toggle("popup-editor-open", shown);
|
||||||
|
}, [shown]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NoteContextContext.Provider value={noteContext}>
|
||||||
|
<DialogWrapper>
|
||||||
|
<Modal
|
||||||
|
title={<TitleRow />}
|
||||||
|
className="popup-editor-dialog"
|
||||||
|
size="lg"
|
||||||
|
show={shown}
|
||||||
|
onShown={() => {
|
||||||
|
parentComponent?.handleEvent("focusOnDetail", { ntxId: noteContext.ntxId });
|
||||||
|
}}
|
||||||
|
onHidden={() => setShown(false)}
|
||||||
|
>
|
||||||
|
<StandaloneRibbonAdapter component={FormattingToolbar} />
|
||||||
|
<NoteDetail />
|
||||||
|
<NoteList media="screen" displayOnlyCollections />
|
||||||
|
</Modal>
|
||||||
|
</DialogWrapper>
|
||||||
|
</NoteContextContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DialogWrapper({ children }: { children: ComponentChildren }) {
|
||||||
|
const { note } = useNoteContext();
|
||||||
|
const wrapperRef = useRef<HTMLDivElement>(null);
|
||||||
|
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 ]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div ref={wrapperRef} class={`quick-edit-dialog-wrapper ${note?.getColorClass() ?? ""} ${hasTint ? "tinted-quick-edit-dialog" : ""}`}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function TitleRow() {
|
||||||
|
return (
|
||||||
|
<div className="title-row">
|
||||||
|
<NoteIcon />
|
||||||
|
<NoteTitleWidget />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -1,187 +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";
|
|
||||||
|
|
||||||
const TPL = /*html*/`\
|
|
||||||
<div class="popup-editor-dialog modal fade mx-auto" tabindex="-1" role="dialog">
|
|
||||||
<style>
|
|
||||||
/** Reduce the z-index of modals so that ckeditor popups are properly shown on top of it. */
|
|
||||||
body.popup-editor-open > .modal-backdrop { z-index: 998; }
|
|
||||||
body.popup-editor-open .popup-editor-dialog { z-index: 999; }
|
|
||||||
body.popup-editor-open .ck-clipboard-drop-target-line { z-index: 1000; }
|
|
||||||
|
|
||||||
body.desktop .modal.popup-editor-dialog .modal-dialog {
|
|
||||||
max-width: 75vw;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal.popup-editor-dialog .modal-header .modal-title {
|
|
||||||
font-size: 1.1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal.popup-editor-dialog .modal-body {
|
|
||||||
padding: 0;
|
|
||||||
height: 75vh;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal.popup-editor-dialog .note-detail-editable-text {
|
|
||||||
padding: 0 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal.popup-editor-dialog .title-row,
|
|
||||||
.modal.popup-editor-dialog .modal-title,
|
|
||||||
.modal.popup-editor-dialog .note-icon-widget {
|
|
||||||
height: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal.popup-editor-dialog .note-icon-widget {
|
|
||||||
width: 32px;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal.popup-editor-dialog .note-icon-widget button.note-icon,
|
|
||||||
.modal.popup-editor-dialog .note-title-widget input.note-title {
|
|
||||||
font-size: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal.popup-editor-dialog .classic-toolbar-widget {
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
inset-inline-start: 0;
|
|
||||||
inset-inline-end: 0;
|
|
||||||
background: var(--modal-background-color);
|
|
||||||
z-index: 998;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal.popup-editor-dialog .note-detail-file {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div class="quick-edit-dialog-wrapper">
|
|
||||||
<div class="modal-dialog modal-lg" role="document">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<div class="modal-title">
|
|
||||||
<!-- This is where the first child will be injected -->
|
|
||||||
</div>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="modal-body">
|
|
||||||
<!-- This is where all but the first child will be injected. -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default class PopupEditorDialog extends Container<BasicWidget> {
|
|
||||||
|
|
||||||
private noteContext: NoteContext;
|
|
||||||
private $modalHeader!: JQuery<HTMLElement>;
|
|
||||||
private $modalBody!: JQuery<HTMLElement>;
|
|
||||||
private $wrapper!: JQuery<HTMLDivElement>;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.noteContext = new NoteContext("_popup-editor");
|
|
||||||
}
|
|
||||||
|
|
||||||
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 $dialog = await openDialog(this.$widget, false, {
|
|
||||||
focus: false
|
|
||||||
});
|
|
||||||
|
|
||||||
await this.noteContext.setNote(noteIdOrPath, {
|
|
||||||
viewScope: {
|
|
||||||
readOnlyTemporarilyDisabled: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
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 () => {
|
|
||||||
await this.handleEventInChildren("activeContextChanged", { noteContext: this.noteContext });
|
|
||||||
this.setVisibility(true);
|
|
||||||
await this.handleEventInChildren("focusOnDetail", { ntxId: this.noteContext.ntxId });
|
|
||||||
});
|
|
||||||
$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<T extends EventNames>(name: T, data: EventData<T>): Promise<unknown[] | unknown> | 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -2,7 +2,7 @@ import { CSSProperties } from "preact/compat";
|
|||||||
import { DragData } from "../note_tree";
|
import { DragData } from "../note_tree";
|
||||||
import { FilterLabelsByType, KeyboardActionNames, OptionNames, RelationNames } from "@triliumnext/commons";
|
import { FilterLabelsByType, KeyboardActionNames, OptionNames, RelationNames } from "@triliumnext/commons";
|
||||||
import { MutableRef, useCallback, useContext, useDebugValue, useEffect, useLayoutEffect, useMemo, useRef, useState } from "preact/hooks";
|
import { MutableRef, useCallback, useContext, useDebugValue, useEffect, useLayoutEffect, useMemo, useRef, useState } from "preact/hooks";
|
||||||
import { ParentComponent, refToJQuerySelector } from "./react_utils";
|
import { NoteContextContext, ParentComponent, refToJQuerySelector } from "./react_utils";
|
||||||
import { RefObject, VNode } from "preact";
|
import { RefObject, VNode } from "preact";
|
||||||
import { Tooltip } from "bootstrap";
|
import { Tooltip } from "bootstrap";
|
||||||
import { ViewMode, ViewScope } from "../../services/link";
|
import { ViewMode, ViewScope } from "../../services/link";
|
||||||
@ -257,18 +257,29 @@ export function useUniqueName(prefix?: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function useNoteContext() {
|
export function useNoteContext() {
|
||||||
const [ noteContext, setNoteContext ] = useState<NoteContext>();
|
const noteContextContext = useContext(NoteContextContext);
|
||||||
|
const [ noteContext, setNoteContext ] = useState<NoteContext | undefined>(noteContextContext ?? undefined);
|
||||||
const [ notePath, setNotePath ] = useState<string | null | undefined>();
|
const [ notePath, setNotePath ] = useState<string | null | undefined>();
|
||||||
const [ note, setNote ] = useState<FNote | null | undefined>();
|
const [ note, setNote ] = useState<FNote | null | undefined>();
|
||||||
const [ , setViewScope ] = useState<ViewScope>();
|
const [ , setViewScope ] = useState<ViewScope>();
|
||||||
const [ isReadOnlyTemporarilyDisabled, setIsReadOnlyTemporarilyDisabled ] = useState<boolean | null | undefined>(noteContext?.viewScope?.isReadOnly);
|
const [ isReadOnlyTemporarilyDisabled, setIsReadOnlyTemporarilyDisabled ] = useState<boolean | null | undefined>(noteContext?.viewScope?.isReadOnly);
|
||||||
const [ refreshCounter, setRefreshCounter ] = useState(0);
|
const [ refreshCounter, setRefreshCounter ] = useState(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!noteContextContext) return;
|
||||||
|
setNoteContext(noteContextContext);
|
||||||
|
setNote(noteContextContext.note);
|
||||||
|
setNotePath(noteContextContext.notePath);
|
||||||
|
setViewScope(noteContextContext.viewScope);
|
||||||
|
setIsReadOnlyTemporarilyDisabled(noteContextContext?.viewScope?.readOnlyTemporarilyDisabled);
|
||||||
|
}, [ noteContextContext ]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setNote(noteContext?.note);
|
setNote(noteContext?.note);
|
||||||
}, [ notePath ]);
|
}, [ notePath ]);
|
||||||
|
|
||||||
useTriliumEvents([ "setNoteContext", "activeContextChanged", "noteSwitchedAndActivated", "noteSwitched" ], ({ noteContext }) => {
|
useTriliumEvents([ "setNoteContext", "activeContextChanged", "noteSwitchedAndActivated", "noteSwitched" ], ({ noteContext }) => {
|
||||||
|
if (noteContextContext) return;
|
||||||
setNoteContext(noteContext);
|
setNoteContext(noteContext);
|
||||||
setNotePath(noteContext.notePath);
|
setNotePath(noteContext.notePath);
|
||||||
setViewScope(noteContext.viewScope);
|
setViewScope(noteContext.viewScope);
|
||||||
@ -282,6 +293,7 @@ export function useNoteContext() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
useTriliumEvent("readOnlyTemporarilyDisabled", ({ noteContext: eventNoteContext }) => {
|
useTriliumEvent("readOnlyTemporarilyDisabled", ({ noteContext: eventNoteContext }) => {
|
||||||
|
if (noteContextContext) return;
|
||||||
if (eventNoteContext.ntxId === noteContext?.ntxId) {
|
if (eventNoteContext.ntxId === noteContext?.ntxId) {
|
||||||
setIsReadOnlyTemporarilyDisabled(eventNoteContext?.viewScope?.readOnlyTemporarilyDisabled);
|
setIsReadOnlyTemporarilyDisabled(eventNoteContext?.viewScope?.readOnlyTemporarilyDisabled);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,11 @@
|
|||||||
import { ComponentChild, createContext, render, type JSX, type RefObject } from "preact";
|
import { ComponentChild, createContext, render, type JSX, type RefObject } from "preact";
|
||||||
import Component from "../../components/component";
|
import Component from "../../components/component";
|
||||||
|
import NoteContext from "../../components/note_context";
|
||||||
|
|
||||||
export const ParentComponent = createContext<Component | null>(null);
|
export const ParentComponent = createContext<Component | null>(null);
|
||||||
|
|
||||||
|
export const NoteContextContext = createContext<NoteContext | null>(null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes in a React ref and returns a corresponding JQuery selector.
|
* Takes in a React ref and returns a corresponding JQuery selector.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -163,7 +163,12 @@ function useResizer(containerRef: RefObject<HTMLDivElement>, noteId: string, svg
|
|||||||
pan: zoomInstance.getPan(),
|
pan: zoomInstance.getPan(),
|
||||||
zoom: zoomInstance.getZoom()
|
zoom: zoomInstance.getZoom()
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
zoomInstance.destroy();
|
zoomInstance.destroy();
|
||||||
|
} catch (e) {
|
||||||
|
// Sometimes crashes with "Matrix is not invertible" which can cause havoc such as breaking the popup editor from ever showing up again.
|
||||||
|
console.warn(e);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}, [ svg ]);
|
}, [ svg ]);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user