mirror of
https://github.com/yattee/yattee.git
synced 2026-10-23 13:12:53 +00:00
SubscriptionService held one provider per backend and each resolved its instance from settingsManager.subscriptionAccount, falling back to "the first enabled Invidious instance" when that was unset. With several logins possible on one instance that model breaks twice: two accounts would share a single in-memory subscription cache, and the fallback could send an account's request to a server it holds no credential for. Providers are now built per account and cached by account ID, and each resolves its instance and credential from the account it was built for - no fallback. The protocol's accountType becomes a DataContext, which is what actually identifies a provider now. Views that branched on "is the subscription account local" read the context instead, and the settings picker writes both stores. Keeping the legacy setting in step is deliberate for now: several views still read it, and letting the two diverge would show one account in the UI while serving another's data. The Phase 3 switcher removes the last readers. Signing out discards the account's provider so its cached subscriptions cannot be served after the account is gone.
71 lines
2.2 KiB
Swift
71 lines
2.2 KiB
Swift
//
|
|
// LocalSubscriptionProvider.swift
|
|
// Yattee
|
|
//
|
|
// Local subscription provider using SwiftData with iCloud sync.
|
|
// This is the default provider when using "Yattee (iCloud)" subscription account.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
/// Local subscription provider that stores subscriptions in SwiftData.
|
|
/// Syncs with iCloud via CloudKitSyncEngine.
|
|
@MainActor
|
|
final class LocalSubscriptionProvider: SubscriptionProvider {
|
|
// MARK: - Properties
|
|
|
|
let context: DataContext = .local
|
|
private let dataManager: DataManager
|
|
|
|
// MARK: - Initialization
|
|
|
|
init(dataManager: DataManager) {
|
|
self.dataManager = dataManager
|
|
}
|
|
|
|
// MARK: - SubscriptionProvider
|
|
|
|
func fetchSubscriptions() async throws -> [Channel] {
|
|
// Convert Subscription models to Channel models
|
|
dataManager.subscriptions().map { subscription in
|
|
Channel(
|
|
id: ChannelID(source: subscription.contentSource, channelID: subscription.channelID),
|
|
name: subscription.name,
|
|
description: subscription.channelDescription,
|
|
subscriberCount: subscription.subscriberCount,
|
|
thumbnailURL: subscription.avatarURL,
|
|
bannerURL: subscription.bannerURL,
|
|
isVerified: subscription.isVerified
|
|
)
|
|
}
|
|
}
|
|
|
|
func subscribe(to channel: Channel) async throws {
|
|
// Check if already subscribed
|
|
if dataManager.isSubscribed(to: channel.id.channelID) {
|
|
throw SubscriptionProviderError.alreadySubscribed
|
|
}
|
|
dataManager.subscribe(to: channel)
|
|
}
|
|
|
|
func unsubscribe(from channelID: String) async throws {
|
|
// Check if subscribed
|
|
guard dataManager.isSubscribed(to: channelID) else {
|
|
throw SubscriptionProviderError.notSubscribed
|
|
}
|
|
dataManager.unsubscribe(from: channelID)
|
|
}
|
|
|
|
func isSubscribed(to channelID: String) async -> Bool {
|
|
dataManager.isSubscribed(to: channelID)
|
|
}
|
|
|
|
func refreshCache() async throws {
|
|
// Local provider doesn't need cache refresh - data is already local
|
|
}
|
|
|
|
var cachedSubscriptionCount: Int? {
|
|
dataManager.subscriptionCount
|
|
}
|
|
}
|