From f18ac3a9234a912eb2657d9593193fcb6dcd0c55 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Wed, 10 Dec 2025 18:20:23 +0200 Subject: [PATCH] feat(note_actions): integrate bookmark into new layout --- .../src/widgets/ribbon/BasicPropertiesTab.tsx | 54 +++++++++++-------- .../client/src/widgets/ribbon/NoteActions.tsx | 14 ++++- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/apps/client/src/widgets/ribbon/BasicPropertiesTab.tsx b/apps/client/src/widgets/ribbon/BasicPropertiesTab.tsx index 11a843233..dc14284f3 100644 --- a/apps/client/src/widgets/ribbon/BasicPropertiesTab.tsx +++ b/apps/client/src/widgets/ribbon/BasicPropertiesTab.tsx @@ -21,6 +21,9 @@ import Modal from "../react/Modal"; import { CodeMimeTypesList } from "../type_widgets/options/code_notes"; import { ContentLanguagesList } from "../type_widgets/options/i18n"; import { LocaleSelector } from "../type_widgets/options/components/LocaleSelector"; +import { isExperimentalFeatureEnabled } from "../../services/experimental_features"; + +const isNewLayout = isExperimentalFeatureEnabled("new-layout"); export default function BasicPropertiesTab({ note }: TabContext) { return ( @@ -28,7 +31,7 @@ export default function BasicPropertiesTab({ note }: TabContext) { - + {!isNewLayout && } @@ -191,18 +194,7 @@ 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 ]); - useTriliumEvent("entitiesReloaded", ({ loadResults }) => { - if (note && loadResults.getBranchRows().find((b) => b.noteId === note.noteId)) { - refreshState(); - } - }); + const [ isBookmarked, setIsBookmarked ] = useNoteBookmarkState(note); return (
@@ -210,18 +202,36 @@ function BookmarkSwitch({ note }: { note?: FNote | null }) { switchOnName={t("bookmark_switch.bookmark")} switchOnTooltip={t("bookmark_switch.bookmark_this_note")} switchOffName={t("bookmark_switch.bookmark")} switchOffTooltip={t("bookmark_switch.remove_bookmark")} currentValue={isBookmarked} - onChange={async (shouldBookmark) => { - 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); - } - }} + onChange={setIsBookmarked} disabled={["root", "_hidden"].includes(note?.noteId ?? "")} />
- ) + ); +} + +export function useNoteBookmarkState(note: FNote | null | undefined) { + const [ isBookmarked, setIsBookmarked ] = useState(false); + const refreshState = useCallback(() => { + const isBookmarked = note && !!note.getParentBranches().find((b) => b.parentNoteId === "_lbBookmarks"); + setIsBookmarked(!!isBookmarked); + }, [ note ]); + + const changeHandler = useCallback(async (shouldBookmark: boolean) => { + 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); + } + }, [ note ]); + + useEffect(() => refreshState(), [ refreshState ]); + useTriliumEvent("entitiesReloaded", ({ loadResults }) => { + if (note && loadResults.getBranchRows().find((b) => b.noteId === note.noteId)) { + refreshState(); + } + }); + return [ isBookmarked, changeHandler ] as const; } function TemplateSwitch({ note }: { note?: FNote | null }) { diff --git a/apps/client/src/widgets/ribbon/NoteActions.tsx b/apps/client/src/widgets/ribbon/NoteActions.tsx index 12655262e..ee5c949d7 100644 --- a/apps/client/src/widgets/ribbon/NoteActions.tsx +++ b/apps/client/src/widgets/ribbon/NoteActions.tsx @@ -13,10 +13,11 @@ import { isElectron as getIsElectron, isMac as getIsMac } from "../../services/u import ws from "../../services/ws"; import ActionButton from "../react/ActionButton"; import Dropdown from "../react/Dropdown"; -import { FormDropdownDivider, FormDropdownSubmenu, FormListItem } from "../react/FormList"; +import { FormDropdownDivider, FormDropdownSubmenu, FormListItem, FormListToggleableItem } from "../react/FormList"; import { useIsNoteReadOnly, useNoteContext, useNoteLabel, useNoteProperty, useTriliumOption } from "../react/hooks"; import { ParentComponent } from "../react/react_utils"; import { isExperimentalFeatureEnabled } from "../../services/experimental_features"; +import { useNoteBookmarkState } from "./BasicPropertiesTab"; const isNewLayout = isExperimentalFeatureEnabled("new-layout"); @@ -79,6 +80,9 @@ function NoteContextMenu({ note, noteContext }: { note: FNote, noteContext?: Not {isElectron && } + {isNewLayout && } + + parentComponent?.triggerCommand("showImportDialog", { noteId: note.noteId })} /> @@ -112,6 +116,14 @@ function NoteContextMenu({ note, noteContext }: { note: FNote, noteContext?: Not ); } +function NoteBasicProperties({ note }: { note: FNote }) { + const [ isBookmarked, setIsBookmarked ] = useNoteBookmarkState(note); + + return <> + + ; +} + function DevelopmentActions({ note, noteContext }: { note: FNote, noteContext?: NoteContext }) { return (