feat: offline article caching + smart pull-to-refresh reshuffle
Offline caching: - BackgroundRefreshManager.preCacheArticles() fetches top article per story (score ≥60, up to 20 stories) and stores as CachedArticle in SwiftData - Runs after every BG fetch AND after every foreground sync via StoryStore - Articles are available in ArticleReaderView offline without ever opening them Pull-to-refresh reshuffle when nothing new: - loadStories(refresh:) now returns newCount (genuinely new story IDs) - If server returns 0 new stories, feed merges in any BG-cached stories not already in the live feed, then re-sorts by signal score (reshuffle) - seenSnapshot is always cleared so everything re-ranks fresh Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -251,11 +251,20 @@ struct SignalFeedView: View {
|
||||
.animation(.snappy, value: readStories.count)
|
||||
.onAppear { captureSeenSnapshot() }
|
||||
.refreshable {
|
||||
// Reshuffle: clear the seen snapshot so all stories re-rank by signal
|
||||
// score, and any stories cached by background refresh float to the top.
|
||||
seenSnapshot = []
|
||||
seenTracker.ids = []
|
||||
await store.loadStories(refresh: true)
|
||||
let new = await store.loadStories(refresh: true)
|
||||
// Nothing new from server — pull in any stories cached by background
|
||||
// refresh that aren't already in the live feed, then reshuffle.
|
||||
if new == 0 {
|
||||
let liveIds = Set(store.stories.map(\.id))
|
||||
let extra = cachedStories
|
||||
.filter { !liveIds.contains($0.id) }
|
||||
.map(StorySummary.init(cached:))
|
||||
if !extra.isEmpty {
|
||||
await store.mergeStories(extra)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user