diff --git a/Frameworks/Account/Account.swift b/Frameworks/Account/Account.swift index 0b1e47fe0..a8f99784c 100644 --- a/Frameworks/Account/Account.swift +++ b/Frameworks/Account/Account.swift @@ -1098,6 +1098,7 @@ private extension Account { self.fetchingAllUnreadCounts = false self.updateUnreadCount() self.isUnreadCountsInitialized = true + self.postUnreadCountDidInitializeNotification() return } @@ -1111,9 +1112,11 @@ private extension Account { feed.unreadCount = 0 } } + self.fetchingAllUnreadCounts = false self.updateUnreadCount() self.isUnreadCountsInitialized = true + self.postUnreadCountDidInitializeNotification() } } } diff --git a/Frameworks/Account/AccountManager.swift b/Frameworks/Account/AccountManager.swift index 76ddcfdba..a6483c939 100644 --- a/Frameworks/Account/AccountManager.swift +++ b/Frameworks/Account/AccountManager.swift @@ -102,6 +102,7 @@ public final class AccountManager: UnreadCountProvider { readAccountsFromDisk() + NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidInitialize(_:)), name: .UnreadCountDidInitialize, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(accountStateDidChange(_:)), name: .AccountStateDidChange, object: nil) @@ -269,6 +270,15 @@ public final class AccountManager: UnreadCountProvider { // MARK: - Notifications + @objc func unreadCountDidInitialize(_ notification: Notification) { + guard let _ = notification.object as? Account else { + return + } + if isUnreadCountsInitialized { + postUnreadCountDidInitializeNotification() + } + } + @objc dynamic func unreadCountDidChange(_ notification: Notification) { guard let _ = notification.object as? Account else { return diff --git a/Frameworks/Account/UnreadCountProvider.swift b/Frameworks/Account/UnreadCountProvider.swift index e776c8285..f6bc48d4a 100644 --- a/Frameworks/Account/UnreadCountProvider.swift +++ b/Frameworks/Account/UnreadCountProvider.swift @@ -9,7 +9,7 @@ import Foundation public extension Notification.Name { - + static let UnreadCountDidInitialize = Notification.Name("UnreadCountDidInitialize") static let UnreadCountDidChange = Notification.Name(rawValue: "UnreadCountDidChange") } @@ -24,6 +24,10 @@ public protocol UnreadCountProvider { public extension UnreadCountProvider { + func postUnreadCountDidInitializeNotification() { + NotificationCenter.default.post(name: .UnreadCountDidInitialize, object: self, userInfo: nil) + } + func postUnreadCountDidChangeNotification() { NotificationCenter.default.post(name: .UnreadCountDidChange, object: self, userInfo: nil) } diff --git a/Shared/UserInfoKey.swift b/Shared/UserInfoKey.swift index 81f939766..1823643c7 100644 --- a/Shared/UserInfoKey.swift +++ b/Shared/UserInfoKey.swift @@ -25,5 +25,6 @@ struct UserInfoKey { static let windowState = "windowState" static let containerExpandedWindowState = "containerExpandedWindowState" + static let readFeedsFilterState = "readFeedsFilterState" } diff --git a/iOS/MasterFeed/MasterFeedViewController.swift b/iOS/MasterFeed/MasterFeedViewController.swift index df391180f..bde039d2c 100644 --- a/iOS/MasterFeed/MasterFeedViewController.swift +++ b/iOS/MasterFeed/MasterFeedViewController.swift @@ -383,12 +383,12 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { } @IBAction func toggleFilter(_ sender: Any) { - if coordinator.isUnreadFeedsFiltered { + if coordinator.isReadFeedsFiltered { filterButton.image = AppAssets.filterInactiveImage coordinator.showAllFeeds() } else { filterButton.image = AppAssets.filterActiveImage - coordinator.hideUnreadFeeds() + coordinator.hideReadFeeds() } } @@ -506,14 +506,16 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { } } - func reloadFeeds() { + func reloadFeeds(initialLoad: Bool) { updateUI() // We have to reload all the visible cells because if we got here by doing a table cell move, // then the table itself is in a weird state. This is because we do unusual things like allowing // drops on a "folder" that should cause the dropped cell to disappear. - applyChanges(animated: true) { [weak self] in - self?.reloadAllVisibleCells() + applyChanges(animated: !initialLoad) { [weak self] in + if !initialLoad { + self?.reloadAllVisibleCells() + } } } @@ -633,6 +635,11 @@ private extension MasterFeedViewController { } func updateUI() { + if coordinator.isReadFeedsFiltered { + filterButton.image = AppAssets.filterActiveImage + } else { + filterButton.image = AppAssets.filterInactiveImage + } refreshProgressView?.updateRefreshLabel() addNewItemButton?.isEnabled = !AccountManager.shared.activeAccounts.isEmpty } diff --git a/iOS/SceneCoordinator.swift b/iOS/SceneCoordinator.swift index 36299017f..9ae4c4ae7 100644 --- a/iOS/SceneCoordinator.swift +++ b/iOS/SceneCoordinator.swift @@ -117,7 +117,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { return panelMode == .three } - var isUnreadFeedsFiltered: Bool { + var isReadFeedsFiltered: Bool { return treeControllerDelegate.isReadFiltered } @@ -279,8 +279,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { shadowTable.append([Node]()) } - rebuildShadowTable() - + NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidInitialize(_:)), name: .UnreadCountDidInitialize, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(statusesDidChange(_:)), name: .StatusesDidChange, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(containerChildrenDidChange(_:)), name: .ChildrenDidChange, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(batchUpdateDidPerform(_:)), name: .BatchUpdateDidPerform, object: nil) @@ -307,7 +306,6 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { masterFeedViewController = UIStoryboard.main.instantiateController(ofType: MasterFeedViewController.self) masterFeedViewController.coordinator = self masterNavigationController.pushViewController(masterFeedViewController, animated: false) - masterFeedViewController.reloadFeeds() let articleViewController = UIStoryboard.main.instantiateController(ofType: ArticleViewController.self) articleViewController.coordinator = self @@ -319,12 +317,11 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { return rootSplitViewController } - func restoreWindowState(_ activity: NSUserActivity) { - if let windowState = activity.userInfo?[UserInfoKey.windowState] as? [AnyHashable: Any] { + func restoreWindowState(_ activity: NSUserActivity?) { + if let activity = activity, let windowState = activity.userInfo?[UserInfoKey.windowState] as? [AnyHashable: Any] { restoreWindowState(windowState) - rebuildShadowTable() - masterFeedViewController.reloadFeeds() } + rebuildBackingStores(initialLoad: true) } func handle(_ activity: NSUserActivity) { @@ -387,6 +384,15 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { // MARK: Notifications + @objc func unreadCountDidInitialize(_ notification: Notification) { + guard notification.object is AccountManager else { + return + } + if isReadFeedsFiltered { + rebuildBackingStores() + } + } + @objc func statusesDidChange(_ note: Notification) { updateUnreadCount() } @@ -525,7 +531,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { rebuildBackingStores() } - func hideUnreadFeeds() { + func hideReadFeeds() { treeControllerDelegate.isReadFiltered = true rebuildBackingStores() } @@ -1150,12 +1156,12 @@ private extension SceneCoordinator { unreadCount = count } - func rebuildBackingStores(_ updateExpandedNodes: (() -> Void)? = nil) { + func rebuildBackingStores(initialLoad: Bool = false, updateExpandedNodes: (() -> Void)? = nil) { if !animatingChanges && !BatchUpdate.shared.isPerforming { treeController.rebuild() updateExpandedNodes?() rebuildShadowTable() - masterFeedViewController.reloadFeeds() + masterFeedViewController.reloadFeeds(initialLoad: initialLoad) } } @@ -1759,11 +1765,15 @@ private extension SceneCoordinator { func windowState() -> [AnyHashable: Any] { let containerIdentifierUserInfos = expandedTable.map( { $0.userInfo }) return [ + UserInfoKey.readFeedsFilterState: isReadFeedsFiltered, UserInfoKey.containerExpandedWindowState: containerIdentifierUserInfos ] } func restoreWindowState(_ windowState: [AnyHashable: Any]) { + if let readFeedsFilterState = windowState[UserInfoKey.readFeedsFilterState] as? Bool { + treeControllerDelegate.isReadFiltered = readFeedsFilterState + } if let containerIdentifierUserInfos = windowState[UserInfoKey.containerExpandedWindowState] as? [[AnyHashable: Any]] { let containerIdentifers = containerIdentifierUserInfos.compactMap( { ContainerIdentifier(userInfo: $0) }) expandedTable = Set(containerIdentifers) diff --git a/iOS/SceneDelegate.swift b/iOS/SceneDelegate.swift index 839517f07..d88e38d61 100644 --- a/iOS/SceneDelegate.swift +++ b/iOS/SceneDelegate.swift @@ -23,9 +23,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { window!.tintColor = AppAssets.primaryAccentColor window!.rootViewController = coordinator.start(for: window!.frame.size) - if let stateRestorationActivity = session.stateRestorationActivity { - coordinator.restoreWindowState(stateRestorationActivity) - } + coordinator.restoreWindowState(session.stateRestorationActivity) if let shortcutItem = connectionOptions.shortcutItem { window!.makeKeyAndVisible()