[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
This commit is contained in:
97
application/state/useNetworkDeviceModeSuggestion.ts
Normal file
97
application/state/useNetworkDeviceModeSuggestion.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import { getEffectiveHostDistro, shouldSuggestNetworkDeviceMode } from '../../domain/host';
|
||||
import { isSavedVaultHost } from '../../domain/ephemeralHosts';
|
||||
import { resolveEffectiveTerminalProtocol } from '../../domain/terminalProtocol';
|
||||
import type { Host } from '../../domain/models';
|
||||
import {
|
||||
isNetworkDeviceSuggestionHandled,
|
||||
markNetworkDeviceSuggestionShown,
|
||||
resolveNetworkDeviceSuggestion,
|
||||
subscribeNetworkDeviceSuggestionHandled,
|
||||
} from './networkDeviceModeSuggestion';
|
||||
|
||||
export interface NetworkDeviceModeSuggestion {
|
||||
/** Whether the one-line tip should be rendered for this session. */
|
||||
visible: boolean;
|
||||
/** User accepted: persist + hide, then run the caller's enable side effects. */
|
||||
enable: () => void;
|
||||
/** User dismissed: persist + hide. */
|
||||
dismiss: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Owns the lifecycle of the "enable Network Device Mode" suggestion for a single
|
||||
* terminal session: eligibility, the once-per-host persistence boundary, and
|
||||
* cross-pane/window synchronization. Components consume `visible`/`enable`/
|
||||
* `dismiss` and keep their own view/side-effect glue (host update, toast).
|
||||
*
|
||||
* `visible` is a latch rather than a live predicate: once we decide to show the
|
||||
* tip we record the display (which also suppresses reconnects and other panes)
|
||||
* and keep it visible until the user acts, the host is classified elsewhere, or
|
||||
* another surface resolves it.
|
||||
*/
|
||||
export function useNetworkDeviceModeSuggestion({
|
||||
host,
|
||||
connected,
|
||||
canUpdateHost,
|
||||
onEnable,
|
||||
}: {
|
||||
host: Host;
|
||||
connected: boolean;
|
||||
canUpdateHost: boolean;
|
||||
onEnable: () => void;
|
||||
}): NetworkDeviceModeSuggestion {
|
||||
const [visible, setVisible] = useState(false);
|
||||
|
||||
// Reset on host change and hide when the suggestion is resolved elsewhere
|
||||
// (another pane or window) for this host. Declared before the eligibility
|
||||
// effect so, on mount, the reset (a no-op false->false) runs first and cannot
|
||||
// clobber the latch the eligibility effect sets below.
|
||||
useEffect(() => {
|
||||
setVisible(false);
|
||||
return subscribeNetworkDeviceSuggestionHandled((changedHostId) => {
|
||||
if (changedHostId === host.id) setVisible(false);
|
||||
});
|
||||
}, [host.id]);
|
||||
|
||||
useEffect(() => {
|
||||
if (visible) return;
|
||||
// Enabling writes back through onEnable, which only lands for vault hosts.
|
||||
// Skip when updates can't persist: the detached popup (no host updates) and
|
||||
// ephemeral deep-link hosts (not in the vault array).
|
||||
if (!connected || !canUpdateHost || !isSavedVaultHost(host)) return;
|
||||
const eligible = shouldSuggestNetworkDeviceMode({
|
||||
host,
|
||||
detectedDistro: getEffectiveHostDistro(host),
|
||||
alreadyHandled: isNetworkDeviceSuggestionHandled(host.id),
|
||||
// Match the Host Details toggle: only plain SSH (not Mosh/ET/serial/etc.).
|
||||
effectiveProtocol: resolveEffectiveTerminalProtocol(host),
|
||||
});
|
||||
if (!eligible) return;
|
||||
// Record the display silently so reconnects and later-mounting panes stay
|
||||
// quiet, but this instance keeps the tip until the user acts.
|
||||
markNetworkDeviceSuggestionShown(host.id);
|
||||
setVisible(true);
|
||||
}, [visible, connected, canUpdateHost, host]);
|
||||
|
||||
useEffect(() => {
|
||||
// The mode may be enabled from another surface (Host Details, a synced
|
||||
// pane) while the tip is latched open; drop it as soon as the host is
|
||||
// already classified so we don't keep offering an enabled action.
|
||||
if (host.deviceType === 'network') setVisible(false);
|
||||
}, [host.deviceType]);
|
||||
|
||||
const dismiss = useCallback(() => {
|
||||
resolveNetworkDeviceSuggestion(host.id);
|
||||
setVisible(false);
|
||||
}, [host.id]);
|
||||
|
||||
const enable = useCallback(() => {
|
||||
resolveNetworkDeviceSuggestion(host.id);
|
||||
setVisible(false);
|
||||
onEnable();
|
||||
}, [host.id, onEnable]);
|
||||
|
||||
return { visible, enable, dismiss };
|
||||
}
|
||||
Reference in New Issue
Block a user