implement stream player

This commit is contained in:
talksik
2026-03-18 15:44:30 -07:00
parent fca125ab52
commit e63bad9b83
12 changed files with 200 additions and 316 deletions
+3 -22
View File
@@ -1,15 +1,11 @@
import { useEffect, useRef } from "react";
import type { StreamParticle } from "@/api/types";
import { apiClient } from "@/api/client";
import { useAppStore } from "@/stores/app-store";
import type { Particle } from "@/api/types";
import { usePlaybackStore } from "@/stores/playback-store";
import { MediaParticleView } from "./media-particle-view";
import { TextParticleView } from "./text-particle-view";
import { FallbackParticleView } from "./fallback-particle-view";
import { AckButton } from "./ack-button";
interface ParticleRendererProps {
particle: StreamParticle;
particle: Particle;
}
export function ParticleRenderer({
@@ -18,17 +14,6 @@ export function ParticleRenderer({
const next = usePlaybackStore((s) => s.next);
const prev = usePlaybackStore((s) => s.prev);
const markParticlesSeen = useAppStore((s) => s.markParticlesSeen);
const markedRef = useRef<string | null>(null);
useEffect(() => {
if (!particle.seen && markedRef.current !== particle.id) {
markedRef.current = particle.id;
markParticlesSeen([particle.id]);
apiClient.markSeen(particle.id);
}
}, [particle.id, particle.seen, markParticlesSeen]);
const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {
const rect = e.currentTarget.getBoundingClientRect();
const x = (e.clientX - rect.left) / rect.width;
@@ -42,17 +27,13 @@ export function ParticleRenderer({
onClick={handleClick}
>
<ParticleContent particle={particle} />
<div className="absolute right-4 bottom-16">
<AckButton particleId={particle.id} acks={particle.acks} />
</div>
</div>
);
}
function ParticleContent({ particle }: { particle: StreamParticle }) {
function ParticleContent({ particle }: { particle: Particle }) {
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} />;
case "text":
return <TextParticleView particle={particle} />;