mirror of
https://github.com/linsa-io/linsa.git
synced 2026-01-11 20:00:23 +01:00
Improve VideoPlayer event handling and streamline viewer count sync
- Add a `callReady` function to ensure `onReady` is called only once - Attach `canplay` event listener for native HLS support to trigger `onReady` - Call `onReady` immediately after manifest parsing for HLS streams - Simplify `useStreamViewers` hook to skip viewer count sync for user "nikiv" - Silently handle errors during viewer count synchronization to avoid unnecessary logs
This commit is contained in:
@@ -38,19 +38,23 @@ export function VideoPlayer({
|
|||||||
const video = videoRef.current
|
const video = videoRef.current
|
||||||
if (!video || !src) return
|
if (!video || !src) return
|
||||||
|
|
||||||
|
let hasCalledReady = false
|
||||||
|
const callReady = () => {
|
||||||
|
if (!hasCalledReady) {
|
||||||
|
hasCalledReady = true
|
||||||
|
onReady?.()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check if native HLS is supported (Safari)
|
// Check if native HLS is supported (Safari)
|
||||||
if (video.canPlayType("application/vnd.apple.mpegurl")) {
|
if (video.canPlayType("application/vnd.apple.mpegurl")) {
|
||||||
video.src = src
|
video.src = src
|
||||||
|
// Call ready when video can play
|
||||||
|
video.addEventListener("canplay", callReady, { once: true })
|
||||||
if (autoPlay) {
|
if (autoPlay) {
|
||||||
video.play()
|
video.play()
|
||||||
.then(() => {
|
.then(() => setIsPlaying(true))
|
||||||
setIsPlaying(true)
|
|
||||||
onReady?.()
|
|
||||||
})
|
|
||||||
.catch(() => setIsPlaying(false))
|
.catch(() => setIsPlaying(false))
|
||||||
} else {
|
|
||||||
// Even if not autoplay, notify ready when we can play
|
|
||||||
video.addEventListener("canplay", () => onReady?.(), { once: true })
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -68,15 +72,12 @@ export function VideoPlayer({
|
|||||||
hls.attachMedia(video)
|
hls.attachMedia(video)
|
||||||
|
|
||||||
hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
||||||
|
// Call ready as soon as manifest is parsed
|
||||||
|
callReady()
|
||||||
if (autoPlay) {
|
if (autoPlay) {
|
||||||
video.play()
|
video.play()
|
||||||
.then(() => {
|
.then(() => setIsPlaying(true))
|
||||||
setIsPlaying(true)
|
|
||||||
onReady?.()
|
|
||||||
})
|
|
||||||
.catch(() => setIsPlaying(false))
|
.catch(() => setIsPlaying(false))
|
||||||
} else {
|
|
||||||
onReady?.()
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -140,8 +140,9 @@ export function useStreamViewers(username: string): UseStreamViewersResult {
|
|||||||
}, [presenceFeed?.$isLoaded, presenceFeed])
|
}, [presenceFeed?.$isLoaded, presenceFeed])
|
||||||
|
|
||||||
// Sync viewer count to database for external access
|
// Sync viewer count to database for external access
|
||||||
|
// Skip for nikiv since it's a hardcoded user without a database entry
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (viewerCount === 0) return
|
if (viewerCount === 0 || username === "nikiv") return
|
||||||
|
|
||||||
// Debounce the API call
|
// Debounce the API call
|
||||||
const timeout = setTimeout(() => {
|
const timeout = setTimeout(() => {
|
||||||
@@ -149,8 +150,8 @@ export function useStreamViewers(username: string): UseStreamViewersResult {
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ viewerCount }),
|
body: JSON.stringify({ viewerCount }),
|
||||||
}).catch((err) => {
|
}).catch(() => {
|
||||||
console.error("Failed to sync viewer count:", err)
|
// Silently ignore sync errors - not critical
|
||||||
})
|
})
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user