diff --git a/SUBSONIC_SERVER_BLUEPRINT.md b/SUBSONIC_SERVER_BLUEPRINT.md index 70ca00f..33eb8a7 100644 --- a/SUBSONIC_SERVER_BLUEPRINT.md +++ b/SUBSONIC_SERVER_BLUEPRINT.md @@ -574,9 +574,9 @@ Responsibilities: - [x] Add delete playlist endpoint - [ ] Add reorder tracks endpoint - [x] Add add/remove track endpoints -- [ ] Add listening history table -- [ ] Record play/scrobble events -- [ ] Add recently played endpoint +- [x] Add listening history table +- [x] Record play/scrobble events +- [x] Add recently played endpoint ## Favorites @@ -608,7 +608,7 @@ Responsibilities: - [x] Implement `star` - [x] Implement `unstar` - [x] Implement playlist endpoints -- [ ] Implement `scrobble` +- [x] Implement `scrobble` - [ ] Test against at least one existing Subsonic client ## Frontend Bootstrap diff --git a/apps/web/src/components/player-bar.tsx b/apps/web/src/components/player-bar.tsx index fe95ce8..efc441a 100644 --- a/apps/web/src/components/player-bar.tsx +++ b/apps/web/src/components/player-bar.tsx @@ -10,11 +10,13 @@ import { Shuffle, Volume2, } from 'lucide-react' -import { streamUrl } from '@/lib/api' +import { scrobbleTrack, streamUrl } from '@/lib/api' import { usePlayerStore } from '@/stores/player-store' export function PlayerBar() { const audioRef = useRef(null) + const lastStartedTrackRef = useRef(null) + const lastSubmittedTrackRef = useRef(null) const currentTrack = usePlayerStore((state) => state.currentTrack) const isPlaying = usePlayerStore((state) => state.isPlaying) const volume = usePlayerStore((state) => state.volume) @@ -41,6 +43,7 @@ export function PlayerBar() { return } audioRef.current.src = streamUrl(currentTrack.id) + lastSubmittedTrackRef.current = null if (isPlaying) { void audioRef.current.play().catch(() => {}) } @@ -66,13 +69,55 @@ export function PlayerBar() { clearSeekRequest() }, [seekRequest, clearSeekRequest]) + useEffect(() => { + if (!currentTrack || !isPlaying || lastStartedTrackRef.current === currentTrack.id) { + return + } + lastStartedTrackRef.current = currentTrack.id + void scrobbleTrack({ + trackId: currentTrack.id, + submission: false, + time: Date.now(), + clientName: 'temporserv-web', + }).catch(() => {}) + }, [currentTrack, isPlaying]) + return (