Fix repeater comms coming back in different channel if a user sends and changes convos rapidly.

This commit is contained in:
Jack Kingsman
2026-02-10 19:25:35 -08:00
parent de683e77ab
commit da558e06ae
2 changed files with 28 additions and 14 deletions
+1 -1
View File
@@ -127,7 +127,7 @@ export function App() {
activeContactIsRepeater, activeContactIsRepeater,
handleTelemetryRequest, handleTelemetryRequest,
handleRepeaterCommand, handleRepeaterCommand,
} = useRepeaterMode(activeConversation, contacts, setMessages); } = useRepeaterMode(activeConversation, contacts, setMessages, activeConversationRef);
// WebSocket handlers - memoized to prevent reconnection loops // WebSocket handlers - memoized to prevent reconnection loops
const wsHandlers = useMemo( const wsHandlers = useMemo(
+27 -13
View File
@@ -1,4 +1,4 @@
import { useState, useCallback, useMemo, useEffect } from 'react'; import { useState, useCallback, useMemo, useEffect, type RefObject } from 'react';
import { api } from '../api'; import { api } from '../api';
import type { import type {
Contact, Contact,
@@ -118,7 +118,8 @@ export interface UseRepeaterModeResult {
export function useRepeaterMode( export function useRepeaterMode(
activeConversation: Conversation | null, activeConversation: Conversation | null,
contacts: Contact[], contacts: Contact[],
setMessages: React.Dispatch<React.SetStateAction<Message[]>> setMessages: React.Dispatch<React.SetStateAction<Message[]>>,
activeConversationRef: RefObject<Conversation | null>
): UseRepeaterModeResult { ): UseRepeaterModeResult {
const [repeaterLoggedIn, setRepeaterLoggedIn] = useState(false); const [repeaterLoggedIn, setRepeaterLoggedIn] = useState(false);
const { handleAirtimeCommand, stopTracking } = useAirtimeTracking(setMessages); const { handleAirtimeCommand, stopTracking } = useAirtimeTracking(setMessages);
@@ -142,26 +143,31 @@ export function useRepeaterMode(
if (!activeConversation || activeConversation.type !== 'contact') return; if (!activeConversation || activeConversation.type !== 'contact') return;
if (!activeContactIsRepeater) return; if (!activeContactIsRepeater) return;
const conversationId = activeConversation.id;
try { try {
const telemetry = await api.requestTelemetry(activeConversation.id, password); const telemetry = await api.requestTelemetry(conversationId, password);
// User may have switched conversations during the await
if (activeConversationRef.current?.id !== conversationId) return;
// Create local messages to display the telemetry (not persisted to database) // Create local messages to display the telemetry (not persisted to database)
const telemetryMessage = createLocalMessage( const telemetryMessage = createLocalMessage(
activeConversation.id, conversationId,
formatTelemetry(telemetry), formatTelemetry(telemetry),
false, false,
0 0
); );
const neighborsMessage = createLocalMessage( const neighborsMessage = createLocalMessage(
activeConversation.id, conversationId,
formatNeighbors(telemetry.neighbors), formatNeighbors(telemetry.neighbors),
false, false,
1 1
); );
const aclMessage = createLocalMessage( const aclMessage = createLocalMessage(
activeConversation.id, conversationId,
formatAcl(telemetry.acl), formatAcl(telemetry.acl),
false, false,
2 2
@@ -173,8 +179,9 @@ export function useRepeaterMode(
// Mark as logged in for CLI command mode // Mark as logged in for CLI command mode
setRepeaterLoggedIn(true); setRepeaterLoggedIn(true);
} catch (err) { } catch (err) {
if (activeConversationRef.current?.id !== conversationId) return;
const errorMessage = createLocalMessage( const errorMessage = createLocalMessage(
activeConversation.id, conversationId,
`Telemetry request failed: ${err instanceof Error ? err.message : 'Unknown error'}`, `Telemetry request failed: ${err instanceof Error ? err.message : 'Unknown error'}`,
false, false,
0 0
@@ -182,7 +189,7 @@ export function useRepeaterMode(
setMessages((prev) => [...prev, errorMessage]); setMessages((prev) => [...prev, errorMessage]);
} }
}, },
[activeConversation, activeContactIsRepeater, setMessages] [activeConversation, activeContactIsRepeater, setMessages, activeConversationRef]
); );
// Send CLI command to a repeater (after logged in) // Send CLI command to a repeater (after logged in)
@@ -191,20 +198,25 @@ export function useRepeaterMode(
if (!activeConversation || activeConversation.type !== 'contact') return; if (!activeConversation || activeConversation.type !== 'contact') return;
if (!activeContactIsRepeater || !repeaterLoggedIn) return; if (!activeContactIsRepeater || !repeaterLoggedIn) return;
const conversationId = activeConversation.id;
// Check for special airtime commands first (handled locally) // Check for special airtime commands first (handled locally)
const handled = await handleAirtimeCommand(command, activeConversation.id); const handled = await handleAirtimeCommand(command, conversationId);
if (handled) return; if (handled) return;
// Show the command as an outgoing message // Show the command as an outgoing message
const commandMessage = createLocalMessage(activeConversation.id, `> ${command}`, true, 0); const commandMessage = createLocalMessage(conversationId, `> ${command}`, true, 0);
setMessages((prev) => [...prev, commandMessage]); setMessages((prev) => [...prev, commandMessage]);
try { try {
const response = await api.sendRepeaterCommand(activeConversation.id, command); const response = await api.sendRepeaterCommand(conversationId, command);
// User may have switched conversations during the await
if (activeConversationRef.current?.id !== conversationId) return;
// Use the actual timestamp from the repeater if available // Use the actual timestamp from the repeater if available
const responseMessage = createLocalMessage( const responseMessage = createLocalMessage(
activeConversation.id, conversationId,
response.response, response.response,
false, false,
1 1
@@ -215,8 +227,9 @@ export function useRepeaterMode(
setMessages((prev) => [...prev, responseMessage]); setMessages((prev) => [...prev, responseMessage]);
} catch (err) { } catch (err) {
if (activeConversationRef.current?.id !== conversationId) return;
const errorMessage = createLocalMessage( const errorMessage = createLocalMessage(
activeConversation.id, conversationId,
`Command failed: ${err instanceof Error ? err.message : 'Unknown error'}`, `Command failed: ${err instanceof Error ? err.message : 'Unknown error'}`,
false, false,
1 1
@@ -230,6 +243,7 @@ export function useRepeaterMode(
repeaterLoggedIn, repeaterLoggedIn,
setMessages, setMessages,
handleAirtimeCommand, handleAirtimeCommand,
activeConversationRef,
] ]
); );