chenbhao commited on
Commit
ac8598b
·
1 Parent(s): 7d9eccd

fix: can't start when not onboard

Browse files
src/components/LoginOnboarding.tsx ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useState } from 'react';
2
+ import { Box, Text, useTheme } from '../ink.js';
3
+ import { PressEnterToContinue } from './PressEnterToContinue.js';
4
+ import { WelcomeV2 } from './LogoV2/WelcomeV2.js';
5
+ import { ThemePicker } from './ThemePicker.js';
6
+ import { Login } from '../commands/login/login.js';
7
+ import { useExitOnCtrlCDWithKeybindings } from '../hooks/useExitOnCtrlCDWithKeybindings.js';
8
+
9
+ type StepId = 'theme' | 'login';
10
+
11
+ interface LoginOnboardingStep {
12
+ id: StepId;
13
+ component: React.ReactNode;
14
+ }
15
+
16
+ type Props = {
17
+ onDone(): void;
18
+ };
19
+
20
+ export function LoginOnboarding({
21
+ onDone
22
+ }: Props): React.ReactNode {
23
+ const [currentStepIndex, setCurrentStepIndex] = useState(0);
24
+ const [theme, setTheme] = useTheme();
25
+ const exitState = useExitOnCtrlCDWithKeybindings();
26
+
27
+ function goToNextStep() {
28
+ if (currentStepIndex < steps.length - 1) {
29
+ setCurrentStepIndex(prev => prev + 1);
30
+ } else {
31
+ onDone();
32
+ }
33
+ }
34
+
35
+ function handleThemeSelection(newTheme: string) {
36
+ setTheme(newTheme);
37
+ goToNextStep();
38
+ }
39
+
40
+ const themeStep = (
41
+ <Box marginX={1}>
42
+ <ThemePicker
43
+ onThemeSelect={handleThemeSelection}
44
+ showIntroText={true}
45
+ helpText="To change this later, run /theme"
46
+ hideEscToCancel={true}
47
+ skipExitHandling={true}
48
+ />
49
+ </Box>
50
+ );
51
+
52
+ const loginStep = (
53
+ <Box marginX={1}>
54
+ <Login
55
+ onDone={(success) => {
56
+ if (success) {
57
+ goToNextStep();
58
+ }
59
+ }}
60
+ startingMessage="Choose which provider you want Better-Clawd to use."
61
+ />
62
+ </Box>
63
+ );
64
+
65
+ const steps: LoginOnboardingStep[] = [
66
+ {
67
+ id: 'theme',
68
+ component: themeStep,
69
+ },
70
+ {
71
+ id: 'login',
72
+ component: loginStep,
73
+ },
74
+ ];
75
+
76
+ const currentStep = steps[currentStepIndex];
77
+
78
+ return (
79
+ <Box flexDirection="column">
80
+ <WelcomeV2 />
81
+ <Box flexDirection="column" marginTop={1}>
82
+ {currentStep?.component}
83
+ {exitState.pending && (
84
+ <Box padding={1}>
85
+ <Box flexDirection="column" gap={1}>
86
+ <Text dimColor>Press {exitState.keyName} again to exit</Text>
87
+ <PressEnterToContinue />
88
+ </Box>
89
+ </Box>
90
+ )}
91
+ </Box>
92
+ </Box>
93
+ );
94
+ }
src/interactiveHelpers.tsx CHANGED
@@ -28,6 +28,7 @@ import { applyConfigEnvironmentVariables } from './utils/managedEnv.js';
28
  import type { PermissionMode } from './utils/permissions/PermissionMode.js';
29
  import { getBaseRenderOptions } from './utils/renderOptions.js';
30
  import { getSettingsWithAllErrors } from './utils/settings/allErrors.js';
 
31
  import { hasAutoModeOptIn, hasSkipDangerousModePermissionPrompt } from './utils/settings/settings.js';
32
  export function completeOnboarding(): void {
33
  saveGlobalConfig(current => ({
@@ -108,7 +109,34 @@ export async function showSetupScreens(root: Root, permissionMode: PermissionMod
108
  }
109
  const config = getGlobalConfig();
110
  let onboardingShown = false;
111
- if (!config.theme || !config.hasCompletedOnboarding // always show onboarding at least once
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  ) {
113
  onboardingShown = true;
114
  const {
 
28
  import type { PermissionMode } from './utils/permissions/PermissionMode.js';
29
  import { getBaseRenderOptions } from './utils/renderOptions.js';
30
  import { getSettingsWithAllErrors } from './utils/settings/allErrors.js';
31
+ import { getConfiguredAuthProvider } from './utils/auth.js';
32
  import { hasAutoModeOptIn, hasSkipDangerousModePermissionPrompt } from './utils/settings/settings.js';
33
  export function completeOnboarding(): void {
34
  saveGlobalConfig(current => ({
 
109
  }
110
  const config = getGlobalConfig();
111
  let onboardingShown = false;
112
+
113
+ // Check if user is logged in
114
+ const authProvider = getConfiguredAuthProvider();
115
+
116
+ // Write debug info to file
117
+ try {
118
+ const fs = require('fs');
119
+ const debugInfo = {
120
+ hasCompletedOnboarding: config.hasCompletedOnboarding,
121
+ authProvider: authProvider,
122
+ hasTheme: !!config.theme,
123
+ timestamp: new Date().toISOString()
124
+ };
125
+ fs.writeFileSync('/tmp/cli-debug.json', JSON.stringify(debugInfo, null, 2));
126
+ } catch (e) {
127
+ // Ignore errors
128
+ }
129
+
130
+ // If user has completed onboarding but is not logged in, show theme picker then login
131
+ if (config.hasCompletedOnboarding && !authProvider) {
132
+ onboardingShown = true;
133
+ const { LoginOnboarding } = await import('./components/LoginOnboarding.js');
134
+ await showSetupDialog(root, done => <LoginOnboarding onDone={() => {
135
+ void done();
136
+ }} />, {
137
+ onChangeAppState
138
+ });
139
+ } else if (!config.theme || !config.hasCompletedOnboarding // always show onboarding at least once
140
  ) {
141
  onboardingShown = true;
142
  const {