Subscribed channels list in tab navigation

This commit is contained in:
Arkadiusz Fal
2022-12-11 12:38:57 +01:00
parent 7ba743afbc
commit 5e0f13cace
28 changed files with 566 additions and 222 deletions

View File

@@ -17,7 +17,7 @@ struct FeedCacheModel {
)
func storeFeed(account: Account, videos: [Video]) {
let date = dateFormatter.string(from: Date())
let date = iso8601DateFormatter.string(from: Date())
logger.info("caching feed \(account.feedCacheKey) -- \(date)")
let feedTimeObject: JSON = ["date": date]
let videosObject: JSON = ["videos": videos.map(\.json).map(\.object)]
@@ -40,7 +40,7 @@ struct FeedCacheModel {
func getFeedTime(account: Account) -> Date? {
if let json = try? storage.object(forKey: feedTimeCacheKey(account.feedCacheKey)),
let string = json.dictionaryValue["date"]?.string,
let date = dateFormatter.date(from: string)
let date = iso8601DateFormatter.date(from: string)
{
return date
}
@@ -52,11 +52,27 @@ struct FeedCacheModel {
try? storage.removeAll()
}
private var dateFormatter: ISO8601DateFormatter {
.init()
}
private func feedTimeCacheKey(_ feedCacheKey: String) -> String {
"\(feedCacheKey)-feedTime"
}
private var iso8601DateFormatter: ISO8601DateFormatter {
.init()
}
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
}
}

View File

@@ -113,14 +113,16 @@ struct Channel: Identifiable, Hashable {
var json: JSON {
[
"id": id,
"name": name
"name": name,
"thumbnailURL": thumbnailURL?.absoluteString ?? ""
]
}
static func from(_ json: JSON) -> Self {
.init(
id: json["id"].stringValue,
name: json["name"].stringValue
name: json["name"].stringValue,
thumbnailURL: json["thumbnailURL"].url
)
}
}

View File

@@ -221,7 +221,7 @@ final class NavigationModel: ObservableObject {
presentingPlaylistForm = true
}
func presentUnsubscribeAlert(_ channel: Channel, subscriptions: SubscriptionsModel) {
func presentUnsubscribeAlert(_ channel: Channel, subscriptions: SubsribedChannelsModel) {
channelToUnsubscribe = channel
alert = Alert(
title: Text(

View File

@@ -5,19 +5,20 @@ import Siesta
import SwiftUI
import SwiftyJSON
final class SubscriptionsModel: ObservableObject {
static var shared = SubscriptionsModel()
final class SubsribedChannelsModel: ObservableObject {
static var shared = SubsribedChannelsModel()
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: SubscriptionsModel.diskConfig,
memoryConfig: SubscriptionsModel.memoryConfig,
diskConfig: SubsribedChannelsModel.diskConfig,
memoryConfig: SubsribedChannelsModel.memoryConfig,
transformer: CacheModel.jsonTransformer
)
@Published var isLoading = false
@Published var channels = [Channel]()
var accounts: AccountsModel { .shared }
@@ -46,37 +47,49 @@ final class SubscriptionsModel: ObservableObject {
}
func load(force: Bool = false, onSuccess: @escaping () -> Void = {}) {
guard accounts.app.supportsSubscriptions, accounts.signedIn, let account = accounts.current else {
guard accounts.app.supportsSubscriptions, !isLoading, accounts.signedIn, let account = accounts.current else {
channels = []
return
}
loadCachedChannels(account)
let request = force ? resource?.load() : resource?.loadIfNeeded()
DispatchQueue.main.async { [weak self] in
guard let self else { return }
let request = force ? self.resource?.load() : self.resource?.loadIfNeeded()
request?
.onSuccess { resource in
if let channels: [Channel] = resource.typedContent() {
self.channels = channels
self.storeChannels(account: account, channels: channels)
onSuccess()
if request != nil {
self.isLoading = true
}
request?
.onCompletion { [weak self] _ in
self?.isLoading = false
}
}
.onFailure { _ in
self.channels = []
}
.onSuccess { resource in
if let channels: [Channel] = resource.typedContent() {
self.channels = channels
self.storeChannels(account: account, channels: channels)
onSuccess()
}
}
.onFailure { _ in
self.channels = []
}
}
}
func loadCachedChannels(_ account: Account) {
let cache = getChannels(account: account)
if !cache.isEmpty {
channels = cache
DispatchQueue.main.async {
self.channels = cache
}
}
}
func storeChannels(account: Account, channels: [Channel]) {
let date = dateFormatter.string(from: Date())
let date = iso8601DateFormatter.string(from: Date())
logger.info("caching channels \(channelsDateCacheKey(account)) -- \(date)")
let dateObject: JSON = ["date": date]
@@ -104,7 +117,7 @@ final class SubscriptionsModel: ObservableObject {
}
}
private var dateFormatter: ISO8601DateFormatter {
private var iso8601DateFormatter: ISO8601DateFormatter {
.init()
}
@@ -115,4 +128,49 @@ final class SubscriptionsModel: ObservableObject {
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
}
}