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
108 lines
4.2 KiB
TypeScript
108 lines
4.2 KiB
TypeScript
import { useLayoutEffect, useMemo, useSyncExternalStore } from 'react';
|
|
|
|
import { getHostSearchMatch } from '../../../lib/searchMatcher';
|
|
import type { Host } from '../../../types';
|
|
import { useEditorTabChromeList } from '../../state/editorTabStore';
|
|
import { useVaultSnapshot } from '../../state/vaultSnapshotStore';
|
|
import { getAppHandlers, subscribeAppHandlers } from '../appHandlersBridge';
|
|
import {
|
|
publishAppShellDomainSlice,
|
|
publishAppShellOverlays,
|
|
} from '../appShellPropsStore';
|
|
import { useAppLocalUiStore } from '../appLocalUiStore';
|
|
|
|
const EMPTY_HOST_RESULTS: Host[] = [];
|
|
|
|
/**
|
|
* Dialogs island: local dialog/queue state from `appLocalUiStore`, plus a
|
|
* selective vault hosts subscription for quick-search results when open.
|
|
* Assembles dialogs + overlays field-by-field — never spreads a prepared bag.
|
|
*/
|
|
export function DialogsHost() {
|
|
const local = useAppLocalUiStore();
|
|
const vault = useVaultSnapshot();
|
|
const editorTabs = useEditorTabChromeList();
|
|
const handlers = useSyncExternalStore(
|
|
subscribeAppHandlers,
|
|
getAppHandlers,
|
|
getAppHandlers,
|
|
);
|
|
|
|
const quickResults = useMemo(() => {
|
|
if (!local.isQuickSwitcherOpen) return EMPTY_HOST_RESULTS;
|
|
const term = local.quickSearch.trim();
|
|
if (!term) return vault.hosts as Host[];
|
|
return (vault.hosts as Host[])
|
|
.map((host) => ({ host, match: getHostSearchMatch(term, host) }))
|
|
.filter((entry) => entry.match.matched)
|
|
.sort((left, right) => {
|
|
if (left.match.score !== right.match.score) {
|
|
return right.match.score - left.match.score;
|
|
}
|
|
return left.host.label.localeCompare(right.host.label);
|
|
})
|
|
.map((entry) => entry.host);
|
|
}, [local.isQuickSwitcherOpen, local.quickSearch, vault.hosts]);
|
|
|
|
const dialogsDomain = useMemo(() => {
|
|
if (!handlers) return null;
|
|
return {
|
|
addToWorkspaceDialog: local.addToWorkspaceDialog,
|
|
clearAndRemoveSource: handlers.clearAndRemoveSource,
|
|
clearAndRemoveSources: handlers.clearAndRemoveSources,
|
|
editorTabs,
|
|
emptyVaultConflict: local.emptyVaultConflict,
|
|
handleHostConnectWithProtocolCheck: handlers.handleHostConnectWithProtocolCheck,
|
|
handleKeyboardInteractiveCancel: handlers.handleKeyboardInteractiveCancel,
|
|
handleKeyboardInteractiveSubmit: handlers.handleKeyboardInteractiveSubmit,
|
|
handlePassphraseCancel: handlers.handlePassphraseCancel,
|
|
handlePassphraseSkip: handlers.handlePassphraseSkip,
|
|
handlePassphraseSubmit: handlers.handlePassphraseSubmit,
|
|
handleProtocolSelect: handlers.handleProtocolSelect,
|
|
handleRequestCloseEditorTabRef: handlers.handleRequestCloseEditorTabRef,
|
|
isCreateWorkspaceOpen: local.isCreateWorkspaceOpen,
|
|
isQuickSwitcherOpen: local.isQuickSwitcherOpen,
|
|
keyboardInteractiveQueue: local.keyboardInteractiveQueue,
|
|
passphraseQueue: local.passphraseQueue,
|
|
protocolSelectHost: local.protocolSelectHost,
|
|
quickResults,
|
|
quickSearch: local.quickSearch,
|
|
resolveEmptyVaultConflict: handlers.resolveEmptyVaultConflict,
|
|
setAddToWorkspaceDialog: handlers.setAddToWorkspaceDialog,
|
|
setIsCreateWorkspaceOpen: handlers.setIsCreateWorkspaceOpen,
|
|
setIsQuickSwitcherOpen: handlers.setIsQuickSwitcherOpen,
|
|
setProtocolSelectHost: handlers.setProtocolSelectHost,
|
|
setQuickSearch: handlers.setQuickSearch,
|
|
};
|
|
}, [
|
|
editorTabs,
|
|
handlers,
|
|
local.addToWorkspaceDialog,
|
|
local.emptyVaultConflict,
|
|
local.isCreateWorkspaceOpen,
|
|
local.isQuickSwitcherOpen,
|
|
local.keyboardInteractiveQueue,
|
|
local.passphraseQueue,
|
|
local.protocolSelectHost,
|
|
local.quickSearch,
|
|
quickResults,
|
|
]);
|
|
|
|
const overlays = useMemo(() => {
|
|
if (!handlers) return null;
|
|
return {
|
|
onAddKnownHost: handlers.handleAddKnownHost as (knownHost: never) => void,
|
|
deleteHostConfirm: local.deleteHostConfirm,
|
|
onCancelDeleteHost: handlers.handleCancelDeleteHost as () => void,
|
|
onConfirmDeleteHost: handlers.handleConfirmDeleteHost as () => void,
|
|
};
|
|
}, [handlers, local.deleteHostConfirm]);
|
|
|
|
useLayoutEffect(() => {
|
|
if (dialogsDomain) publishAppShellDomainSlice('dialogs', dialogsDomain);
|
|
if (overlays) publishAppShellOverlays(overlays as never);
|
|
}, [dialogsDomain, overlays]);
|
|
|
|
return null;
|
|
}
|