mirror of
https://github.com/yattee/yattee.git
synced 2026-10-23 13:12:53 +00:00
Let a status flap fence the feed instead of throwing it away
MAC3-R1 from the fix verification: refreshCachesForEffectiveContext purged on every effective-context move, so the cache the Subscriptions fix meant to keep was already empty when its keep-path ran. A move under an unchanged selection now fences the feed cache non-destructively; only a genuine selection move still purges. Also settles the destination loader's observer callback onto the main actor without a capture-of-var warning.
This commit is contained in:
@@ -78,6 +78,10 @@ final class AppEnvironment {
|
||||
/// The context the account-scoped caches currently hold data for.
|
||||
@ObservationIgnored private var lastCachedContext: DataContext = .local
|
||||
|
||||
/// The selection behind `lastCachedContext`, kept to tell a move of the
|
||||
/// selection apart from a status flap under an unchanged one.
|
||||
@ObservationIgnored private var lastSelectedContext: DataContext = .local
|
||||
|
||||
/// A digest of each account's stored credential, so a replacement arriving
|
||||
/// over iCloud Keychain can be told from the same secret being re-read.
|
||||
///
|
||||
@@ -649,6 +653,7 @@ final class AppEnvironment {
|
||||
// Seeded once the statuses it depends on are known, so launching does
|
||||
// not look like a change and throw away caches that are still right.
|
||||
lastCachedContext = dataContextValidator.effectiveContext
|
||||
lastSelectedContext = accountsManager.currentContext
|
||||
|
||||
// Accounts and instances arriving are triggers too, not redundant ones:
|
||||
// a context naming an account that has not synced yet — or one whose
|
||||
@@ -812,10 +817,26 @@ final class AppEnvironment {
|
||||
// as a move would throw the caches away several times a day. "Cannot
|
||||
// tell yet" is not grounds for anything destructive.
|
||||
let effective = dataContextValidator.effectiveContext
|
||||
if effective != lastCachedContext, credentialIdentityScope.isResolved {
|
||||
guard credentialIdentityScope.isResolved else { return }
|
||||
|
||||
let selected = accountsManager.currentContext
|
||||
if effective != lastCachedContext {
|
||||
lastCachedContext = effective
|
||||
clearAccountScopedCaches()
|
||||
if selected == lastSelectedContext {
|
||||
// The selection is where it was; only the *reads* moved — a
|
||||
// status flap, an unreachable fallback, a credential arriving.
|
||||
// The data on screen still belongs to the same choice of
|
||||
// account, so it is fenced rather than thrown away: an outage
|
||||
// that flips the status every minute must not leave the user
|
||||
// staring at an empty feed they had cached seconds ago.
|
||||
SubscriptionFeedCache.shared.handleEffectiveContextChange()
|
||||
HomeInstanceCache.shared.clearAllFeeds()
|
||||
remotePlaylistsCache.clearAll()
|
||||
} else {
|
||||
clearAccountScopedCaches()
|
||||
}
|
||||
}
|
||||
lastSelectedContext = selected
|
||||
}
|
||||
|
||||
/// Discards everything cached under an account's previous credential.
|
||||
|
||||
@@ -73,7 +73,7 @@ final class SubscriptionDestinationMembershipLoader {
|
||||
for name: Notification.Name in [.accountCredentialDidChange, .accountsDidChange, .instancesDidChange] {
|
||||
observers.append(
|
||||
NotificationCenter.default.addObserver(forName: name, object: nil, queue: .main) { [weak self] _ in
|
||||
Task { @MainActor in self?.reload() }
|
||||
MainActor.assumeIsolated { self?.reload() }
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user