mirror of
https://github.com/stablyai/orca.git
synced 2026-10-24 00:04:01 +00:00
fix(mobile): fence queued taps across reconnects
This commit is contained in:
@@ -3416,11 +3416,19 @@ export default function SessionScreen() {
|
||||
}, [])
|
||||
const startAccessoryRepeat = useCallback(
|
||||
(input: ReturnType<typeof createTerminalLiveAccessoryInput>) => {
|
||||
// Why: the controller queue sits outside RPC, so fence pre-outage taps from a later connection.
|
||||
const targetClient = clientRef.current
|
||||
const targetConnectedAt = targetClient?.getLastConnectedAt() ?? null
|
||||
accessoryRepeatRef.current.start(
|
||||
input,
|
||||
createTerminalAccessoryRepeatSender(
|
||||
activeHandleRef.current,
|
||||
() => activeHandleRef.current,
|
||||
(targetHandle) =>
|
||||
activeHandleRef.current === targetHandle &&
|
||||
targetClient !== null &&
|
||||
clientRef.current === targetClient &&
|
||||
connStateRef.current === 'connected' &&
|
||||
targetClient.getLastConnectedAt() === targetConnectedAt,
|
||||
(nextInput, targetHandle) => handleAccessoryKeyRef.current(nextInput, targetHandle)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -155,7 +155,7 @@ describe('terminal accessory repeat', () => {
|
||||
const sendToTerminal = vi.fn(async () => true)
|
||||
const send = createTerminalAccessoryRepeatSender(
|
||||
activeTerminal,
|
||||
() => activeTerminal,
|
||||
(targetHandle) => activeTerminal === targetHandle,
|
||||
sendToTerminal
|
||||
)
|
||||
|
||||
@@ -166,4 +166,35 @@ describe('terminal accessory repeat', () => {
|
||||
expect(sendToTerminal).toHaveBeenCalledTimes(1)
|
||||
expect(sendToTerminal).toHaveBeenCalledWith('down', 'terminal-a')
|
||||
})
|
||||
|
||||
it('drops a queued send when its press-time connection is no longer current', async () => {
|
||||
vi.useFakeTimers()
|
||||
let connectionGeneration = 1
|
||||
const first = deferred()
|
||||
const sent: string[] = []
|
||||
const sendToTerminal = vi.fn((input: string) => {
|
||||
sent.push(input)
|
||||
return input === 'down' ? first.promise.then(() => true) : Promise.resolve(true)
|
||||
})
|
||||
const createSender = () => {
|
||||
const pressedConnectionGeneration = connectionGeneration
|
||||
return createTerminalAccessoryRepeatSender(
|
||||
'terminal-a',
|
||||
() => connectionGeneration === pressedConnectionGeneration,
|
||||
sendToTerminal
|
||||
)
|
||||
}
|
||||
const repeat = createTerminalAccessoryRepeatController<string>()
|
||||
|
||||
repeat.start('down', createSender())
|
||||
repeat.stop()
|
||||
repeat.start('up', createSender())
|
||||
repeat.stop()
|
||||
|
||||
connectionGeneration = 2
|
||||
first.resolve()
|
||||
await vi.runAllTimersAsync()
|
||||
|
||||
expect(sent).toEqual(['down'])
|
||||
})
|
||||
})
|
||||
|
||||
@@ -5,11 +5,11 @@ type TerminalAccessoryRepeatSender<TInput> = (input: TInput) => Promise<boolean>
|
||||
|
||||
export function createTerminalAccessoryRepeatSender<TInput>(
|
||||
targetHandle: string | null,
|
||||
getActiveHandle: () => string | null,
|
||||
isDeliveryTargetCurrent: (targetHandle: string) => boolean,
|
||||
sendToTerminal: (input: TInput, targetHandle: string) => Promise<boolean>
|
||||
): TerminalAccessoryRepeatSender<TInput> {
|
||||
return (input) => {
|
||||
if (!targetHandle || getActiveHandle() !== targetHandle) {
|
||||
if (!targetHandle || !isDeliveryTargetCurrent(targetHandle)) {
|
||||
return Promise.resolve(false)
|
||||
}
|
||||
return sendToTerminal(input, targetHandle)
|
||||
|
||||
Reference in New Issue
Block a user