From 6a281c7672c42833ecdf9822f5326d431a899533 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Fri, 25 Oct 2019 13:34:59 -0500 Subject: [PATCH] Replace Mark All as Read with progress indicator. Issues #1157 and #1165 --- NetNewsWire.xcodeproj/project.pbxproj | 26 ++-- iOS/Article/ArticleViewController.swift | 16 -- iOS/Base.lproj/LaunchScreenPad.storyboard | 7 +- iOS/Base.lproj/LaunchScreenPhone.storyboard | 7 +- iOS/Base.lproj/Main.storyboard | 21 +-- iOS/MasterFeed/MasterFeedViewController.swift | 40 +++-- iOS/MasterFeed/RefreshProgressView.swift | 70 +++++++++ iOS/MasterFeed/RefreshProgressView.xib | 49 ++++++ .../MasterTimelineViewController.swift | 29 ---- .../UndoAvailableAlertController.swift | 0 iOS/Progress/NavigationProgressView.swift | 132 ---------------- .../UINavigationController+Progress.swift | 145 ------------------ iOS/SceneCoordinator.swift | 9 -- 13 files changed, 153 insertions(+), 398 deletions(-) create mode 100644 iOS/MasterFeed/RefreshProgressView.swift create mode 100644 iOS/MasterFeed/RefreshProgressView.xib rename iOS/{MasterFeed => MasterTimeline}/UndoAvailableAlertController.swift (100%) delete mode 100644 iOS/Progress/NavigationProgressView.swift delete mode 100644 iOS/Progress/UINavigationController+Progress.swift diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj index 4102a510f..b1a501672 100644 --- a/NetNewsWire.xcodeproj/project.pbxproj +++ b/NetNewsWire.xcodeproj/project.pbxproj @@ -93,8 +93,6 @@ 517630232336657E00E15FFF /* ArticleViewControllerWebViewProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 517630222336657E00E15FFF /* ArticleViewControllerWebViewProvider.swift */; }; 5183CCD0226E1E880010922C /* NonIntrinsicLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCCF226E1E880010922C /* NonIntrinsicLabel.swift */; }; 5183CCDA226E31A50010922C /* NonIntrinsicImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCD9226E31A50010922C /* NonIntrinsicImageView.swift */; }; - 5183CCDD226F1F5C0010922C /* NavigationProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCDC226F1F5C0010922C /* NavigationProgressView.swift */; }; - 5183CCDF226F1FCC0010922C /* UINavigationController+Progress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCDE226F1FCC0010922C /* UINavigationController+Progress.swift */; }; 5183CCE5226F4DFA0010922C /* RefreshInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */; }; 5183CCE6226F4E110010922C /* RefreshInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */; }; 5183CCE8226F68D90010922C /* AccountRefreshTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE7226F68D90010922C /* AccountRefreshTimer.swift */; }; @@ -194,6 +192,8 @@ 51C452B42265141B00C03939 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51C452B32265141B00C03939 /* WebKit.framework */; }; 51C452B82265178500C03939 /* styleSheet.css in Resources */ = {isa = PBXBuildFile; fileRef = 51C452B72265178500C03939 /* styleSheet.css */; }; 51CC9B3E231720B2000E842F /* MasterFeedDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51CC9B3D231720B2000E842F /* MasterFeedDataSource.swift */; }; + 51CE1C0923621EDA005548FC /* RefreshProgressView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 51CE1C0823621EDA005548FC /* RefreshProgressView.xib */; }; + 51CE1C0B23622007005548FC /* RefreshProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51CE1C0A23622006005548FC /* RefreshProgressView.swift */; }; 51D5948722668EFA00DFC836 /* MarkStatusCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84702AA31FA27AC0006B8943 /* MarkStatusCommand.swift */; }; 51D6A5BC23199C85001C27D8 /* MasterTimelineDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51D6A5BB23199C85001C27D8 /* MasterTimelineDataSource.swift */; }; 51D87EE12311D34700E63F03 /* ActivityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51D87EE02311D34700E63F03 /* ActivityType.swift */; }; @@ -1251,8 +1251,6 @@ 517630222336657E00E15FFF /* ArticleViewControllerWebViewProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleViewControllerWebViewProvider.swift; sourceTree = ""; }; 5183CCCF226E1E880010922C /* NonIntrinsicLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonIntrinsicLabel.swift; sourceTree = ""; }; 5183CCD9226E31A50010922C /* NonIntrinsicImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonIntrinsicImageView.swift; sourceTree = ""; }; - 5183CCDC226F1F5C0010922C /* NavigationProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationProgressView.swift; sourceTree = ""; }; - 5183CCDE226F1FCC0010922C /* UINavigationController+Progress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Progress.swift"; sourceTree = ""; }; 5183CCE4226F4DFA0010922C /* RefreshInterval.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshInterval.swift; sourceTree = ""; }; 5183CCE7226F68D90010922C /* AccountRefreshTimer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountRefreshTimer.swift; sourceTree = ""; }; 518651AB23555EB20078E021 /* NNW3Document.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NNW3Document.swift; sourceTree = ""; }; @@ -1300,6 +1298,8 @@ 51C452B32265141B00C03939 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/WebKit.framework; sourceTree = DEVELOPER_DIR; }; 51C452B72265178500C03939 /* styleSheet.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = styleSheet.css; sourceTree = ""; }; 51CC9B3D231720B2000E842F /* MasterFeedDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MasterFeedDataSource.swift; sourceTree = ""; }; + 51CE1C0823621EDA005548FC /* RefreshProgressView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RefreshProgressView.xib; sourceTree = ""; }; + 51CE1C0A23622006005548FC /* RefreshProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshProgressView.swift; sourceTree = ""; }; 51D6A5BB23199C85001C27D8 /* MasterTimelineDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MasterTimelineDataSource.swift; sourceTree = ""; }; 51D87EE02311D34700E63F03 /* ActivityType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityType.swift; sourceTree = ""; }; 51E3EB32229AB02C00645299 /* ErrorHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorHandler.swift; sourceTree = ""; }; @@ -1766,15 +1766,6 @@ path = Account; sourceTree = ""; }; - 5183CCDB226F1EEB0010922C /* Progress */ = { - isa = PBXGroup; - children = ( - 5183CCDC226F1F5C0010922C /* NavigationProgressView.swift */, - 5183CCDE226F1FCC0010922C /* UINavigationController+Progress.swift */, - ); - path = Progress; - sourceTree = ""; - }; 5183CCEA226F70350010922C /* Timer */ = { isa = PBXGroup; children = ( @@ -1854,9 +1845,10 @@ 51C4525D226508F600C03939 /* MasterFeed */ = { isa = PBXGroup; children = ( - FFD43E372340F320009E5CA3 /* UndoAvailableAlertController.swift */, 51C45264226508F600C03939 /* MasterFeedViewController.swift */, 51CC9B3D231720B2000E842F /* MasterFeedDataSource.swift */, + 51CE1C0A23622006005548FC /* RefreshProgressView.swift */, + 51CE1C0823621EDA005548FC /* RefreshProgressView.xib */, 51C45260226508F600C03939 /* Cell */, ); path = MasterFeed; @@ -1881,6 +1873,7 @@ 5148F4542336DB7000F8CD8B /* MasterTimelineTitleView.swift */, 5148F44A2336DB4700F8CD8B /* MasterTimelineTitleView.xib */, 51FD413A2342BD0500880194 /* MasterTimelineUnreadCountView.swift */, + FFD43E372340F320009E5CA3 /* UndoAvailableAlertController.swift */, 51C4526F2265091600C03939 /* Cell */, ); path = MasterTimeline; @@ -2538,7 +2531,6 @@ 51C452802265093600C03939 /* Add */, 5123DB95233EC69300282CC9 /* Inspector */, 513145F9235A55A700387FDC /* Intents */, - 5183CCDB226F1EEB0010922C /* Progress */, 5183CCEB227117C70010922C /* Settings */, 519D740423243C68008BB345 /* Model Extensions */, 51C45245226506C800C03939 /* UIKit Extensions */, @@ -3403,6 +3395,7 @@ 51A1699A235E10D700EB091F /* Settings.storyboard in Resources */, 49F40DF92335B71000552BF4 /* newsfoot.js in Resources */, 51F85BEF2272520B00C787DC /* Thanks.rtf in Resources */, + 51CE1C0923621EDA005548FC /* RefreshProgressView.xib in Resources */, 84C9FC9D2262A1A900D921D6 /* Assets.xcassets in Resources */, 514219582353C28900E07E2C /* main_ios.js in Resources */, 51C452B82265178500C03939 /* styleSheet.css in Resources */, @@ -3889,7 +3882,6 @@ 51AF460E232488C6001742EF /* Account-Extensions.swift in Sources */, 51FD413B2342BD0500880194 /* MasterTimelineUnreadCountView.swift in Sources */, 513146B2235A81A400387FDC /* AddFeedIntentHandler.swift in Sources */, - 5183CCDD226F1F5C0010922C /* NavigationProgressView.swift in Sources */, 51D87EE12311D34700E63F03 /* ActivityType.swift in Sources */, 51C452772265091600C03939 /* MultilineUILabelSizer.swift in Sources */, 51C452A522650A2D00C03939 /* SmallIconProvider.swift in Sources */, @@ -3915,7 +3907,6 @@ 51BB7C272335A8E5008E8144 /* ArticleActivityItemSource.swift in Sources */, 51F85BF52273625800C787DC /* Bundle-Extensions.swift in Sources */, 51C452A622650A3500C03939 /* Node-Extensions.swift in Sources */, - 5183CCDF226F1FCC0010922C /* UINavigationController+Progress.swift in Sources */, 51C45294226509C800C03939 /* SearchFeedDelegate.swift in Sources */, 5F323809231DF9F000706F6B /* VibrantTableViewCell.swift in Sources */, 512E09352268B25900BDCFDD /* UISplitViewController-Extensions.swift in Sources */, @@ -3982,6 +3973,7 @@ 51FFF0C4235EE8E5002762AA /* VibrantButton.swift in Sources */, 513228FC233037630033D4ED /* Reachability.swift in Sources */, 51C45259226508D300C03939 /* AppDefaults.swift in Sources */, + 51CE1C0B23622007005548FC /* RefreshProgressView.swift in Sources */, 511D4419231FC02D00FB1562 /* KeyboardManager.swift in Sources */, 51A1699D235E10D700EB091F /* SettingsViewController.swift in Sources */, 51C45293226509C800C03939 /* StarredFeedDelegate.swift in Sources */, diff --git a/iOS/Article/ArticleViewController.swift b/iOS/Article/ArticleViewController.swift index c73636727..a479e693f 100644 --- a/iOS/Article/ArticleViewController.swift +++ b/iOS/Article/ArticleViewController.swift @@ -96,7 +96,6 @@ class ArticleViewController: UIViewController { NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(statusesDidChange(_:)), name: .StatusesDidChange, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(progressDidChange(_:)), name: .AccountRefreshProgressDidChange, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(contentSizeCategoryDidChange(_:)), name: UIContentSizeCategory.didChangeNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(willEnterForeground(_:)), name: UIApplication.willEnterForegroundNotification, object: nil) @@ -126,11 +125,6 @@ class ArticleViewController: UIViewController { } - override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - updateProgressIndicatorIfNeeded() - } - func updateUI() { guard let article = currentArticle else { @@ -209,10 +203,6 @@ class ArticleViewController: UIViewController { } } - @objc func progressDidChange(_ note: Notification) { - updateProgressIndicatorIfNeeded() - } - @objc func contentSizeCategoryDidChange(_ note: Notification) { reloadHTML() } @@ -427,12 +417,6 @@ private struct ImageClickMessage: Codable { private extension ArticleViewController { - func updateProgressIndicatorIfNeeded() { - if !(UIDevice.current.userInterfaceIdiom == .pad) { - navigationController?.updateAccountRefreshProgressIndicator() - } - } - func imageWasClicked(body: String?) { guard let body = body, let data = body.data(using: .utf8), diff --git a/iOS/Base.lproj/LaunchScreenPad.storyboard b/iOS/Base.lproj/LaunchScreenPad.storyboard index 81d675131..070aca5aa 100644 --- a/iOS/Base.lproj/LaunchScreenPad.storyboard +++ b/iOS/Base.lproj/LaunchScreenPad.storyboard @@ -1,8 +1,8 @@ - + - + @@ -65,7 +65,6 @@ - @@ -114,6 +113,6 @@ - + diff --git a/iOS/Base.lproj/LaunchScreenPhone.storyboard b/iOS/Base.lproj/LaunchScreenPhone.storyboard index 7e19f8713..a61b6f5d9 100644 --- a/iOS/Base.lproj/LaunchScreenPhone.storyboard +++ b/iOS/Base.lproj/LaunchScreenPhone.storyboard @@ -1,8 +1,8 @@ - + - + @@ -65,7 +65,6 @@ - @@ -114,6 +113,6 @@ - + diff --git a/iOS/Base.lproj/Main.storyboard b/iOS/Base.lproj/Main.storyboard index 994202c66..e767ead95 100644 --- a/iOS/Base.lproj/Main.storyboard +++ b/iOS/Base.lproj/Main.storyboard @@ -190,22 +190,7 @@ - - - - - - - - - - - - - - - - + @@ -218,10 +203,6 @@ - - - - diff --git a/iOS/MasterFeed/MasterFeedViewController.swift b/iOS/MasterFeed/MasterFeedViewController.swift index 15a86ba80..c0c606a96 100644 --- a/iOS/MasterFeed/MasterFeedViewController.swift +++ b/iOS/MasterFeed/MasterFeedViewController.swift @@ -14,8 +14,8 @@ import RSTree class MasterFeedViewController: UITableViewController, UndoableCommandRunner { - @IBOutlet private weak var markAllAsReadButton: UIBarButtonItem! - @IBOutlet private weak var addNewItemButton: UIBarButtonItem! + private var refreshProgressView: RefreshProgressView! + private var addNewItemButton: UIBarButtonItem! private lazy var dataSource = makeDataSource() var undoableCommands = [UndoableCommand]() @@ -54,12 +54,13 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { NotificationCenter.default.addObserver(self, selector: #selector(feedSettingDidChange(_:)), name: .FeedSettingDidChange, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(feedMetadataDidChange(_:)), name: .FeedMetadataDidChange, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(userDidAddFeed(_:)), name: .UserDidAddFeed, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(progressDidChange(_:)), name: .AccountRefreshProgressDidChange, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(contentSizeCategoryDidChange), name: UIContentSizeCategory.didChangeNotification, object: nil) refreshControl = UIRefreshControl() refreshControl!.addTarget(self, action: #selector(refreshAccounts(_:)), for: .valueChanged) + configureToolbar() + updateUI() becomeFirstResponder() @@ -73,7 +74,6 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - navigationController?.updateAccountRefreshProgressIndicator() } // MARK: Notifications @@ -133,10 +133,6 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { discloseFeed(feed) } - @objc func progressDidChange(_ note: Notification) { - navigationController?.updateAccountRefreshProgressIndicator() - } - @objc func contentSizeCategoryDidChange(_ note: Notification) { applyChanges(animate: false) } @@ -344,19 +340,6 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { @IBAction func settings(_ sender: UIBarButtonItem) { coordinator.showSettings() } - - @IBAction func markAllAsRead(_ sender: Any) { - if coordinator.displayUndoAvailableTip { - let alertController = UndoAvailableAlertController.alert { [weak self] _ in - self?.coordinator.displayUndoAvailableTip = false - self?.coordinator.markAllAsRead() - } - - present(alertController, animated: true) - } else { - coordinator.markAllAsRead() - } - } @IBAction func add(_ sender: UIBarButtonItem) { coordinator.showAdd(.feed) @@ -573,8 +556,21 @@ extension MasterFeedViewController: MasterFeedTableViewCellDelegate { private extension MasterFeedViewController { + func configureToolbar() { + guard let refreshProgressView = Bundle.main.loadNibNamed("RefreshProgressView", owner: self, options: nil)?[0] as? RefreshProgressView else { + return + } + + self.refreshProgressView = refreshProgressView + + let refreshProgressItemButton = UIBarButtonItem(customView: refreshProgressView) + let spaceItemButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) + addNewItemButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(add(_:))) + setToolbarItems([refreshProgressItemButton, spaceItemButton, addNewItemButton], animated: false) + } + func updateUI() { - markAllAsReadButton.isEnabled = coordinator.isAnyUnreadAvailable + refreshProgressView.updateRefreshLabel() addNewItemButton.isEnabled = !AccountManager.shared.activeAccounts.isEmpty } diff --git a/iOS/MasterFeed/RefreshProgressView.swift b/iOS/MasterFeed/RefreshProgressView.swift new file mode 100644 index 000000000..a153ada73 --- /dev/null +++ b/iOS/MasterFeed/RefreshProgressView.swift @@ -0,0 +1,70 @@ +// +// RefeshProgressView.swift +// NetNewsWire-iOS +// +// Created by Maurice Parker on 10/24/19. +// Copyright © 2019 Ranchero Software. All rights reserved. +// + +import UIKit +import Account + +class RefreshProgressView: UIView { + + @IBOutlet weak var progressView: UIProgressView! + @IBOutlet weak var label: UILabel! + private lazy var progressWidth = progressView.widthAnchor.constraint(equalToConstant: 100.0) + + override init(frame: CGRect) { + super.init(frame: frame) + commonInit() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + commonInit() + } + + func commonInit() { + NotificationCenter.default.addObserver(self, selector: #selector(progressDidChange(_:)), name: .AccountRefreshProgressDidChange, object: nil) + } + + func updateRefreshLabel() { + if let refreshDate = AppDefaults.lastRefresh { + let relativeDateTimeFormatter = RelativeDateTimeFormatter() + relativeDateTimeFormatter.dateTimeStyle = .named + let refreshed = relativeDateTimeFormatter.localizedString(for: refreshDate, relativeTo: Date()) + let localizedRefreshText = NSLocalizedString("Refreshed %@", comment: "Refreshed") + let refreshText = NSString.localizedStringWithFormat(localizedRefreshText as NSString, refreshed) as String + label.text = refreshText + } + + } + @objc func progressDidChange(_ note: Notification) { + + let progress = AccountManager.shared.combinedRefreshProgress + + if progress.isComplete { + progressView.progress = 1 + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + self.updateRefreshLabel() + self.label.isHidden = false + self.progressView.isHidden = true + self.progressWidth.isActive = false + } + } else { + label.isHidden = true + progressView.isHidden = false + self.progressWidth.isActive = true + let percent = Float(progress.numberCompleted) / Float(progress.numberOfTasks) + progressView.progress = percent + } + + } + + deinit { + NotificationCenter.default.removeObserver(self) + } + +} + diff --git a/iOS/MasterFeed/RefreshProgressView.xib b/iOS/MasterFeed/RefreshProgressView.xib new file mode 100644 index 000000000..6fa3b68d0 --- /dev/null +++ b/iOS/MasterFeed/RefreshProgressView.xib @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOS/MasterTimeline/MasterTimelineViewController.swift b/iOS/MasterTimeline/MasterTimelineViewController.swift index edad2461b..d27e14a20 100644 --- a/iOS/MasterTimeline/MasterTimelineViewController.swift +++ b/iOS/MasterTimeline/MasterTimelineViewController.swift @@ -44,14 +44,9 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner NotificationCenter.default.addObserver(self, selector: #selector(avatarDidBecomeAvailable(_:)), name: .AvatarDidBecomeAvailable, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(faviconDidBecomeAvailable(_:)), name: .FaviconDidBecomeAvailable, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(userDefaultsDidChange(_:)), name: UserDefaults.didChangeNotification, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(progressDidChange(_:)), name: .AccountRefreshProgressDidChange, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(contentSizeCategoryDidChange), name: UIContentSizeCategory.didChangeNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(displayNameDidChange), name: .DisplayNameDidChange, object: nil) - // Setup the Refresh Control - refreshControl = UIRefreshControl() - refreshControl!.addTarget(self, action: #selector(refreshAccounts(_:)), for: .valueChanged) - // Configure the table tableView.dataSource = dataSource numberOfTextLines = AppDefaults.timelineNumberOfLines @@ -66,11 +61,6 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner super.viewWillAppear(animated) } - override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - updateProgressIndicatorIfNeeded() - } - override func viewWillLayoutSubviews() { // If you setup the Search Controller in viewWillLayoutSubviews it won't show by default on creation searchController.delegate = self @@ -368,10 +358,6 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner reloadAllVisibleCells() } - @objc func progressDidChange(_ note: Notification) { - updateProgressIndicatorIfNeeded() - } - @objc func displayNameDidChange(_ note: Notification) { titleView?.label.text = coordinator.timelineName } @@ -455,15 +441,6 @@ extension MasterTimelineViewController: UISearchBarDelegate { private extension MasterTimelineViewController { - @objc private func refreshAccounts(_ sender: Any) { - refreshControl?.endRefreshing() - // This is a hack to make sure that an error dialog doesn't interfere with dismissing the refreshControl. - // If the error dialog appears too closely to the call to endRefreshing, then the refreshControl never disappears. - DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { - AccountManager.shared.refreshAll(errorHandler: ErrorHandler.present(self)) - } - } - func resetUI() { title = coordinator.timelineName @@ -521,12 +498,6 @@ private extension MasterTimelineViewController { } } - func updateProgressIndicatorIfNeeded() { - if !coordinator.isThreePanelMode { - navigationController?.updateAccountRefreshProgressIndicator() - } - } - func applyChanges(animate: Bool, completion: (() -> Void)? = nil) { var snapshot = NSDiffableDataSourceSnapshot() snapshot.appendSections([0]) diff --git a/iOS/MasterFeed/UndoAvailableAlertController.swift b/iOS/MasterTimeline/UndoAvailableAlertController.swift similarity index 100% rename from iOS/MasterFeed/UndoAvailableAlertController.swift rename to iOS/MasterTimeline/UndoAvailableAlertController.swift diff --git a/iOS/Progress/NavigationProgressView.swift b/iOS/Progress/NavigationProgressView.swift deleted file mode 100644 index e28562ba8..000000000 --- a/iOS/Progress/NavigationProgressView.swift +++ /dev/null @@ -1,132 +0,0 @@ -// -// NavigationProgressView.swift -// KYNavigationProgress -// -// Created by kyo__hei on 2015/12/29. -// Copyright (c) 2015 kyo__hei. All rights reserved. -// -// Original project: https://github.com/ykyouhei/KYNavigationProgress - -import UIKit - -public final class NavigationProgressView: UIView { - - /* ====================================================================== */ - // MARK: - Properties - /* ====================================================================== */ - - internal var progress: Float = 0 { - didSet { - progress = min(1, progress) - barWidthConstraint.constant = bounds.width * CGFloat(progress) - } - } - - internal let bar = UIView() - - @objc public dynamic var progressTintColor: UIColor? = AppAssets.primaryAccentColor { - didSet { - bar.backgroundColor = progressTintColor - } - } - - @objc public dynamic var trackTintColor: UIColor? = .clear { - didSet { - backgroundColor = trackTintColor - } - } - - fileprivate let barWidthConstraint: NSLayoutConstraint - - override public var frame: CGRect { - didSet { - let tmpProgress = progress - progress = tmpProgress - } - } - - /* ====================================================================== */ - // MARK: - initializer - /* ====================================================================== */ - - required public init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override init(frame: CGRect) { - barWidthConstraint = NSLayoutConstraint( - item: bar, - attribute: .width, - relatedBy: .equal, - toItem: nil, - attribute: .notAnAttribute, - multiplier: 1, - constant: frame.width * CGFloat(progress)) - - super.init(frame: frame) - - let leftConstraint = NSLayoutConstraint( - item: bar, - attribute: .left, - relatedBy: .equal, - toItem: self, - attribute: .left, - multiplier: 1, - constant: 0) - - let bottomConstraint = NSLayoutConstraint( - item: bar, - attribute: .bottom, - relatedBy: .equal, - toItem: self, - attribute: .bottom, - multiplier: 1, - constant: 0) - - let topConstraint = NSLayoutConstraint( - item: bar, - attribute: .top, - relatedBy: .equal, - toItem: self, - attribute: .top, - multiplier: 1, - constant: 0) - - addSubview(bar) - - backgroundColor = trackTintColor - - bar.backgroundColor = progressTintColor - bar.translatesAutoresizingMaskIntoConstraints = false - addConstraints([ - barWidthConstraint, - leftConstraint, - topConstraint, - bottomConstraint]) - } - - - /* ====================================================================== */ - // MARK: - Notification - /* ====================================================================== */ - - func deviceDidRotate(_ notification: Notification) { - } - - - /* ====================================================================== */ - // MARK: - Method - /* ====================================================================== */ - - internal func setProgress(_ progress: Float, animated: Bool, completion: @escaping () -> Void) { - let duration: TimeInterval = animated ? 0.2 : 0 - - self.progress = progress - - UIView.animate(withDuration: duration, animations: { self.layoutIfNeeded() }) { _ in - completion() - } - - } - -} diff --git a/iOS/Progress/UINavigationController+Progress.swift b/iOS/Progress/UINavigationController+Progress.swift deleted file mode 100644 index 6d80f9b92..000000000 --- a/iOS/Progress/UINavigationController+Progress.swift +++ /dev/null @@ -1,145 +0,0 @@ -// -// UINavigationController+Progress.swift -// KYNavigationProgress -// -// Created by kyo__hei on 2015/12/29. -// Copyright (c) 2015 kyo__hei. All rights reserved. -// -// Original project: https://github.com/ykyouhei/KYNavigationProgress - -import UIKit -import Account - -private let constraintIdentifier = "progressHeightConstraint" - -public extension UINavigationController { - - /* ====================================================================== */ - // MARK: - Properties - /* ====================================================================== */ - - /** - Default is 2.0 - */ - var progressHeight: CGFloat { - get { return progressView.frame.height } - set { - progressView.frame.origin.y = navigationBar.frame.height - newValue - progressView.frame.size.height = newValue - } - } - - /** - The color shown for the portion of the progress bar that is not filled. - default is clear color. - */ - var trackTintColor: UIColor? { - get { return progressView.trackTintColor } - set { progressView.trackTintColor = newValue } - } - - /** - The color shown for the portion of the progress bar that is filled. - default is (r: 0, g: 122, b: 225, a: 255. - */ - var progressTintColor: UIColor? { - get { return progressView.progressTintColor } - set { progressView.progressTintColor = newValue } - } - - /** - The current progress is represented by a floating-point value between 0.0 and 1.0, - inclusive, where 1.0 indicates the completion of the task. The default value is 0.0. - */ - var progress: Float { - get { return progressView.progress } - set { progressView.progress = newValue } - } - - - private var progressView: NavigationProgressView { - - for subview in navigationBar.subviews { - if let progressView = subview as? NavigationProgressView { - return progressView - } - } - - let defaultHeight = CGFloat(2) - let frame = CGRect( - x: 0, - y: navigationBar.frame.height - defaultHeight, - width: navigationBar.frame.width, - height: defaultHeight - ) - let progressView = NavigationProgressView(frame: frame) - - navigationBar.addSubview(progressView) - - progressView.autoresizingMask = [ - .flexibleWidth, .flexibleTopMargin - ] - - - return progressView - } - - - /* ====================================================================== */ - // MARK: - Public Method - /* ====================================================================== */ - - /** - Adjusts the current progress shown by the receiver, optionally animating the change. - - - parameter progress: The new progress value. - - parameter animated: true if the change should be animated, false if the change should happen immediately. - */ - func setProgress(_ progress: Float, animated: Bool, completion: @escaping () -> Void) { - progressView.bar.alpha = 1 - progressView.setProgress(progress, animated: animated, completion: completion) - } - - /** - While progress is changed to 1.0, the bar will fade out. After that, progress will be 0.0. - */ - func finishProgress() { - progressView.bar.alpha = 1 - progressView.setProgress(1, animated: true) { - DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { - UIView.animate(withDuration: 0.5, animations: { self.progressView.bar.alpha = 0 }) { finished in - self.progressView.progress = 0 - } - } - } - } - - /** - While progress is changed to 0.0, the bar will fade out. - */ - func cancelProgress() { - progressView.setProgress(0, animated: true) { - DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { - UIView.animate(withDuration: 0.5, animations: { - self.progressView.bar.alpha = 0 - }) - } - } - } - - func updateAccountRefreshProgressIndicator() { - - let progress = AccountManager.shared.combinedRefreshProgress - - if progress.isComplete { - if self.progress != 0 { - finishProgress() - } - } else { - let percent = Float(progress.numberCompleted) / Float(progress.numberOfTasks) - setProgress(percent, animated: true) {} - } - - } - -} diff --git a/iOS/SceneCoordinator.swift b/iOS/SceneCoordinator.swift index bfd636ccd..e9ca3bf07 100644 --- a/iOS/SceneCoordinator.swift +++ b/iOS/SceneCoordinator.swift @@ -718,15 +718,6 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { markArticlesWithUndo(articles, statusKey: .read, flag: true) } - func markAllAsRead() { - let accounts = AccountManager.shared.activeAccounts - var articles = Set
() - accounts.forEach { account in - articles.formUnion(account.fetchArticles(.unread)) - } - markAllAsRead(Array(articles)) - } - func markAllAsReadInTimeline() { markAllAsRead(articles) masterNavigationController.popViewController(animated: true)