Skip to content

Commit 05a7a3d

Browse files
committed
Make login it's own screen. Handle auth in app.tsx instead of chat.tsx
1 parent 3519c0e commit 05a7a3d

File tree

3 files changed

+57
-60
lines changed

3 files changed

+57
-60
lines changed

cli/src/app.tsx

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
import os from 'os'
22
import path from 'path'
33

4-
import { useMemo, useState } from 'react'
4+
import { useMemo, useRef, useState } from 'react'
5+
import { useShallow } from 'zustand/react/shallow'
56

67
import { Chat } from './chat'
8+
import { LoginModal } from './components/login-modal'
79
import { TerminalLink } from './components/terminal-link'
810
import { ToolCallItem } from './components/tools/tool-call-item'
11+
import { useAuthState } from './hooks/use-auth-state'
912
import { useLogo } from './hooks/use-logo'
1013
import { useTerminalDimensions } from './hooks/use-terminal-dimensions'
1114
import { useTheme } from './hooks/use-theme'
15+
import { useChatStore } from './state/chat-store'
1216
import { createValidationErrorBlocks } from './utils/create-validation-error-blocks'
1317
import { openFileAtPath } from './utils/open-file'
1418
import { pluralize } from '@codebuff/common/util/string'
1519

20+
import type { MultilineInputHandle } from './components/multiline-input'
1621
import type { FileTreeNode } from '@codebuff/common/util/file'
1722

