From 1603d0b3f2b15ec06b972982a3b947e2e3f68358 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Fri, 16 Feb 2018 22:35:04 -0800 Subject: [PATCH] Make progress on the star/unstar command and on updating its toolbar item. --- Evergreen/Base.lproj/MainWindow.storyboard | 2 +- .../MainWindow/MainWindowController.swift | 39 +++++++++++++++ .../Timeline/TimelineViewController.swift | 47 ++++++++++++++++++- 3 files changed, 86 insertions(+), 2 deletions(-) diff --git a/Evergreen/Base.lproj/MainWindow.storyboard b/Evergreen/Base.lproj/MainWindow.storyboard index ea7e91e46..d47facebf 100644 --- a/Evergreen/Base.lproj/MainWindow.storyboard +++ b/Evergreen/Base.lproj/MainWindow.storyboard @@ -134,7 +134,7 @@ - + diff --git a/Evergreen/MainWindow/MainWindowController.swift b/Evergreen/MainWindow/MainWindowController.swift index 46063dfaa..da44085c6 100644 --- a/Evergreen/MainWindow/MainWindowController.swift +++ b/Evergreen/MainWindow/MainWindowController.swift @@ -12,6 +12,11 @@ import Account private let kWindowFrameKey = "MainWindow" +extension NSImage.Name { + static let star = NSImage.Name(rawValue: "star") + static let unstar = NSImage.Name(rawValue: "unstar") +} + class MainWindowController : NSWindowController, NSUserInterfaceValidations { var isOpen: Bool { @@ -152,6 +157,10 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations { return canMarkRead() } + if item.action == #selector(toggleStarred(_:)) { + return validateToggleStarred(item) + } + if item.action == #selector(markOlderArticlesAsRead(_:)) { return canMarkOlderArticlesAsRead() } @@ -178,6 +187,31 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations { return true } + private func validateToggleStarred(_ item: NSValidatedUserInterfaceItem) -> Bool { + + let validationStatus = timelineViewController?.markStarredCommandStatus() ?? .canDoNothing + let showStar: Bool + let result: Bool + + switch validationStatus { + case .canMark: + showStar = true + result = true + case .canUnmark: + showStar = false + result = true + case .canDoNothing: + showStar = true + result = false + } + + if let button = (item as? NSToolbarItem)?.view as? NSButton { + button.image = NSImage(named: showStar ? .star : .unstar) + } + + return result + } + // MARK: - Actions @IBAction func scrollOrGoToNextUnread(_ sender: Any?) { @@ -267,6 +301,11 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations { timelineViewController?.markSelectedArticlesAsUnread(sender) } + @IBAction func toggleStarred(_ sender: Any?) { + + timelineViewController?.toggleStarredStatusForSelectedArticles() + } + @IBAction func markAllAsReadAndGoToNextUnread(_ sender: Any?) { markAllAsRead(sender) diff --git a/Evergreen/MainWindow/Timeline/TimelineViewController.swift b/Evergreen/MainWindow/Timeline/TimelineViewController.swift index 4de75c8db..ea3bd1e7c 100644 --- a/Evergreen/MainWindow/Timeline/TimelineViewController.swift +++ b/Evergreen/MainWindow/Timeline/TimelineViewController.swift @@ -12,6 +12,19 @@ import RSTextDrawing import Data import Account +enum MarkCommandValidationStatus { + + case canMark, canUnmark, canDoNothing + + static func statusFor(_ articles: ArticleArray, _ canMarkTest: ((ArticleArray) -> Bool)) -> MarkCommandValidationStatus { + + if articles.isEmpty { + return .canDoNothing + } + return canMarkTest(articles) ? .canMark : .canUnmark + } +} + class TimelineViewController: NSViewController, UndoableCommandRunner { @IBOutlet var tableView: TimelineTableView! @@ -191,7 +204,7 @@ class TimelineViewController: NSViewController, UndoableCommandRunner { markSelectedArticlesAsUnread(sender) } } - + @IBAction func markSelectedArticlesAsRead(_ sender: Any?) { guard let undoManager = undoManager, let markReadCommand = MarkStatusCommand(initialArticles: selectedArticles, markingRead: true, undoManager: undoManager) else { @@ -213,6 +226,38 @@ class TimelineViewController: NSViewController, UndoableCommandRunner { NSPasteboard.general.copyObjects(selectedArticles) } + func toggleStarredStatusForSelectedArticles() { + + // If any one of the selected articles is not starred, then star them. + // If all articles are starred, then unstar them. + + let commandStatus = markStarredCommandStatus() + let starring: Bool + switch commandStatus { + case .canMark: + starring = true + case .canUnmark: + starring = false + case .canDoNothing: + return + } + + guard let undoManager = undoManager, let markStarredCommand = MarkStatusCommand(initialArticles: selectedArticles, markingStarred: starring, undoManager: undoManager) else { + return + } + runCommand(markStarredCommand) + } + + func markStarredCommandStatus() -> MarkCommandValidationStatus { + + return MarkCommandValidationStatus.statusFor(selectedArticles) { $0.anyArticleIsUnstarred() } + } + + func markReadCommandStatus() -> MarkCommandValidationStatus { + + return MarkCommandValidationStatus.statusFor(selectedArticles) { $0.anyArticleIsUnread() } + } + func markOlderArticlesAsRead() { // Mark articles the same age or older than the selected article(s) as read.