Add option to disable scroll. Closes #299.

This commit is contained in:
Jack Kingsman
2026-06-20 21:53:28 -07:00
parent 66148c2c39
commit 8d8bc13a3b
5 changed files with 75 additions and 5 deletions
@@ -478,6 +478,8 @@ export function RawPacketFeedView({
const [analyzeModalOpen, setAnalyzeModalOpen] = useState(false);
const [mobileFiltersOpen, setMobileFiltersOpen] = useState(false);
const [enabledTypes, setEnabledTypes] = useState<Set<string>>(() => new Set(KNOWN_PAYLOAD_TYPES));
// Autoscroll defaults on; intentionally not persisted across refreshes.
const [autoScroll, setAutoScroll] = useState(true);
const decoderOptions = useMemo(() => createDecoderOptions(channels), [channels]);
@@ -638,6 +640,15 @@ export function RawPacketFeedView({
</button>
</span>
))}
<label className="ml-auto flex items-center gap-1 text-xs text-foreground cursor-pointer">
<input
type="checkbox"
checked={autoScroll}
onChange={(e) => setAutoScroll(e.target.checked)}
className="rounded"
/>
Autoscroll
</label>
</div>
)}
@@ -671,6 +682,15 @@ export function RawPacketFeedView({
</button>
</span>
))}
<label className="ml-auto flex items-center gap-1 text-xs text-foreground cursor-pointer">
<input
type="checkbox"
checked={autoScroll}
onChange={(e) => setAutoScroll(e.target.checked)}
className="rounded"
/>
Autoscroll
</label>
</div>
</div>
@@ -680,6 +700,7 @@ export function RawPacketFeedView({
packets={filteredPackets}
channels={channels}
onPacketClick={setSelectedPacket}
autoScroll={autoScroll}
/>
</div>
+12 -3
View File
@@ -8,6 +8,8 @@ interface RawPacketListProps {
packets: RawPacket[];
channels?: Channel[];
onPacketClick?: (packet: RawPacket) => void;
/** When true (default), the feed sticks to the newest packet. */
autoScroll?: boolean;
}
function formatTime(timestamp: number): string {
@@ -58,7 +60,12 @@ function getRouteTypeLabel(routeType: string): string {
}
}
export function RawPacketList({ packets, channels, onPacketClick }: RawPacketListProps) {
export function RawPacketList({
packets,
channels,
onPacketClick,
autoScroll = true,
}: RawPacketListProps) {
const listRef = useRef<HTMLDivElement>(null);
const decoderOptions = useMemo(() => createDecoderOptions(channels), [channels]);
@@ -76,11 +83,13 @@ export function RawPacketList({ packets, channels, onPacketClick }: RawPacketLis
[decodedPackets]
);
// Stick to the newest packet while autoscroll is on. Toggling it back on also
// jumps to the bottom immediately (autoScroll is a dependency).
useEffect(() => {
if (listRef.current) {
if (autoScroll && listRef.current) {
listRef.current.scrollTop = listRef.current.scrollHeight;
}
}, [packets]);
}, [packets, autoScroll]);
if (packets.length === 0) {
return (