diff options
Diffstat (limited to '')
4 files changed, 66 insertions, 20 deletions
diff --git a/apps/web/components/shared/sidebar/Sidebar.tsx b/apps/web/components/shared/sidebar/Sidebar.tsx index bf5a626b..3f4780e7 100644 --- a/apps/web/components/shared/sidebar/Sidebar.tsx +++ b/apps/web/components/shared/sidebar/Sidebar.tsx @@ -32,7 +32,10 @@ export default async function Sidebar({ </ul> </div> {extraSections} - <SidebarVersion serverVersion={serverConfig.serverVersion} /> + <SidebarVersion + serverVersion={serverConfig.serverVersion} + changeLogVersion={serverConfig.changelogVersion} + /> </aside> ); } diff --git a/apps/web/components/shared/sidebar/SidebarItem.tsx b/apps/web/components/shared/sidebar/SidebarItem.tsx index e602a435..eb61d48b 100644 --- a/apps/web/components/shared/sidebar/SidebarItem.tsx +++ b/apps/web/components/shared/sidebar/SidebarItem.tsx @@ -14,6 +14,11 @@ export default function SidebarItem({ style, collapseButton, right = null, + dropHighlight = false, + onDrop, + onDragOver, + onDragEnter, + onDragLeave, }: { name: string; logo: React.ReactNode; @@ -23,6 +28,11 @@ export default function SidebarItem({ linkClassName?: string; right?: React.ReactNode; collapseButton?: React.ReactNode; + dropHighlight?: boolean; + onDrop?: React.DragEventHandler; + onDragOver?: React.DragEventHandler; + onDragEnter?: React.DragEventHandler; + onDragLeave?: React.DragEventHandler; }) { const currentPath = usePathname(); return ( @@ -32,9 +42,14 @@ export default function SidebarItem({ path == currentPath ? "bg-accent/50 text-foreground" : "text-muted-foreground", + dropHighlight && "bg-accent ring-2 ring-primary", className, )} style={style} + onDrop={onDrop} + onDragOver={onDragOver} + onDragEnter={onDragEnter} + onDragLeave={onDragLeave} > <div className="flex-1"> {collapseButton} diff --git a/apps/web/components/shared/sidebar/SidebarLayout.tsx b/apps/web/components/shared/sidebar/SidebarLayout.tsx index 8ea8655e..e1b35634 100644 --- a/apps/web/components/shared/sidebar/SidebarLayout.tsx +++ b/apps/web/components/shared/sidebar/SidebarLayout.tsx @@ -1,7 +1,11 @@ +import { Suspense } from "react"; +import ErrorFallback from "@/components/dashboard/ErrorFallback"; import Header from "@/components/dashboard/header/Header"; import DemoModeBanner from "@/components/DemoModeBanner"; import { Separator } from "@/components/ui/separator"; +import LoadingSpinner from "@/components/ui/spinner"; import ValidAccountCheck from "@/components/utils/ValidAccountCheck"; +import { ErrorBoundary } from "react-error-boundary"; import serverConfig from "@karakeep/shared/config"; @@ -29,7 +33,11 @@ export default function SidebarLayout({ <Separator /> </div> {modal} - <div className="min-h-30 container p-4">{children}</div> + <div className="min-h-30 container p-4"> + <ErrorBoundary fallback={<ErrorFallback />}> + <Suspense fallback={<LoadingSpinner />}>{children}</Suspense> + </ErrorBoundary> + </div> </main> </div> </div> diff --git a/apps/web/components/shared/sidebar/SidebarVersion.tsx b/apps/web/components/shared/sidebar/SidebarVersion.tsx index fc2ec5a3..2d6d3380 100644 --- a/apps/web/components/shared/sidebar/SidebarVersion.tsx +++ b/apps/web/components/shared/sidebar/SidebarVersion.tsx @@ -46,36 +46,50 @@ function isStableRelease(version?: string) { } interface SidebarVersionProps { + // The actual version of the server serverVersion?: string; + // The version that should be displayed in the changelog + changeLogVersion?: string; } -export default function SidebarVersion({ serverVersion }: SidebarVersionProps) { +export default function SidebarVersion({ + serverVersion, + changeLogVersion, +}: SidebarVersionProps) { const { disableNewReleaseCheck } = useClientConfig(); const { t } = useTranslation(); - const stableRelease = isStableRelease(serverVersion); + const effectiveChangelogVersion = changeLogVersion ?? serverVersion; + const stableRelease = isStableRelease(effectiveChangelogVersion); const displayVersion = serverVersion ?? "unknown"; + const changelogDisplayVersion = effectiveChangelogVersion ?? displayVersion; const versionLabel = `Karakeep v${displayVersion}`; const releasePageUrl = useMemo(() => { - if (!serverVersion || !isStableRelease(serverVersion)) { + if ( + !effectiveChangelogVersion || + !isStableRelease(effectiveChangelogVersion) + ) { return GITHUB_REPO_URL; } - return `${GITHUB_RELEASE_URL}v${serverVersion}`; - }, [serverVersion]); + return `${GITHUB_RELEASE_URL}v${effectiveChangelogVersion}`; + }, [effectiveChangelogVersion]); const [open, setOpen] = useState(false); const [shouldNotify, setShouldNotify] = useState(false); const releaseNotesQuery = useQuery<string>({ - queryKey: ["sidebar-release-notes", serverVersion], + queryKey: ["sidebar-release-notes", effectiveChangelogVersion], queryFn: async ({ signal }) => { - if (!serverVersion) { + if (!effectiveChangelogVersion) { return ""; } - const response = await fetch(`${RELEASE_API_URL}v${serverVersion}`, { - signal, - }); + const response = await fetch( + `${RELEASE_API_URL}v${effectiveChangelogVersion}`, + { + signal, + }, + ); if (!response.ok) { throw new Error("Failed to load release notes"); @@ -89,7 +103,7 @@ export default function SidebarVersion({ serverVersion }: SidebarVersionProps) { open && stableRelease && !disableNewReleaseCheck && - Boolean(serverVersion), + Boolean(effectiveChangelogVersion), staleTime: RELEASE_NOTES_STALE_TIME, retry: 1, refetchOnWindowFocus: false, @@ -123,30 +137,34 @@ export default function SidebarVersion({ serverVersion }: SidebarVersionProps) { }, [releaseNotesQuery.error, t]); useEffect(() => { - if (!stableRelease || !serverVersion || disableNewReleaseCheck) { + if ( + !stableRelease || + !effectiveChangelogVersion || + disableNewReleaseCheck + ) { setShouldNotify(false); return; } try { const seenVersion = window.localStorage.getItem(LOCAL_STORAGE_KEY); - setShouldNotify(seenVersion !== serverVersion); + setShouldNotify(seenVersion !== effectiveChangelogVersion); } catch (error) { console.warn("Failed to read localStorage:", error); setShouldNotify(true); } - }, [serverVersion, stableRelease, disableNewReleaseCheck]); + }, [effectiveChangelogVersion, stableRelease, disableNewReleaseCheck]); const markReleaseAsSeen = useCallback(() => { - if (!serverVersion) return; + if (!effectiveChangelogVersion) return; try { - window.localStorage.setItem(LOCAL_STORAGE_KEY, serverVersion); + window.localStorage.setItem(LOCAL_STORAGE_KEY, effectiveChangelogVersion); } catch (error) { console.warn("Failed to write to localStorage:", error); // Ignore failures, we still clear the notification for the session } setShouldNotify(false); - }, [serverVersion]); + }, [effectiveChangelogVersion]); const handleOpenChange = useCallback( (nextOpen: boolean) => { @@ -202,7 +220,9 @@ export default function SidebarVersion({ serverVersion }: SidebarVersionProps) { <DialogContent className="max-w-3xl"> <DialogHeader> <DialogTitle> - {t("version.whats_new_title", { version: displayVersion })} + {t("version.whats_new_title", { + version: changelogDisplayVersion, + })} </DialogTitle> <DialogDescription> {t("version.release_notes_description")} |
