fix: skip polling with empty session ID, use correct XDA parser API
- Add `enabled` option to useSession hook; OrchestratorScreen passes enabled: !!orchestratorId to avoid polling /api/sessions/ with an empty string when no orchestrator is running - Replace term.onData XDA handler with term.parser.registerCsiHandler matching the web dashboard implementation — onData only fires for outgoing user input, not incoming WebSocket data where the CSI > q query actually arrives Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
0773137a65
commit
d6d5dd6642
|
|
@ -5,6 +5,11 @@ import type { DashboardSession } from "../types";
|
|||
|
||||
const POLL_INTERVAL = 5_000;
|
||||
|
||||
interface UseSessionOptions {
|
||||
/** Set to false to disable polling. Defaults to true. */
|
||||
enabled?: boolean;
|
||||
}
|
||||
|
||||
interface UseSessionResult {
|
||||
session: DashboardSession | null;
|
||||
loading: boolean;
|
||||
|
|
@ -12,7 +17,8 @@ interface UseSessionResult {
|
|||
refresh: () => void;
|
||||
}
|
||||
|
||||
export function useSession(id: string): UseSessionResult {
|
||||
export function useSession(id: string, options?: UseSessionOptions): UseSessionResult {
|
||||
const enabled = options?.enabled ?? true;
|
||||
const { fetchSession } = useBackend();
|
||||
const [session, setSession] = useState<DashboardSession | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
|
@ -51,6 +57,12 @@ export function useSession(id: string): UseSessionResult {
|
|||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!enabled) {
|
||||
setSession(null);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
startPolling();
|
||||
|
||||
const handleAppState = (nextState: AppStateStatus) => {
|
||||
|
|
@ -69,12 +81,13 @@ export function useSession(id: string): UseSessionResult {
|
|||
stopPolling();
|
||||
sub.remove();
|
||||
};
|
||||
}, [startPolling, stopPolling]);
|
||||
}, [enabled, startPolling, stopPolling]);
|
||||
|
||||
const refresh = useCallback(() => {
|
||||
if (!enabled) return;
|
||||
setLoading(true);
|
||||
doFetch();
|
||||
}, [doFetch]);
|
||||
}, [enabled, doFetch]);
|
||||
|
||||
return { session, loading, error, refresh };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ function getZoneCounts(sessions: DashboardSession[]) {
|
|||
export default function OrchestratorScreen({ navigation }: Props) {
|
||||
const { sessions, orchestratorId, loading, error, refresh } = useSessions();
|
||||
const { sendMessage, terminalWsUrl } = useBackend();
|
||||
const { session: orchSession } = useSession(orchestratorId ?? "");
|
||||
const { session: orchSession } = useSession(orchestratorId ?? "", { enabled: !!orchestratorId });
|
||||
const [message, setMessage] = useState("");
|
||||
const [sending, setSending] = useState(false);
|
||||
|
||||
|
|
|
|||
|
|
@ -148,10 +148,11 @@ export const TERMINAL_HTML = `<!DOCTYPE html>
|
|||
});
|
||||
|
||||
// XDA handler: respond to CSI > q with XTerm identity (enables tmux clipboard)
|
||||
term.onData(function (data) {
|
||||
if (data === '\\x1b[>q') {
|
||||
term.write('\\x1bP>|XTerm(370)\\x1b\\\\');
|
||||
}
|
||||
// Must use parser.registerCsiHandler — onData only captures outgoing user input,
|
||||
// not incoming data from the WebSocket. The XDA query arrives via ws → term.write().
|
||||
term.parser.registerCsiHandler({ prefix: '>', final: 'q' }, function () {
|
||||
term.write('\\x1bP>|XTerm(370)\\x1b\\\\');
|
||||
return true;
|
||||
});
|
||||
|
||||
document.addEventListener('message', function (evt) { handleRNMessage(evt.data); });
|
||||
|
|
|
|||
Loading…
Reference in New Issue