fix: list of streams glitching to top
This was due to real-time changes to items leading to scrolling to top. Closes #123
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { useMemo } from "react";
|
import { useMemo, useRef, useEffect, memo } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import {
|
import {
|
||||||
Radio,
|
Radio,
|
||||||
@@ -75,7 +75,7 @@ function getMessagePreview(particle: Particle): string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function StreamRow({
|
const StreamRow = memo(function StreamRow({
|
||||||
particle,
|
particle,
|
||||||
networkId,
|
networkId,
|
||||||
onClick,
|
onClick,
|
||||||
@@ -234,7 +234,7 @@ function StreamRow({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
interface ParticleListViewProps {
|
interface ParticleListViewProps {
|
||||||
streams: StreamParticle[];
|
streams: StreamParticle[];
|
||||||
@@ -248,6 +248,13 @@ interface ParticleListViewProps {
|
|||||||
*/
|
*/
|
||||||
export function ParticleListView({ streams, networkId, isLoading, selectedIndex }: ParticleListViewProps) {
|
export function ParticleListView({ streams, networkId, isLoading, selectedIndex }: ParticleListViewProps) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const rowRefs = useRef<(HTMLDivElement | null)[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedIndex !== null && selectedIndex !== undefined && selectedIndex >= 0) {
|
||||||
|
rowRefs.current[selectedIndex]?.scrollIntoView({ block: "nearest" });
|
||||||
|
}
|
||||||
|
}, [selectedIndex]);
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return <Progress />;
|
return <Progress />;
|
||||||
@@ -269,7 +276,7 @@ export function ParticleListView({ streams, networkId, isLoading, selectedIndex
|
|||||||
{streams.map((stream, index) => (
|
{streams.map((stream, index) => (
|
||||||
<StreamContextMenu key={stream.id} particle={stream} networkId={networkId}>
|
<StreamContextMenu key={stream.id} particle={stream} networkId={networkId}>
|
||||||
<div
|
<div
|
||||||
ref={index === selectedIndex ? (el) => el?.scrollIntoView({ block: "nearest" }) : undefined}
|
ref={(el) => { rowRefs.current[index] = el; }}
|
||||||
>
|
>
|
||||||
<StreamRow
|
<StreamRow
|
||||||
particle={stream}
|
particle={stream}
|
||||||
|
|||||||
@@ -13,9 +13,14 @@ export function useStreamKeyboardNav({
|
|||||||
}: UseStreamKeyboardNavOptions) {
|
}: UseStreamKeyboardNavOptions) {
|
||||||
const [selectedIndex, setSelectedIndex] = useState<number | null>(null);
|
const [selectedIndex, setSelectedIndex] = useState<number | null>(null);
|
||||||
|
|
||||||
// Reset selection to first item when streams change or view mode switches
|
// Initialize selection when streams first load; clear if streams become empty.
|
||||||
|
// Do NOT reset on every Firestore update — that would scroll the list to the top.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSelectedIndex(streams.length > 0 ? 0 : null);
|
setSelectedIndex((prev) => {
|
||||||
|
if (streams.length === 0) return null;
|
||||||
|
if (prev === null) return 0;
|
||||||
|
return prev;
|
||||||
|
});
|
||||||
}, [streams.length]);
|
}, [streams.length]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user