Skip to content

Commit 466c29e

Browse files
committed
fix: tweaks to feedback input bar
1 parent 8852f34 commit 466c29e

File tree

6 files changed

+37
-38
lines changed

6 files changed

+37
-38
lines changed

cli/src/chat.tsx

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { useAgentValidation } from './hooks/use-agent-validation'
2424
import { useAuthState } from './hooks/use-auth-state'
2525
import { useChatInput } from './hooks/use-chat-input'
2626
import { useClipboard } from './hooks/use-clipboard'
27+
import { showClipboardMessage } from './utils/clipboard'
2728
import { useConnectionStatus } from './hooks/use-connection-status'
2829
import { useElapsedTime } from './hooks/use-elapsed-time'
2930
import { useExitHandler } from './hooks/use-exit-handler'
@@ -223,7 +224,7 @@ export const Chat = ({
223224
const abortControllerRef = useRef<AbortController | null>(null)
224225
const sendMessageRef = useRef<SendMessageFn>()
225226

226-
const { clipboardMessage } = useClipboard()
227+
const { statusMessage } = useClipboard()
227228
const isConnected = useConnectionStatus()
228229
const mainAgentTimer = useElapsedTime()
229230
const timerStartTime = mainAgentTimer.startTime
@@ -459,7 +460,7 @@ export const Chat = ({
459460
const [savedInputValue, setSavedInputValue] = useState('')
460461
const [savedCursorPosition, setSavedCursorPosition] = useState(0)
461462
const [showFeedbackConfirmation, setShowFeedbackConfirmation] = useState(false)
462-
const [feedbackSentMessage, setFeedbackSentMessage] = useState<string | null>(null)
463+
463464
const [messagesWithFeedback, setMessagesWithFeedback] = useState<Set<string>>(new Set())
464465

465466
const openFeedbackForMessage = useCallback((id: string) => {
@@ -522,14 +523,16 @@ export const Chat = ({
522523
setMessagesWithFeedback(prev => new Set(prev).add(feedbackMessageId))
523524
}
524525

525-
// Show success in status indicator and exit feedback mode
526+
// Exit feedback mode first
526527
setFeedbackMode(false)
527528
setFeedbackText('')
528529
setFeedbackCategory('other')
529-
setFeedbackSentMessage('Feedback sent ✔')
530-
setTimeout(() => {
531-
setFeedbackSentMessage(null)
532-
}, 5000)
530+
531+
// Show success message in status indicator for 5 seconds
532+
showClipboardMessage('Feedback sent ✔', { durationMs: 5000 })
533+
534+
// Restore input focus
535+
setInputFocused(true)
533536
}, [feedbackText, feedbackCategory, feedbackMessageId, messages, agentMode, sessionCreditsUsed])
534537

535538
const handleFeedbackCancel = useCallback(() => {
@@ -700,7 +703,7 @@ export const Chat = ({
700703
const shouldCenterInputVertically =
701704
!hasSuggestionMenu && !showAgentStatusLine && !isMultilineInput
702705
const statusIndicatorState = getStatusIndicatorState({
703-
clipboardMessage,
706+
statusMessage,
704707
streamStatus,
705708
nextCtrlCWillExit,
706709
isConnected,
@@ -712,7 +715,7 @@ export const Chat = ({
712715

713716
const statusIndicatorNode = (
714717
<StatusIndicator
715-
clipboardMessage={feedbackSentMessage ?? clipboardMessage}
718+
statusMessage={statusMessage}
716719
streamStatus={streamStatus}
717720
timerStartTime={timerStartTime}
718721
nextCtrlCWillExit={nextCtrlCWillExit}

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type { StatusIndicatorStateArgs } from '../status-indicator'
66
describe('StatusIndicator state logic', () => {
77
describe('getStatusIndicatorState', () => {
88
const baseArgs: StatusIndicatorStateArgs = {
9-
clipboardMessage: null,
9+
statusMessage: null,
1010
streamStatus: 'idle',
1111
nextCtrlCWillExit: false,
1212
isConnected: true,
@@ -21,7 +21,7 @@ describe('StatusIndicator state logic', () => {
2121
const state = getStatusIndicatorState({
2222
...baseArgs,
2323
nextCtrlCWillExit: true,
24-
clipboardMessage: 'Some message',
24+
statusMessage: 'Some message',
2525
streamStatus: 'streaming',
2626
isConnected: false,
2727
})
@@ -31,7 +31,7 @@ describe('StatusIndicator state logic', () => {
3131
test('returns clipboard state when message exists (second priority)', () => {
3232
const state = getStatusIndicatorState({
3333
...baseArgs,
34-
clipboardMessage: 'Copied to clipboard!',
34+
statusMessage: 'Copied to clipboard!',
3535
streamStatus: 'streaming',
3636
isConnected: false,
3737
})
@@ -69,7 +69,7 @@ describe('StatusIndicator state logic', () => {
6969
test('handles empty clipboard message as falsy', () => {
7070
const state = getStatusIndicatorState({
7171
...baseArgs,
72-
clipboardMessage: '',
72+
statusMessage: '',
7373
streamStatus: 'streaming',
7474
})
7575
// Empty string is falsy, should fall through to streaming state
@@ -81,15 +81,15 @@ describe('StatusIndicator state logic', () => {
8181
const state = getStatusIndicatorState({
8282
...baseArgs,
8383
nextCtrlCWillExit: true,
84-
clipboardMessage: 'Test',
84+
statusMessage: 'Test',
8585
})
8686
expect(state.kind).toBe('ctrlC')
8787
})
8888

8989
test('clipboard beats connecting', () => {
9090
const state = getStatusIndicatorState({
9191
...baseArgs,
92-
clipboardMessage: 'Test',
92+
statusMessage: 'Test',
9393
isConnected: false,
9494
})
9595
expect(state.kind).toBe('clipboard')

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ describe('StatusIndicator state transitions', () => {
1414
const now = Date.now()
1515
const markup = renderToStaticMarkup(
1616
<StatusIndicator
17-
clipboardMessage={null}
17+
statusMessage={null}
1818
streamStatus="waiting"
1919
timerStartTime={now - 5000}
2020
nextCtrlCWillExit={false}
@@ -35,7 +35,7 @@ describe('StatusIndicator state transitions', () => {
3535
const now = Date.now()
3636
const markup = renderToStaticMarkup(
3737
<StatusIndicator
38-
clipboardMessage={null}
38+
statusMessage={null}
3939
streamStatus="streaming"
4040
timerStartTime={now - 5000}
4141
nextCtrlCWillExit={false}
@@ -53,7 +53,7 @@ describe('StatusIndicator state transitions', () => {
5353
test('shows nothing when inactive (streamStatus = idle)', () => {
5454
const markup = renderToStaticMarkup(
5555
<StatusIndicator
56-
clipboardMessage={null}
56+
statusMessage={null}
5757
streamStatus="idle"
5858
timerStartTime={null}
5959
nextCtrlCWillExit={false}
@@ -70,7 +70,7 @@ describe('StatusIndicator state transitions', () => {
7070
const now = Date.now()
7171
const markup = renderToStaticMarkup(
7272
<StatusIndicator
73-
clipboardMessage="Copied!"
73+
statusMessage="Copied!"
7474
streamStatus="waiting"
7575
timerStartTime={now - 5000}
7676
nextCtrlCWillExit={true}
@@ -88,7 +88,7 @@ describe('StatusIndicator state transitions', () => {
8888
const now = Date.now()
8989
const markup = renderToStaticMarkup(
9090
<StatusIndicator
91-
clipboardMessage="Copied!"
91+
statusMessage="Copied!"
9292
streamStatus="waiting"
9393
timerStartTime={now - 12000}
9494
nextCtrlCWillExit={false}
@@ -105,7 +105,7 @@ describe('StatusIndicator state transitions', () => {
105105
test('shows "connecting..." shimmer when offline and idle', () => {
106106
const markup = renderToStaticMarkup(
107107
<StatusIndicator
108-
clipboardMessage={null}
108+
statusMessage={null}
109109
streamStatus="idle"
110110
timerStartTime={null}
111111
nextCtrlCWillExit={false}
@@ -120,7 +120,7 @@ describe('StatusIndicator state transitions', () => {
120120

121121
test('getStatusIndicatorState reports connecting state when offline', () => {
122122
const state = getStatusIndicatorState({
123-
clipboardMessage: null,
123+
statusMessage: null,
124124
streamStatus: 'idle',
125125
nextCtrlCWillExit: false,
126126
isConnected: false,

cli/src/components/feedback-input-mode.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,7 @@ export const FeedbackInputMode: React.FC<FeedbackInputModeProps> = ({
145145
onKeyIntercept={(key) => {
146146
const isEnter = key.name === 'return' || key.name === 'enter'
147147
if (!isEnter) return false
148-
if (key.meta) {
149-
if (canSubmit) onSubmit()
150-
return true
151-
}
148+
// Just add newline on Enter
152149
const newText = feedbackText.slice(0, feedbackCursor) + '\n' + feedbackText.slice(feedbackCursor)
153150
onFeedbackTextChange(newText, feedbackCursor + 1)
154151
return true
@@ -198,8 +195,7 @@ export const FeedbackInputMode: React.FC<FeedbackInputModeProps> = ({
198195
}}
199196
>
200197
<text style={{ wrapMode: 'none' }}>
201-
<span fg={canSubmit ? theme.foreground : theme.muted}>SUBMIT </span>
202-
<span fg={theme.muted}>⌘↵</span>
198+
<span fg={canSubmit ? theme.foreground : theme.muted}>SUBMIT</span>
203199
</text>
204200
</Button>
205201
</box>

cli/src/components/status-indicator.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export type StatusIndicatorState =
1717
| { kind: 'streaming' }
1818

1919
export type StatusIndicatorStateArgs = {
20-
clipboardMessage?: string | null
20+
statusMessage?: string | null
2121
streamStatus: StreamStatus
2222
nextCtrlCWillExit: boolean
2323
isConnected: boolean
@@ -28,7 +28,7 @@ export type StatusIndicatorStateArgs = {
2828
*
2929
* State priority (highest to lowest):
3030
* 1. nextCtrlCWillExit - User pressed Ctrl+C once, warn about exit
31-
* 2. clipboardMessage - Temporary feedback for clipboard operations
31+
* 2. statusMessage - Temporary status messages (clipboard, feedback, etc.)
3232
* 3. connecting - Not connected to backend
3333
* 4. waiting - Waiting for AI response to start
3434
* 5. streaming - AI is actively responding
@@ -38,7 +38,7 @@ export type StatusIndicatorStateArgs = {
3838
* @returns The appropriate state indicator
3939
*/
4040
export const getStatusIndicatorState = ({
41-
clipboardMessage,
41+
statusMessage,
4242
streamStatus,
4343
nextCtrlCWillExit,
4444
isConnected,
@@ -47,8 +47,8 @@ export const getStatusIndicatorState = ({
4747
return { kind: 'ctrlC' }
4848
}
4949

50-
if (clipboardMessage) {
51-
return { kind: 'clipboard', message: clipboardMessage }
50+
if (statusMessage) {
51+
return { kind: 'clipboard', message: statusMessage }
5252
}
5353

5454
if (!isConnected) {
@@ -71,15 +71,15 @@ type StatusIndicatorProps = StatusIndicatorStateArgs & {
7171
}
7272

7373
export const StatusIndicator = ({
74-
clipboardMessage,
74+
statusMessage,
7575
streamStatus,
7676
timerStartTime,
7777
nextCtrlCWillExit,
7878
isConnected,
7979
}: StatusIndicatorProps) => {
8080
const theme = useTheme()
8181
const state = getStatusIndicatorState({
82-
clipboardMessage,
82+
statusMessage,
8383
streamStatus,
8484
nextCtrlCWillExit,
8585
isConnected,

cli/src/hooks/use-clipboard.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ function formatDefaultClipboardMessage(text: string): string | null {
1717

1818
export const useClipboard = () => {
1919
const renderer = useRenderer()
20-
const [clipboardMessage, setClipboardMessage] = useState<string | null>(null)
20+
const [statusMessage, setStatusMessage] = useState<string | null>(null)
2121
const pendingCopyTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(
2222
null,
2323
)
@@ -26,7 +26,7 @@ export const useClipboard = () => {
2626
const lastCopiedRef = useRef<string | null>(null)
2727

2828
useEffect(() => {
29-
return subscribeClipboardMessages(setClipboardMessage)
29+
return subscribeClipboardMessages(setStatusMessage)
3030
}, [])
3131

3232
useEffect(() => {
@@ -94,6 +94,6 @@ export const useClipboard = () => {
9494
}, [])
9595

9696
return {
97-
clipboardMessage,
97+
statusMessage,
9898
}
9999
}

0 commit comments

Comments
 (0)