f93c759bf2
VersionCheck and Toaster were rendering outside the BrowserRouter in App.tsx, so the <Link> in the version update toast had no Router context. Moved both into AppRouter.tsx inside BrowserRouter. Also truncate changelog excerpt to 60 chars with ellipsis for cleaner toast display.
71 lines
2.2 KiB
TypeScript
71 lines
2.2 KiB
TypeScript
import { useEffect } from 'react';
|
|
import { Link } from 'react-router-dom';
|
|
|
|
import { toast } from '@/hooks/useToast';
|
|
import { ToastAction } from '@/components/ui/toast';
|
|
import { parseChangelog } from '@/lib/changelog';
|
|
|
|
const STORAGE_KEY = 'ditto:app-version';
|
|
|
|
/** Fetch the first changelog item for the given version (or the latest entry). */
|
|
async function fetchChangelogExcerpt(version: string): Promise<string | undefined> {
|
|
try {
|
|
const res = await fetch('/CHANGELOG.md');
|
|
if (!res.ok) return undefined;
|
|
const markdown = await res.text();
|
|
const entries = parseChangelog(markdown);
|
|
|
|
// Try to find the entry matching the current version, otherwise use the first entry.
|
|
const entry = entries.find((e) => e.version === version) ?? entries[0];
|
|
if (!entry) return undefined;
|
|
|
|
// Return a truncated first item from the first section.
|
|
const item = entry.sections[0]?.items[0];
|
|
if (!item) return undefined;
|
|
if (item.length <= 60) return item;
|
|
return item.slice(0, 60).trimEnd() + '…';
|
|
} catch {
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
/** Compares the running app version against localStorage and shows a toast when the version changes. */
|
|
export function VersionCheck() {
|
|
useEffect(() => {
|
|
const currentVersion = import.meta.env.VERSION;
|
|
if (!currentVersion) return;
|
|
|
|
const storedVersion = localStorage.getItem(STORAGE_KEY);
|
|
localStorage.setItem(STORAGE_KEY, currentVersion);
|
|
|
|
if (storedVersion && storedVersion !== currentVersion) {
|
|
// Show the toast immediately, then enrich it with a changelog excerpt.
|
|
const { update, id } = toast({
|
|
title: `What's new in v${currentVersion}`,
|
|
action: (
|
|
<ToastAction altText="View changelog" asChild>
|
|
<Link to="/changelog">See all</Link>
|
|
</ToastAction>
|
|
),
|
|
});
|
|
|
|
fetchChangelogExcerpt(currentVersion).then((excerpt) => {
|
|
if (excerpt) {
|
|
update({
|
|
id,
|
|
title: `What's new in v${currentVersion}`,
|
|
description: excerpt,
|
|
action: (
|
|
<ToastAction altText="View changelog" asChild>
|
|
<Link to="/changelog">See all</Link>
|
|
</ToastAction>
|
|
),
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}, []);
|
|
|
|
return null;
|
|
}
|