| ... | @@ -2866,13 +2866,16 @@ export const ThreadFeed = memo(function ThreadFeed(props: ThreadFeedProps) { | ... | @@ -2866,13 +2866,16 @@ export const ThreadFeed = memo(function ThreadFeed(props: ThreadFeedProps) { |
| 2866 | entry.type === "message" ? `message:${entry.message.role}` : entry.type | 2866 | entry.type === "message" ? `message:${entry.message.role}` : entry.type |
| 2867 | } | 2867 | } |
| 2868 | getFixedItemSize={getFixedItemSize} | 2868 | getFixedItemSize={getFixedItemSize} |
| 2869 | // LegendList swaps its position and size component types when this | 2869 | // Android can retain stale native row positions when layout transitions |
| 2870 | // becomes undefined, remounting the feed and replaying row entrances. | 2870 | // race the measurements arriving during sync, even with duration 0. |
| 2871 | // Keep those containers mounted while ordinary updates stay immediate. | 2871 | // Keep its rows on LegendList's non-animated positioning path. On iOS, |
| | 2872 | // keep a transition installed between disclosures so containers don't remount. |
| 2872 | itemLayoutAnimation={ | 2873 | itemLayoutAnimation={ |
| 2873 | disclosureToggleSettling | 2874 | Platform.OS === "android" |
| 2874 | ? THREAD_FEED_LAYOUT_TRANSITION | 2875 | ? undefined |
| 2875 | : THREAD_FEED_IMMEDIATE_TRANSITION | 2876 | : disclosureToggleSettling |
| | 2877 | ? THREAD_FEED_LAYOUT_TRANSITION |
| | 2878 | : THREAD_FEED_IMMEDIATE_TRANSITION |
| 2876 | } | 2879 | } |
| 2877 | onItemSizeChanged={handleItemSizeChanged} | 2880 | onItemSizeChanged={handleItemSizeChanged} |
| 2878 | // Measure rows well before they scroll into view so estimate→actual | 2881 | // Measure rows well before they scroll into view so estimate→actual |