idiomatic react
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useEffect, useEffectEvent, useRef } from 'react';
|
||||
import beepSound from '../../assets/sounds/beep.wav';
|
||||
import type { Network, Particle, StreamProperties } from '@/api/types';
|
||||
import { apiClient } from '@/api/client';
|
||||
@@ -22,6 +22,49 @@ export function useStreamAutoplay(
|
||||
const userId = useAuthStore((s) => s.user?.id) ?? '';
|
||||
const settledIdRef = useRef<string | undefined>(undefined);
|
||||
|
||||
// The autoplay action reads the latest userId/network/stream/networkId at the
|
||||
// moment a new child settles, without making any of them a reactive trigger —
|
||||
// the only thing that should fire this is a change in the latest child's id.
|
||||
const onNewLatestChild = useEffectEvent((child: Particle) => {
|
||||
if (child.created_by_human_id === userId) return;
|
||||
|
||||
if (useAutoplayStore.getState().muted) return;
|
||||
|
||||
if (child.type === 'text') {
|
||||
// Browser autoplay policy can block this before user interaction; that's
|
||||
// fine — the beep is a nice-to-have, not a critical signal.
|
||||
new Audio(beepSound)
|
||||
.play()
|
||||
.catch((err) => logError(err, { scope: 'autoplay.beep' }));
|
||||
return;
|
||||
}
|
||||
|
||||
if (child.type !== 'media') return;
|
||||
|
||||
const { displayName, initials } = resolveHumanDisplay(
|
||||
child.created_by_human_id,
|
||||
network?.humans,
|
||||
);
|
||||
|
||||
apiClient
|
||||
.getParticleDownloadUrl(child.properties.object_id)
|
||||
.then((downloadUrl) => {
|
||||
platform.autoplay.play({
|
||||
particleId: child.id,
|
||||
streamId: streamParticle.id,
|
||||
networkId,
|
||||
downloadUrl,
|
||||
mimeType: child.properties.mime_type,
|
||||
durationMs: child.properties.duration_ms,
|
||||
senderName: displayName,
|
||||
senderInitials: initials,
|
||||
});
|
||||
})
|
||||
.catch((err) =>
|
||||
logError(err, { scope: 'autoplay.fetchUrl', particleId: child.id }),
|
||||
);
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!latestChild) return;
|
||||
|
||||
@@ -34,43 +77,6 @@ export function useStreamAutoplay(
|
||||
if (latestChild.id === settledIdRef.current) return;
|
||||
settledIdRef.current = latestChild.id;
|
||||
|
||||
if (latestChild.created_by_human_id === userId) return;
|
||||
|
||||
if (useAutoplayStore.getState().muted) return;
|
||||
|
||||
if (latestChild.type === 'text') {
|
||||
// Browser autoplay policy can block this before user interaction; that's
|
||||
// fine — the beep is a nice-to-have, not a critical signal.
|
||||
new Audio(beepSound)
|
||||
.play()
|
||||
.catch((err) => logError(err, { scope: 'autoplay.beep' }));
|
||||
return;
|
||||
}
|
||||
|
||||
if (latestChild.type !== 'media') return;
|
||||
|
||||
const particle = latestChild;
|
||||
const { displayName, initials } = resolveHumanDisplay(
|
||||
particle.created_by_human_id,
|
||||
network?.humans,
|
||||
);
|
||||
|
||||
apiClient
|
||||
.getParticleDownloadUrl(particle.properties.object_id)
|
||||
.then((downloadUrl) => {
|
||||
platform.autoplay.play({
|
||||
particleId: particle.id,
|
||||
streamId: streamParticle.id,
|
||||
networkId,
|
||||
downloadUrl,
|
||||
mimeType: particle.properties.mime_type,
|
||||
durationMs: particle.properties.duration_ms,
|
||||
senderName: displayName,
|
||||
senderInitials: initials,
|
||||
});
|
||||
})
|
||||
.catch((err) =>
|
||||
logError(err, { scope: 'autoplay.fetchUrl', particleId: particle.id }),
|
||||
);
|
||||
}, [latestChild?.id]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
onNewLatestChild(latestChild);
|
||||
}, [latestChild]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user