feat(playlists): #417 — "Refreshed …" subtitle on system tiles
Closes the last buildable item of the #411 system-playlists-v2 umbrella. System playlists atomic-replace on rebuild, so created_at (already on the wire — no server change) is the last-rotated time. Surface it as a small tile subtitle so users see how fresh a mix is: "Refreshed just now / today / yesterday / N days ago / Mon D". - web PlaylistCard: refreshedLabel() + a muted footer line, shown only when system_variant != null. Unparseable/empty timestamp → suppressed (web test fixtures use created_at:'' so no test churn). - flutter PlaylistCard: mirrored _refreshedLabel() + subtitle under the system badge for isSystem playlists. Friendly wording deliberately distinct from HistoryRow's "m/h ago"; per-surface helper per the project's existing relative-time convention. CI-pending; closes with the umbrella on device-check. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,27 @@
|
||||
// (#411 R2) — no hardcoded kind list here.
|
||||
const refreshable = $derived(playlist.refreshable === true);
|
||||
|
||||
// #417: system playlists atomic-replace on rebuild, so created_at
|
||||
// is the last-rotated time. Surface it so users know how fresh the
|
||||
// mix is. Friendly wording, not the HistoryRow "m/h ago" style.
|
||||
function refreshedLabel(iso: string): string {
|
||||
const t = new Date(iso);
|
||||
if (Number.isNaN(t.getTime())) return '';
|
||||
const now = new Date();
|
||||
const mins = Math.floor((now.getTime() - t.getTime()) / 60000);
|
||||
if (mins < 5) return 'Refreshed just now';
|
||||
const startOfToday = new Date(now);
|
||||
startOfToday.setHours(0, 0, 0, 0);
|
||||
const days = Math.floor((startOfToday.getTime() - t.getTime()) / 86400000) + 1;
|
||||
if (t.getTime() >= startOfToday.getTime()) return 'Refreshed today';
|
||||
if (days <= 1) return 'Refreshed yesterday';
|
||||
if (days < 7) return `Refreshed ${days} days ago`;
|
||||
return `Refreshed ${t.toLocaleDateString(undefined, { month: 'short', day: 'numeric' })}`;
|
||||
}
|
||||
const refreshed = $derived(
|
||||
playlist.system_variant != null ? refreshedLabel(playlist.created_at) : ''
|
||||
);
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
let starting = $state(false);
|
||||
@@ -153,6 +174,9 @@
|
||||
· by {playlist.owner_username}
|
||||
{/if}
|
||||
</div>
|
||||
{#if refreshed}
|
||||
<div class="truncate text-xs text-text-muted">{refreshed}</div>
|
||||
{/if}
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user