import React, {useEffect, useState} from "react"; import {Alert, AlertDescription, AlertTitle} from "@/components/ui/alert.tsx"; import {Button} from "@/components/ui/button.tsx"; import {Separator} from "@/components/ui/separator.tsx"; import { getReleasesRSS, getVersionInfo } from "@/ui/main-axios.ts"; import {useTranslation} from "react-i18next"; interface HomepageUpdateLogProps extends React.ComponentProps<"div"> { loggedIn: boolean; } interface ReleaseItem { id: number; title: string; description: string; link: string; pubDate: string; version: string; isPrerelease: boolean; isDraft: boolean; assets: Array<{ name: string; size: number; download_count: number; download_url: string; }>; } interface RSSResponse { feed: { title: string; description: string; link: string; updated: string; }; items: ReleaseItem[]; total_count: number; cached: boolean; cache_age?: number; } interface VersionResponse { status: 'up_to_date' | 'requires_update'; version: string; latest_release: { name: string; published_at: string; html_url: string; }; cached: boolean; cache_age?: number; } export function HomepageUpdateLog({loggedIn}: HomepageUpdateLogProps) { const {t} = useTranslation(); const [releases, setReleases] = useState(null); const [versionInfo, setVersionInfo] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); useEffect(() => { if (loggedIn) { setLoading(true); Promise.all([ getReleasesRSS(100), getVersionInfo() ]) .then(([releasesRes, versionRes]) => { setReleases(releasesRes); setVersionInfo(versionRes); setError(null); }) .catch(err => { setError(t('common.failedToFetchUpdateInfo')); }) .finally(() => setLoading(false)); } }, [loggedIn]); if (!loggedIn) { return null; } const formatDescription = (description: string) => { const firstLine = description.split('\n')[0]; return firstLine .replace(/[#*`]/g, '') .replace(/\s+/g, ' ') .trim(); }; return (

{t('common.updatesAndReleases')}

{versionInfo && versionInfo.status === 'requires_update' && ( {t('common.updateAvailable')} {t('common.newVersionAvailable', { version: versionInfo.version })} )}
{versionInfo && versionInfo.status === 'requires_update' && ( )}
{loading && (
)} {error && ( {t('common.error')} {error} )} {releases?.items.map((release) => (
window.open(release.link, '_blank')} >

{release.title}

{release.isPrerelease && ( {t('common.preRelease')} )}

{formatDescription(release.description)}

{new Date(release.pubDate).toLocaleDateString()} {release.assets.length > 0 && ( <> {release.assets.length} asset{release.assets.length !== 1 ? 's' : ''} )}
))} {releases && releases.items.length === 0 && !loading && ( {t('common.noReleases')} {t('common.noReleasesFound')} )}
); }