NewArticleNotificationsView Changes

WebFeed is an ObservableObject, which allows the Notifications View to update favicons based on the feed.
This commit is contained in:
Stuart Breckenridge
2022-12-13 13:32:57 +08:00
parent 9a0a79619a
commit 766e092d21
2 changed files with 53 additions and 26 deletions

View File

@@ -11,7 +11,7 @@ import RSCore
import RSWeb
import Articles
public final class WebFeed: Feed, Renamable, Hashable {
public final class WebFeed: Feed, Renamable, Hashable, ObservableObject {
public var defaultReadFilterType: ReadFilterType {
return .none

View File

@@ -10,49 +10,76 @@ import SwiftUI
import Account
import RSCore
struct NewArticleNotificationsView: View {
struct NewArticleNotificationsView: View, Logging {
@State private var activeAccounts = AccountManager.shared.sortedActiveAccounts
var body: some View {
List {
ForEach(activeAccounts, id: \.accountID) { account in
Section(header: Text(account.nameForDisplay)) {
ForEach(sortedWebFeedsForAccount(account), id: \.webFeedID) { feed in
notificationToggle(feed)
}
List(activeAccounts, id: \.accountID) { account in
Section(header: Text(account.nameForDisplay)) {
ForEach(sortedWebFeedsForAccount(account), id: \.webFeedID) { feed in
WebFeedToggle(webfeed: feed)
.id(feed.webFeedID)
}
}
.navigationTitle(Text("New Article Notifications"))
.navigationBarTitleDisplayMode(.inline)
.onReceive(NotificationCenter.default.publisher(for: .WebFeedIconDidBecomeAvailable)) { _ in
activeAccounts = AccountManager.shared.sortedActiveAccounts
}
.onReceive(NotificationCenter.default.publisher(for: .FaviconDidBecomeAvailable)) { _ in
activeAccounts = AccountManager.shared.sortedActiveAccounts
}
}
.tint(Color(uiColor: AppAssets.primaryAccentColor))
.onReceive(NotificationCenter.default.publisher(for: .FaviconDidBecomeAvailable)) { notification in
guard let faviconURLString = notification.userInfo?["faviconURL"] as? String,
let faviconHost = URL(string: faviconURLString)?.host else {
return
}
activeAccounts.forEach { account in
for feed in Array(account.flattenedWebFeeds()) {
if let feedURLHost = URL(string: feed.url)?.host {
if faviconHost == feedURLHost {
feed.objectWillChange.send()
}
}
}
}
}
.onReceive(NotificationCenter.default.publisher(for: .WebFeedIconDidBecomeAvailable)) { notification in
guard let webFeed = notification.userInfo?[UserInfoKey.webFeed] as? WebFeed else { return }
webFeed.objectWillChange.send()
}
}
private func sortedWebFeedsForAccount(_ account: Account) -> [WebFeed] {
return Array(account.flattenedWebFeeds()).sorted(by: { $0.nameForDisplay.caseInsensitiveCompare($1.nameForDisplay) == .orderedAscending })
}
private func notificationToggle(_ webfeed: WebFeed) -> some View {
HStack {
Image(uiImage: IconImageCache.shared.imageFor(webfeed.feedID!)!.image)
.resizable()
.frame(width: 25, height: 25)
.cornerRadius(4)
Toggle(webfeed.nameForDisplay, isOn: Binding(
get: { webfeed.isNotifyAboutNewArticles ?? false },
set: { webfeed.isNotifyAboutNewArticles = $0 }))
}
}
}
fileprivate struct WebFeedToggle: View {
@ObservedObject var webfeed: WebFeed
var body: some View {
//let _ = Self._printChanges()
Toggle(isOn: Binding(
get: { webfeed.isNotifyAboutNewArticles ?? false },
set: { webfeed.isNotifyAboutNewArticles = $0 })) {
Label {
Text(webfeed.nameForDisplay)
} icon: {
Image(uiImage: IconImageCache.shared.imageFor(webfeed.feedID!)!.image)
.resizable()
.frame(width: 25, height: 25)
.cornerRadius(4)
}
}
}
}
struct NewArticleNotificationsView_Previews: PreviewProvider {
static var previews: some View {
NewArticleNotificationsView()