Add clear button

This commit is contained in:
Jack Kingsman
2026-01-20 16:54:11 -08:00
parent 973d6953a1
commit 2fb5100745
9 changed files with 625 additions and 549 deletions
+6 -1
View File
@@ -721,7 +721,12 @@ export function App() {
</div>
</>
) : activeConversation.type === 'visualizer' ? (
<VisualizerView packets={rawPackets} contacts={contacts} config={config} />
<VisualizerView
packets={rawPackets}
contacts={contacts}
config={config}
onClearPackets={() => setRawPackets([])}
/>
) : activeConversation.type === 'raw' ? (
<>
<div className="flex justify-between items-center px-4 py-3 border-b border-border font-medium text-lg">
@@ -276,6 +276,7 @@ interface VisualizerData {
stats: { processed: number; animated: number; nodes: number; links: number };
randomizePositions: () => void;
expandContract: () => void;
clearAndReset: () => void;
}
function useVisualizerData({
@@ -859,6 +860,56 @@ function useVisualizerData({
requestAnimationFrame(animate);
}, [chargeStrength]);
// Clear all state and reset to initial (keeps self node only)
const clearAndReset = useCallback(() => {
// Clear all pending timers
for (const timer of timersRef.current.values()) {
clearTimeout(timer);
}
timersRef.current.clear();
// Clear pending packets
pendingRef.current.clear();
// Clear processed packet IDs so they can be re-processed if needed
processedRef.current.clear();
// Clear particles
particlesRef.current.length = 0;
// Clear links
linksRef.current.clear();
// Clear nodes except self, then reset self position
const selfNode = nodesRef.current.get('self');
nodesRef.current.clear();
if (selfNode) {
selfNode.x = dimensions.width / 2;
selfNode.y = dimensions.height / 2;
selfNode.vx = 0;
selfNode.vy = 0;
selfNode.lastActivity = Date.now();
nodesRef.current.set('self', selfNode);
}
// Reset simulation with just self node
const sim = simulationRef.current;
if (sim) {
sim.nodes(Array.from(nodesRef.current.values()));
sim.force(
'link',
forceLink<GraphNode, GraphLink>([])
.id((d) => d.id)
.distance(80)
.strength(0.3)
);
sim.alpha(0.3).restart();
}
// Reset stats
setStats({ processed: 0, animated: 0, nodes: 1, links: 0 });
}, [dimensions]);
return {
nodes: nodesRef.current,
links: linksRef.current,
@@ -867,6 +918,7 @@ function useVisualizerData({
stats,
randomizePositions,
expandContract,
clearAndReset,
};
}
@@ -1013,6 +1065,7 @@ interface PacketVisualizerProps {
config: RadioConfig | null;
fullScreen?: boolean;
onFullScreenChange?: (fullScreen: boolean) => void;
onClearPackets?: () => void;
}
export function PacketVisualizer({
@@ -1021,6 +1074,7 @@ export function PacketVisualizer({
config,
fullScreen,
onFullScreenChange,
onClearPackets,
}: PacketVisualizerProps) {
const canvasRef = useRef<HTMLCanvasElement>(null);
const containerRef = useRef<HTMLDivElement>(null);
@@ -1383,6 +1437,16 @@ export function PacketVisualizer({
>
Oooh Big Stretch!
</button>
<button
onClick={() => {
data.clearAndReset();
onClearPackets?.();
}}
className="mt-1 px-3 py-1.5 bg-yellow-500/20 hover:bg-yellow-500/30 text-yellow-500 rounded text-xs transition-colors"
title="Clear all nodes, links, and packets - reset to initial state"
>
Clear &amp; Reset
</button>
</div>
</>
)}
+9 -2
View File
@@ -9,9 +9,10 @@ interface VisualizerViewProps {
packets: RawPacket[];
contacts: Contact[];
config: RadioConfig | null;
onClearPackets?: () => void;
}
export function VisualizerView({ packets, contacts, config }: VisualizerViewProps) {
export function VisualizerView({ packets, contacts, config, onClearPackets }: VisualizerViewProps) {
const [fullScreen, setFullScreen] = useState(false);
return (
@@ -29,7 +30,12 @@ export function VisualizerView({ packets, contacts, config }: VisualizerViewProp
<TabsTrigger value="packets">Packet Feed</TabsTrigger>
</TabsList>
<TabsContent value="visualizer" className="flex-1 m-0 overflow-hidden">
<PacketVisualizer packets={packets} contacts={contacts} config={config} />
<PacketVisualizer
packets={packets}
contacts={contacts}
config={config}
onClearPackets={onClearPackets}
/>
</TabsContent>
<TabsContent value="packets" className="flex-1 m-0 overflow-hidden">
<RawPacketList packets={packets} />
@@ -52,6 +58,7 @@ export function VisualizerView({ packets, contacts, config }: VisualizerViewProp
config={config}
fullScreen={fullScreen}
onFullScreenChange={setFullScreen}
onClearPackets={onClearPackets}
/>
</div>