1823
interface AppProps {
@@ -42,6 +47,28 @@ export const App = ({
4247
const { textBlock: logoBlock } = useLogo({ availableWidth: contentMaxWidth })
4348

4449
const [isAgentListCollapsed, setIsAgentListCollapsed] = useState(true)
50+
51+
const inputRef = useRef<MultilineInputHandle | null>(null)
52+
const { setInputFocused, resetChatStore } = useChatStore(
53+
useShallow((store) => ({
54+
setInputFocused: store.setInputFocused,
55+
resetChatStore: store.reset,
56+
}))
57+
)
58+
59+
const {
60+
isAuthenticated,
61+
setIsAuthenticated,
62+
setUser,
63+
handleLoginSuccess,
64+
logoutMutation,
65+
} = useAuthState({
66+
requireAuth,
67+
hasInvalidCredentials,
68+
inputRef,
69+
setInputFocused,
70+
resetChatStore,
71+
})
4572

4673
const headerContent = useMemo(() => {
4774
if (!loadedAgentsData) {
@@ -172,16 +199,28 @@ export const App = ({
172199
separatorWidth,
173200
])
174201

202+
// Render login modal when not authenticated, otherwise render chat
203+
if (requireAuth !== null && isAuthenticated === false) {
204+
return (
205+
<LoginModal
206+
onLoginSuccess={handleLoginSuccess}
207+
hasInvalidCredentials={hasInvalidCredentials}
208+
/>
209+
)
210+
}
211+
175212
return (
176213
<Chat
177214
headerContent={headerContent}
178215
initialPrompt={initialPrompt}
179216
agentId={agentId}
180-
requireAuth={requireAuth}
181-
hasInvalidCredentials={hasInvalidCredentials}
182217
loadedAgentsData={loadedAgentsData}
183218
validationErrors={validationErrors}
184219
fileTree={fileTree}
220+
inputRef={inputRef}
221+
setIsAuthenticated={setIsAuthenticated}
222+
setUser={setUser}
223+
logoutMutation={logoutMutation}
185224
/>
186225
)
187226
}

cli/src/chat.tsx

Lines changed: 11 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ import { useShallow } from 'zustand/react/shallow'
33

44
import { routeUserPrompt } from './commands/router'
55
import { AgentModeToggle } from './components/agent-mode-toggle'
6-
import { Button } from './components/button'
7-
import { LoginModal } from './components/login-modal'
86
import { MessageWithAgents } from './components/message-with-agents'
97
import {
108
MultilineInput,
@@ -15,7 +13,6 @@ import { StatusBar } from './components/status-bar'
1513
import { SuggestionMenu } from './components/suggestion-menu'
1614
import { SLASH_COMMANDS } from './data/slash-commands'
1715
import { useAgentValidation } from './hooks/use-agent-validation'
18-
import { useAuthState } from './hooks/use-auth-state'
1916
import { useChatInput } from './hooks/use-chat-input'
2017
import { useClipboard } from './hooks/use-clipboard'
2118
import { useConnectionStatus } from './hooks/use-connection-status'
@@ -44,33 +41,39 @@ import { BORDER_CHARS } from './utils/ui-constants'
4441

4542
import type { ContentBlock } from './types/chat'
4643
import type { SendMessageFn } from './types/contracts/send-message'
44+
import type { User } from './utils/auth'
4745
import type { FileTreeNode } from '@codebuff/common/util/file'
4846
import type { ScrollBoxRenderable } from '@opentui/core'
47+
import type { UseMutationResult } from '@tanstack/react-query'
48+
import type { Dispatch, SetStateAction } from 'react'
4949

5050
export const Chat = ({
5151
headerContent,
5252
initialPrompt,
5353
agentId,
54-
requireAuth,
55-
hasInvalidCredentials,
5654
loadedAgentsData,
5755
validationErrors,
5856
fileTree,
57+
inputRef,
58+
setIsAuthenticated,
59+
setUser,
60+
logoutMutation,
5961
}: {
6062
headerContent: React.ReactNode
6163
initialPrompt: string | null
6264
agentId?: string
63-
requireAuth: boolean | null
64-
hasInvalidCredentials: boolean
6565
loadedAgentsData: {
6666
agents: Array<{ id: string; displayName: string }>
6767
agentsDir: string
6868
} | null
6969
validationErrors: Array<{ id: string; message: string }>
7070
fileTree: FileTreeNode[]
71+
inputRef: React.MutableRefObject<MultilineInputHandle | null>
72+
setIsAuthenticated: Dispatch<SetStateAction<boolean | null>>
73+
setUser: Dispatch<SetStateAction<User | null>>
74+
logoutMutation: UseMutationResult<boolean, Error, void, unknown>
7175
}) => {
7276
const scrollRef = useRef<ScrollBoxRenderable | null>(null)
73-
const inputRef = useRef<MultilineInputHandle | null>(null)
7477

7578
const { separatorWidth, terminalWidth } = useTerminalDimensions()
7679

@@ -178,20 +181,6 @@ export const Chat = ({
178181
return ids
179182
}, [messages])
180183

181-
const {
182-
isAuthenticated,
183-
setIsAuthenticated,
184-
setUser,
185-
handleLoginSuccess,
186-
logoutMutation,
187-
} = useAuthState({
188-
requireAuth,
189-
hasInvalidCredentials,
190-
inputRef,
191-
setInputFocused,
192-
resetChatStore,
193-
})
194-
195184
// Refs for tracking state across renders
196185
const activeAgentStreamsRef = useRef<number>(0)
197186
const isChainInProgressRef = useRef<boolean>(isChainInProgress)
@@ -800,15 +789,7 @@ export const Chat = ({
800789
</box>
801790
</box>
802791

803-
{/* Login Modal Overlay - show when not authenticated and done checking */}
804792
{validationBanner}
805-
806-
{requireAuth !== null && isAuthenticated === false && (
807-
<LoginModal
808-
onLoginSuccess={handleLoginSuccess}
809-
hasInvalidCredentials={hasInvalidCredentials}
810-
/>
811-
)}
812793
</box>
813794
)
814795
}

cli/src/components/login-modal.tsx

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -255,48 +255,24 @@ export const LoginModal = ({
255255
textColor: theme.foreground,
256256
})
257257

258-
// Calculate modal dimensions
259-
const { modalHeight } = calculateModalDimensions(
260-
terminalHeight,
261-
!!hasInvalidCredentials,
262-
DEFAULT_TERMINAL_HEIGHT,
263-
MODAL_VERTICAL_MARGIN,
264-
MAX_MODAL_BASE_HEIGHT,
265-
WARNING_BANNER_HEIGHT,
266-
)
267-
268-
// Calculate modal width and center position
269-
const modalWidth = Math.floor(terminalWidth * 0.95)
270-
const modalLeft = Math.floor((terminalWidth - modalWidth) / 2)
271-
const modalTop = Math.floor((terminalHeight - modalHeight) / 2)
272-
273258
// Format URL for display (wrap if needed)
274259
return (
275260
<box
276-
position="absolute"
277-
left={modalLeft}
278-
top={modalTop}
279-
border
280-
borderStyle="double"
281-
borderColor={theme.primary}
282261
style={{
283-
width: modalWidth,
284-
height: modalHeight,
285-
maxHeight: modalHeight,
262+
width: '100%',
263+
height: '100%',
286264
backgroundColor: theme.surface,
287265
padding: 0,
288266
flexDirection: 'column',
289267
}}
290268
>
291-
{/* Sticky banner at top - outside scrollbox */}
269+
{/* Sticky banner at top */}
292270
{hasInvalidCredentials && (
293271
<box
294272
style={{
295273
width: '100%',
296274
padding: 1,
297275
backgroundColor: theme.error,
298-
borderStyle: 'single',
299-
borderColor: theme.error,
300276
flexShrink: 0,
301277
}}
302278
>
@@ -314,6 +290,7 @@ export const LoginModal = ({
314290
style={{
315291
flexDirection: 'column',
316292
alignItems: 'center',
293+
justifyContent: 'center',
317294
width: '100%',
318295
height: '100%',
319296
padding: containerPadding,

0 commit comments

Comments
 (0)