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
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -13,7 +13,7 @@
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="manifest" href="/site.webmanifest" />
<script type="module" crossorigin src="/assets/index-CWnjp-zX.js"></script>
<script type="module" crossorigin src="/assets/index-Bns2erWl.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DJA5wYVF.css">
</head>
<body>
+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>;