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?
var accounts: AccountsModel { .shared }
var unwatchedFeedCount: UnwatchedFeedCountModel { .shared }
var resource: Resource? {
accounts.api.subscriptions
@ -32,6 +33,19 @@ final class SubscribedChannelsModel: ObservableObject, CacheModel {
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 = {}) {
accounts.api.subscribe(channelID) {
self.scheduleLoad(onSuccess: onSuccess)

View File

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

View File

@ -8,6 +8,7 @@ struct BrowsingSettings: View {
#endif
@Default(.accountPickerDisplaysAnonymousAccounts) private var accountPickerDisplaysAnonymousAccounts
@Default(.showUnwatchedFeedBadges) private var showUnwatchedFeedBadges
@Default(.keepChannelsWithUnwatchedFeedOnTop) private var keepChannelsWithUnwatchedFeedOnTop
#if os(iOS)
@Default(.lockPortraitWhenBrowsing) private var lockPortraitWhenBrowsing
@Default(.showDocuments) private var showDocuments
@ -180,9 +181,11 @@ struct BrowsingSettings: View {
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)
}
}

View File

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