1
0
mirror of https://github.com/yattee/yattee.git synced 2024-12-14 06:10:32 +05:30
yattee/Model/SubsribedChannelsModel.swift

177 lines
5.2 KiB
Swift
Raw Normal View History

2022-12-11 01:38:03 +05:30
import Cache
2021-09-25 13:48:22 +05:30
import Foundation
2022-12-11 01:38:03 +05:30
import Logging
2021-09-25 13:48:22 +05:30
import Siesta
import SwiftUI
2022-12-11 01:38:03 +05:30
import SwiftyJSON
2021-09-25 13:48:22 +05:30
final class SubsribedChannelsModel: ObservableObject {
static var shared = SubsribedChannelsModel()
2022-12-11 01:38:03 +05:30
let logger = Logger(label: "stream.yattee.cache.channels")
static let diskConfig = DiskConfig(name: "channels")
static let memoryConfig = MemoryConfig()
let storage = try! Storage<String, JSON>(
diskConfig: SubsribedChannelsModel.diskConfig,
memoryConfig: SubsribedChannelsModel.memoryConfig,
2022-12-11 01:38:03 +05:30
transformer: CacheModel.jsonTransformer
)
@Published var isLoading = false
2021-09-25 13:48:22 +05:30
@Published var channels = [Channel]()
var accounts: AccountsModel { .shared }
2021-10-17 04:18:58 +05:30
2021-10-21 03:51:50 +05:30
var resource: Resource? {
accounts.api.subscriptions
2021-09-25 13:48:22 +05:30
}
var all: [Channel] {
channels.sorted { $0.name.lowercased() < $1.name.lowercased() }
}
func subscribe(_ channelID: String, onSuccess: @escaping () -> Void = {}) {
accounts.api.subscribe(channelID) {
self.scheduleLoad(onSuccess: onSuccess)
}
2021-09-25 13:48:22 +05:30
}
func unsubscribe(_ channelID: String, onSuccess: @escaping () -> Void = {}) {
accounts.api.unsubscribe(channelID) {
self.scheduleLoad(onSuccess: onSuccess)
}
2021-09-25 13:48:22 +05:30
}
func isSubscribing(_ channelID: String) -> Bool {
channels.contains { $0.id == channelID }
}
func load(force: Bool = false, onSuccess: @escaping () -> Void = {}) {
guard accounts.app.supportsSubscriptions, !isLoading, accounts.signedIn, let account = accounts.current else {
channels = []
return
}
2022-12-11 01:38:03 +05:30
loadCachedChannels(account)
DispatchQueue.main.async { [weak self] in
guard let self else { return }
let request = force ? self.resource?.load() : self.resource?.loadIfNeeded()
2021-09-25 13:48:22 +05:30
if request != nil {
self.isLoading = true
2021-09-25 13:48:22 +05:30
}
request?
.onCompletion { [weak self] _ in
self?.isLoading = false
}
.onSuccess { resource in
if let channels: [Channel] = resource.typedContent() {
self.channels = channels
self.storeChannels(account: account, channels: channels)
onSuccess()
}
}
.onFailure { _ in
self.channels = []
}
}
2021-09-25 13:48:22 +05:30
}
2022-12-11 01:38:03 +05:30
func loadCachedChannels(_ account: Account) {
let cache = getChannels(account: account)
if !cache.isEmpty {
DispatchQueue.main.async {
self.channels = cache
}
2022-12-11 01:38:03 +05:30
}
}
func storeChannels(account: Account, channels: [Channel]) {
let date = iso8601DateFormatter.string(from: Date())
2022-12-11 01:38:03 +05:30
logger.info("caching channels \(channelsDateCacheKey(account)) -- \(date)")
let dateObject: JSON = ["date": date]
let channelsObject: JSON = ["channels": channels.map(\.json).map(\.object)]
try? storage.setObject(dateObject, forKey: channelsDateCacheKey(account))
try? storage.setObject(channelsObject, forKey: channelsCacheKey(account))
}
func getChannels(account: Account) -> [Channel] {
logger.info("getting channels \(channelsDateCacheKey(account))")
if let json = try? storage.object(forKey: channelsCacheKey(account)),
let channels = json.dictionaryValue["channels"]
{
return channels.arrayValue.map { Channel.from($0) }
}
return []
}
private func scheduleLoad(onSuccess: @escaping () -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
2021-09-25 13:48:22 +05:30
self.load(force: true, onSuccess: onSuccess)
}
}
2022-12-11 01:38:03 +05:30
private var iso8601DateFormatter: ISO8601DateFormatter {
2022-12-11 01:38:03 +05:30
.init()
}
private func channelsCacheKey(_ account: Account) -> String {
"channels-\(account.id)"
}
private func channelsDateCacheKey(_ account: Account) -> String {
"channels-\(account.id)-date"
}
func getFeedTime(account: Account) -> Date? {
if let json = try? storage.object(forKey: channelsDateCacheKey(account)),
let string = json.dictionaryValue["date"]?.string,
let date = iso8601DateFormatter.date(from: string)
{
return date
}
return nil
}
var feedTime: Date? {
if let account = accounts.current {
return getFeedTime(account: account)
}
return nil
}
var formattedCacheTime: String {
if let feedTime {
let isSameDay = Calendar(identifier: .iso8601).isDate(feedTime, inSameDayAs: Date())
let formatter = isSameDay ? dateFormatterForTimeOnly : dateFormatter
return formatter.string(from: feedTime)
}
return ""
}
private var dateFormatter: DateFormatter {
let formatter = DateFormatter()
formatter.dateStyle = .short
formatter.timeStyle = .medium
return formatter
}
private var dateFormatterForTimeOnly: DateFormatter {
let formatter = DateFormatter()
formatter.dateStyle = .none
formatter.timeStyle = .medium
return formatter
}
2021-09-25 13:48:22 +05:30
}