From f7f7f4dddb26352dd9d10261d6a68d3901148d02 Mon Sep 17 00:00:00 2001 From: Rizwan Mohamed Ibrahim Date: Thu, 14 May 2020 17:58:38 +0530 Subject: [PATCH 1/6] adds keyboard shortcuts for open in Safari --- Shared/Resources/GlobalKeyboardShortcuts.plist | 4 ++-- iOS/KeyboardManager.swift | 3 +++ iOS/MasterFeed/MasterFeedViewController.swift | 4 ++++ iOS/RootSplitViewController.swift | 4 ++++ iOS/SceneCoordinator.swift | 16 ++++++++++++++++ 5 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Shared/Resources/GlobalKeyboardShortcuts.plist b/Shared/Resources/GlobalKeyboardShortcuts.plist index 4c6f3662c..4471354f7 100644 --- a/Shared/Resources/GlobalKeyboardShortcuts.plist +++ b/Shared/Resources/GlobalKeyboardShortcuts.plist @@ -106,11 +106,11 @@ title - Open in Browser + Open in Safari key [return] action - openInBrowser: + openInSafari: key diff --git a/iOS/KeyboardManager.swift b/iOS/KeyboardManager.swift index c463fcde2..bf0a4c465 100644 --- a/iOS/KeyboardManager.swift +++ b/iOS/KeyboardManager.swift @@ -177,6 +177,9 @@ private extension KeyboardManager { let openInBrowserTitle = NSLocalizedString("Open In Browser", comment: "Open In Browser") keys.append(KeyboardManager.createKeyCommand(title: openInBrowserTitle, action: "openInBrowser:", input: UIKeyCommand.inputRightArrow, modifiers: [.command])) + let openInSafariTitle = NSLocalizedString("Open In Safari", comment: "Open In Safari") + keys.append(KeyboardManager.createKeyCommand(title: openInSafariTitle, action: "openInSafari:", input: "\r", modifiers: [])) + let toggleReadTitle = NSLocalizedString("Toggle Read Status", comment: "Toggle Read Status") keys.append(KeyboardManager.createKeyCommand(title: toggleReadTitle, action: "toggleRead:", input: "u", modifiers: [.command, .shift])) diff --git a/iOS/MasterFeed/MasterFeedViewController.swift b/iOS/MasterFeed/MasterFeedViewController.swift index accf4b67e..1ca161c31 100644 --- a/iOS/MasterFeed/MasterFeedViewController.swift +++ b/iOS/MasterFeed/MasterFeedViewController.swift @@ -420,6 +420,10 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { @objc func openInBrowser(_ sender: Any?) { coordinator.showBrowserForCurrentFeed() } + + @objc func openInSafari(_ sender: Any?) { + coordinator.showSafariForCurrentFeed() + } @objc override func delete(_ sender: Any?) { if let indexPath = coordinator.currentFeedIndexPath { diff --git a/iOS/RootSplitViewController.swift b/iOS/RootSplitViewController.swift index 33bd740c1..1089dbe26 100644 --- a/iOS/RootSplitViewController.swift +++ b/iOS/RootSplitViewController.swift @@ -81,6 +81,10 @@ class RootSplitViewController: UISplitViewController { @objc func openInBrowser(_ sender: Any?) { coordinator.showBrowserForCurrentArticle() } + + @objc func openInSafari(_ sender: Any?) { + coordinator.showSafariForCurrentArticle() + } @objc func articleSearch(_ sender: Any?) { coordinator.showSearch() diff --git a/iOS/SceneCoordinator.swift b/iOS/SceneCoordinator.swift index 64abb8d3d..93a73fd5c 100644 --- a/iOS/SceneCoordinator.swift +++ b/iOS/SceneCoordinator.swift @@ -12,6 +12,7 @@ import Account import Articles import RSCore import RSTree +import SafariServices enum PanelMode { case unset @@ -1183,6 +1184,21 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { } UIApplication.shared.open(url, options: [:]) } + + func showSafariForCurrentFeed() { + if let ip = currentFeedIndexPath, let url = homePageURLForFeed(ip) { + let vc = SFSafariViewController(url: url) + rootSplitViewController.viewControllers.last?.present(vc, animated: true) + } + } + + func showSafariForCurrentArticle() { + guard let preferredLink = currentArticle?.preferredLink, let url = URL(string: preferredLink) else { + return + } + let vc = SFSafariViewController(url: url) + rootSplitViewController.viewControllers.last?.present(vc, animated: true) + } func navigateToFeeds() { masterFeedViewController?.focus() From c9ebb6bd752d37c497e862029773465664e1edae Mon Sep 17 00:00:00 2001 From: Rizwan Mohamed Ibrahim Date: Fri, 15 May 2020 12:39:33 +0530 Subject: [PATCH 2/6] adds "Open In App Browser" shortcut --- Shared/Resources/GlobalKeyboardShortcuts.plist | 4 ++-- iOS/Article/ArticleViewController.swift | 6 +++++- iOS/Article/WebViewController.swift | 10 +++++++++- iOS/KeyboardManager.swift | 4 ++-- iOS/MasterFeed/MasterFeedViewController.swift | 14 +++++++++----- iOS/RootSplitViewController.swift | 8 ++++++-- iOS/SceneCoordinator.swift | 15 ++++----------- 7 files changed, 37 insertions(+), 24 deletions(-) diff --git a/Shared/Resources/GlobalKeyboardShortcuts.plist b/Shared/Resources/GlobalKeyboardShortcuts.plist index 4471354f7..88e4eac90 100644 --- a/Shared/Resources/GlobalKeyboardShortcuts.plist +++ b/Shared/Resources/GlobalKeyboardShortcuts.plist @@ -106,11 +106,11 @@ title - Open in Safari + Open in App Browser key [return] action - openInSafari: + openFeedInAppBrowser: key diff --git a/iOS/Article/ArticleViewController.swift b/iOS/Article/ArticleViewController.swift index 9bd609774..b43783b64 100644 --- a/iOS/Article/ArticleViewController.swift +++ b/iOS/Article/ArticleViewController.swift @@ -256,6 +256,7 @@ class ArticleViewController: UIViewController { } // MARK: Keyboard Shortcuts + @objc func navigateToTimeline(_ sender: Any?) { coordinator.navigateToTimeline() } @@ -277,7 +278,10 @@ class ArticleViewController: UIViewController { func stopArticleExtractorIfProcessing() { currentWebViewController?.stopArticleExtractorIfProcessing() } - + + func openInAppBrowser() { + currentWebViewController?.openInAppBrowser() + } } // MARK: WebViewControllerDelegate diff --git a/iOS/Article/WebViewController.swift b/iOS/Article/WebViewController.swift index 3483c2079..c08c38ecf 100644 --- a/iOS/Article/WebViewController.swift +++ b/iOS/Article/WebViewController.swift @@ -226,7 +226,15 @@ class WebViewController: UIViewController { activityViewController.popoverPresentationController?.barButtonItem = popOverBarButtonItem present(activityViewController, animated: true) } - + + func openInAppBrowser() { + guard let preferredLink = article?.preferredLink, let url = URL(string: preferredLink) else { + return + } + + let vc = SFSafariViewController(url: url) + present(vc, animated: true) + } } // MARK: ArticleExtractorDelegate diff --git a/iOS/KeyboardManager.swift b/iOS/KeyboardManager.swift index bf0a4c465..9129a4032 100644 --- a/iOS/KeyboardManager.swift +++ b/iOS/KeyboardManager.swift @@ -177,8 +177,8 @@ private extension KeyboardManager { let openInBrowserTitle = NSLocalizedString("Open In Browser", comment: "Open In Browser") keys.append(KeyboardManager.createKeyCommand(title: openInBrowserTitle, action: "openInBrowser:", input: UIKeyCommand.inputRightArrow, modifiers: [.command])) - let openInSafariTitle = NSLocalizedString("Open In Safari", comment: "Open In Safari") - keys.append(KeyboardManager.createKeyCommand(title: openInSafariTitle, action: "openInSafari:", input: "\r", modifiers: [])) + let openInAppBrowserTitle = NSLocalizedString("Open In App Browser", comment: "Open In App Browser") + keys.append(KeyboardManager.createKeyCommand(title: openInAppBrowserTitle, action: "openInAppBrowser:", input: "\r", modifiers: [])) let toggleReadTitle = NSLocalizedString("Toggle Read Status", comment: "Toggle Read Status") keys.append(KeyboardManager.createKeyCommand(title: toggleReadTitle, action: "toggleRead:", input: "u", modifiers: [.command, .shift])) diff --git a/iOS/MasterFeed/MasterFeedViewController.swift b/iOS/MasterFeed/MasterFeedViewController.swift index 1ca161c31..27aa0c9cc 100644 --- a/iOS/MasterFeed/MasterFeedViewController.swift +++ b/iOS/MasterFeed/MasterFeedViewController.swift @@ -11,6 +11,7 @@ import Account import Articles import RSCore import RSTree +import SafariServices class MasterFeedViewController: UITableViewController, UndoableCommandRunner { @@ -420,10 +421,6 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { @objc func openInBrowser(_ sender: Any?) { coordinator.showBrowserForCurrentFeed() } - - @objc func openInSafari(_ sender: Any?) { - coordinator.showSafariForCurrentFeed() - } @objc override func delete(_ sender: Any?) { if let indexPath = coordinator.currentFeedIndexPath { @@ -507,7 +504,14 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { func focus() { becomeFirstResponder() } - + + func openInAppBrowser() { + if let indexPath = coordinator.currentFeedIndexPath, + let url = coordinator.homePageURLForFeed(indexPath) { + let vc = SFSafariViewController(url: url) + present(vc, animated: true) + } + } } // MARK: UIContextMenuInteractionDelegate diff --git a/iOS/RootSplitViewController.swift b/iOS/RootSplitViewController.swift index 1089dbe26..4117a0ee7 100644 --- a/iOS/RootSplitViewController.swift +++ b/iOS/RootSplitViewController.swift @@ -82,8 +82,12 @@ class RootSplitViewController: UISplitViewController { coordinator.showBrowserForCurrentArticle() } - @objc func openInSafari(_ sender: Any?) { - coordinator.showSafariForCurrentArticle() + @objc func openInAppBrowser(_ sender: Any?) { + coordinator.showInAppBrowserForCurrentArticle() + } + + @objc func openFeedInAppBrowser(_ sender: Any?) { + coordinator.showInAppBrowserForCurrentFeed() } @objc func articleSearch(_ sender: Any?) { diff --git a/iOS/SceneCoordinator.swift b/iOS/SceneCoordinator.swift index 93a73fd5c..22d1f30a3 100644 --- a/iOS/SceneCoordinator.swift +++ b/iOS/SceneCoordinator.swift @@ -1185,19 +1185,12 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { UIApplication.shared.open(url, options: [:]) } - func showSafariForCurrentFeed() { - if let ip = currentFeedIndexPath, let url = homePageURLForFeed(ip) { - let vc = SFSafariViewController(url: url) - rootSplitViewController.viewControllers.last?.present(vc, animated: true) - } + func showInAppBrowserForCurrentArticle() { + articleViewController?.openInAppBrowser() } - func showSafariForCurrentArticle() { - guard let preferredLink = currentArticle?.preferredLink, let url = URL(string: preferredLink) else { - return - } - let vc = SFSafariViewController(url: url) - rootSplitViewController.viewControllers.last?.present(vc, animated: true) + func showInAppBrowserForCurrentFeed() { + masterFeedViewController.openInAppBrowser() } func navigateToFeeds() { From 23ee6761ca589ebcff70de0da4a9e2ed4d19d5ae Mon Sep 17 00:00:00 2001 From: Stuart Breckenridge Date: Fri, 15 May 2020 19:53:44 +0800 Subject: [PATCH 3/6] adds grouping and summaries to notifications --- .../UserNotifications/UserNotificationManager.swift | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Shared/UserNotifications/UserNotificationManager.swift b/Shared/UserNotifications/UserNotificationManager.swift index 2f37a2438..aa345bf4a 100644 --- a/Shared/UserNotifications/UserNotificationManager.swift +++ b/Shared/UserNotifications/UserNotificationManager.swift @@ -47,15 +47,21 @@ private extension UserNotificationManager { let content = UNMutableNotificationContent() content.title = webFeed.nameForDisplay - content.body = ArticleStringFormatter.truncatedTitle(article) - if content.body.isEmpty { - content.body = ArticleStringFormatter.truncatedSummary(article) + + if !ArticleStringFormatter.truncatedTitle(article).isEmpty { + content.subtitle = ArticleStringFormatter.truncatedTitle(article) } + + content.body = ArticleStringFormatter.truncatedSummary(article) content.sound = UNNotificationSound.default content.userInfo = [UserInfoKey.articlePath: article.pathUserInfo] + content.threadIdentifier = webFeed.webFeedID + content.summaryArgument = "\(webFeed.nameForDisplay)" + content.summaryArgumentCount = 1 let request = UNNotificationRequest.init(identifier: "articleID:\(article.articleID)", content: content, trigger: nil) + UNUserNotificationCenter.current().add(request) } From fa51fa47b469decb7e46c671761881d19f85c31a Mon Sep 17 00:00:00 2001 From: Stuart Breckenridge Date: Fri, 15 May 2020 20:32:33 +0800 Subject: [PATCH 4/6] reorged the send notification code --- Shared/UserNotifications/UserNotificationManager.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Shared/UserNotifications/UserNotificationManager.swift b/Shared/UserNotifications/UserNotificationManager.swift index aa345bf4a..6ddbad025 100644 --- a/Shared/UserNotifications/UserNotificationManager.swift +++ b/Shared/UserNotifications/UserNotificationManager.swift @@ -53,15 +53,15 @@ private extension UserNotificationManager { } content.body = ArticleStringFormatter.truncatedSummary(article) - - content.sound = UNNotificationSound.default - content.userInfo = [UserInfoKey.articlePath: article.pathUserInfo] + content.threadIdentifier = webFeed.webFeedID content.summaryArgument = "\(webFeed.nameForDisplay)" content.summaryArgumentCount = 1 - - let request = UNNotificationRequest.init(identifier: "articleID:\(article.articleID)", content: content, trigger: nil) + content.sound = UNNotificationSound.default + content.userInfo = [UserInfoKey.articlePath: article.pathUserInfo] + + let request = UNNotificationRequest.init(identifier: "articleID:\(article.articleID)", content: content, trigger: nil) UNUserNotificationCenter.current().add(request) } From 8ff2776d88e342f58649c6630084b7860f686f67 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Fri, 15 May 2020 10:45:05 -0500 Subject: [PATCH 5/6] Make sure we have only one web view in the view hierarchy after navigation. Issue #2075 --- iOS/Article/WebViewController.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/iOS/Article/WebViewController.swift b/iOS/Article/WebViewController.swift index dacd94ced..e7270b919 100644 --- a/iOS/Article/WebViewController.swift +++ b/iOS/Article/WebViewController.swift @@ -60,7 +60,7 @@ class WebViewController: UIViewController { private(set) var article: Article? - let scrollPositionQueue = CoalescingQueue(name: "Article Scroll Position", interval: 0.3, maxInterval: 1.0) + let scrollPositionQueue = CoalescingQueue(name: "Article Scroll Position", interval: 0.3, maxInterval: 0.3) var windowScrollY = 0 override func viewDidLoad() { @@ -291,7 +291,7 @@ extension WebViewController: UIContextMenuInteractionDelegate { extension WebViewController: WKNavigationDelegate { func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { - if view.subviews.count > 1 { + while view.subviews.count > 1 { view.subviews.last?.removeFromSuperview() } } From c2b749a74cd9c7849d697fa3c968d71a9ccbde62 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Fri, 15 May 2020 17:06:49 -0500 Subject: [PATCH 6/6] Rebuild backing stores immediately when deselecting a Feed. Issue #2079 --- iOS/SceneCoordinator.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS/SceneCoordinator.swift b/iOS/SceneCoordinator.swift index 22d1f30a3..a877756ee 100644 --- a/iOS/SceneCoordinator.swift +++ b/iOS/SceneCoordinator.swift @@ -750,7 +750,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { setTimelineFeed(nil, animated: false) { if self.isReadFeedsFiltered { - self.queueRebuildBackingStores() + self.rebuildBackingStores() } self.activityManager.invalidateSelecting() if self.rootSplitViewController.isCollapsed && self.navControllerForTimeline().viewControllers.last is MasterTimelineViewController {