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/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 new file mode 100644 index 000000000..d105be343 --- /dev/null +++ b/iOS/MasterFeed/MarkArticlesReadAlertController.swift @@ -0,0 +1,31 @@ +// +// 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 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 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: confirmTitle, 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..7fb07f9ce 100644 --- a/iOS/MasterFeed/MasterFeedViewController.swift +++ b/iOS/MasterFeed/MasterFeedViewController.swift @@ -344,24 +344,16 @@ 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.displayMarkAllAsReadUndoTip { + let alertController = MarkArticlesReadAlertController.markAllAsReadAlert { [weak self] _ in + self?.coordinator.displayMarkAllAsReadUndoTip = false + 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..df8a58b1b 100644 --- a/iOS/MasterTimeline/MasterTimelineViewController.swift +++ b/iOS/MasterTimeline/MasterTimelineViewController.swift @@ -89,24 +89,16 @@ 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.displayMarkAllAsReadUndoTip { + let alertController = MarkArticlesReadAlertController.markAllAsReadAlert { [weak self] _ in + self?.coordinator.displayMarkAllAsReadUndoTip = false + 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..50d8c6bd7 100644 --- a/iOS/SceneCoordinator.swift +++ b/iOS/SceneCoordinator.swift @@ -82,6 +82,11 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { } } } + + var displayMarkAllAsReadUndoTip: Bool { + get { AppDefaults.displayMarkAllAsReadUndoTip } + set { AppDefaults.displayMarkAllAsReadUndoTip = newValue } + } private let treeControllerDelegate = FeedTreeControllerDelegate() private lazy var treeController: TreeController = {