diff --git a/apps/client/src/widgets/launch_bar/BookmarkButtons.tsx b/apps/client/src/widgets/launch_bar/BookmarkButtons.tsx index 76286c288..f3b88c7aa 100644 --- a/apps/client/src/widgets/launch_bar/BookmarkButtons.tsx +++ b/apps/client/src/widgets/launch_bar/BookmarkButtons.tsx @@ -20,7 +20,7 @@ export default function BookmarkButtons() { return (
- {childNotes?.map(childNote => )} + {childNotes?.map(childNote => )}
) } @@ -48,8 +48,8 @@ function BookmarkFolder({ note }: { note: FNote }) { diff --git a/apps/client/src/widgets/launch_bar/Calendar.tsx b/apps/client/src/widgets/launch_bar/Calendar.tsx index d619f768c..f081eee8c 100644 --- a/apps/client/src/widgets/launch_bar/Calendar.tsx +++ b/apps/client/src/widgets/launch_bar/Calendar.tsx @@ -35,11 +35,10 @@ export interface CalendarArgs { } export default function Calendar(args: CalendarArgs) { - const [ rawFirstDayOfWeek ] = useTriliumOptionInt("firstDayOfWeek") ?? 0; + const [ rawFirstDayOfWeek ] = useTriliumOptionInt("firstDayOfWeek"); const firstDayOfWeekISO = (rawFirstDayOfWeek === 0 ? 7 : rawFirstDayOfWeek); const date = args.date; - const month = date.format('YYYY-MM'); const firstDay = date.startOf('month'); const firstDayISO = firstDay.isoWeekday(); const monthInfo = getMonthInformation(date, firstDayISO, firstDayOfWeekISO); diff --git a/apps/client/src/widgets/launch_bar/CalendarWidget.tsx b/apps/client/src/widgets/launch_bar/CalendarWidget.tsx index aa58b183b..197267223 100644 --- a/apps/client/src/widgets/launch_bar/CalendarWidget.tsx +++ b/apps/client/src/widgets/launch_bar/CalendarWidget.tsx @@ -1,4 +1,4 @@ -import { Dispatch, StateUpdater, useEffect, useMemo, useRef, useState } from "preact/hooks"; +import { Dispatch, StateUpdater, useMemo, useRef, useState } from "preact/hooks"; import FNote from "../../entities/fnote"; import { LaunchBarDropdownButton, LauncherNoteProps, useLauncherIconAndTitle } from "./launch_bar_widgets"; import { Dayjs, dayjs } from "@triliumnext/commons"; @@ -59,7 +59,7 @@ export default function CalendarWidget({ launcherNote }: LauncherNoteProps) { return ( { + onShown={async () => { const dateNote = appContext.tabManager.getActiveContextNote()?.getOwnedLabelValue("dateNote"); const activeDate = dateNote ? dayjs(`${dateNote}T12:00:00`) : null const todaysDate = dayjs(); @@ -68,7 +68,11 @@ export default function CalendarWidget({ launcherNote }: LauncherNoteProps) { todaysDate, }); setDate(dayjs(activeDate || todaysDate).startOf('month')); - checkEnableWeekNotes(); + try { + await checkEnableWeekNotes(); + } catch (e: unknown) { + // Non-critical. + } }} dropdownRef={dropdownRef} dropdownOptions={{ diff --git a/apps/client/src/widgets/launch_bar/HistoryNavigation.tsx b/apps/client/src/widgets/launch_bar/HistoryNavigation.tsx index 18dc67f05..f9ea51c57 100644 --- a/apps/client/src/widgets/launch_bar/HistoryNavigation.tsx +++ b/apps/client/src/widgets/launch_bar/HistoryNavigation.tsx @@ -12,6 +12,8 @@ interface HistoryNavigationProps { command: "backInNoteHistory" | "forwardInNoteHistory"; } +const HISTORY_LIMIT = 20; + export default function HistoryNavigationButton({ launcherNote, command }: HistoryNavigationProps) { const { icon, title } = useLauncherIconAndTitle(launcherNote); const webContentsRef = useRef(null); @@ -63,8 +65,8 @@ export default function HistoryNavigationButton({ launcherNote, command }: Histo items.reverse(); - if (items.length > 20) { - items = items.slice(0, 50); + if (items.length > HISTORY_LIMIT) { + items = items.slice(0, HISTORY_LIMIT); } contextMenu.show({ diff --git a/apps/client/src/widgets/launch_bar/LauncherContainer.tsx b/apps/client/src/widgets/launch_bar/LauncherContainer.tsx index 109f20478..26a502a8a 100644 --- a/apps/client/src/widgets/launch_bar/LauncherContainer.tsx +++ b/apps/client/src/widgets/launch_bar/LauncherContainer.tsx @@ -1,4 +1,4 @@ -import { useLayoutEffect, useState } from "preact/hooks"; +import { useCallback, useLayoutEffect, useState } from "preact/hooks"; import FNote from "../../entities/fnote"; import froca from "../../services/froca"; import { isDesktop, isMobile } from "../../services/utils"; @@ -8,7 +8,7 @@ import BookmarkButtons from "./BookmarkButtons"; import ProtectedSessionStatusWidget from "./ProtectedSessionStatusWidget"; import SyncStatus from "./SyncStatus"; import HistoryNavigationButton from "./HistoryNavigation"; -import AiChatButton, { CommandButton, CustomWidget, NoteLauncher, QuickSearchLauncherWidget, ScriptLauncher, TodayLauncher } from "./LauncherDefinitions"; +import { AiChatButton, CommandButton, CustomWidget, NoteLauncher, QuickSearchLauncherWidget, ScriptLauncher, TodayLauncher } from "./LauncherDefinitions"; import { useTriliumEvent } from "../react/hooks"; import { onWheelHorizontalScroll } from "../widget_utils"; import { LaunchBarContext } from "./launch_bar_widgets"; @@ -111,10 +111,10 @@ function useLauncherChildNotes() { }, []); // Load the children. - function refresh() { + const refresh = useCallback(() => { if (!visibleLaunchersRoot) return; visibleLaunchersRoot.getChildNotes().then(setChildNotes); - } + }, [ visibleLaunchersRoot, setChildNotes ]); useLayoutEffect(refresh, [ visibleLaunchersRoot ]); // React to position changes. diff --git a/apps/client/src/widgets/launch_bar/LauncherDefinitions.tsx b/apps/client/src/widgets/launch_bar/LauncherDefinitions.tsx index d0fbb645e..a0c379b22 100644 --- a/apps/client/src/widgets/launch_bar/LauncherDefinitions.tsx +++ b/apps/client/src/widgets/launch_bar/LauncherDefinitions.tsx @@ -1,16 +1,17 @@ import { useCallback, useContext, useEffect, useMemo, useState } from "preact/hooks"; -import { useGlobalShortcut, useLegacyWidget, useNoteContext, useNoteLabel, useNoteRelationTarget, useTriliumOptionBool } from "../react/hooks"; +import { useGlobalShortcut, useLegacyWidget, useNoteLabel, useNoteRelationTarget, useTriliumOptionBool } from "../react/hooks"; import { ParentComponent } from "../react/react_utils"; import BasicWidget from "../basic_widget"; import FNote from "../../entities/fnote"; import QuickSearchWidget from "../quick_search"; -import { isMobile } from "../../services/utils"; +import { getErrorMessage, isMobile } from "../../services/utils"; import date_notes from "../../services/date_notes"; import { CustomNoteLauncher } from "./GenericButtons"; import { LaunchBarActionButton, LaunchBarContext, LauncherNoteProps, useLauncherIconAndTitle } from "./launch_bar_widgets"; import dialog from "../../services/dialog"; import { t } from "../../services/i18n"; import appContext, { CommandNames } from "../../components/app_context"; +import toast from "../../services/toast"; export function CommandButton({ launcherNote }: LauncherNoteProps) { const { icon, title } = useLauncherIconAndTitle(launcherNote); @@ -77,7 +78,7 @@ export function ScriptLauncher({ launcherNote }: LauncherNoteProps) { ) } -export default function AiChatButton({ launcherNote }: LauncherNoteProps) { +export function AiChatButton({ launcherNote }: LauncherNoteProps) { const [ aiEnabled ] = useTriliumOptionBool("aiEnabled"); const { icon, title } = useLauncherIconAndTitle(launcherNote); @@ -123,12 +124,24 @@ export function CustomWidget({ launcherNote }: LauncherNoteProps) { parentComponent?.contentSized(); useEffect(() => { - widgetNote?.executeScript().then(widget => { - if (widget instanceof BasicWidget) { + (async function() { + let widget: BasicWidget; + try { + widget = await widgetNote?.executeScript(); + } catch (e) { + toast.showError(t("toast.bundle-error.message", { + id: widgetNote?.noteId, + title: widgetNote?.title, + message: getErrorMessage(e) + })); + return; + } + + if (widgetNote && widget instanceof BasicWidget) { widget._noteId = widgetNote.noteId; } setWidget(widget); - }); + })(); }, [ widgetNote ]); return ( diff --git a/apps/client/src/widgets/launch_bar/RightDropdownButton.tsx b/apps/client/src/widgets/launch_bar/RightDropdownButton.tsx deleted file mode 100644 index e47b5624c..000000000 --- a/apps/client/src/widgets/launch_bar/RightDropdownButton.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function RightDropdownButton() { - return

Button goes here.

; -} diff --git a/apps/client/src/widgets/launch_bar/SyncStatus.tsx b/apps/client/src/widgets/launch_bar/SyncStatus.tsx index b6f122d44..3cf8ab777 100644 --- a/apps/client/src/widgets/launch_bar/SyncStatus.tsx +++ b/apps/client/src/widgets/launch_bar/SyncStatus.tsx @@ -88,7 +88,7 @@ function useSyncStatus() { // First, read last synced push. if ("lastSyncedPush" in message) { lastSyncedPush = message.lastSyncedPush; - } else if ("data" in message && message.data && "lastSyncedPush" in message.data && lastSyncedPush) { + } else if ("data" in message && message.data && "lastSyncedPush" in message.data && lastSyncedPush !== undefined) { lastSyncedPush = message.data.lastSyncedPush; } diff --git a/apps/client/src/widgets/react/Dropdown.tsx b/apps/client/src/widgets/react/Dropdown.tsx index 18f060a86..5416e38ac 100644 --- a/apps/client/src/widgets/react/Dropdown.tsx +++ b/apps/client/src/widgets/react/Dropdown.tsx @@ -67,7 +67,7 @@ export default function Dropdown({ id, className, buttonClassName, isStatic, chi resizeObserver.disconnect(); dropdown.dispose(); } - }, [ triggerRef, dropdownContainerRef ]); + }, []); const onShown = useCallback(() => { setShown(true); @@ -101,7 +101,7 @@ export default function Dropdown({ id, className, buttonClassName, isStatic, chi $dropdown.off("show.bs.dropdown", onShown); $dropdown.off("hide.bs.dropdown", onHidden); }; - }, []); // Add dependency array + }, [ onShown, onHidden ]); const ariaId = useUniqueName("button"); diff --git a/apps/client/src/widgets/react/NoteLink.tsx b/apps/client/src/widgets/react/NoteLink.tsx index c8bcc5065..7c3578db7 100644 --- a/apps/client/src/widgets/react/NoteLink.tsx +++ b/apps/client/src/widgets/react/NoteLink.tsx @@ -72,6 +72,5 @@ export default function NoteLink({ className, containerClassName, notePath, show $linkEl?.addClass(className); } - return - + return ; } diff --git a/apps/client/src/widgets/react/hooks.tsx b/apps/client/src/widgets/react/hooks.tsx index 3cd4cffff..c56002940 100644 --- a/apps/client/src/widgets/react/hooks.tsx +++ b/apps/client/src/widgets/react/hooks.tsx @@ -813,7 +813,7 @@ export function useKeyboardShortcuts(scope: "code-detail" | "text-detail", conta } /** - * Register a global shortcut. Internally it uses the shortcut service and assignes a random namespace to make it unique. + * Register a global shortcut. Internally it uses the shortcut service and assigns a random namespace to make it unique. * * @param keyboardShortcut the keyboard shortcut combination to register. * @param handler the corresponding handler to be called when the keyboard shortcut is invoked by the user. @@ -877,12 +877,13 @@ async function isNoteReadOnly(note: FNote, noteContext: NoteContext) { export function useChildNotes(parentNoteId: string) { const [ childNotes, setChildNotes ] = useState([]); - async function refreshChildNotes() { - const parentNote = await froca.getNote(parentNoteId); - const childNotes = await parentNote?.getChildNotes(); - setChildNotes(childNotes ?? []); - } - useEffect(() => { refreshChildNotes() }, [ parentNoteId ]); + useEffect(() => { + (async function() { + const parentNote = await froca.getNote(parentNoteId); + const childNotes = await parentNote?.getChildNotes(); + setChildNotes(childNotes ?? []); + })(); + }, [ parentNoteId ]); return childNotes; }