mirror of
https://github.com/stablyai/orca.git
synced 2026-10-20 08:03:28 +00:00
fix(mobile): isolate question answers from composer drafts
This commit is contained in:
@@ -48,7 +48,7 @@ export function MobileNativeChatOverlay({
|
||||
onAnswerAsk={controller.handleNativeChatAnswerAsk}
|
||||
onCancelAsk={controller.handleNativeChatCancelAsk}
|
||||
question={controller.nativeChatQuestion}
|
||||
onAnswerQuestion={controller.handleNativeChatSend}
|
||||
onAnswerQuestion={controller.handleNativeChatQuestionAnswer}
|
||||
permission={controller.nativeChatPermission}
|
||||
onRespondPermission={controller.handleNativeChatRespondPermission}
|
||||
onOpenFile={controller.handleNativeChatOpenFile}
|
||||
|
||||
@@ -149,4 +149,17 @@ describe('useMobileNativeChatController handleNativeChatSend', () => {
|
||||
// A definite rejection puts the optimistically-cleared text back.
|
||||
expect(restoreRejectedDraft).toHaveBeenCalledWith(ORIGIN, 'look')
|
||||
})
|
||||
|
||||
it('does not restore a rejected question answer into the composer', async () => {
|
||||
sendWithOutcome.mockResolvedValue('rejected')
|
||||
let accepted = true
|
||||
await act(async () => {
|
||||
accepted = await controller!.handleNativeChatQuestionAnswer('1')
|
||||
})
|
||||
|
||||
expect(accepted).toBe(false)
|
||||
expect(clearDraftForSend).not.toHaveBeenCalled()
|
||||
expect(restoreRejectedDraft).not.toHaveBeenCalled()
|
||||
expect(onSendError).toHaveBeenCalledWith('Message not sent')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -58,6 +58,7 @@ export type MobileNativeChatController = {
|
||||
handleNativeChatStop: () => void
|
||||
nativeChatFilePaths: string[]
|
||||
loadNativeChatFiles: (query: string) => void
|
||||
handleNativeChatQuestionAnswer: (text: string) => Promise<boolean>
|
||||
handleNativeChatSend: (text: string, images?: string[]) => Promise<boolean>
|
||||
}
|
||||
|
||||
@@ -226,18 +227,17 @@ export function useMobileNativeChatController(args: {
|
||||
worktreeId
|
||||
})
|
||||
|
||||
const handleNativeChatSend = useCallback(
|
||||
async (text: string, images?: string[]): Promise<boolean> => {
|
||||
const sendNativeChatMessage = useCallback(
|
||||
async (text: string, images: string[] | undefined, syncComposer: boolean): Promise<boolean> => {
|
||||
const handle = activeHandleRef.current
|
||||
const origin = captureSendOrigin(text)
|
||||
if (!client || !handle || !origin || !nativeChatInputLeaseReady) {
|
||||
onSendError('Message not sent (disconnected)')
|
||||
return false
|
||||
}
|
||||
// Why: empty the composer at send time, not on the ack — over relay the
|
||||
// round trip is visible, and a lost ack must not strand the sent prompt
|
||||
// in the box. Only a definite rejection puts the text back.
|
||||
clearDraftForSend(origin, text)
|
||||
if (syncComposer) {
|
||||
clearDraftForSend(origin, text)
|
||||
}
|
||||
const outcome = await sendMobileNativeChatMessageWithOutcome({
|
||||
client,
|
||||
terminal: handle,
|
||||
@@ -255,7 +255,9 @@ export function useMobileNativeChatController(args: {
|
||||
return true
|
||||
}
|
||||
if (outcome === 'rejected') {
|
||||
restoreRejectedDraft(origin, text)
|
||||
if (syncComposer) {
|
||||
restoreRejectedDraft(origin, text)
|
||||
}
|
||||
onSendError('Message not sent')
|
||||
return false
|
||||
}
|
||||
@@ -277,6 +279,14 @@ export function useMobileNativeChatController(args: {
|
||||
restoreRejectedDraft
|
||||
]
|
||||
)
|
||||
const handleNativeChatQuestionAnswer = useCallback(
|
||||
(text: string) => sendNativeChatMessage(text, undefined, false),
|
||||
[sendNativeChatMessage]
|
||||
)
|
||||
const handleNativeChatSend = useCallback(
|
||||
(text: string, images?: string[]) => sendNativeChatMessage(text, images, true),
|
||||
[sendNativeChatMessage]
|
||||
)
|
||||
|
||||
return {
|
||||
isTabChatView,
|
||||
@@ -300,6 +310,7 @@ export function useMobileNativeChatController(args: {
|
||||
handleNativeChatStop,
|
||||
nativeChatFilePaths,
|
||||
loadNativeChatFiles,
|
||||
handleNativeChatQuestionAnswer,
|
||||
handleNativeChatSend
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user