From 461c681a9dd00c99dc86456f8190ce75c2e662b0 Mon Sep 17 00:00:00 2001 From: Phil Viso Date: Mon, 7 Oct 2019 19:33:30 -0500 Subject: [PATCH 1/4] Added a flag to suppress mark all as read warning alert --- NetNewsWire.xcodeproj/project.pbxproj | 4 ++ .../MarkArticlesReadAlertController.swift | 44 +++++++++++++++++++ iOS/MasterFeed/MasterFeedViewController.swift | 27 ++++-------- .../MasterTimelineViewController.swift | 25 ++++------- iOS/SceneCoordinator.swift | 2 + 5 files changed, 67 insertions(+), 35 deletions(-) create mode 100644 iOS/MasterFeed/MarkArticlesReadAlertController.swift diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj index 11257243d..7792cc046 100644 --- a/NetNewsWire.xcodeproj/project.pbxproj +++ b/NetNewsWire.xcodeproj/project.pbxproj @@ -404,6 +404,7 @@ FF3ABF13232599810074C542 /* ArticleSorterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF3ABF09232599450074C542 /* ArticleSorterTests.swift */; }; FF3ABF1523259DDB0074C542 /* ArticleSorter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF3ABF1423259DDB0074C542 /* ArticleSorter.swift */; }; FF3ABF162325AF5D0074C542 /* ArticleSorter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF3ABF1423259DDB0074C542 /* ArticleSorter.swift */; }; + FFD43E412340F488009E5CA3 /* MarkArticlesReadAlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFD43E372340F320009E5CA3 /* MarkArticlesReadAlertController.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -1034,6 +1035,7 @@ DF999FF622B5AEFA0064B687 /* SafariView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariView.swift; sourceTree = ""; }; FF3ABF09232599450074C542 /* ArticleSorterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleSorterTests.swift; sourceTree = ""; }; FF3ABF1423259DDB0074C542 /* ArticleSorter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleSorter.swift; sourceTree = ""; }; + FFD43E372340F320009E5CA3 /* MarkArticlesReadAlertController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkArticlesReadAlertController.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -1278,6 +1280,7 @@ 51C4525D226508F600C03939 /* MasterFeed */ = { isa = PBXGroup; children = ( + FFD43E372340F320009E5CA3 /* MarkArticlesReadAlertController.swift */, 51C45264226508F600C03939 /* MasterFeedViewController.swift */, 51CC9B3D231720B2000E842F /* MasterFeedDataSource.swift */, 51C45260226508F600C03939 /* Cell */, @@ -2810,6 +2813,7 @@ 51C4529F22650A1900C03939 /* AuthorAvatarDownloader.swift in Sources */, 519E743D22C663F900A78E47 /* SceneDelegate.swift in Sources */, 51CC9B3E231720B2000E842F /* MasterFeedDataSource.swift in Sources */, + FFD43E412340F488009E5CA3 /* MarkArticlesReadAlertController.swift in Sources */, 51C452A322650A1E00C03939 /* HTMLMetadataDownloader.swift in Sources */, 51C4528D2265095F00C03939 /* AddFolderViewController.swift in Sources */, 51C452782265091600C03939 /* MasterTimelineCellData.swift in Sources */, diff --git a/iOS/MasterFeed/MarkArticlesReadAlertController.swift b/iOS/MasterFeed/MarkArticlesReadAlertController.swift new file mode 100644 index 000000000..6e4f4a8a3 --- /dev/null +++ b/iOS/MasterFeed/MarkArticlesReadAlertController.swift @@ -0,0 +1,44 @@ +// +// MarkArticlesReadAlertControllerr.swift +// NetNewsWire +// +// Created by Phil Viso on 9/29/19. +// Copyright © 2019 Ranchero Software. All rights reserved. +// + +import Foundation +import UIKit + +struct MarkArticlesReadAlertController { + + static func allArticlesAlert(handler: @escaping (UIAlertAction) -> Void) -> UIAlertController { + let message = NSLocalizedString("Mark all articles in all accounts as read?", + comment: "Mark all articles") + return markAllReadAlert(message: message, handler: handler) + } + + static func timelineArticlesAlert(handler: @escaping (UIAlertAction) -> Void) -> UIAlertController { + let message = NSLocalizedString("Mark all articles in this timeline as read?", + comment: "Mark all articles") + return markAllReadAlert(message: message, handler: handler) + } + + // MARK: - + + private static func markAllReadAlert(message: String, + handler: @escaping (UIAlertAction) -> Void) -> UIAlertController { + let title = NSLocalizedString("Mark All Read", comment: "Mark All Read") + let cancelTitle = NSLocalizedString("Cancel", comment: "Cancel") + let markTitle = NSLocalizedString("Mark All Read", comment: "Mark All Read") + + let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert) + let cancelAction = UIAlertAction(title: cancelTitle, style: .cancel) + let markAction = UIAlertAction(title: markTitle, style: .default, handler: handler) + + alertController.addAction(cancelAction) + alertController.addAction(markAction) + + return alertController + } + +} diff --git a/iOS/MasterFeed/MasterFeedViewController.swift b/iOS/MasterFeed/MasterFeedViewController.swift index e6754ae1d..ef4f48736 100644 --- a/iOS/MasterFeed/MasterFeedViewController.swift +++ b/iOS/MasterFeed/MasterFeedViewController.swift @@ -344,24 +344,15 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { } @IBAction func markAllAsRead(_ sender: Any) { - - let title = NSLocalizedString("Mark All Read", comment: "Mark All Read") - let message = NSLocalizedString("Mark all articles in all accounts as read?", comment: "Mark all articles") - let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert) - - let cancelTitle = NSLocalizedString("Cancel", comment: "Cancel") - let cancelAction = UIAlertAction(title: cancelTitle, style: .cancel) - alertController.addAction(cancelAction) - - let markTitle = NSLocalizedString("Mark All Read", comment: "Mark All Read") - let markAction = UIAlertAction(title: markTitle, style: .default) { [weak self] (action) in - self?.coordinator.markAllAsRead() - } - - alertController.addAction(markAction) - - present(alertController, animated: true) - + if coordinator.shouldDisplayMarkAllAsReadUndoTip { + let alertController = MarkArticlesReadAlertController.allArticlesAlert { [weak self] _ in + self?.coordinator.markAllAsRead() + } + + present(alertController, animated: true) + } else { + coordinator.markAllAsRead() + } } @IBAction func add(_ sender: UIBarButtonItem) { diff --git a/iOS/MasterTimeline/MasterTimelineViewController.swift b/iOS/MasterTimeline/MasterTimelineViewController.swift index 36c61034c..52d80e7f1 100644 --- a/iOS/MasterTimeline/MasterTimelineViewController.swift +++ b/iOS/MasterTimeline/MasterTimelineViewController.swift @@ -89,24 +89,15 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner // MARK: Actions @IBAction func markAllAsRead(_ sender: Any) { - - let title = NSLocalizedString("Mark All Read", comment: "Mark All Read") - let message = NSLocalizedString("Mark all articles in this timeline as read?", comment: "Mark all articles") - let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert) - - let cancelTitle = NSLocalizedString("Cancel", comment: "Cancel") - let cancelAction = UIAlertAction(title: cancelTitle, style: .cancel) - alertController.addAction(cancelAction) - - let markTitle = NSLocalizedString("Mark All Read", comment: "Mark All Read") - let markAction = UIAlertAction(title: markTitle, style: .default) { [weak self] (action) in - self?.coordinator.markAllAsReadInTimeline() + if coordinator.shouldDisplayMarkAllAsReadUndoTip { + let alertController = MarkArticlesReadAlertController.timelineArticlesAlert { [weak self] _ in + self?.coordinator.markAllAsReadInTimeline() + } + + present(alertController, animated: true) + } else { + coordinator.markAllAsReadInTimeline() } - - alertController.addAction(markAction) - - present(alertController, animated: true) - } @IBAction func firstUnread(_ sender: Any) { diff --git a/iOS/SceneCoordinator.swift b/iOS/SceneCoordinator.swift index 9a0b79878..3d1468d85 100644 --- a/iOS/SceneCoordinator.swift +++ b/iOS/SceneCoordinator.swift @@ -82,6 +82,8 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { } } } + + private(set) var shouldDisplayMarkAllAsReadUndoTip = true private let treeControllerDelegate = FeedTreeControllerDelegate() private lazy var treeController: TreeController = { From b963d97922f3d08d01a524c0c67f10b0f211988e Mon Sep 17 00:00:00 2001 From: Phil Viso Date: Mon, 7 Oct 2019 19:48:58 -0500 Subject: [PATCH 2/4] Show an alert the first time mark all as read is tapped --- iOS/AppDefaults.swift | 13 ++++++++++++- .../MarkArticlesReadAlertController.swift | 4 ++-- iOS/MasterFeed/MasterFeedViewController.swift | 3 ++- .../MasterTimelineViewController.swift | 3 ++- iOS/SceneCoordinator.swift | 5 ++++- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/iOS/AppDefaults.swift b/iOS/AppDefaults.swift index dce1fdc19..dcf2439a5 100644 --- a/iOS/AppDefaults.swift +++ b/iOS/AppDefaults.swift @@ -18,6 +18,7 @@ struct AppDefaults { static let timelineGroupByFeed = "timelineGroupByFeed" static let timelineNumberOfLines = "timelineNumberOfLines" static let timelineSortDirection = "timelineSortDirection" + static let displayMarkAllAsReadUndoTip = "displayMarkAllAsReadUndoTip" static let refreshInterval = "refreshInterval" static let lastRefresh = "lastRefresh" } @@ -67,6 +68,15 @@ struct AppDefaults { } } + static var displayMarkAllAsReadUndoTip: Bool { + get { + return bool(for: Key.displayMarkAllAsReadUndoTip) + } + set { + setBool(for: Key.displayMarkAllAsReadUndoTip, newValue) + } + } + static var lastRefresh: Date? { get { return date(for: Key.lastRefresh) @@ -90,7 +100,8 @@ struct AppDefaults { Key.refreshInterval: RefreshInterval.everyHour.rawValue, Key.timelineGroupByFeed: false, Key.timelineNumberOfLines: 3, - Key.timelineSortDirection: ComparisonResult.orderedDescending.rawValue] + Key.timelineSortDirection: ComparisonResult.orderedDescending.rawValue, + Key.displayMarkAllAsReadUndoTip: true] AppDefaults.shared.register(defaults: defaults) } diff --git a/iOS/MasterFeed/MarkArticlesReadAlertController.swift b/iOS/MasterFeed/MarkArticlesReadAlertController.swift index 6e4f4a8a3..82d2b328b 100644 --- a/iOS/MasterFeed/MarkArticlesReadAlertController.swift +++ b/iOS/MasterFeed/MarkArticlesReadAlertController.swift @@ -12,13 +12,13 @@ import UIKit struct MarkArticlesReadAlertController { static func allArticlesAlert(handler: @escaping (UIAlertAction) -> Void) -> UIAlertController { - let message = NSLocalizedString("Mark all articles in all accounts as read?", + let message = NSLocalizedString("Mark all articles in all accounts as read? You can undo this action with a three finger swipe to the right.", comment: "Mark all articles") return markAllReadAlert(message: message, handler: handler) } static func timelineArticlesAlert(handler: @escaping (UIAlertAction) -> Void) -> UIAlertController { - let message = NSLocalizedString("Mark all articles in this timeline as read?", + let message = NSLocalizedString("Mark all articles in this timeline as read? You can undo this action with a three finger swipe to the right.", comment: "Mark all articles") return markAllReadAlert(message: message, handler: handler) } diff --git a/iOS/MasterFeed/MasterFeedViewController.swift b/iOS/MasterFeed/MasterFeedViewController.swift index ef4f48736..6fbf9c830 100644 --- a/iOS/MasterFeed/MasterFeedViewController.swift +++ b/iOS/MasterFeed/MasterFeedViewController.swift @@ -344,8 +344,9 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { } @IBAction func markAllAsRead(_ sender: Any) { - if coordinator.shouldDisplayMarkAllAsReadUndoTip { + if coordinator.displayMarkAllAsReadUndoTip { let alertController = MarkArticlesReadAlertController.allArticlesAlert { [weak self] _ in + self?.coordinator.displayMarkAllAsReadUndoTip = false self?.coordinator.markAllAsRead() } diff --git a/iOS/MasterTimeline/MasterTimelineViewController.swift b/iOS/MasterTimeline/MasterTimelineViewController.swift index 52d80e7f1..862e8da18 100644 --- a/iOS/MasterTimeline/MasterTimelineViewController.swift +++ b/iOS/MasterTimeline/MasterTimelineViewController.swift @@ -89,8 +89,9 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner // MARK: Actions @IBAction func markAllAsRead(_ sender: Any) { - if coordinator.shouldDisplayMarkAllAsReadUndoTip { + if coordinator.displayMarkAllAsReadUndoTip { let alertController = MarkArticlesReadAlertController.timelineArticlesAlert { [weak self] _ in + self?.coordinator.displayMarkAllAsReadUndoTip = false self?.coordinator.markAllAsReadInTimeline() } diff --git a/iOS/SceneCoordinator.swift b/iOS/SceneCoordinator.swift index 3d1468d85..50d8c6bd7 100644 --- a/iOS/SceneCoordinator.swift +++ b/iOS/SceneCoordinator.swift @@ -83,7 +83,10 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { } } - private(set) var shouldDisplayMarkAllAsReadUndoTip = true + var displayMarkAllAsReadUndoTip: Bool { + get { AppDefaults.displayMarkAllAsReadUndoTip } + set { AppDefaults.displayMarkAllAsReadUndoTip = newValue } + } private let treeControllerDelegate = FeedTreeControllerDelegate() private lazy var treeController: TreeController = { From b635fd4d45c07561bd5bbef703cc400f493cf942 Mon Sep 17 00:00:00 2001 From: Phil Viso Date: Mon, 7 Oct 2019 20:00:14 -0500 Subject: [PATCH 3/4] Fixed swipe direction in copy --- iOS/MasterFeed/MarkArticlesReadAlertController.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/iOS/MasterFeed/MarkArticlesReadAlertController.swift b/iOS/MasterFeed/MarkArticlesReadAlertController.swift index 82d2b328b..4fa18f667 100644 --- a/iOS/MasterFeed/MarkArticlesReadAlertController.swift +++ b/iOS/MasterFeed/MarkArticlesReadAlertController.swift @@ -12,13 +12,13 @@ import UIKit struct MarkArticlesReadAlertController { static func allArticlesAlert(handler: @escaping (UIAlertAction) -> Void) -> UIAlertController { - let message = NSLocalizedString("Mark all articles in all accounts as read? You can undo this action with a three finger swipe to the right.", + let message = NSLocalizedString("Mark all articles in all accounts as read? You can undo this action with a three finger swipe to the left.", comment: "Mark all articles") return markAllReadAlert(message: message, handler: handler) } static func timelineArticlesAlert(handler: @escaping (UIAlertAction) -> Void) -> UIAlertController { - let message = NSLocalizedString("Mark all articles in this timeline as read? You can undo this action with a three finger swipe to the right.", + let message = NSLocalizedString("Mark all articles in this timeline as read? You can undo this action with a three finger swipe to the left.", comment: "Mark all articles") return markAllReadAlert(message: message, handler: handler) } From 93ab639509fc01123b794b9f6f285635e9905f11 Mon Sep 17 00:00:00 2001 From: Phil Viso Date: Mon, 7 Oct 2019 21:13:00 -0500 Subject: [PATCH 4/4] Updated modal copy. Copy update removed the need for separate versions of the modal. --- .../MarkArticlesReadAlertController.swift | 25 +++++-------------- iOS/MasterFeed/MasterFeedViewController.swift | 2 +- .../MasterTimelineViewController.swift | 2 +- 3 files changed, 8 insertions(+), 21 deletions(-) diff --git a/iOS/MasterFeed/MarkArticlesReadAlertController.swift b/iOS/MasterFeed/MarkArticlesReadAlertController.swift index 4fa18f667..d105be343 100644 --- a/iOS/MasterFeed/MarkArticlesReadAlertController.swift +++ b/iOS/MasterFeed/MarkArticlesReadAlertController.swift @@ -10,30 +10,17 @@ import Foundation import UIKit struct MarkArticlesReadAlertController { - - static func allArticlesAlert(handler: @escaping (UIAlertAction) -> Void) -> UIAlertController { - let message = NSLocalizedString("Mark all articles in all accounts as read? You can undo this action with a three finger swipe to the left.", - comment: "Mark all articles") - return markAllReadAlert(message: message, handler: handler) - } - - static func timelineArticlesAlert(handler: @escaping (UIAlertAction) -> Void) -> UIAlertController { - let message = NSLocalizedString("Mark all articles in this timeline as read? You can undo this action with a three finger swipe to the left.", - comment: "Mark all articles") - return markAllReadAlert(message: message, handler: handler) - } - - // MARK: - - - private static func markAllReadAlert(message: String, - handler: @escaping (UIAlertAction) -> Void) -> UIAlertController { + + static func markAllAsReadAlert(handler: @escaping (UIAlertAction) -> Void) -> UIAlertController { let title = NSLocalizedString("Mark All Read", comment: "Mark All Read") + let message = NSLocalizedString("You can undo this and other actions with a three finger swipe to the left.", + comment: "Mark all articles") let cancelTitle = NSLocalizedString("Cancel", comment: "Cancel") - let markTitle = NSLocalizedString("Mark All Read", comment: "Mark All Read") + let confirmTitle = NSLocalizedString("Got It", comment: "Got It") let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert) let cancelAction = UIAlertAction(title: cancelTitle, style: .cancel) - let markAction = UIAlertAction(title: markTitle, style: .default, handler: handler) + let markAction = UIAlertAction(title: confirmTitle, style: .default, handler: handler) alertController.addAction(cancelAction) alertController.addAction(markAction) diff --git a/iOS/MasterFeed/MasterFeedViewController.swift b/iOS/MasterFeed/MasterFeedViewController.swift index 6fbf9c830..7fb07f9ce 100644 --- a/iOS/MasterFeed/MasterFeedViewController.swift +++ b/iOS/MasterFeed/MasterFeedViewController.swift @@ -345,7 +345,7 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { @IBAction func markAllAsRead(_ sender: Any) { if coordinator.displayMarkAllAsReadUndoTip { - let alertController = MarkArticlesReadAlertController.allArticlesAlert { [weak self] _ in + let alertController = MarkArticlesReadAlertController.markAllAsReadAlert { [weak self] _ in self?.coordinator.displayMarkAllAsReadUndoTip = false self?.coordinator.markAllAsRead() } diff --git a/iOS/MasterTimeline/MasterTimelineViewController.swift b/iOS/MasterTimeline/MasterTimelineViewController.swift index 862e8da18..df8a58b1b 100644 --- a/iOS/MasterTimeline/MasterTimelineViewController.swift +++ b/iOS/MasterTimeline/MasterTimelineViewController.swift @@ -90,7 +90,7 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner @IBAction func markAllAsRead(_ sender: Any) { if coordinator.displayMarkAllAsReadUndoTip { - let alertController = MarkArticlesReadAlertController.timelineArticlesAlert { [weak self] _ in + let alertController = MarkArticlesReadAlertController.markAllAsReadAlert { [weak self] _ in self?.coordinator.displayMarkAllAsReadUndoTip = false self?.coordinator.markAllAsReadInTimeline() }