Get the unread count from the timeline for the currently selected node in the sidebar. This ensures that transients in the timeline are accounted for. (The database query for the unread count wouldn’t necessarily match.)

This commit is contained in:
Brent Simmons 2019-07-27 22:53:27 -07:00
parent 05faea53c4
commit 44ec6a026d
4 changed files with 57 additions and 3 deletions

View File

@ -387,6 +387,16 @@ extension MainWindowController: SidebarDelegate {
updateWindowTitle() updateWindowTitle()
NotificationCenter.default.post(name: .InspectableObjectsDidChange, object: nil) NotificationCenter.default.post(name: .InspectableObjectsDidChange, object: nil)
} }
func unreadCount(for representedObject: AnyObject) -> Int {
guard let timelineViewController = regularTimelineViewController else {
return 0
}
guard timelineViewController.representsThisObjectOnly(representedObject) else {
return 0
}
return timelineViewController.unreadCount
}
} }
// MARK: - TimelineContainerViewControllerDelegate // MARK: - TimelineContainerViewControllerDelegate
@ -545,6 +555,10 @@ private extension MainWindowController {
return timelineContainerViewController?.currentTimelineViewController return timelineContainerViewController?.currentTimelineViewController
} }
var regularTimelineViewController: TimelineViewController? {
return timelineContainerViewController?.regularTimelineViewController
}
var sidebarSplitViewItem: NSSplitViewItem? { var sidebarSplitViewItem: NSSplitViewItem? {
return splitViewController?.splitViewItems[0] return splitViewController?.splitViewItems[0]
} }

View File

@ -14,6 +14,7 @@ import RSCore
protocol SidebarDelegate: class { protocol SidebarDelegate: class {
func sidebarSelectionDidChange(_: SidebarViewController, selectedObjects: [AnyObject]?) func sidebarSelectionDidChange(_: SidebarViewController, selectedObjects: [AnyObject]?)
func unreadCount(for: AnyObject) -> Int
} }
@objc class SidebarViewController: NSViewController, NSOutlineViewDelegate, NSOutlineViewDataSource, NSMenuDelegate, UndoableCommandRunner { @objc class SidebarViewController: NSViewController, NSOutlineViewDelegate, NSOutlineViewDataSource, NSMenuDelegate, UndoableCommandRunner {
@ -496,6 +497,14 @@ private extension SidebarViewController {
} }
func unreadCountFor(_ node: Node) -> Int { func unreadCountFor(_ node: Node) -> Int {
// If this node is the one and only selection,
// then the unread count comes from the timeline.
// This ensures that any transients in the timeline
// are accounted for in the unread count.
if selectedNodes.count == 1 && node === selectedNodes.first! {
return delegate?.unreadCount(for: node.representedObject) ?? 0
}
if let unreadCountProvider = node.representedObject as? UnreadCountProvider { if let unreadCountProvider = node.representedObject as? UnreadCountProvider {
return unreadCountProvider.unreadCount return unreadCountProvider.unreadCount
} }

View File

@ -30,7 +30,7 @@ final class TimelineContainerViewController: NSViewController {
weak var delegate: TimelineContainerViewControllerDelegate? weak var delegate: TimelineContainerViewControllerDelegate?
private lazy var regularTimelineViewController = { lazy var regularTimelineViewController = {
return TimelineViewController(delegate: self) return TimelineViewController(delegate: self)
}() }()
private lazy var searchTimelineViewController: TimelineViewController = { private lazy var searchTimelineViewController: TimelineViewController = {

View File

@ -19,14 +19,14 @@ protocol TimelineDelegate: class {
func timelineSelectionDidChange(_: TimelineViewController, selectedArticles: [Article]?) func timelineSelectionDidChange(_: TimelineViewController, selectedArticles: [Article]?)
} }
final class TimelineViewController: NSViewController, UndoableCommandRunner { final class TimelineViewController: NSViewController, UndoableCommandRunner, UnreadCountProvider {
@IBOutlet var tableView: TimelineTableView! @IBOutlet var tableView: TimelineTableView!
var representedObjects: [AnyObject]? { var representedObjects: [AnyObject]? {
didSet { didSet {
if !representedObjectArraysAreEqual(oldValue, representedObjects) { if !representedObjectArraysAreEqual(oldValue, representedObjects) {
unreadCount = 0
if let representedObjects = representedObjects { if let representedObjects = representedObjects {
if representedObjects.count == 1 && representedObjects.first is Feed { if representedObjects.count == 1 && representedObjects.first is Feed {
showFeedNames = false showFeedNames = false
@ -76,11 +76,21 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner {
// Just reload visible cells in this case: dont call reloadData. // Just reload visible cells in this case: dont call reloadData.
articleRowMap = [String: Int]() articleRowMap = [String: Int]()
reloadVisibleCells() reloadVisibleCells()
updateUnreadCount()
return return
} }
updateShowAvatars() updateShowAvatars()
articleRowMap = [String: Int]() articleRowMap = [String: Int]()
tableView.reloadData() tableView.reloadData()
updateUnreadCount()
}
}
var unreadCount: Int = 0 {
didSet {
if unreadCount != oldValue {
postUnreadCountDidChangeNotification()
}
} }
} }
@ -221,6 +231,16 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner {
return selectedArticles.canMarkAllAsRead() return selectedArticles.canMarkAllAsRead()
} }
func representsThisObjectOnly(_ object: AnyObject) -> Bool {
guard let representedObjects = representedObjects else {
return false
}
if representedObjects.count != 1 {
return false
}
return representedObjects.first! === object
}
// MARK: - Actions // MARK: - Actions
@objc func openArticleInBrowser(_ sender: Any?) { @objc func openArticleInBrowser(_ sender: Any?) {
@ -448,6 +468,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner {
return return
} }
reloadVisibleCells(for: articles) reloadVisibleCells(for: articles)
updateUnreadCount()
} }
@objc func feedIconDidBecomeAvailable(_ note: Notification) { @objc func feedIconDidBecomeAvailable(_ note: Notification) {
@ -810,6 +831,16 @@ private extension TimelineViewController {
} }
} }
func updateUnreadCount() {
var count = 0
for article in articles {
if !article.status.read {
count += 1
}
}
unreadCount = count
}
func queueReloadAvailableCells() { func queueReloadAvailableCells() {
CoalescingQueue.standard.add(self, #selector(reloadAvailableCells)) CoalescingQueue.standard.add(self, #selector(reloadAvailableCells))