diff --git a/apps/client/src/widgets/bookmark_switch.ts b/apps/client/src/widgets/bookmark_switch.ts deleted file mode 100644 index 93d4789aa..000000000 --- a/apps/client/src/widgets/bookmark_switch.ts +++ /dev/null @@ -1,54 +0,0 @@ -import SwitchWidget from "./switch.js"; -import server from "../services/server.js"; -import toastService from "../services/toast.js"; -import { t } from "../services/i18n.js"; -import type FNote from "../entities/fnote.js"; -import type { EventData } from "../components/app_context.js"; - -// TODO: Deduplicate -type Response = { - success: true; -} | { - success: false; - message: string; -} - -export default class BookmarkSwitchWidget extends SwitchWidget { - isEnabled() { - return ( - super.isEnabled() && - // it's not possible to bookmark root because that would clone it under bookmarks and thus create a cycle - !["root", "_hidden"].includes(this.noteId ?? "") - ); - } - - doRender() { - super.doRender(); - - this.switchOnName = t("bookmark_switch.bookmark"); - this.switchOnTooltip = t("bookmark_switch.bookmark_this_note"); - - this.switchOffName = t("bookmark_switch.bookmark"); - this.switchOffTooltip = t("bookmark_switch.remove_bookmark"); - } - - async toggle(state: boolean | null | undefined) { - const resp = await server.put(`notes/${this.noteId}/toggle-in-parent/_lbBookmarks/${!!state}`); - - if (!resp.success && "message" in resp) { - toastService.showError(resp.message); - } - } - - async refreshWithNote(note: FNote) { - const isBookmarked = !!note.getParentBranches().find((b) => b.parentNoteId === "_lbBookmarks"); - - this.isToggled = isBookmarked; - } - - entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { - if (loadResults.getBranchRows().find((b) => b.noteId === this.noteId)) { - this.refresh(); - } - } -} diff --git a/apps/client/src/widgets/react/FormToggle.tsx b/apps/client/src/widgets/react/FormToggle.tsx index a6dc2fe1d..c41ea6750 100644 --- a/apps/client/src/widgets/react/FormToggle.tsx +++ b/apps/client/src/widgets/react/FormToggle.tsx @@ -10,16 +10,17 @@ interface FormToggleProps { switchOffName: string; switchOffTooltip: string; helpPage?: string; + disabled?: boolean; } -export default function FormToggle({ currentValue, helpPage, switchOnName, switchOnTooltip, switchOffName, switchOffTooltip, onChange }: FormToggleProps) { +export default function FormToggle({ currentValue, helpPage, switchOnName, switchOnTooltip, switchOffName, switchOffTooltip, onChange, disabled }: FormToggleProps) { return (
{ currentValue ? switchOffName : switchOnName } diff --git a/apps/client/src/widgets/ribbon/BasicPropertiesTab.tsx b/apps/client/src/widgets/ribbon/BasicPropertiesTab.tsx index 733c2dbe2..918d01760 100644 --- a/apps/client/src/widgets/ribbon/BasicPropertiesTab.tsx +++ b/apps/client/src/widgets/ribbon/BasicPropertiesTab.tsx @@ -1,17 +1,18 @@ -import { useCallback, useMemo } from "preact/hooks"; +import { useCallback, useEffect, useMemo, useState } from "preact/hooks"; import Dropdown from "../react/Dropdown"; import { NOTE_TYPES } from "../../services/note_types"; import { FormDivider, FormListBadge, FormListItem } from "../react/FormList"; import { t } from "../../services/i18n"; -import { useNoteContext, useNoteLabel, useNoteLabelBoolean, useNoteProperty, useTriliumOption } from "../react/hooks"; +import { useNoteContext, useNoteLabel, useNoteLabelBoolean, useNoteProperty, useTriliumEventBeta, useTriliumOption } from "../react/hooks"; import mime_types from "../../services/mime_types"; -import { NoteType } from "@triliumnext/commons"; +import { NoteType, ToggleInParentResponse } from "@triliumnext/commons"; import server from "../../services/server"; import dialog from "../../services/dialog"; import FormToggle from "../react/FormToggle"; import FNote from "../../entities/fnote"; import protected_session from "../../services/protected_session"; import FormDropdownList from "../react/FormDropdownList"; +import toast from "../../services/toast"; export default function BasicPropertiesTab() { const { note } = useNoteContext(); @@ -21,6 +22,7 @@ export default function BasicPropertiesTab() { +
); } @@ -114,10 +116,10 @@ function ProtectedNoteSwitch({ note }: { note?: FNote | null }) { return (
note && protected_session.protectNote(note.noteId, shouldProtect, false)} switchOnName={t("protect_note.toggle-on")} switchOnTooltip={t("protect_note.toggle-on-hint")} switchOffName={t("protect_note.toggle-off")} switchOffTooltip={t("protect_note.toggle-off-hint")} + currentValue={isProtected} + onChange={(shouldProtect) => note && protected_session.protectNote(note.noteId, shouldProtect, false)} />
) @@ -163,6 +165,40 @@ function EditabilitySelect({ note }: { note?: FNote | null }) { ) } +function BookmarkSwitch({ note }: { note?: FNote | null }) { + const [ isBookmarked, setIsBookmarked ] = useState(false); + const refreshState = useCallback(() => { + const isBookmarked = note && !!note.getParentBranches().find((b) => b.parentNoteId === "_lbBookmarks"); + setIsBookmarked(!!isBookmarked); + }, [ note ]); + + useEffect(() => refreshState(), [ note ]); + useTriliumEventBeta("entitiesReloaded", ({ loadResults }) => { + if (note && loadResults.getBranchRows().find((b) => b.noteId === note.noteId)) { + refreshState(); + } + }); + + return ( +
+ { + if (!note) return; + const resp = await server.put(`notes/${note.noteId}/toggle-in-parent/_lbBookmarks/${shouldBookmark}`); + + if (!resp.success && "message" in resp) { + toast.showError(resp.message); + } + }} + disabled={["root", "_hidden"].includes(note?.noteId ?? "")} + /> +
+ ) +} + function findTypeTitle(type?: NoteType, mime?: string | null) { if (type === "code") { const mimeTypes = mime_types.getMimeTypes(); diff --git a/apps/client/src/widgets/ribbon_widgets/basic_properties.ts b/apps/client/src/widgets/ribbon_widgets/basic_properties.ts index f80e163a8..e4127e0bc 100644 --- a/apps/client/src/widgets/ribbon_widgets/basic_properties.ts +++ b/apps/client/src/widgets/ribbon_widgets/basic_properties.ts @@ -10,8 +10,6 @@ import type FNote from "../../entities/fnote.js"; import NoteLanguageWidget from "../note_language.js"; const TPL = /*html*/` -
-
@@ -23,8 +21,6 @@ const TPL = /*html*/` export default class BasicPropertiesWidget extends NoteContextAwareWidget { - private editabilitySelectWidget: EditabilitySelectWidget; - private bookmarkSwitchWidget: BookmarkSwitchWidget; private sharedSwitchWidget: SharedSwitchWidget; private templateSwitchWidget: TemplateSwitchWidget; private noteLanguageWidget: NoteLanguageWidget; @@ -32,15 +28,11 @@ export default class BasicPropertiesWidget extends NoteContextAwareWidget { constructor() { super(); - this.editabilitySelectWidget = new EditabilitySelectWidget().contentSized(); - this.bookmarkSwitchWidget = new BookmarkSwitchWidget().contentSized(); this.sharedSwitchWidget = new SharedSwitchWidget().contentSized(); this.templateSwitchWidget = new TemplateSwitchWidget().contentSized(); this.noteLanguageWidget = new NoteLanguageWidget().contentSized(); this.child( - this.editabilitySelectWidget, - this.bookmarkSwitchWidget, this.sharedSwitchWidget, this.templateSwitchWidget, this.noteLanguageWidget); diff --git a/apps/client/src/widgets/switch.ts b/apps/client/src/widgets/switch.ts index 8c521fb99..1f5956a6e 100644 --- a/apps/client/src/widgets/switch.ts +++ b/apps/client/src/widgets/switch.ts @@ -40,9 +40,6 @@ export default class SwitchWidget extends NoteContextAwareWidget { } set canToggle(isEnabled) { - this.$switchButton.toggleClass("disabled", !isEnabled); - this.$switchToggle.attr("disabled", !isEnabled ? "disabled" : null); - if (isEnabled) { this.isToggled = this.currentState; // Reapply the correct tooltip } else { diff --git a/packages/commons/src/lib/server_api.ts b/packages/commons/src/lib/server_api.ts index e660e049c..311e45fb0 100644 --- a/packages/commons/src/lib/server_api.ts +++ b/packages/commons/src/lib/server_api.ts @@ -155,3 +155,10 @@ export interface OpenAiOrAnthropicModelResponse { type: string; }>; } + +export type ToggleInParentResponse = { + success: true; +} | { + success: false; + message: string; +}