Add setting "Keep channels with unwatched videos on top of subscriptions list"

This commit is contained in:
Arkadiusz Fal 2023-05-26 22:38:32 +02:00
parent 6856506834
commit e5f137a2d2
4 changed files with 44 additions and 5 deletions

View File

@ -23,6 +23,7 @@ final class SubscribedChannelsModel: ObservableObject, CacheModel {
@Published var error: RequestError? @Published var error: RequestError?
var accounts: AccountsModel { .shared } var accounts: AccountsModel { .shared }
var unwatchedFeedCount: UnwatchedFeedCountModel { .shared }
var resource: Resource? { var resource: Resource? {
accounts.api.subscriptions accounts.api.subscriptions
@ -32,6 +33,19 @@ final class SubscribedChannelsModel: ObservableObject, CacheModel {
channels.sorted { $0.name.lowercased() < $1.name.lowercased() } channels.sorted { $0.name.lowercased() < $1.name.lowercased() }
} }
var allByUnwatchedCount: [Channel] {
if let account = accounts.current {
return all.sorted { c1, c2 in
let c1HasUnwatched = (unwatchedFeedCount.unwatchedByChannel[account]?[c1.id] ?? -1) > 0
let c2HasUnwatched = (unwatchedFeedCount.unwatchedByChannel[account]?[c2.id] ?? -1) > 0
let nameIncreasing = c1.name.lowercased() < c2.name.lowercased()
return c1HasUnwatched ? (c2HasUnwatched ? nameIncreasing : true) : (c2HasUnwatched ? false : nameIncreasing)
}
}
return all
}
func subscribe(_ channelID: String, onSuccess: @escaping () -> Void = {}) { func subscribe(_ channelID: String, onSuccess: @escaping () -> Void = {}) {
accounts.api.subscribe(channelID) { accounts.api.subscribe(channelID) {
self.scheduleLoad(onSuccess: onSuccess) self.scheduleLoad(onSuccess: onSuccess)

View File

@ -51,6 +51,7 @@ extension Defaults.Keys {
static let lockPortraitWhenBrowsing = Key<Bool>("lockPortraitWhenBrowsing", default: UIDevice.current.userInterfaceIdiom == .phone) static let lockPortraitWhenBrowsing = Key<Bool>("lockPortraitWhenBrowsing", default: UIDevice.current.userInterfaceIdiom == .phone)
#endif #endif
static let showUnwatchedFeedBadges = Key<Bool>("showUnwatchedFeedBadges", default: false) static let showUnwatchedFeedBadges = Key<Bool>("showUnwatchedFeedBadges", default: false)
static let keepChannelsWithUnwatchedFeedOnTop = Key<Bool>("keepChannelsWithUnwatchedFeedOnTop", default: true)
static let showToggleWatchedStatusButton = Key<Bool>("showToggleWatchedStatusButton", default: false) static let showToggleWatchedStatusButton = Key<Bool>("showToggleWatchedStatusButton", default: false)
static let expandChannelDescription = Key<Bool>("expandChannelDescription", default: false) static let expandChannelDescription = Key<Bool>("expandChannelDescription", default: false)
static let channelOnThumbnail = Key<Bool>("channelOnThumbnail", default: false) static let channelOnThumbnail = Key<Bool>("channelOnThumbnail", default: false)

View File

@ -8,6 +8,7 @@ struct BrowsingSettings: View {
#endif #endif
@Default(.accountPickerDisplaysAnonymousAccounts) private var accountPickerDisplaysAnonymousAccounts @Default(.accountPickerDisplaysAnonymousAccounts) private var accountPickerDisplaysAnonymousAccounts
@Default(.showUnwatchedFeedBadges) private var showUnwatchedFeedBadges @Default(.showUnwatchedFeedBadges) private var showUnwatchedFeedBadges
@Default(.keepChannelsWithUnwatchedFeedOnTop) private var keepChannelsWithUnwatchedFeedOnTop
#if os(iOS) #if os(iOS)
@Default(.lockPortraitWhenBrowsing) private var lockPortraitWhenBrowsing @Default(.lockPortraitWhenBrowsing) private var lockPortraitWhenBrowsing
@Default(.showDocuments) private var showDocuments @Default(.showDocuments) private var showDocuments
@ -180,10 +181,12 @@ struct BrowsingSettings: View {
FeedModel.shared.calculateUnwatchedFeed() FeedModel.shared.calculateUnwatchedFeed()
} }
} }
}
Toggle("Open channels with description expanded", isOn: $expandChannelDescription) Toggle("Open channels with description expanded", isOn: $expandChannelDescription)
} }
Toggle("Keep channels with unwatched videos on top of subscriptions list", isOn: $keepChannelsWithUnwatchedFeedOnTop)
}
} }
private var thumbnailsSettings: some View { private var thumbnailsSettings: some View {

View File

@ -11,20 +11,28 @@ struct ChannelsView: View {
@Default(.showCacheStatus) private var showCacheStatus @Default(.showCacheStatus) private var showCacheStatus
@Default(.showUnwatchedFeedBadges) private var showUnwatchedFeedBadges @Default(.showUnwatchedFeedBadges) private var showUnwatchedFeedBadges
@Default(.keepChannelsWithUnwatchedFeedOnTop) private var keepChannelsWithUnwatchedFeedOnTop
@State private var channelLinkActive = false
@State private var channelForLink: Channel?
var body: some View { var body: some View {
List { List {
Section(header: header) { Section(header: header) {
ForEach(subscriptions.all) { channel in ForEach(channels) { channel in
let label = HStack { let label = HStack {
if let url = channel.thumbnailURLOrCached { if let url = channel.thumbnailURLOrCached {
ThumbnailView(url: url) ThumbnailView(url: url)
.frame(width: 35, height: 35) .frame(width: 35, height: 35)
.clipShape(RoundedRectangle(cornerRadius: 35)) .clipShape(RoundedRectangle(cornerRadius: 35))
Text(channel.name)
} else { } else {
Label(channel.name, systemImage: RecentsModel.symbolSystemImage(channel.name)) Image(systemName: RecentsModel.symbolSystemImage(channel.name))
.imageScale(.large)
.foregroundColor(.accentColor)
.frame(width: 35, height: 35)
} }
Text(channel.name)
.lineLimit(1)
} }
.backport .backport
.badge(showUnwatchedFeedBadges ? feedCount.unwatchedByChannelText(channel) : nil) .badge(showUnwatchedFeedBadges ? feedCount.unwatchedByChannelText(channel) : nil)
@ -37,9 +45,15 @@ struct ChannelsView: View {
label label
} }
#else #else
NavigationLink(destination: ChannelVideosView(channel: channel)) { Button {
channelForLink = channel
channelLinkActive = channelForLink != nil
} label: {
label label
.contentShape(Rectangle())
.foregroundColor(.primary)
} }
.buttonStyle(.plain)
#endif #endif
} }
.contextMenu { .contextMenu {
@ -63,6 +77,9 @@ struct ChannelsView: View {
.listRowSeparator(false) .listRowSeparator(false)
} }
} }
.background(
NavigationLink(destination: ChannelVideosView(channel: channelForLink), isActive: $channelLinkActive, label: EmptyView.init)
)
.onAppear { .onAppear {
subscriptions.load() subscriptions.load()
} }
@ -99,6 +116,10 @@ struct ChannelsView: View {
#endif #endif
} }
var channels: [Channel] {
keepChannelsWithUnwatchedFeedOnTop ? subscriptions.allByUnwatchedCount : subscriptions.all
}
var header: some View { var header: some View {
HStack { HStack {
#if os(tvOS) #if os(tvOS)