A decentralized music tracking and discovery platform built on AT Protocol 🎵 rocksky.app
spotify atproto lastfm musicbrainz scrobbling listenbrainz
98
fork

Configure Feed

Select the types of activity you want to include in your feed.

Move WebSocket handling to Feed and update cache

Remove duplicate WebSocket and heartbeat logic from NowPlayings. Feed
now opens the socket using WS_URL (without a trailing /ws), updates the
["now-playings"] and ["scrobblesChart"] query data, and includes
queryClient in the effect dependencies.

+5 -39
+4 -2
apps/web/src/pages/home/feed/Feed.tsx
··· 37 37 const { data, isLoading } = useFeedQuery(); 38 38 39 39 useEffect(() => { 40 - const ws = new WebSocket(`${WS_URL.replace("http", "ws")}/ws`); 40 + const ws = new WebSocket(`${WS_URL.replace("http", "ws")}`); 41 41 socketRef.current = ws; 42 42 43 43 ws.onopen = () => { ··· 53 53 54 54 const message = JSON.parse(event.data); 55 55 queryClient.setQueryData(["feed"], message.scrobbles); 56 + queryClient.setQueryData(["now-playings"], message.nowPlayings); 57 + queryClient.setQueryData(["scrobblesChart"], message.scrobblesChart); 56 58 }; 57 59 58 60 return () => { ··· 64 66 } 65 67 console.log(">> WebSocket connection closed"); 66 68 }; 67 - }, []); 69 + }, [queryClient]); 68 70 69 71 return ( 70 72 <Container>
+1 -37
apps/web/src/pages/home/nowplayings/NowPlayings.tsx
··· 7 7 import dayjs from "dayjs"; 8 8 import relativeTime from "dayjs/plugin/relativeTime"; 9 9 import utc from "dayjs/plugin/utc"; 10 - import { useEffect, useRef, useState } from "react"; 10 + import { useEffect, useState } from "react"; 11 11 import { useNowPlayingsQuery } from "../../../hooks/useNowPlaying"; 12 12 import styles from "./styles"; 13 - import { WS_URL } from "../../../consts"; 14 - import { useQueryClient } from "@tanstack/react-query"; 15 13 16 14 dayjs.extend(relativeTime); 17 15 dayjs.extend(utc); ··· 90 88 `; 91 89 92 90 function NowPlayings() { 93 - const queryClient = useQueryClient(); 94 91 const [isOpen, setIsOpen] = useState(false); 95 - const socketRef = useRef<WebSocket | null>(null); 96 - const heartbeatInterval = useRef<number | null>(null); 97 92 const { data: nowPlayings, isLoading } = useNowPlayingsQuery(); 98 93 const [currentlyPlaying, setCurrentlyPlaying] = useState<{ 99 94 id: string; ··· 111 106 } | null>(null); 112 107 const [currentIndex, setCurrentIndex] = useState(0); 113 108 const [progress, setProgress] = useState(0); 114 - 115 - useEffect(() => { 116 - const ws = new WebSocket(`${WS_URL.replace("http", "ws")}/ws`); 117 - socketRef.current = ws; 118 - 119 - ws.onopen = () => { 120 - heartbeatInterval.current = window.setInterval(() => { 121 - ws.send("ping"); 122 - }, 3000); 123 - }; 124 - 125 - ws.onmessage = (event) => { 126 - if (event.data === "pong") { 127 - return; 128 - } 129 - 130 - const message = JSON.parse(event.data); 131 - queryClient.setQueryData(["now-playings"], message.nowPlayings); 132 - queryClient.setQueryData(["scrobblesChart"], message.scrobblesChart); 133 - }; 134 - 135 - return () => { 136 - if (ws) { 137 - if (heartbeatInterval.current) { 138 - clearInterval(heartbeatInterval.current); 139 - } 140 - ws.close(); 141 - } 142 - console.log(">> WebSocket connection closed"); 143 - }; 144 - }, []); 145 109 146 110 const onNext = () => { 147 111 const nextIndex = currentIndex + 1;