From e290635ba5fc63ddf71eb1e94af021c01ac4d8d6 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Wed, 27 Aug 2025 22:09:00 +0300 Subject: [PATCH] feat(react/floating_buttons): port toggle read only button --- apps/client/src/widgets/FloatingButtons.tsx | 33 +++++++++-- .../toggle_read_only_button.ts | 58 ------------------- 2 files changed, 29 insertions(+), 62 deletions(-) delete mode 100644 apps/client/src/widgets/floating_buttons/toggle_read_only_button.ts diff --git a/apps/client/src/widgets/FloatingButtons.tsx b/apps/client/src/widgets/FloatingButtons.tsx index 04936d1fe..60ef54a74 100644 --- a/apps/client/src/widgets/FloatingButtons.tsx +++ b/apps/client/src/widgets/FloatingButtons.tsx @@ -4,11 +4,12 @@ import Button from "./react/Button"; import ActionButton from "./react/ActionButton"; import FNote from "../entities/fnote"; import NoteContext from "../components/note_context"; -import { useNoteContext, useNoteLabel, useNoteLabelBoolean, useTriliumOption } from "./react/hooks"; -import { useContext, useEffect, useMemo } from "preact/hooks"; +import { useNoteContext, useNoteLabel, useNoteLabelBoolean, useTriliumEvent, useTriliumOption, useTriliumOptionBool } from "./react/hooks"; +import { useContext, useEffect, useMemo, useState } from "preact/hooks"; import { ParentComponent } from "./react/react_utils"; import Component from "../components/component"; import { VNode } from "preact"; +import attributes from "../services/attributes"; interface FloatingButtonContext { parentComponent: Component; @@ -29,6 +30,13 @@ const FLOATING_BUTTON_DEFINITIONS: FloatingButtonDefinition[] = [ { component: SwitchSplitOrientationButton, isEnabled: ({ note, noteContext }) => note.type === "mermaid" && note.isContentAvailable() && !note.hasLabel("readOnly") && noteContext.viewScope?.viewMode === "default" + }, + { + component: ToggleReadOnlyButton, + isEnabled: ({ note, noteContext }) => + (note.type === "mermaid" || note.getLabelValue("viewType") === "geoMap") + && note.isContentAvailable() + && noteContext.viewScope?.viewMode === "default" } ]; @@ -52,11 +60,18 @@ export default function FloatingButtons() { }; }, [ note, noteContext, parentComponent ]); - const isReadOnly = useNoteLabelBoolean(note, "readOnly"); + // Refresh on any note attribute change. + const [ refreshCounter, setRefreshCounter ] = useState(0); + useTriliumEvent("entitiesReloaded", ({ loadResults }) => { + if (loadResults.getAttributeRows().find(attrRow => attributes.isAffecting(attrRow, note))) { + setRefreshCounter(refreshCounter+1); + } + }); + const definitions = useMemo(() => { if (!context) return []; return FLOATING_BUTTON_DEFINITIONS.filter(def => def.isEnabled(context)); - }, [ context, isReadOnly ]); + }, [ context, refreshCounter ]); return (
@@ -90,6 +105,16 @@ function SwitchSplitOrientationButton({ }: FloatingButtonContext) { /> } +function ToggleReadOnlyButton({ note }: FloatingButtonContext) { + const [ isReadOnly, setReadOnly ] = useNoteLabelBoolean(note, "readOnly"); + + return setReadOnly(!isReadOnly)} + /> +} + /** * Show button that displays floating button after click on close button */ diff --git a/apps/client/src/widgets/floating_buttons/toggle_read_only_button.ts b/apps/client/src/widgets/floating_buttons/toggle_read_only_button.ts deleted file mode 100644 index 571e99017..000000000 --- a/apps/client/src/widgets/floating_buttons/toggle_read_only_button.ts +++ /dev/null @@ -1,58 +0,0 @@ -import type FNote from "../../entities/fnote.js"; -import attributes from "../../services/attributes.js"; -import { t } from "../../services/i18n.js"; -import OnClickButtonWidget from "../buttons/onclick_button.js"; - -export default class ToggleReadOnlyButton extends OnClickButtonWidget { - - private isReadOnly?: boolean; - - constructor() { - super(); - - this - .title(() => this.isReadOnly ? t("toggle_read_only_button.unlock-editing") : t("toggle_read_only_button.lock-editing")) - .titlePlacement("bottom") - .icon(() => this.isReadOnly ? "bx-lock-open-alt" : "bx-lock-alt") - .onClick(() => this.#toggleReadOnly()); - } - - #toggleReadOnly() { - if (!this.noteId || !this.note) { - return; - } - - if (this.isReadOnly) { - attributes.removeOwnedLabelByName(this.note, "readOnly"); - } else { - attributes.setLabel(this.noteId, "readOnly"); - } - } - - async refreshWithNote(note: FNote | null | undefined) { - const isReadOnly = !!note?.hasLabel("readOnly"); - - if (isReadOnly !== this.isReadOnly) { - this.isReadOnly = isReadOnly; - this.refreshIcon(); - } - } - - isEnabled() { - if (!super.isEnabled()) { - return false; - } - - if (!this?.note?.isContentAvailable()) { - return false; - } - - if (this.noteContext?.viewScope?.viewMode !== "default") { - return false; - } - - return this.note.type === "mermaid" || - (this.note.getLabelValue("viewType") === "geoMap"); - } - -}