diff --git a/apps/client/src/widgets/layout/Breadcrumb.tsx b/apps/client/src/widgets/layout/Breadcrumb.tsx index a836f8a5f..bc445068a 100644 --- a/apps/client/src/widgets/layout/Breadcrumb.tsx +++ b/apps/client/src/widgets/layout/Breadcrumb.tsx @@ -6,7 +6,6 @@ import { Fragment } from "preact/jsx-runtime"; import appContext from "../../components/app_context"; import Component from "../../components/component"; import NoteContext from "../../components/note_context"; -import FNote from "../../entities/fnote"; import contextMenu, { MenuItem } from "../../menus/context_menu"; import NoteColorPicker from "../../menus/custom-items/NoteColorPicker"; import link_context_menu from "../../menus/link_context_menu"; @@ -24,7 +23,7 @@ import ActionButton from "../react/ActionButton"; import { Badge } from "../react/Badge"; import Dropdown from "../react/Dropdown"; import { FormListItem } from "../react/FormList"; -import { useChildNotes, useNote, useNoteIcon, useNoteLabel, useNoteLabelBoolean, useNoteProperty, useStaticTooltip } from "../react/hooks"; +import { useActiveNoteContext, useChildNotes, useNote, useNoteIcon, useNoteLabel, useNoteLabelBoolean, useNoteProperty, useStaticTooltip } from "../react/hooks"; import Icon from "../react/Icon"; import NoteLink from "../react/NoteLink"; import { ParentComponent } from "../react/react_utils"; @@ -33,37 +32,37 @@ const COLLAPSE_THRESHOLD = 5; const INITIAL_ITEMS = 2; const FINAL_ITEMS = 2; -export default function Breadcrumb({ note, noteContext }: { note: FNote, noteContext: NoteContext }) { - const notePath = buildNotePaths(noteContext); +export default function Breadcrumb() { + const { note, notePaths, noteContext } = useNotePaths(); const parentComponent = useContext(ParentComponent); return (
- {notePath.length > COLLAPSE_THRESHOLD ? ( + {notePaths.length > COLLAPSE_THRESHOLD ? ( <> - {notePath.slice(0, INITIAL_ITEMS).map((item, index) => ( + {notePaths.slice(0, INITIAL_ITEMS).map((item, index) => ( - - + + ))} - - {notePath.slice(-FINAL_ITEMS).map((item, index) => ( + + {notePaths.slice(-FINAL_ITEMS).map((item, index) => ( - - + + ))} ) : ( - notePath.map((item, index) => ( + notePaths.map((item, index) => ( {index === 0 ? - : + : } - {(index < notePath.length - 1 || note?.hasChildren()) && - } + {(index < notePaths.length - 1 || note?.hasChildren()) && + } )) )} @@ -239,16 +238,16 @@ function BreadcrumbCollapsed({ items, noteContext }: { items: string[], noteCont ); } -function buildNotePaths(noteContext: NoteContext) { - const notePathArray = noteContext.notePathArray; - if (!notePathArray) return []; +function useNotePaths() { + const { note, notePath, hoistedNoteId, noteContext } = useActiveNoteContext(); + const notePathArray = (notePath ?? "").split("/"); let prefix = ""; let output: string[] = []; let pos = 0; let hoistedNotePos = -1; for (const notePath of notePathArray) { - if (noteContext.hoistedNoteId !== "root" && notePath === noteContext.hoistedNoteId) { + if (hoistedNoteId !== "root" && notePath === hoistedNoteId) { hoistedNotePos = pos; } output.push(`${prefix}${notePath}`); @@ -257,11 +256,15 @@ function buildNotePaths(noteContext: NoteContext) { } // When hoisted, display only the path starting with the hoisted note. - if (noteContext.hoistedNoteId !== "root" && hoistedNotePos > -1) { + if (hoistedNoteId !== "root" && hoistedNotePos > -1) { output = output.slice(hoistedNotePos); } - return output; + return { + note, + notePaths: output, + noteContext + }; } //#region Context menu diff --git a/apps/client/src/widgets/layout/StatusBar.tsx b/apps/client/src/widgets/layout/StatusBar.tsx index 4d3a273cf..9b99524b0 100644 --- a/apps/client/src/widgets/layout/StatusBar.tsx +++ b/apps/client/src/widgets/layout/StatusBar.tsx @@ -64,7 +64,7 @@ export default function StatusBar() {
{context && attributesContext && noteInfoContext && <> - +
diff --git a/apps/client/src/widgets/react/hooks.tsx b/apps/client/src/widgets/react/hooks.tsx index d01fb8156..36c142505 100644 --- a/apps/client/src/widgets/react/hooks.tsx +++ b/apps/client/src/widgets/react/hooks.tsx @@ -20,6 +20,7 @@ import server from "../../services/server"; import shortcuts, { Handler, removeIndividualBinding } from "../../services/shortcuts"; import SpacedUpdate from "../../services/spaced_update"; import toast, { ToastOptions } from "../../services/toast"; +import tree from "../../services/tree"; import utils, { escapeRegExp, randomString, reloadFrontendApp } from "../../services/utils"; import BasicWidget, { ReactWrappedWidget } from "../basic_widget"; import NoteContextAwareWidget from "../note_context_aware_widget"; @@ -386,6 +387,16 @@ export function useActiveNoteContext() { setHoistedNoteId(noteId); } }); + /** + * Note context doesn't actually refresh at all if the active note is moved around (e.g. the note path changes). + * Address that by listening to note changes. + */ + useTriliumEvent("entitiesReloaded", async ({ loadResults }) => { + if (note && notePath && loadResults.getBranchRows().some(b => b.noteId === note.noteId)) { + const resolvedNotePath = await tree.resolveNotePath(notePath, hoistedNoteId); + setNotePath(resolvedNotePath); + } + }); const parentComponent = useContext(ParentComponent) as ReactWrappedWidget; useDebugValue(() => `notePath=${notePath}, ntxId=${noteContext?.ntxId}`); @@ -393,7 +404,8 @@ export function useActiveNoteContext() { return { note, noteId: noteContext?.note?.noteId, - notePath: noteContext?.notePath, + /** The note path of the note context. Unlike `noteContext.notePath`, this one actually reacts to the active note being moved around. */ + notePath, hoistedNoteId, ntxId: noteContext?.ntxId, viewScope: noteContext?.viewScope,