Files
openchamber/packages/ui/src/apps/runtimeEndpointReset.ts
T
Bohdan Triapitsyn 89f7c37d60 fix: make session ordering follow activity lifecycle
Session lists now promote a conversation when it starts working and again when it settles, instead of reacting to every streaming timestamp update. This keeps ordering responsive without bringing back the sidebar churn removed by the recent performance work.

Apply the same user-visible order across Recent, project and worktree groups, session switchers, mobile navigation, widgets, the command palette, and the desktop tray. Preserve pinned priority, freeze timestamp fallback ordering, and keep child-session activity scoped to siblings under the same parent so it never moves the root conversation.

Seed reconnect snapshots without synthetic jumps, clear ephemeral ranks on deletion and runtime changes, and cover lifecycle transitions, mixed root/child trees, metadata-only updates, and project-group ordering with regression tests.
2026-07-23 15:45:53 +03:00

70 lines
3.6 KiB
TypeScript

import { opencodeClient } from '@/lib/opencode/client';
import type { RuntimeEndpointChangedDetail } from '@/lib/runtime-switch';
import { disposeTerminalInputTransport } from '@/lib/terminalApi';
import { useConfigStore } from '@/stores/useConfigStore';
import { useProjectsStore } from '@/stores/useProjectsStore';
import { useGlobalSessionsStore } from '@/stores/useGlobalSessionsStore';
import { useAutoReviewStore } from '@/stores/useAutoReviewStore';
import { useUIStore } from '@/stores/useUIStore';
import { usePermissionStore } from '@/stores/permissionStore';
import { useFileSearchStore } from '@/stores/useFileSearchStore';
import { useGitStore } from '@/stores/useGitStore';
import { useGitHubPrStatusStore } from '@/stores/useGitHubPrStatusStore';
import { useSessionFoldersStore } from '@/stores/useSessionFoldersStore';
import { useFilesViewTabsStore } from '@/stores/useFilesViewTabsStore';
import { useTerminalStore } from '@/stores/useTerminalStore';
import { useSessionUIStore } from '@/sync/session-ui-store';
import { resetStreamingState } from '@/sync/streaming';
import { useGlobalSessionStatusStore } from '@/sync/global-session-status';
import { resetSessionOrdering } from '@/sync/session-ordering';
import { syncDesktopSettings } from '@/lib/persistence';
// Same-device transport switch (LAN⇄relay for one paired device): rebind the SDK
// to the new transport WITHOUT tearing down connection/session state or remounting
// the sync layer. `reconnectToRuntimeBaseUrl` swaps in a fresh SDK client; the
// caller then forces a re-render so SyncProvider receives it as a new `sdk` prop,
// which re-runs its event-pipeline + bootstrap effects (keyed on `sdk`) to
// reconnect over the new transport IN PLACE. Message-pagination refs, the open
// session, and the whole view are preserved — no reconnecting screen, no flash,
// no bounce back to the draft.
export const reconnectAppForTransportSwitch = (): void => {
disposeTerminalInputTransport();
opencodeClient.reconnectToRuntimeBaseUrl();
resetStreamingState();
};
export const resetAppForRuntimeEndpointChange = (detail: RuntimeEndpointChangedDetail): void => {
useSessionUIStore.getState().prepareForRuntimeSwitch(detail.previousRuntimeKey);
useUIStore.getState().prepareForRuntimeSwitch(detail.previousRuntimeKey);
if (detail.previousRuntimeKey) {
useAutoReviewStore.getState().stopRunningRunsForRuntime(detail.previousRuntimeKey);
}
disposeTerminalInputTransport();
useTerminalStore.getState().clearAll();
opencodeClient.reconnectToRuntimeBaseUrl();
useConfigStore.setState({
providers: [],
agents: [],
isConnected: false,
isInitialized: false,
connectionPhase: 'connecting',
lastDisconnectReason: null,
});
useProjectsStore.getState().resetForRuntimeSwitch();
// Cross-project session list (mobile sessions sheet & co) belongs to the
// previous instance — drop it so stale sessions can't linger after a switch.
useGlobalSessionsStore.getState().resetForRuntimeSwitch();
useGlobalSessionStatusStore.setState({ statusById: new Map() });
resetSessionOrdering();
usePermissionStore.getState().reset();
useFileSearchStore.getState().resetForRuntimeSwitch();
useGitStore.getState().resetForRuntimeSwitch(detail.runtimeKey);
useGitHubPrStatusStore.getState().resetForRuntimeSwitch();
useSessionFoldersStore.getState().resetForRuntimeSwitch(detail.runtimeKey);
useFilesViewTabsStore.getState().resetForRuntimeSwitch(detail.runtimeKey);
useSessionUIStore.getState().restoreForRuntimeSwitch(detail.runtimeKey);
useUIStore.getState().restoreForRuntimeSwitch(detail.runtimeKey);
resetStreamingState();
queueMicrotask(() => void syncDesktopSettings());
};