Two changes to remove the main sources of scroll jank:
- Index own interactions once per feed parse instead of per row.
OwnInteractionCache.ingest bulk-imports reactions, boosts and poll
votes from the user's own feed wherever it is already parsed
(timeline load, mergeOwnFeed, FollowCoordinator.apply). The
loadExisting* methods become synchronous cache reads, removing the
full own-feed download + parse that ran on the main actor for every
row that scrolled into view. Merge-only so a just-written interaction
is never wiped by a CDN-stale copy. Vote detection no longer requires
an empty body (the spec allows vote posts with text).
- Keep row heights stable while scrolling. New InteractionSnapshotStore
remembers the last interaction data per post for the session;
PostRowView restores it synchronously in onAppear so rows recreated
by the LazyVStack render at final height immediately instead of
growing when /interactions/ answers. First-ever data arrival is
animated instead of appearing abruptly.