From 4d8ba7e0284fe82ed0209c2b8bd36d630d4160c4 Mon Sep 17 00:00:00 2001 From: Arkadiusz Fal Date: Mon, 19 Oct 2026 22:54:55 +0200 Subject: [PATCH] Invalidate the subscription feed when subscriptions change (#968) Subscribing or unsubscribing, locally or via iCloud, only posted a notification, so the cached feed stayed valid and Yattee Server never received the new channel list until the cache expired. Invalidate the feed cache on every subscription add and removal, and skip the disk write when it is already stale. --- Yattee/Core/FeedCache.swift | 3 ++- Yattee/Data/DataManager+Subscriptions.swift | 7 ++++++- Yattee/Services/CloudKit/CloudKitSyncEngine.swift | 4 +++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Yattee/Core/FeedCache.swift b/Yattee/Core/FeedCache.swift index 061e60a6..0949785a 100644 --- a/Yattee/Core/FeedCache.swift +++ b/Yattee/Core/FeedCache.swift @@ -104,7 +104,8 @@ actor FeedCache { /// Invalidates the cache by clearing the lastUpdated timestamp. /// The cached videos remain available but will be considered stale. func invalidate() async { - guard var data = cachedData else { return } + // Already stale: skip the disk write (remote syncs invalidate once per record). + guard var data = cachedData, data.lastUpdated != .distantPast else { return } data.lastUpdated = .distantPast cachedData = data await save(videos: data.videos, lastUpdated: .distantPast) diff --git a/Yattee/Data/DataManager+Subscriptions.swift b/Yattee/Data/DataManager+Subscriptions.swift index 587afda0..b1c9c9b2 100644 --- a/Yattee/Data/DataManager+Subscriptions.swift +++ b/Yattee/Data/DataManager+Subscriptions.swift @@ -31,7 +31,10 @@ extension DataManager { // Queue for CloudKit sync cloudKitSync?.queueSubscriptionSave(subscription) - + + // The stateless feed must be rebuilt from the new channel list (#968) + SubscriptionFeedCache.shared.invalidate() + let change = SubscriptionChange(addedSubscriptions: [subscription], removedChannelIDs: []) NotificationCenter.default.post( name: .subscriptionsDidChange, @@ -71,6 +74,8 @@ extension DataManager { cloudKitSync?.queueSubscriptionDelete(channelID: channelID, scope: scope) } + SubscriptionFeedCache.shared.invalidate() + let change = SubscriptionChange(addedSubscriptions: [], removedChannelIDs: [channelID]) NotificationCenter.default.post( name: .subscriptionsDidChange, diff --git a/Yattee/Services/CloudKit/CloudKitSyncEngine.swift b/Yattee/Services/CloudKit/CloudKitSyncEngine.swift index 4209c4be..35763f67 100644 --- a/Yattee/Services/CloudKit/CloudKitSyncEngine.swift +++ b/Yattee/Services/CloudKit/CloudKitSyncEngine.swift @@ -2693,7 +2693,8 @@ extension CloudKitSyncEngine: CKSyncEngineDelegate { } else { // New subscription from iCloud dataManager.insertSubscription(subscription) - + SubscriptionFeedCache.shared.invalidate() + // Post notification to update UI let change = SubscriptionChange(addedSubscriptions: [subscription], removedChannelIDs: []) NotificationCenter.default.post( @@ -3125,6 +3126,7 @@ extension CloudKitSyncEngine: CKSyncEngineDelegate { if let subscription = localSubscription(matching: recordName, channelID: channelID, in: dataManager) { dataManager.deleteSubscription(subscription) dataManager.save() + SubscriptionFeedCache.shared.invalidate() let change = SubscriptionChange(addedSubscriptions: [], removedChannelIDs: [channelID]) NotificationCenter.default.post( name: .subscriptionsDidChange,