diff --git a/js/src/features/particles/stream-view.tsx b/js/src/features/particles/stream-view.tsx index c239e08..24e2324 100644 --- a/js/src/features/particles/stream-view.tsx +++ b/js/src/features/particles/stream-view.tsx @@ -28,6 +28,7 @@ import { usePlaybackPauseStore, selectIsPaused } from "@/stores/playback-pause-s import { usePlaybackKeys } from "@/hooks/use-playback-keys"; import { useStreamNavigationKeys } from "@/hooks/use-stream-navigation-keys"; import { useStreamActionKeys } from "@/hooks/use-stream-action-keys"; +import { c } from "vite/dist/node/types.d-aGj9QkWt"; function getReactions(particle: Particle): Record | undefined { if (isParticleDeleted(particle)) return undefined; @@ -156,6 +157,7 @@ function StreamViewInner({ path, streamParticle }: StreamViewProps) { next, prev, goTo, + goToParticle } = useStreamPlayback(streamParticle, path); usePrefetchAdjacentMedia(children, currentIndex); @@ -277,6 +279,18 @@ function StreamViewInner({ path, streamParticle }: StreamViewProps) { setProgress(0); }, [currentParticle?.id]); + const handleParticleCreated = useCallback((particleId: string) => { + if (currentIndex === -1) return; + + // When local user is at children.length - 1, and they send a new particle, + // we want to navigate to the new particle immediately so the user is considered caught up in the stream. + // In other cases (e.g. when user is in the middle of the stream and new particles are added), + // we don't want to disrupt their current position by jumping them to the end of the stream. + // NOTE: at this point, `children` contains stale data from the time when compose was sending, so it doesn't include the new particle yet. + if (currentIndex === children.length - 1) { + goToParticle(particleId); + } + }, [children, goToParticle, currentIndex]); if (children.length === 0) { return ( @@ -293,6 +307,7 @@ function StreamViewInner({ path, streamParticle }: StreamViewProps) { targetPath={path} onActiveChange={setComposeActive} disabled={streamParticle.status === "closed"} + onParticleCreated={handleParticleCreated} /> ); @@ -390,6 +405,7 @@ function StreamViewInner({ path, streamParticle }: StreamViewProps) { onActiveChange={setComposeActive} onStepChange={setComposeStep} disabled={streamParticle.status === "closed"} + onParticleCreated={handleParticleCreated} /> {/* Bottom gradient safe zone for keyboard hints */}