From 0d42bc3877e9020d3032547407f8e91ac96adea5 Mon Sep 17 00:00:00 2001 From: afkarxyz Date: Thu, 2 Apr 2026 18:34:48 +0700 Subject: [PATCH] .time ago --- frontend/src/components/AboutPage.tsx | 71 +++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 10 deletions(-) diff --git a/frontend/src/components/AboutPage.tsx b/frontend/src/components/AboutPage.tsx index 7b5e661..68ca93d 100644 --- a/frontend/src/components/AboutPage.tsx +++ b/frontend/src/components/AboutPage.tsx @@ -28,7 +28,7 @@ export function AboutPage() { const [copiedUsdt, setCopiedUsdt] = useState(false); useEffect(() => { const fetchRepoStats = async () => { - const CACHE_KEY = "github_repo_stats_v3"; + const CACHE_KEY = "github_repo_stats_v4"; const CACHE_DURATION = 1000 * 60 * 60; const cached = localStorage.getItem(CACHE_KEY); if (cached) { @@ -70,8 +70,10 @@ export function AboutPage() { let totalDownloads = 0; let latestDownloads = 0; let latestVersion = ""; + let latestReleaseAt = ""; if (releases.length > 0) { latestVersion = releases[0].tag_name || ""; + latestReleaseAt = releases[0].published_at || releases[0].created_at || ""; latestDownloads = releases[0].assets?.reduce((sum: number, asset: any) => sum + (asset.download_count || 0), 0) || 0; totalDownloads = releases.reduce((sum: number, release: any) => { @@ -91,6 +93,7 @@ export function AboutPage() { totalDownloads, latestDownloads, latestVersion, + latestReleaseAt, languages: topLangs, }; } @@ -128,6 +131,39 @@ export function AboutPage() { const diffYears = Math.floor(diffMonths / 12); return `${diffYears}y`; }; + const formatReleaseTimeAgo = (dateString: string): string => { + if (!dateString) { + return ""; + } + const now = Date.now(); + const releasedAt = new Date(dateString).getTime(); + if (Number.isNaN(releasedAt)) { + return ""; + } + const diffMs = Math.max(0, now - releasedAt); + const totalMinutes = Math.floor(diffMs / (1000 * 60)); + const totalHours = Math.floor(totalMinutes / 60); + const totalDays = Math.floor(totalHours / 24); + const totalMonths = Math.floor(totalDays / 30); + const totalYears = Math.floor(totalMonths / 12); + if (totalYears > 0) { + const remainingMonths = totalMonths % 12; + return remainingMonths > 0 ? `${totalYears}y ${remainingMonths}m ago` : `${totalYears}y ago`; + } + if (totalMonths > 0) { + const remainingDays = totalDays % 30; + return remainingDays > 0 ? `${totalMonths}m ${remainingDays}d ago` : `${totalMonths}m ago`; + } + if (totalDays > 0) { + const remainingHours = totalHours % 24; + return remainingHours > 0 ? `${totalDays}d ${remainingHours}h ago` : `${totalDays}d ago`; + } + if (totalHours > 0) { + const remainingMinutes = totalMinutes % 60; + return `${totalHours}h ${remainingMinutes}m ago`; + } + return `${totalMinutes}m ago`; + }; const formatNumber = (num: number): string => { if (num >= 1000) { return num.toLocaleString(); @@ -165,9 +201,14 @@ export function AboutPage() {
SpotiFLAC Next - {repoStats["SpotiFLAC-Next"]?.latestVersion && ( - {repoStats["SpotiFLAC-Next"].latestVersion} - )} +
+ {repoStats["SpotiFLAC-Next"]?.latestReleaseAt && ( + {formatReleaseTimeAgo(repoStats["SpotiFLAC-Next"].latestReleaseAt)} + )} + {repoStats["SpotiFLAC-Next"]?.latestVersion && ( + {repoStats["SpotiFLAC-Next"].latestVersion} + )} +
SpotiFLAC Next @@ -214,9 +255,14 @@ export function AboutPage() {
SpotiDownloader - {repoStats["SpotiDownloader"]?.latestVersion && ( - {repoStats["SpotiDownloader"].latestVersion} - )} +
+ {repoStats["SpotiDownloader"]?.latestReleaseAt && ( + {formatReleaseTimeAgo(repoStats["SpotiDownloader"].latestReleaseAt)} + )} + {repoStats["SpotiDownloader"]?.latestVersion && ( + {repoStats["SpotiDownloader"].latestVersion} + )} +
SpotiDownloader @@ -264,9 +310,14 @@ export function AboutPage() {
Twitter/X Media Batch Downloader - {repoStats["Twitter-X-Media-Batch-Downloader"]?.latestVersion && ( - {repoStats["Twitter-X-Media-Batch-Downloader"].latestVersion} - )} +
+ {repoStats["Twitter-X-Media-Batch-Downloader"]?.latestReleaseAt && ( + {formatReleaseTimeAgo(repoStats["Twitter-X-Media-Batch-Downloader"].latestReleaseAt)} + )} + {repoStats["Twitter-X-Media-Batch-Downloader"]?.latestVersion && ( + {repoStats["Twitter-X-Media-Batch-Downloader"].latestVersion} + )} +
Twitter/X Media Batch Downloader