diff --git a/Shared/Resources/GlobalKeyboardShortcuts.plist b/Shared/Resources/GlobalKeyboardShortcuts.plist index 4c6f3662c..88e4eac90 100644 --- a/Shared/Resources/GlobalKeyboardShortcuts.plist +++ b/Shared/Resources/GlobalKeyboardShortcuts.plist @@ -106,11 +106,11 @@ title - Open in Browser + Open in App Browser key [return] action - openInBrowser: + openFeedInAppBrowser: key diff --git a/Shared/UserNotifications/UserNotificationManager.swift b/Shared/UserNotifications/UserNotificationManager.swift index 2f37a2438..6ddbad025 100644 --- a/Shared/UserNotifications/UserNotificationManager.swift +++ b/Shared/UserNotifications/UserNotificationManager.swift @@ -47,14 +47,20 @@ 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.threadIdentifier = webFeed.webFeedID + content.summaryArgument = "\(webFeed.nameForDisplay)" + content.summaryArgumentCount = 1 + 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) } 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 e7270b919..83dba122d 100644 --- a/iOS/Article/WebViewController.swift +++ b/iOS/Article/WebViewController.swift @@ -227,7 +227,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 c463fcde2..9129a4032 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 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 accf4b67e..57babb007 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 { @@ -458,7 +459,18 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { self.reloadAllVisibleCells() } } - + + @objc func markAllAsRead(_ sender: Any) { + guard let indexPath = tableView.indexPathForSelectedRow, let contentView = tableView.cellForRow(at: indexPath)?.contentView else { + return + } + + let title = NSLocalizedString("Mark All as Read", comment: "Mark All as Read") + MarkAsReadAlertController.confirm(self, coordinator: coordinator, confirmTitle: title, sourceType: contentView) { [weak self] in + self?.coordinator.markAllAsReadInTimeline() + } + } + // MARK: API func restoreSelectionIfNecessary(adjustScroll: Bool) { @@ -503,7 +515,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 33bd740c1..4117a0ee7 100644 --- a/iOS/RootSplitViewController.swift +++ b/iOS/RootSplitViewController.swift @@ -81,6 +81,14 @@ class RootSplitViewController: UISplitViewController { @objc func openInBrowser(_ sender: Any?) { coordinator.showBrowserForCurrentArticle() } + + @objc func openInAppBrowser(_ sender: Any?) { + coordinator.showInAppBrowserForCurrentArticle() + } + + @objc func openFeedInAppBrowser(_ sender: Any?) { + coordinator.showInAppBrowserForCurrentFeed() + } @objc func articleSearch(_ sender: Any?) { coordinator.showSearch() diff --git a/iOS/SceneCoordinator.swift b/iOS/SceneCoordinator.swift index 64abb8d3d..22d1f30a3 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,14 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { } UIApplication.shared.open(url, options: [:]) } + + func showInAppBrowserForCurrentArticle() { + articleViewController?.openInAppBrowser() + } + + func showInAppBrowserForCurrentFeed() { + masterFeedViewController.openInAppBrowser() + } func navigateToFeeds() { masterFeedViewController?.focus()