refactor: prevent unnecessary prop drilling
Components throughout the tree are anyways utilizing the zustand store, so there is no reason to send props for the same store methods.
This commit is contained in:
@@ -8,7 +8,6 @@ import { useAudioSource } from "@/components/audio/use-audio-source";
|
||||
|
||||
interface MediaParticleViewProps {
|
||||
particle: StreamParticle;
|
||||
onEnded: () => void;
|
||||
}
|
||||
|
||||
function formatTime(ms: number): string {
|
||||
@@ -36,12 +35,12 @@ function DurationPill({
|
||||
|
||||
export function MediaParticleView({
|
||||
particle,
|
||||
onEnded,
|
||||
}: MediaParticleViewProps) {
|
||||
const cachedUrl = usePlaybackStore(
|
||||
(s) => s.downloadUrlCache[particle.id],
|
||||
);
|
||||
const cacheDownloadUrl = usePlaybackStore((s) => s.cacheDownloadUrl);
|
||||
const next = usePlaybackStore((s) => s.next);
|
||||
const paused = usePlaybackStore((s) => s.paused);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
@@ -113,7 +112,7 @@ export function MediaParticleView({
|
||||
crossOrigin="anonymous"
|
||||
src={cachedUrl}
|
||||
autoPlay
|
||||
onEnded={onEnded}
|
||||
onEnded={next}
|
||||
onTimeUpdate={(e) => {
|
||||
setCurrentTimeMs(e.currentTarget.currentTime * 1000);
|
||||
}}
|
||||
@@ -134,7 +133,7 @@ export function MediaParticleView({
|
||||
src={cachedUrl}
|
||||
autoPlay
|
||||
playsInline
|
||||
onEnded={onEnded}
|
||||
onEnded={next}
|
||||
onTimeUpdate={(e) => {
|
||||
setCurrentTimeMs(e.currentTarget.currentTime * 1000);
|
||||
}}
|
||||
|
||||
@@ -10,15 +10,14 @@ import { AckButton } from "./ack-button";
|
||||
|
||||
interface ParticleRendererProps {
|
||||
particle: StreamParticle;
|
||||
onNext: () => void;
|
||||
onPrev: () => void;
|
||||
}
|
||||
|
||||
export function ParticleRenderer({
|
||||
particle,
|
||||
onNext,
|
||||
onPrev,
|
||||
}: ParticleRendererProps) {
|
||||
const next = usePlaybackStore((s) => s.next);
|
||||
const prev = usePlaybackStore((s) => s.prev);
|
||||
|
||||
const markParticlesSeen = useAppStore((s) => s.markParticlesSeen);
|
||||
const markedRef = useRef<string | null>(null);
|
||||
|
||||
@@ -33,15 +32,15 @@ export function ParticleRenderer({
|
||||
const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {
|
||||
const rect = e.currentTarget.getBoundingClientRect();
|
||||
const x = (e.clientX - rect.left) / rect.width;
|
||||
if (x < 0.3) onPrev();
|
||||
else if (x > 0.7) onNext();
|
||||
if (x < 0.3) prev();
|
||||
else if (x > 0.7) next();
|
||||
};
|
||||
|
||||
const renderContent = () => {
|
||||
switch (particle.type) {
|
||||
case "media":
|
||||
{/* NOTE: it's more robust to re-mount the MediaParticleView when the particle changes, to ensure playback state is well-behaved */}
|
||||
return <MediaParticleView key={particle.id} particle={particle} onEnded={onNext} />;
|
||||
{/* NOTE: it's more robust to re-mount the MediaParticleView when the particle changes, to ensure playback state is well-behaved */ }
|
||||
return <MediaParticleView key={particle.id} particle={particle} />;
|
||||
case "text":
|
||||
return <TextParticleView particle={particle} />;
|
||||
default:
|
||||
@@ -61,3 +60,14 @@ export function ParticleRenderer({
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function RenderParticle({ particle }: { particle: StreamParticle }) {
|
||||
switch (particle.type) {
|
||||
case "media":
|
||||
return <MediaParticleView particle={particle} />;
|
||||
case "text":
|
||||
return <TextParticleView particle={particle} />;
|
||||
default:
|
||||
return <FallbackParticleView particle={particle} />;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,11 +211,7 @@ export function StreamPlayerPage() {
|
||||
{/* Particle content — fills entire viewport */}
|
||||
<div className="absolute inset-0">
|
||||
{currentParticle && (
|
||||
<ParticleRenderer
|
||||
particle={currentParticle}
|
||||
onNext={next}
|
||||
onPrev={prev}
|
||||
/>
|
||||
<ParticleRenderer particle={currentParticle} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user