Add one hop trace

This commit is contained in:
Jack Kingsman
2026-02-04 15:29:33 -08:00
parent 64d261e6f9
commit c2040ea6bc
11 changed files with 135 additions and 26 deletions
+26
View File
@@ -693,6 +693,22 @@ export function App() {
[fetchUndecryptedCount]
);
// Handle direct trace request
const handleTrace = useCallback(async () => {
if (!activeConversation || activeConversation.type !== 'contact') return;
toast('Trace started...');
try {
const result = await api.requestTrace(activeConversation.id);
const parts: string[] = [];
if (result.remote_snr !== null) parts.push(`Remote SNR: ${result.remote_snr.toFixed(1)} dB`);
if (result.local_snr !== null) parts.push(`Local SNR: ${result.local_snr.toFixed(1)} dB`);
const detail = parts.join(', ');
toast.success(detail ? `Trace complete! ${detail}` : 'Trace complete!');
} catch {
toast.error('No trace response heard');
}
}, [activeConversation]);
// Handle sort order change via API with optimistic update
const handleSortOrderChange = useCallback(
async (order: 'recent' | 'alpha') => {
@@ -879,6 +895,16 @@ export function App() {
})()}
</span>
<div className="flex items-center gap-1 flex-shrink-0">
{/* Direct trace button (contacts only) */}
{activeConversation.type === 'contact' && (
<button
className="p-1.5 rounded hover:bg-accent text-xl leading-none"
onClick={handleTrace}
title="Direct Trace"
>
&#x1F6CE;
</button>
)}
{/* Favorite button */}
{(activeConversation.type === 'channel' ||
activeConversation.type === 'contact') && (
+5
View File
@@ -13,6 +13,7 @@ import type {
RadioConfig,
RadioConfigUpdate,
TelemetryResponse,
TraceResponse,
UnreadCounts,
} from './types';
@@ -114,6 +115,10 @@ export const api = {
method: 'POST',
body: JSON.stringify({ command }),
}),
requestTrace: (publicKey: string) =>
fetchJson<TraceResponse>(`/contacts/${publicKey}/trace`, {
method: 'POST',
}),
// Channels
getChannels: () => fetchJson<Channel[]>('/channels'),
+6
View File
@@ -199,6 +199,12 @@ export interface CommandResponse {
sender_timestamp: number | null;
}
export interface TraceResponse {
remote_snr: number | null;
local_snr: number | null;
path_len: number;
}
export interface UnreadCounts {
counts: Record<string, number>;
mentions: Record<string, boolean>;