diff --git a/mobile/src/session/mobile-native-chat-literal-marker-echo.test.ts b/mobile/src/session/mobile-native-chat-literal-marker-echo.test.ts index 77ad99005ba..660a6c20282 100644 --- a/mobile/src/session/mobile-native-chat-literal-marker-echo.test.ts +++ b/mobile/src/session/mobile-native-chat-literal-marker-echo.test.ts @@ -198,4 +198,46 @@ describe('mobile literal image-marker turns', () => { ['file:///a.jpg', 'file:///b.jpg', 'file:///c.jpg'] ]) }) + + it('reconciles rapid equal captions in separate image-count namespaces', async () => { + await mount() + send('compare', ['file:///a.jpg']) + send('compare', ['file:///b.jpg', 'file:///c.jpg', 'file:///d.jpg']) + + const messages = [ + userTextMessage('source-a', '[Image: source: /tmp/a.png]'), + userTextMessage('prompt-a', 'compare [Image #1]'), + userTextMessage('source-b', '[Image: source: /tmp/b.png]'), + userTextMessage('source-c', '[Image: source: /tmp/c.png]'), + userTextMessage('source-d', '[Image: source: /tmp/d.png]'), + userTextMessage('prompt-b', 'compare [Image #1] [Image #2] [Image #3]') + ] + await transcript(messages) + + const rendered = rows(messages) + expect(rendered).toHaveLength(2) + expect(rendered.map(rowImages)).toEqual([ + ['file:///a.jpg'], + ['file:///b.jpg', 'file:///c.jpg', 'file:///d.jpg'] + ]) + }) + + it('reconciles rapid captionless sends in separate image-count namespaces', async () => { + await mount() + send('', ['file:///a.jpg']) + send('', ['file:///b.jpg', 'file:///c.jpg', 'file:///d.jpg']) + + const messages = [ + userTextMessage('prompt-a', '[Image #1]'), + userTextMessage('prompt-b', '[Image #1] [Image #2] [Image #3]') + ] + await transcript(messages) + + const rendered = rows(messages) + expect(rendered).toHaveLength(2) + expect(rendered.map(rowImages)).toEqual([ + ['file:///a.jpg'], + ['file:///b.jpg', 'file:///c.jpg', 'file:///d.jpg'] + ]) + }) }) diff --git a/mobile/src/session/mobile-native-chat-pending-echo.ts b/mobile/src/session/mobile-native-chat-pending-echo.ts index b5fb6ab4f90..a40c5c4bc75 100644 --- a/mobile/src/session/mobile-native-chat-pending-echo.ts +++ b/mobile/src/session/mobile-native-chat-pending-echo.ts @@ -52,13 +52,16 @@ export function appendMobileNativeChatPending( const earlierOutstanding = current.filter( (pending) => pendingMatchText(pending) === origin.normalizedText && + (pending.images?.length ?? 0) >= origin.imageCount && pending.expectedOccurrence > origin.baselineOccurrences ).length // An image send whose caption is only markers still reconciles by image // ordinal, matching how `captureSendOrigin` normalized it. const expectedImageEchoOrdinal = current.filter( - (pending) => pending.images?.length && normalizeNativeChatUserText(pending.text) === '' + (pending) => + (pending.images?.length ?? 0) >= origin.imageCount && + normalizeNativeChatUserText(pending.text) === '' ).length + 1 return { ...previous,