diff --git a/Mac/AppDelegate.swift b/Mac/AppDelegate.swift index c40b12386..a4fa2b286 100644 --- a/Mac/AppDelegate.swift +++ b/Mac/AppDelegate.swift @@ -170,6 +170,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, authorAvatarDownloader = AuthorAvatarDownloader(imageDownloader: imageDownloader) webFeedIconDownloader = WebFeedIconDownloader(imageDownloader: imageDownloader, folder: cacheFolder) + appName = (Bundle.main.infoDictionary!["CFBundleExecutable"]! as! String) } func applicationDidFinishLaunching(_ note: Notification) { @@ -190,8 +191,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, } #endif - appName = (Bundle.main.infoDictionary!["CFBundleExecutable"]! as! String) - AppDefaults.registerDefaults() let isFirstRun = AppDefaults.isFirstRun if isFirstRun { diff --git a/Mac/MainWindow/Sidebar/SidebarViewController.swift b/Mac/MainWindow/Sidebar/SidebarViewController.swift index f41e224c8..c60f1b4d1 100644 --- a/Mac/MainWindow/Sidebar/SidebarViewController.swift +++ b/Mac/MainWindow/Sidebar/SidebarViewController.swift @@ -63,6 +63,7 @@ protocol SidebarDelegate: class { outlineView.setDraggingSourceOperationMask([.move, .copy], forLocal: true) outlineView.registerForDraggedTypes([WebFeedPasteboardWriter.webFeedUTIInternalType, WebFeedPasteboardWriter.webFeedUTIType, .URL, .string]) + 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(containerChildrenDidChange(_:)), name: .ChildrenDidChange, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(accountsDidChange(_:)), name: .UserDidAddAccount, object: nil) @@ -92,21 +93,52 @@ protocol SidebarDelegate: class { func saveState(to coder: NSCoder) { coder.encode(isReadFiltered, forKey: UserInfoKey.readFeedsFilterState) coder.encode(expandedTable.map( { $0.userInfo }), forKey: UserInfoKey.containerExpandedWindowState) + coder.encode(selectedFeeds.compactMap({ $0.feedID?.userInfo }), forKey: UserInfoKey.selectedFeedsState) } func restoreState(from coder: NSCoder) { - isReadFiltered = coder.decodeBool(forKey: UserInfoKey.readFeedsFilterState) if let containerExpandedWindowState = try? coder.decodeTopLevelObject(forKey: UserInfoKey.containerExpandedWindowState) as? [[AnyHashable: AnyHashable]] { let containerIdentifers = containerExpandedWindowState.compactMap( { ContainerIdentifier(userInfo: $0) }) expandedTable = Set(containerIdentifers) } - rebuildTreeAndRestoreSelection() + guard let selectedFeedsState = try? coder.decodeTopLevelObject(forKey: UserInfoKey.selectedFeedsState) as? [[AnyHashable: AnyHashable]] else { + return + } + + let selectedFeedIdentifers = Set(selectedFeedsState.compactMap( { FeedIdentifier(userInfo: $0) })) + selectedFeedIdentifers.forEach { treeControllerDelegate.addFilterException($0) } + + rebuildTreeAndReloadDataIfNeeded() + + var selectIndexes = IndexSet() + + func selectFeedsVisitor(node: Node) { + if let feedID = (node.representedObject as? FeedIdentifiable)?.feedID { + if selectedFeedIdentifers.contains(feedID) { + selectIndexes.insert(outlineView.row(forItem: node) ) + } + } + } + + treeController.visitNodes(selectFeedsVisitor(node:)) + outlineView.selectRowIndexes(selectIndexes, byExtendingSelection: false) + + isReadFiltered = coder.decodeBool(forKey: UserInfoKey.readFeedsFilterState) } // MARK: - Notifications + @objc func unreadCountDidInitialize(_ notification: Notification) { + guard notification.object is AccountManager else { + return + } + if isReadFiltered { + rebuildTreeAndRestoreSelection() + } + } + @objc func unreadCountDidChange(_ note: Notification) { guard let representedObject = note.object else { return @@ -118,6 +150,10 @@ protocol SidebarDelegate: class { configureUnreadCountForCellsForRepresentedObjects([representedObject as AnyObject]) } + guard AccountManager.shared.isUnreadCountsInitialized else { + return + } + if let feed = representedObject as? Feed, isReadFiltered, feed.unreadCount > 0 { addTreeControllerToFilterExceptions() queueRebuildTreeAndRestoreSelection() @@ -563,6 +599,7 @@ private extension SidebarViewController { func selectionDidChange(_ selectedObjects: [AnyObject]?) { delegate?.sidebarSelectionDidChange(self, selectedObjects: selectedObjects) + delegate?.sidebarInvalidatedRestorationState(self) } func updateUnreadCounts(for objects: [AnyObject]) { diff --git a/Shared/UserInfoKey.swift b/Shared/UserInfoKey.swift index 482db7b14..4caccd6d6 100644 --- a/Shared/UserInfoKey.swift +++ b/Shared/UserInfoKey.swift @@ -19,4 +19,6 @@ struct UserInfoKey { static let containerExpandedWindowState = "containerExpandedWindowState" static let readFeedsFilterState = "readFeedsFilterState" static let readArticlesFilterState = "readArticlesFilterState" + static let selectedFeedsState = "selectedFeedsState" + }