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 beepSound from '../../assets/sounds/beep.wav';
|
||||||
import type { Network, Particle, StreamProperties } from '@/api/types';
|
import type { Network, Particle, StreamProperties } from '@/api/types';
|
||||||
import { apiClient } from '@/api/client';
|
import { apiClient } from '@/api/client';
|
||||||
@@ -22,6 +22,49 @@ export function useStreamAutoplay(
|
|||||||
const userId = useAuthStore((s) => s.user?.id) ?? '';
|
const userId = useAuthStore((s) => s.user?.id) ?? '';
|
||||||
const settledIdRef = useRef<string | undefined>(undefined);
|
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(() => {
|
useEffect(() => {
|
||||||
if (!latestChild) return;
|
if (!latestChild) return;
|
||||||
|
|
||||||
@@ -34,43 +77,6 @@ export function useStreamAutoplay(
|
|||||||
if (latestChild.id === settledIdRef.current) return;
|
if (latestChild.id === settledIdRef.current) return;
|
||||||
settledIdRef.current = latestChild.id;
|
settledIdRef.current = latestChild.id;
|
||||||
|
|
||||||
if (latestChild.created_by_human_id === userId) return;
|
onNewLatestChild(latestChild);
|
||||||
|
}, [latestChild]);
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user