mirror of
https://github.com/dpup/meshstream.git
synced 2026-03-28 17:42:37 +01:00
Show more data
This commit is contained in:
@@ -27,6 +27,8 @@ format: |
|
||||
{{ "Text:" | dim }} {{ $data.textMessage }}
|
||||
{{- else if $data.mapReport }}
|
||||
{{ "Map Report:" | dim }} {{ $data.mapReport | table }}
|
||||
{{- else if $data.routeDiscovery }}
|
||||
{{ "Route Discovery:" | dim }} {{ $data.routeDiscovery | table }}
|
||||
{{- else if $data.position }}
|
||||
{{ "Position:" | dim }} Lat: {{ $data.position.latitudeI | mult 0.0000001 }}, Long: {{ $data.position.longitudeI | mult 0.0000001 }}
|
||||
{{- else if $data.nodeInfo }}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import React, { useState, useEffect, useCallback } from "react";
|
||||
import React, { useState, useCallback } from "react";
|
||||
import { useAppSelector, useAppDispatch } from "../hooks";
|
||||
import { PacketRenderer } from "./packets/PacketRenderer";
|
||||
import { StreamControl } from "./StreamControl";
|
||||
import { Trash2, RefreshCw, Archive, Radio } from "lucide-react";
|
||||
import { Trash2, RefreshCw, Archive } from "lucide-react";
|
||||
import { clearPackets, toggleStreamPause } from "../store/slices/packetSlice";
|
||||
import { Packet } from "../lib/types";
|
||||
import { Separator } from "./Separator";
|
||||
|
||||
// Number of packets to show per page
|
||||
const PACKETS_PER_PAGE = 10;
|
||||
const PACKETS_PER_PAGE = 100;
|
||||
|
||||
export const PacketList: React.FC = () => {
|
||||
const { packets, bufferedPackets, loading, error, streamPaused } =
|
||||
|
||||
@@ -27,7 +27,7 @@ export const PacketCard: React.FC<PacketCardProps> = ({
|
||||
<div className="p-4 border-b border-neutral-700/50 shadow-inner">
|
||||
<div className="flex flex-wrap justify-between items-center gap-2">
|
||||
{/* Left side: Icon, From, Channel */}
|
||||
<div className="flex items-center text-xs">
|
||||
<div className="flex items-center text-xs space-x-1">
|
||||
<div
|
||||
className={cn(
|
||||
iconBgColor,
|
||||
@@ -38,12 +38,19 @@ export const PacketCard: React.FC<PacketCardProps> = ({
|
||||
className: "h-3.5 w-3.5 text-white",
|
||||
})}
|
||||
</div>
|
||||
<span className="font-semibold text-neutral-200 tracking-wide mr-3">
|
||||
<span className="font-semibold text-neutral-200 tracking-wide">
|
||||
{data.from
|
||||
? `!${data.from.toString(16).toLowerCase()}`
|
||||
: "Unknown"}
|
||||
</span>
|
||||
<span className="text-neutral-500">on</span>
|
||||
<span className="text-neutral-400">{packet.info.channel}</span>
|
||||
{data.gatewayId && (
|
||||
<>
|
||||
<span className="text-neutral-500">via</span>
|
||||
<span className="text-neutral-400">{data.gatewayId}</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Right side: ID and Type */}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
import { Packet } from '../../lib/types';
|
||||
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
import { Packet } from "../../lib/types";
|
||||
|
||||
// Maximum number of packets to keep in memory
|
||||
const MAX_PACKETS = 100;
|
||||
const MAX_PACKETS = 5000;
|
||||
|
||||
interface PacketState {
|
||||
packets: Packet[];
|
||||
@@ -23,7 +23,7 @@ const initialState: PacketState = {
|
||||
};
|
||||
|
||||
const packetSlice = createSlice({
|
||||
name: 'packets',
|
||||
name: "packets",
|
||||
initialState,
|
||||
reducers: {
|
||||
fetchPacketsStart(state) {
|
||||
@@ -33,12 +33,12 @@ const packetSlice = createSlice({
|
||||
fetchPacketsSuccess(state, action: PayloadAction<Packet[]>) {
|
||||
// Track unique packets and update the seen packets object
|
||||
const uniquePackets: Packet[] = [];
|
||||
|
||||
action.payload.forEach(packet => {
|
||||
|
||||
action.payload.forEach((packet) => {
|
||||
if (packet.data.from !== undefined && packet.data.id !== undefined) {
|
||||
const nodeId = `!${packet.data.from.toString(16).toLowerCase()}`;
|
||||
const packetKey = `${nodeId}_${packet.data.id}`;
|
||||
|
||||
|
||||
if (!state.seenPackets[packetKey]) {
|
||||
state.seenPackets[packetKey] = true;
|
||||
uniquePackets.push(packet);
|
||||
@@ -48,7 +48,7 @@ const packetSlice = createSlice({
|
||||
uniquePackets.push(packet);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Limit initial load to MAX_PACKETS
|
||||
state.packets = uniquePackets.slice(-MAX_PACKETS);
|
||||
state.loading = false;
|
||||
@@ -59,29 +59,29 @@ const packetSlice = createSlice({
|
||||
},
|
||||
addPacket(state, action: PayloadAction<Packet>) {
|
||||
const packet = action.payload;
|
||||
|
||||
|
||||
// Skip packets without valid from/id
|
||||
if (packet.data.from === undefined || packet.data.id === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Create a Meshtastic node ID format
|
||||
const nodeId = `!${packet.data.from.toString(16).toLowerCase()}`;
|
||||
const packetKey = `${nodeId}_${packet.data.id}`;
|
||||
|
||||
|
||||
// Check if we've already seen this packet
|
||||
if (state.seenPackets[packetKey]) {
|
||||
// Packet is a duplicate, ignore it
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Mark this packet as seen
|
||||
state.seenPackets[packetKey] = true;
|
||||
|
||||
|
||||
if (state.streamPaused) {
|
||||
// When paused, add to buffer instead of main list
|
||||
state.bufferedPackets.unshift(packet);
|
||||
|
||||
|
||||
// Ensure buffer doesn't grow too large
|
||||
if (state.bufferedPackets.length > MAX_PACKETS) {
|
||||
state.bufferedPackets = state.bufferedPackets.slice(0, MAX_PACKETS);
|
||||
@@ -89,7 +89,7 @@ const packetSlice = createSlice({
|
||||
} else {
|
||||
// Normal flow - add to main list
|
||||
state.packets.unshift(packet);
|
||||
|
||||
|
||||
// Remove oldest packets if we exceed the limit
|
||||
if (state.packets.length > MAX_PACKETS) {
|
||||
state.packets = state.packets.slice(0, MAX_PACKETS);
|
||||
@@ -103,34 +103,38 @@ const packetSlice = createSlice({
|
||||
},
|
||||
toggleStreamPause(state) {
|
||||
state.streamPaused = !state.streamPaused;
|
||||
|
||||
|
||||
// If unpausing, prepend buffered packets to the main list
|
||||
if (!state.streamPaused && state.bufferedPackets.length > 0) {
|
||||
state.packets = [...state.bufferedPackets, ...state.packets]
|
||||
.slice(0, MAX_PACKETS);
|
||||
state.packets = [...state.bufferedPackets, ...state.packets].slice(
|
||||
0,
|
||||
MAX_PACKETS
|
||||
);
|
||||
state.bufferedPackets = [];
|
||||
}
|
||||
},
|
||||
// Explicitly set the pause state
|
||||
setPauseState(state, action: PayloadAction<boolean>) {
|
||||
const newPausedState = action.payload;
|
||||
|
||||
|
||||
// Only process if state is actually changing
|
||||
if (state.streamPaused !== newPausedState) {
|
||||
state.streamPaused = newPausedState;
|
||||
|
||||
|
||||
// If unpausing, prepend buffered packets to the main list
|
||||
if (!newPausedState && state.bufferedPackets.length > 0) {
|
||||
state.packets = [...state.bufferedPackets, ...state.packets]
|
||||
.slice(0, MAX_PACKETS);
|
||||
state.packets = [...state.bufferedPackets, ...state.packets].slice(
|
||||
0,
|
||||
MAX_PACKETS
|
||||
);
|
||||
state.bufferedPackets = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const {
|
||||
export const {
|
||||
fetchPacketsStart,
|
||||
fetchPacketsSuccess,
|
||||
fetchPacketsFailure,
|
||||
@@ -140,4 +144,4 @@ export const {
|
||||
setPauseState,
|
||||
} = packetSlice.actions;
|
||||
|
||||
export default packetSlice.reducer;
|
||||
export default packetSlice.reducer;
|
||||
|
||||
Reference in New Issue
Block a user