diff --git a/__tests__/ui/screens/InstallPluginsScreen.test.tsx b/__tests__/ui/screens/InstallPluginsScreen.test.tsx
index b7b91dd..9a5f5cd 100644
--- a/__tests__/ui/screens/InstallPluginsScreen.test.tsx
+++ b/__tests__/ui/screens/InstallPluginsScreen.test.tsx
@@ -96,8 +96,8 @@ describe('InstallPluginsScreen', () => {
await waitFor(() => {
const frame = sut.lastFrame()!;
- const codexPos = frame.indexOf('Codex');
- const cursorPos = frame.indexOf('Cursor');
+ const codexPos = frame.lastIndexOf('Codex');
+ const cursorPos = frame.lastIndexOf('Cursor');
expect(codexPos).toBeGreaterThan(-1);
expect(cursorPos).toBeGreaterThan(-1);
expect(codexPos).toBeLessThan(cursorPos);
diff --git a/src/ui/tui/screens/install-plugins/InstallPluginsScreen.tsx b/src/ui/tui/screens/install-plugins/InstallPluginsScreen.tsx
index 6356bdb..ba65b77 100644
--- a/src/ui/tui/screens/install-plugins/InstallPluginsScreen.tsx
+++ b/src/ui/tui/screens/install-plugins/InstallPluginsScreen.tsx
@@ -1,5 +1,7 @@
-import { getIntegrations } from '@integrations/index.js';
import { ScreenId } from '@lib/session.js';
+import { track } from '@lib/telemetry.js';
+import type { IdeId } from '@shared-kernel/types.js';
+
import { MainLayout } from '../../components/MainLayout.js';
import { TaskList } from '../../components/TaskList.js';
import { useAutoAdvance } from '../../hooks/useAutoAdvance.js';
@@ -8,18 +10,15 @@ import { useNavigation } from '../../hooks/useNavigation.js';
import { buildWizardTasks } from '../../lib/wizard-tasks.js';
import { $session, store } from '../../store.js';
import { usePluginInstall } from './usePluginInstall.js';
-import { track } from '@lib/telemetry.js';
import {
pluginsAlreadyInstalled,
pluginInstalled,
pluginExitedAfterError,
} from './log-messages.js';
import * as te from './telemetry-events.js';
-import { type IdeSelectValue, type DetectedSelectValue, type ErrorAction } from './actions.js';
+import { type ErrorAction } from './actions.js';
import { BottomPrompt, MainContent } from './components/index.js';
-const ALL_INTEGRATIONS = getIntegrations();
-
export function InstallPluginsScreen() {
const navigate = useNavigation(ScreenId.InstallPlugins);
const log = useLogger(ScreenId.InstallPlugins);
@@ -35,24 +34,18 @@ export function InstallPluginsScreen() {
},
});
- function handleIdeSelect(value: IdeSelectValue) {
- track(te.pluginIdeSelected(value));
- selectIde(value);
- }
-
- const preferredIndex = ALL_INTEGRATIONS.map((i) => i.id).find((id) => detected.includes(id));
-
- function handleDetectedSelect(value: DetectedSelectValue) {
- if (value === 'continue') {
- if (!preferredIndex) return;
+ function handleIdeSelect(value: IdeId) {
+ if (detected.includes(value)) {
+ store.setIde(value);
- store.setIde(preferredIndex);
log(pluginsAlreadyInstalled(detected));
track(te.pluginsAlreadyDetected());
navigate.to('next');
return;
}
- handleIdeSelect(value);
+
+ track(te.pluginIdeSelected(value));
+ selectIde(value);
}
function handleError(value: ErrorAction) {
@@ -83,8 +76,7 @@ export function InstallPluginsScreen() {
}
diff --git a/src/ui/tui/screens/install-plugins/actions.ts b/src/ui/tui/screens/install-plugins/actions.ts
index 65d69f4..e34afc6 100644
--- a/src/ui/tui/screens/install-plugins/actions.ts
+++ b/src/ui/tui/screens/install-plugins/actions.ts
@@ -1,10 +1,6 @@
import type { IdeId } from '@shared-kernel/types.js';
import type { PromptOption } from '../../components/PromptPanel.js';
-export type IdeSelectValue = IdeId;
-
-export type DetectedSelectValue = IdeSelectValue | 'continue';
-
export const IDE_SELECT_OPTIONS: PromptOption[] = [
{ label: 'Claude Code', value: 'claude' },
{ label: 'Cursor', value: 'cursor' },
diff --git a/src/ui/tui/screens/install-plugins/components/BottomPrompt.tsx b/src/ui/tui/screens/install-plugins/components/BottomPrompt.tsx
index 65e4018..0e0a087 100644
--- a/src/ui/tui/screens/install-plugins/components/BottomPrompt.tsx
+++ b/src/ui/tui/screens/install-plugins/components/BottomPrompt.tsx
@@ -2,41 +2,23 @@ import type { IdeId } from '@shared-kernel/types.js';
import { getIntegrations } from '@integrations/index.js';
import { PromptPanel } from '../../../components/PromptPanel.js';
import type { PluginPhase } from '../usePluginInstall.js';
-import {
- IDE_SELECT_OPTIONS,
- ERROR_OPTIONS,
- type IdeSelectValue,
- type DetectedSelectValue,
- type ErrorAction,
-} from '../actions.js';
+import { ERROR_OPTIONS, type ErrorAction } from '../actions.js';
+import { DefaultPrompt } from './DefaultPrompt.js';
const ALL_INTEGRATIONS = getIntegrations();
type BottomPromptProps = {
phase: PluginPhase;
detected: IdeId[];
- onIdeSelect: (value: IdeSelectValue) => void;
- onDetectedSelect: (value: DetectedSelectValue) => void;
+ onSelect: (value: IdeId) => void;
onError: (value: ErrorAction) => void;
};
-export function BottomPrompt({
- phase,
- detected,
- onIdeSelect,
- onDetectedSelect,
- onError,
-}: BottomPromptProps) {
+export function BottomPrompt({ phase, detected, onSelect, onError }: BottomPromptProps) {
switch (phase) {
case 'choose-ide':
- return (
-
- );
+ return ;
+
case 'error':
return (
);
+
case 'already-installed': {
const detectedSet = new Set(detected);
const preferred = ALL_INTEGRATIONS.find((i) => detectedSet.has(i.id));
- const otherOptions = ALL_INTEGRATIONS.filter((i) => i.id !== preferred?.id)
+
+ if (!preferred) {
+ return ;
+ }
+
+ const rest = ALL_INTEGRATIONS.filter((i) => i.id !== preferred.id)
.toSorted((a, b) => Number(detectedSet.has(b.id)) - Number(detectedSet.has(a.id)))
- .map((i) => ({
- label: i.name,
- value: i.id,
- }));
+ .map((i) => ({ label: i.name, value: i.id }));
return (
);
}
+
case 'detecting':
case 'installing':
case 'installed':
return null;
+
default: {
const _exhaustive: never = phase satisfies never;
throw new Error(`Unhandled phase: ${_exhaustive}`);
diff --git a/src/ui/tui/screens/install-plugins/components/DefaultPrompt.tsx b/src/ui/tui/screens/install-plugins/components/DefaultPrompt.tsx
new file mode 100644
index 0000000..2b0b010
--- /dev/null
+++ b/src/ui/tui/screens/install-plugins/components/DefaultPrompt.tsx
@@ -0,0 +1,18 @@
+import { PromptPanel } from '@ui/tui/components/index.js';
+import type { IdeId } from '@shared-kernel/types.js';
+import { IDE_SELECT_OPTIONS } from '../actions.js';
+
+type DefaultPromptProps = {
+ onSelect: (value: IdeId) => void;
+};
+
+export function DefaultPrompt({ onSelect }: DefaultPromptProps) {
+ return (
+
+ );
+}