Skip to content

Commit a4c707f

Browse files
committed
fix: keep playing after 128 events
1 parent 875387b commit a4c707f

File tree

1 file changed

+63
-35
lines changed

1 file changed

+63
-35
lines changed

src/App.tsx

Lines changed: 63 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState, useEffect, useMemo, useRef } from 'react';
1+
import React, { useState, useEffect, useMemo, useRef, useCallback } from 'react';
22
import styled from 'styled-components';
33
import { useWebSocket, GitHubEvent } from './hooks/useWebSocket';
44
import { useAudio } from './hooks/useAudio';
@@ -98,7 +98,6 @@ const MainArea = styled.div<{ $isOnline: boolean }>`
9898
filter: blur(100px);
9999
border-radius: 99999px;
100100
margin: auto;
101-
transform: scale(0.8);
102101
background: conic-gradient(
103102
from 0deg,
104103
#90D1CA 0%,
@@ -182,8 +181,8 @@ const App: React.FC = () => {
182181
const [volume, setVolumeState] = useState(0.5);
183182
const [orgRepoFilter, setOrgRepoFilter] = useState('');
184183
const [processedEvents, setProcessedEvents] = useState<GitHubEvent[]>([]);
185-
const processedCountRef = useRef(0);
186-
const eventQueueRef = useRef<GitHubEvent[]>([]);
184+
const processedEventIdsRef = useRef<Set<string>>(new Set());
185+
const processingTimeoutRef = useRef<NodeJS.Timeout | null>(null);
187186

188187
// Parse org/repo filter into array
189188
const orgRepoFilterArray = useMemo(() => {
@@ -198,47 +197,76 @@ const App: React.FC = () => {
198197

199198
const { allSoundsLoaded, playSound, setVolume } = useAudio();
200199

201-
// Update eventQueue ref whenever eventQueue changes
202-
useEffect(() => {
203-
eventQueueRef.current = eventQueue;
204-
}, [eventQueue]);
205-
206-
// Process events from queue
207-
useEffect(() => {
208-
if (!showClickToPlay && allSoundsLoaded) {
209-
let isProcessing = true;
200+
// Process events one at a time with proper delays (matching original implementation)
201+
const processNextEvent = useCallback(() => {
202+
if (!showClickToPlay && allSoundsLoaded && eventQueue.length > 0) {
203+
// Find the next unprocessed event using event_url as unique identifier
204+
const nextEvent = eventQueue.find(event =>
205+
event.event_url && !processedEventIdsRef.current.has(event.event_url)
206+
);
210207

211-
const playFromQueue = () => {
212-
if (!isProcessing) return;
208+
if (nextEvent && nextEvent.actor?.display_login && nextEvent.event_url) {
209+
console.log(`Processing event: ${nextEvent.type} by ${nextEvent.actor.display_login} (URL: ${nextEvent.event_url.slice(-8)})`);
213210

214-
// Get next unprocessed event from queue using ref
215-
if (processedCountRef.current < eventQueueRef.current.length) {
216-
const event = eventQueueRef.current[processedCountRef.current];
217-
processedCountRef.current++;
218-
219-
if (event && event.actor?.display_login) {
220-
const size = event.actor.display_login.length * 1.1;
221-
playSound(size, event.type);
222-
setProcessedEvents(prev => [...prev, event]);
223-
}
224-
}
211+
// Mark as processed immediately
212+
processedEventIdsRef.current.add(nextEvent.event_url);
225213

226-
// Schedule next processing with random delay (500-1500ms)
227-
setTimeout(playFromQueue, Math.floor(Math.random() * 1000) + 500);
228-
};
214+
// Play sound and add to visualization
215+
const size = nextEvent.actor.display_login.length * 1.1;
216+
playSound(size, nextEvent.type);
217+
setProcessedEvents(prev => {
218+
const newEvents = [...prev, nextEvent];
219+
// Keep only the last 100 processed events to prevent memory issues
220+
return newEvents.slice(-100);
221+
});
222+
223+
console.log(`Processed count: ${processedEventIdsRef.current.size}, Queue length: ${eventQueue.length}`);
224+
} else if (eventQueue.length > 0) {
225+
console.log(`No new events to process (queue: ${eventQueue.length}, processed: ${processedEventIdsRef.current.size})`);
226+
}
229227

230-
// Start processing after initial random delay
231-
setTimeout(playFromQueue, Math.floor(Math.random() * 1000));
228+
// Clean up the processed IDs set if it gets too large
229+
if (processedEventIdsRef.current.size > 200) {
230+
console.log(`Cleaning up processed URLs set (was ${processedEventIdsRef.current.size})`);
231+
// Keep only the most recent event URLs from the current queue
232+
const recentUrls = new Set<string>();
233+
eventQueue.slice(-100).forEach(event => {
234+
if (event.event_url) recentUrls.add(event.event_url);
235+
});
236+
processedEventIdsRef.current = recentUrls;
237+
console.log(`Cleaned up to ${processedEventIdsRef.current.size} URLs`);
238+
}
239+
}
240+
241+
// Schedule next processing cycle with original timing: 500-1500ms delay
242+
const delay = Math.floor(Math.random() * 1000) + 500;
243+
processingTimeoutRef.current = setTimeout(processNextEvent, delay);
244+
}, [showClickToPlay, allSoundsLoaded, eventQueue, playSound]);
245+
246+
// Start the processing loop when conditions are met
247+
useEffect(() => {
248+
if (!showClickToPlay && allSoundsLoaded) {
249+
// Clear any existing timeout
250+
if (processingTimeoutRef.current) {
251+
clearTimeout(processingTimeoutRef.current);
252+
}
253+
254+
// Start processing with initial delay
255+
const initialDelay = Math.floor(Math.random() * 1000) + 500;
256+
processingTimeoutRef.current = setTimeout(processNextEvent, initialDelay);
232257

233258
return () => {
234-
isProcessing = false;
259+
if (processingTimeoutRef.current) {
260+
clearTimeout(processingTimeoutRef.current);
261+
}
235262
};
236263
}
237-
}, [showClickToPlay, allSoundsLoaded, playSound]);
264+
}, [showClickToPlay, allSoundsLoaded, processNextEvent]);
238265

239-
// Reset processed count when filter changes
266+
// Clear processed events when filter changes
240267
useEffect(() => {
241-
processedCountRef.current = 0;
268+
setProcessedEvents([]);
269+
processedEventIdsRef.current.clear();
242270
}, [orgRepoFilter]);
243271

244272
const handlePlayButtonClick = () => {

0 commit comments

Comments
 (0)