mirror of
https://github.com/yattee/yattee.git
synced 2024-12-22 13:33:42 +00:00
Feed count model
This commit is contained in:
parent
4acf9284f4
commit
26d3fba0f3
@ -10,9 +10,8 @@ final class FeedModel: ObservableObject, CacheModel {
|
||||
@Published var isLoading = false
|
||||
@Published var videos = [Video]()
|
||||
@Published private var page = 1
|
||||
@Published var unwatched = [Account: Int]()
|
||||
@Published var unwatchedByChannel = [Account: [Channel.ID: Int]]()
|
||||
|
||||
private var feedCount = UnwatchedFeedCountModel.shared
|
||||
private var cacheModel = FeedCacheModel.shared
|
||||
private var accounts = AccountsModel.shared
|
||||
|
||||
@ -125,12 +124,12 @@ final class FeedModel: ObservableObject, CacheModel {
|
||||
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self else { return }
|
||||
if unwatchedCount != self.unwatched[account] {
|
||||
self.unwatched[account] = unwatchedCount
|
||||
if unwatchedCount != self.feedCount.unwatched[account] {
|
||||
self.feedCount.unwatched[account] = unwatchedCount
|
||||
}
|
||||
|
||||
let byChannel = Dictionary(grouping: unwatched) { $0.channel.id }.mapValues(\.count)
|
||||
self.unwatchedByChannel[account] = byChannel
|
||||
self.feedCount.unwatchedByChannel[account] = byChannel
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -156,13 +155,13 @@ final class FeedModel: ObservableObject, CacheModel {
|
||||
|
||||
var canMarkAllFeedAsWatched: Bool {
|
||||
guard let account = accounts.current, accounts.signedIn else { return false }
|
||||
return (unwatched[account] ?? 0) > 0
|
||||
return (feedCount.unwatched[account] ?? 0) > 0
|
||||
}
|
||||
|
||||
func canMarkChannelAsWatched(_ channelID: Channel.ID) -> Bool {
|
||||
guard let account = accounts.current, accounts.signedIn else { return false }
|
||||
|
||||
return unwatchedByChannel[account]?.keys.contains(channelID) ?? false
|
||||
return feedCount.unwatchedByChannel[account]?.keys.contains(channelID) ?? false
|
||||
}
|
||||
|
||||
func markChannelAsWatched(_ channelID: Channel.ID) {
|
||||
@ -256,7 +255,7 @@ final class FeedModel: ObservableObject, CacheModel {
|
||||
|
||||
var canPlayUnwatchedFeed: Bool {
|
||||
guard let account = accounts.current, accounts.signedIn else { return false }
|
||||
return (unwatched[account] ?? 0) > 0
|
||||
return (feedCount.unwatched[account] ?? 0) > 0
|
||||
}
|
||||
|
||||
var feedTime: Date? {
|
||||
|
32
Model/UnwatchedFeedCountModel.swift
Normal file
32
Model/UnwatchedFeedCountModel.swift
Normal file
@ -0,0 +1,32 @@
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
final class UnwatchedFeedCountModel: ObservableObject {
|
||||
static let shared = UnwatchedFeedCountModel()
|
||||
|
||||
@Published var unwatched = [Account: Int]()
|
||||
@Published var unwatchedByChannel = [Account: [Channel.ID: Int]]()
|
||||
|
||||
private var accounts = AccountsModel.shared
|
||||
|
||||
var unwatchedText: Text? {
|
||||
if let account = accounts.current,
|
||||
!account.anonymous,
|
||||
let count = unwatched[account]
|
||||
{
|
||||
return Text(String(count))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func unwatchedByChannelText(_ channel: Channel) -> Text? {
|
||||
if let account = accounts.current,
|
||||
!account.anonymous,
|
||||
let count = unwatchedByChannel[account]?[channel.id]
|
||||
{
|
||||
return Text(String(count))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
@ -4,8 +4,8 @@ import SwiftUI
|
||||
struct AppSidebarSubscriptions: View {
|
||||
@ObservedObject private var navigation = NavigationModel.shared
|
||||
@ObservedObject private var feed = FeedModel.shared
|
||||
@ObservedObject private var feedCount = UnwatchedFeedCountModel.shared
|
||||
@ObservedObject private var subscriptions = SubscribedChannelsModel.shared
|
||||
|
||||
@ObservedObject private var accounts = AccountsModel.shared
|
||||
|
||||
var body: some View {
|
||||
@ -23,9 +23,9 @@ struct AppSidebarSubscriptions: View {
|
||||
} else {
|
||||
Label(channel.name, systemImage: RecentsModel.symbolSystemImage(channel.name))
|
||||
}
|
||||
|
||||
feedCount.unwatchedByChannelText(channel)
|
||||
}
|
||||
.backport
|
||||
.badge(channelBadge(channel))
|
||||
}
|
||||
.contextMenu {
|
||||
if subscriptions.isSubscribing(channel.id) {
|
||||
@ -41,14 +41,6 @@ struct AppSidebarSubscriptions: View {
|
||||
}
|
||||
}
|
||||
|
||||
func channelBadge(_ channel: Channel) -> Text? {
|
||||
if let count = feed.unwatchedByChannel[accounts.current]?[channel.id] {
|
||||
return Text(String(count))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ViewBuilder func toggleWatchedButton(_ channel: Channel) -> some View {
|
||||
if feed.canMarkChannelAsWatched(channel.id) {
|
||||
markChannelAsWatchedButton(channel)
|
||||
|
@ -7,6 +7,7 @@ struct AppTabNavigation: View {
|
||||
private var player = PlayerModel.shared
|
||||
@ObservedObject private var feed = FeedModel.shared
|
||||
@ObservedObject private var subscriptions = SubscribedChannelsModel.shared
|
||||
@ObservedObject private var feedCount = UnwatchedFeedCountModel.shared
|
||||
|
||||
@Default(.showHome) private var showHome
|
||||
@Default(.showDocuments) private var showDocuments
|
||||
@ -94,18 +95,7 @@ struct AppTabNavigation: View {
|
||||
}
|
||||
.tag(TabSelection.subscriptions)
|
||||
.backport
|
||||
.badge(subscriptionsBadge)
|
||||
}
|
||||
|
||||
var subscriptionsBadge: Text? {
|
||||
guard let account = accounts.current,
|
||||
let unwatched = feed.unwatched[account],
|
||||
unwatched > 0
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return Text("\(String(unwatched))")
|
||||
.badge(feedCount.unwatchedText)
|
||||
}
|
||||
|
||||
private var subscriptionsVisible: Bool {
|
||||
|
@ -5,6 +5,7 @@ struct Sidebar: View {
|
||||
@ObservedObject private var accounts = AccountsModel.shared
|
||||
@ObservedObject private var navigation = NavigationModel.shared
|
||||
@ObservedObject private var feed = FeedModel.shared
|
||||
@ObservedObject private var feedCount = UnwatchedFeedCountModel.shared
|
||||
|
||||
@Default(.showHome) private var showHome
|
||||
@Default(.visibleSections) private var visibleSections
|
||||
@ -78,7 +79,7 @@ struct Sidebar: View {
|
||||
.accessibility(label: Text("Subscriptions"))
|
||||
}
|
||||
.backport
|
||||
.badge(subscriptionsBadge)
|
||||
.badge(feedCount.unwatchedText)
|
||||
.contextMenu {
|
||||
playUnwatchedButton
|
||||
toggleWatchedButton
|
||||
@ -146,17 +147,6 @@ struct Sidebar: View {
|
||||
}
|
||||
}
|
||||
|
||||
private var subscriptionsBadge: Text? {
|
||||
guard let account = accounts.current,
|
||||
let unwatched = feed.unwatched[account],
|
||||
unwatched > 0
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return Text("\(String(unwatched))")
|
||||
}
|
||||
|
||||
private func scrollScrollViewToItem(scrollView: ScrollViewProxy, for selection: TabSelection) {
|
||||
if case .recentlyOpened = selection {
|
||||
scrollView.scrollTo("recentlyOpened")
|
||||
|
@ -6,6 +6,7 @@ struct ChannelsView: View {
|
||||
@ObservedObject private var feed = FeedModel.shared
|
||||
@ObservedObject private var subscriptions = SubscribedChannelsModel.shared
|
||||
@ObservedObject private var accounts = AccountsModel.shared
|
||||
@ObservedObject private var feedCount = UnwatchedFeedCountModel.shared
|
||||
|
||||
@Default(.showCacheStatus) private var showCacheStatus
|
||||
|
||||
@ -25,7 +26,7 @@ struct ChannelsView: View {
|
||||
}
|
||||
}
|
||||
.backport
|
||||
.badge(channelBadge(channel))
|
||||
.badge(feedCount.unwatchedByChannelText(channel))
|
||||
}
|
||||
.contextMenu {
|
||||
if subscriptions.isSubscribing(channel.id) {
|
||||
@ -84,14 +85,6 @@ struct ChannelsView: View {
|
||||
#endif
|
||||
}
|
||||
|
||||
func channelBadge(_ channel: Channel) -> Text? {
|
||||
if let count = feed.unwatchedByChannel[accounts.current]?[channel.id] {
|
||||
return Text(String(count))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var header: some View {
|
||||
HStack {
|
||||
#if os(tvOS)
|
||||
|
@ -185,6 +185,9 @@
|
||||
37192D5728B179D60012EEDD /* ChaptersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37192D5628B179D60012EEDD /* ChaptersView.swift */; };
|
||||
37192D5828B179D60012EEDD /* ChaptersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37192D5628B179D60012EEDD /* ChaptersView.swift */; };
|
||||
37192D5928B179D60012EEDD /* ChaptersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37192D5628B179D60012EEDD /* ChaptersView.swift */; };
|
||||
371AC09F294D13AA0085989E /* UnwatchedFeedCountModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371AC09E294D13AA0085989E /* UnwatchedFeedCountModel.swift */; };
|
||||
371AC0A0294D13AA0085989E /* UnwatchedFeedCountModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371AC09E294D13AA0085989E /* UnwatchedFeedCountModel.swift */; };
|
||||
371AC0A1294D13AA0085989E /* UnwatchedFeedCountModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371AC09E294D13AA0085989E /* UnwatchedFeedCountModel.swift */; };
|
||||
371B7E5C27596B8400D21217 /* Comment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371B7E5B27596B8400D21217 /* Comment.swift */; };
|
||||
371B7E5D27596B8400D21217 /* Comment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371B7E5B27596B8400D21217 /* Comment.swift */; };
|
||||
371B7E5E27596B8400D21217 /* Comment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371B7E5B27596B8400D21217 /* Comment.swift */; };
|
||||
@ -1155,6 +1158,7 @@
|
||||
37169AA52729E2CC0011DE61 /* AccountsBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountsBridge.swift; sourceTree = "<group>"; };
|
||||
3717407C2949D40800FDDBC7 /* ChannelLinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelLinkView.swift; sourceTree = "<group>"; };
|
||||
37192D5628B179D60012EEDD /* ChaptersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChaptersView.swift; sourceTree = "<group>"; };
|
||||
371AC09E294D13AA0085989E /* UnwatchedFeedCountModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnwatchedFeedCountModel.swift; sourceTree = "<group>"; };
|
||||
371B7E5B27596B8400D21217 /* Comment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Comment.swift; sourceTree = "<group>"; };
|
||||
371B7E602759706A00D21217 /* CommentsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentsView.swift; sourceTree = "<group>"; };
|
||||
371B7E652759786B00D21217 /* Comment+Fixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Comment+Fixtures.swift"; sourceTree = "<group>"; };
|
||||
@ -2328,10 +2332,6 @@
|
||||
3743B86627216A1E00261544 /* Accounts */,
|
||||
3743B864272169E200261544 /* Applications */,
|
||||
377F9F79294403DC0043F856 /* Cache */,
|
||||
3743B86527216A0600261544 /* Player */,
|
||||
3751BA8127E69131007B1A60 /* ReturnYouTubeDislike */,
|
||||
37FB283F2721B20800A57617 /* Search */,
|
||||
374C0539272436DA009BDDBE /* SponsorBlock */,
|
||||
3776ADD5287381240078EBC4 /* Captions.swift */,
|
||||
37AAF28F26740715007FC770 /* Channel.swift */,
|
||||
37C3A24427235DA70087A57A /* ChannelPlaylist.swift */,
|
||||
@ -2354,21 +2354,26 @@
|
||||
3756C2A92861151C00E4B059 /* NetworkStateModel.swift */,
|
||||
377FF88A291A60310028EB0B /* OpenVideosModel.swift */,
|
||||
37130A5E277657300033018A /* PersistenceController.swift */,
|
||||
3743B86527216A0600261544 /* Player */,
|
||||
376578882685471400D4EA09 /* Playlist.swift */,
|
||||
37BA794226DBA973002A0235 /* PlaylistsModel.swift */,
|
||||
375EC95C289EEEE000751258 /* QualityProfile.swift */,
|
||||
375EC969289F232600751258 /* QualityProfilesModel.swift */,
|
||||
37C194C626F6A9C8005D3B96 /* RecentsModel.swift */,
|
||||
3751BA8127E69131007B1A60 /* ReturnYouTubeDislike */,
|
||||
37FB283F2721B20800A57617 /* Search */,
|
||||
374AB3D628BCAF0000DF56FB /* SeekModel.swift */,
|
||||
374AB3DA28BCAF7E00DF56FB /* SeekType.swift */,
|
||||
37EAD86E267B9ED100D9E01B /* Segment.swift */,
|
||||
37F0F4E9286F397E00C06C2E /* SettingsModel.swift */,
|
||||
37CEE4BC2677B670005A1EFE /* SingleAssetStream.swift */,
|
||||
374C0539272436DA009BDDBE /* SponsorBlock */,
|
||||
3797758A2689345500DD52A8 /* Store.swift */,
|
||||
37CEE4C02677B697005A1EFE /* Stream.swift */,
|
||||
373CFADA269663F1003CB2C6 /* Thumbnail.swift */,
|
||||
37C0698127260B2100F7F6CB /* ThumbnailsModel.swift */,
|
||||
3705B181267B4E4900704544 /* TrendingCategory.swift */,
|
||||
371AC09E294D13AA0085989E /* UnwatchedFeedCountModel.swift */,
|
||||
37F5E8B5291BE9D0006C15F5 /* URLBookmarkModel.swift */,
|
||||
37D4B19626717E1500C925CA /* Video.swift */,
|
||||
3784CDDE27772EE40055BBF2 /* Watch.swift */,
|
||||
@ -3207,6 +3212,7 @@
|
||||
3751BA8327E6914F007B1A60 /* ReturnYouTubeDislikeAPI.swift in Sources */,
|
||||
373031F528383A89000CFD59 /* PiPDelegate.swift in Sources */,
|
||||
37F5E8BA291BEF69006C15F5 /* BaseCacheModel.swift in Sources */,
|
||||
371AC09F294D13AA0085989E /* UnwatchedFeedCountModel.swift in Sources */,
|
||||
37DD9DC62785D63A00539416 /* UIResponder+Extensions.swift in Sources */,
|
||||
370015A928BBAE7F000149FD /* ProgressBar.swift in Sources */,
|
||||
37C3A24927235FAA0087A57A /* ChannelPlaylistCell.swift in Sources */,
|
||||
@ -3327,6 +3333,7 @@
|
||||
374C053C2724614F009BDDBE /* PlayerTVMenu.swift in Sources */,
|
||||
377FC7DD267A081A00A6BBAF /* PopularView.swift in Sources */,
|
||||
374924DB2921050B0017D862 /* LocationsSettings.swift in Sources */,
|
||||
371AC0A0294D13AA0085989E /* UnwatchedFeedCountModel.swift in Sources */,
|
||||
37192D5828B179D60012EEDD /* ChaptersView.swift in Sources */,
|
||||
3784CDE327772EE40055BBF2 /* Watch.swift in Sources */,
|
||||
37E80F3D287B107F00561799 /* VideoDetailsOverlay.swift in Sources */,
|
||||
@ -3786,6 +3793,7 @@
|
||||
3782B9542755667600990149 /* String+Format.swift in Sources */,
|
||||
37D836BE294927E700005E5E /* ChannelsCacheModel.swift in Sources */,
|
||||
37152EEC26EFEB95004FB96D /* LazyView.swift in Sources */,
|
||||
371AC0A1294D13AA0085989E /* UnwatchedFeedCountModel.swift in Sources */,
|
||||
37EF9A78275BEB8E0043B585 /* CommentView.swift in Sources */,
|
||||
37484C2726FC83E000287258 /* InstanceForm.swift in Sources */,
|
||||
37E6D7A22944CD3800550C3D /* CacheStatusHeader.swift in Sources */,
|
||||
|
Loading…
Reference in New Issue
Block a user