Skip to content

Commit 77d4b61

Browse files
committed
refactor(cli): consolidate status indicator into status bar component
- Extract status indicator state management into dedicated utility - Replace StatusIndicator with new StatusBar component - Remove timer-based tests in favor of simplified state tests - Reduce code complexity in chat.tsx by moving status logic
1 parent d107cb6 commit 77d4b61

File tree

6 files changed

+276
-417
lines changed

6 files changed

+276
-417
lines changed

cli/src/chat.tsx

Lines changed: 34 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,8 @@ import {
1010
MultilineInput,
1111
type MultilineInputHandle,
1212
} from './components/multiline-input'
13-
import {
14-
StatusIndicator,
15-
StatusElapsedTime,
16-
getStatusIndicatorState,
17-
} from './components/status-indicator'
13+
import { getStatusIndicatorState } from './utils/status-indicator-state'
14+
import { StatusBar } from './components/status-bar'
1815
import { SuggestionMenu } from './components/suggestion-menu'
1916
import { SLASH_COMMANDS } from './data/slash-commands'
2017
import { useAgentValidation } from './hooks/use-agent-validation'
@@ -603,23 +600,6 @@ export const Chat = ({
603600
const shouldShowStatusLine =
604601
hasStatusIndicatorContent || shouldShowQueuePreview || !isAtBottom
605602

606-
const statusIndicatorNode = (
607-
<StatusIndicator
608-
clipboardMessage={clipboardMessage}
609-
streamStatus={streamStatus}
610-
timerStartTime={timerStartTime}
611-
nextCtrlCWillExit={nextCtrlCWillExit}
612-
isConnected={isConnected}
613-
/>
614-
)
615-
616-
const elapsedTimeNode = (
617-
<StatusElapsedTime
618-
streamStatus={streamStatus}
619-
timerStartTime={timerStartTime}
620-
/>
621-
)
622-
623603
const validationBanner = useValidationBanner({
624604
liveValidationErrors: validationErrors,
625605
loadedAgentsData,
@@ -698,70 +678,18 @@ export const Chat = ({
698678
}}
699679
>
700680
{shouldShowStatusLine && (
701-
<box
702-
style={{
703-
flexDirection: 'column',
704-
width: '100%',
705-
}}
706-
>
707-
{/* Main status line: status indicator | scroll indicator | elapsed time */}
708-
<box
709-
style={{
710-
flexDirection: 'row',
711-
alignItems: 'center',
712-
width: '100%',
713-
}}
714-
>
715-
{/* Left section - status indicator */}
716-
<box
717-
style={{
718-
flexGrow: 1,
719-
flexShrink: 1,
720-
flexBasis: 0,
721-
}}
722-
>
723-
<text style={{ wrapMode: 'none' }}>{statusIndicatorNode}</text>
724-
</box>
725-
726-
{/* Center section - scroll indicator (always centered) */}
727-
<box style={{ flexShrink: 0 }}>
728-
{!isAtBottom && (
729-
<Button
730-
style={{ paddingLeft: 2, paddingRight: 2 }}
731-
onClick={() => scrollToLatest()}
732-
onMouseOver={() => setScrollIndicatorHovered(true)}
733-
onMouseOut={() => setScrollIndicatorHovered(false)}
734-
>
735-
<text>
736-
<span
737-
fg={theme.info}
738-
attributes={
739-
scrollIndicatorHovered
740-
? TextAttributes.BOLD
741-
: TextAttributes.DIM
742-
}
743-
>
744-
{scrollIndicatorHovered ? '↓ Scroll to bottom ↓' : '↓'}
745-
</span>
746-
</text>
747-
</Button>
748-
)}
749-
</box>
750-
751-
{/* Right section - elapsed time */}
752-
<box
753-
style={{
754-
flexGrow: 1,
755-
flexShrink: 1,
756-
flexBasis: 0,
757-
flexDirection: 'row',
758-
justifyContent: 'flex-end',
759-
}}
760-
>
761-
<text style={{ wrapMode: 'none' }}>{elapsedTimeNode}</text>
762-
</box>
763-
</box>
764-
</box>
681+
<StatusBar
682+
clipboardMessage={clipboardMessage}
683+
streamStatus={streamStatus}
684+
timerStartTime={timerStartTime}
685+
nextCtrlCWillExit={nextCtrlCWillExit}
686+
isConnected={isConnected}
687+
isAtBottom={isAtBottom}
688+
separatorWidth={separatorWidth}
689+
scrollToLatest={scrollToLatest}
690+
scrollIndicatorHovered={scrollIndicatorHovered}
691+
setScrollIndicatorHovered={setScrollIndicatorHovered}
692+
/>
765693
)}
766694

767695
{/* Wrap the input row in a single OpenTUI border so the toggle stays inside the flex layout.
@@ -871,16 +799,28 @@ export const Chat = ({
871799
{pausedQueueText && (
872800
<box style={{ width: '100%' }}>
873801
<box style={{ flexDirection: 'row', alignItems: 'center' }}>
874-
<text style={{ wrapMode: 'none', flexGrow: 1 }}>
875-
<span fg={theme.warning}>
876-
{BORDER_CHARS.vertical}{pausedQueueText}
877-
</span>
802+
<text style={{ wrapMode: 'none' }}>
803+
<span fg={theme.warning}>{BORDER_CHARS.vertical}</span>
878804
</text>
879-
<Button onClick={handleClearQueue} style={{ paddingRight: 1 }}>
880-
<text>
881-
<span fg={theme.error}></span>
805+
<box
806+
style={{
807+
flexGrow: 1,
808+
flexDirection: 'row',
809+
alignItems: 'center',
810+
paddingLeft: 1,
811+
paddingRight: 1,
812+
gap: 1,
813+
}}
814+
>
815+
<text style={{ wrapMode: 'none', flexGrow: 1 }}>
816+
<span fg={theme.warning}>{pausedQueueText}</span>
882817
</text>
883-
</Button>
818+
<Button onClick={handleClearQueue}>
819+
<text>
820+
<span fg={theme.error}></span>
821+
</text>
822+
</Button>
823+
</box>
884824
<text style={{ wrapMode: 'none' }}>
885825
<span fg={theme.warning}>{BORDER_CHARS.vertical}</span>
886826
</text>

cli/src/components/__tests__/status-indicator.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { describe, test, expect } from 'bun:test'
22

3-
import { getStatusIndicatorState } from '../status-indicator'
4-
import type { StatusIndicatorStateArgs } from '../status-indicator'
3+
import { getStatusIndicatorState } from '../../utils/status-indicator-state'
4+
import type { StatusIndicatorStateArgs } from '../../utils/status-indicator-state'
55

66
describe('StatusIndicator state logic', () => {
77
describe('getStatusIndicatorState', () => {

cli/src/components/__tests__/status-indicator.timer.test.tsx

Lines changed: 0 additions & 163 deletions
This file was deleted.

0 commit comments

Comments
 (0)