perf: instrument cold start and disk-cache first-page feed
Adds AppLaunch OSSignposter intervals/events across the tab/feed/
search/notifications cold path so Instruments can see where startup
time lands. Also:
- FeedCache: synchronous JSON-on-disk cache for the first page of a
pinned feed, keyed by feed id. FeedViewModel reads it in init and
writes back after a successful fetch, so the feed renders real
content on first body eval instead of an empty state that fills in
a few frames later.
- hasFetchedInitial: new flag on FeedViewModel so FeedTabContent
still runs a fresh network fetch on first appear even when the
disk cache pre-populated galleries.
- Background cleanup (viewedStories + storyStatusCache.purgeExpired)
moves out of GrainApp.scenePhase and into MainTabView's scenePhase
observer — MainTabView is the only place they're actually needed
and GrainApp was paying for an extra scenePhase observer on every
app.
authored by