Add recently played to profiles

A play is recorded when a new track starts (pausing and resuming doesn't
count; returning after 10+ minutes does). Profiles show the last 10,
excluding the track playing now; 50 are kept per user. Recent plays are
free on every plan; the paid flag is renamed to fullHistory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MzFywujuH9TiuXbr9vjoX8
This commit is contained in:
2026-10-03 16:02:38 -04:00
co-authored by Claude Opus 5.5
parent 87353ccca3
commit ece9c4fd64
14 changed files with 1147 additions and 11 deletions
+6 -1
View File
@@ -7,6 +7,7 @@ import useSWR from 'swr';
import type { ProfileDTO } from '@musicshare/shared';
import { Avatar } from '@/components/Avatar';
import { NowPlayingCard } from '@/components/NowPlayingCard';
import { RecentPlays } from '@/components/RecentPlays';
import { TrackCard } from '@/components/TrackCard';
import { api, fetcher, useMe } from '@/lib/api';
import { useRealtime } from '@/lib/useRealtime';
@@ -20,7 +21,9 @@ export default function ProfilePage() {
// Live updates arrive for people you follow (and yourself)
useRealtime(Boolean(me), (msg) => {
if (msg.type === 'now_playing' && profile && msg.data.user.id === profile.user.id) {
mutate({ ...profile, nowPlaying: msg.data }, { revalidate: false });
// A new track moves the previous one into "Recently played", so refetch; otherwise patch in place.
const newTrack = msg.data.track.id !== profile.nowPlaying?.track.id;
mutate({ ...profile, nowPlaying: msg.data }, { revalidate: newTrack });
}
});
@@ -94,6 +97,8 @@ export default function ProfilePage() {
) : (
<p className="muted">Nothing playing right now.</p>
)}
<RecentPlays plays={profile.recent} preferred={preferred} />
</div>
);
}