feat(ui): About dialog, Release Notes, and new-version banner

About (in the account menu) shows frontend/backend/database versions + build.
Release Notes renders per-version highlights with a commit-SHA reference; a
dismissible banner appears once after the running build's version changes and
links into the notes. Adds a reusable Modal shell and the release-notes data
(detailed v0.1.0).
This commit is contained in:
npeter83 2026-06-15 00:06:57 +02:00
parent a93ab30fb2
commit 82f0936ca7
9 changed files with 347 additions and 1 deletions

View file

@ -27,6 +27,10 @@ import SettingsPanel from "./components/SettingsPanel";
import OnboardingWizard from "./components/OnboardingWizard";
import { shouldAutoOpenOnboarding } from "./lib/onboarding";
import Toaster from "./components/Toaster";
import About from "./components/About";
import ReleaseNotes from "./components/ReleaseNotes";
import VersionBanner from "./components/VersionBanner";
import { CURRENT_VERSION } from "./lib/releaseNotes";
const DEFAULT_FILTERS: FeedFilters = {
tags: [],
@ -65,6 +69,14 @@ export default function App() {
const [settingsOpen, setSettingsOpen] = useState(false);
const [wizardOpen, setWizardOpen] = useState(false);
const [channelFilter, setChannelFilter] = useState<ChannelStatusFilter>("all");
const [aboutOpen, setAboutOpen] = useState(false);
const [notesOpen, setNotesOpen] = useState(false);
const [notesHighlight, setNotesHighlight] = useState<string | undefined>(undefined);
function openReleaseNotes(highlight?: string) {
setNotesHighlight(highlight);
setNotesOpen(true);
}
function setFilters(next: FeedFilters) {
setFiltersState(next);
@ -158,11 +170,13 @@ export default function App() {
page={page}
setPage={setPage}
onOpenSettings={() => setSettingsOpen(true)}
onOpenAbout={() => setAboutOpen(true)}
onGoToFullHistory={() => {
setChannelFilter("needs_full");
setPage("channels");
}}
/>
<VersionBanner onOpen={() => openReleaseNotes(CURRENT_VERSION)} />
<div className="flex flex-1 min-h-0">
{page === "feed" && (
<Sidebar
@ -213,6 +227,18 @@ export default function App() {
{wizardOpen && meQuery.data && (
<OnboardingWizard me={meQuery.data} onClose={() => setWizardOpen(false)} />
)}
{aboutOpen && (
<About
onClose={() => setAboutOpen(false)}
onOpenReleaseNotes={() => {
setAboutOpen(false);
openReleaseNotes();
}}
/>
)}
{notesOpen && (
<ReleaseNotes onClose={() => setNotesOpen(false)} highlight={notesHighlight} />
)}
<Toaster />
</div>
);