From 5acce87995db91934474845fe93cb3dae189ec53 Mon Sep 17 00:00:00 2001 From: Nate Weaver Date: Fri, 10 Jul 2020 13:33:25 -0500 Subject: [PATCH 1/2] Mac: Make shift-space scroll up even when the detail view doesn't have focus Issue #969. --- Mac/MainWindow/Detail/DetailViewController.swift | 8 ++++++++ Mac/MainWindow/Detail/DetailWebViewController.swift | 10 ++++++++++ Mac/MainWindow/MainWindowController.swift | 13 +++++++++++++ Shared/Resources/GlobalKeyboardShortcuts.plist | 10 ++++++++++ 4 files changed, 41 insertions(+) diff --git a/Mac/MainWindow/Detail/DetailViewController.swift b/Mac/MainWindow/Detail/DetailViewController.swift index c7d2c2497..63e632b21 100644 --- a/Mac/MainWindow/Detail/DetailViewController.swift +++ b/Mac/MainWindow/Detail/DetailViewController.swift @@ -66,9 +66,17 @@ final class DetailViewController: NSViewController, WKUIDelegate { currentWebViewController.canScrollDown(callback) } + func canScrollUp(_ callback: @escaping (Bool) -> Void) { + currentWebViewController.canScrollUp(callback) + } + override func scrollPageDown(_ sender: Any?) { currentWebViewController.scrollPageDown(sender) } + + override func scrollPageUp(_ sender: Any?) { + currentWebViewController.scrollPageUp(sender) + } // MARK: - Navigation diff --git a/Mac/MainWindow/Detail/DetailWebViewController.swift b/Mac/MainWindow/Detail/DetailWebViewController.swift index e77101f9d..e75b8f71a 100644 --- a/Mac/MainWindow/Detail/DetailWebViewController.swift +++ b/Mac/MainWindow/Detail/DetailWebViewController.swift @@ -167,9 +167,19 @@ final class DetailWebViewController: NSViewController, WKUIDelegate { } } + func canScrollUp(_ completion: @escaping (Bool) -> Void) { + fetchScrollInfo { (scrollInfo) in + completion(scrollInfo?.canScrollUp ?? false) + } + } + override func scrollPageDown(_ sender: Any?) { webView.scrollPageDown(sender) } + + override func scrollPageUp(_ sender: Any?) { + webView.scrollPageUp(sender) + } } // MARK: - WKScriptMessageHandler diff --git a/Mac/MainWindow/MainWindowController.swift b/Mac/MainWindow/MainWindowController.swift index eab97ca16..e79300644 100644 --- a/Mac/MainWindow/MainWindowController.swift +++ b/Mac/MainWindow/MainWindowController.swift @@ -264,6 +264,19 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations { } } + @IBAction func scrollUp(_ sender: Any?) { + guard let detailViewController = detailViewController else { + return + } + detailViewController.canScrollUp { (canScroll) in + if (canScroll) { + NSCursor.setHiddenUntilMouseMoves(true) + detailViewController.scrollPageUp(sender) + } + } + + } + @IBAction func openArticleInBrowser(_ sender: Any?) { if let link = currentLink { Browser.open(link, invertPreference: NSApp.currentEvent?.modifierFlags.contains(.shift) ?? false) diff --git a/Shared/Resources/GlobalKeyboardShortcuts.plist b/Shared/Resources/GlobalKeyboardShortcuts.plist index c6288be02..4c2626cbe 100644 --- a/Shared/Resources/GlobalKeyboardShortcuts.plist +++ b/Shared/Resources/GlobalKeyboardShortcuts.plist @@ -10,6 +10,16 @@ action scrollOrGoToNextUnread: + + title + Scroll or Go to Next Unread + key + [space] + shiftModifier + + action + scrollUp: + title Go to Previous Unread From 82f7f9982711ba6878ba926ae5f69fdd6a216c6a Mon Sep 17 00:00:00 2001 From: Nate Weaver Date: Fri, 10 Jul 2020 13:51:41 -0500 Subject: [PATCH 2/2] iOS: Make shift-space scroll up even when the detail view doesn't have focus --- iOS/Article/ArticleViewController.swift | 8 +++++ iOS/Article/WebViewController.swift | 39 ++++++++++++++++++------- iOS/RootSplitViewController.swift | 4 +++ iOS/SceneCoordinator.swift | 6 ++++ 4 files changed, 47 insertions(+), 10 deletions(-) diff --git a/iOS/Article/ArticleViewController.swift b/iOS/Article/ArticleViewController.swift index ddd32ad4a..edb416034 100644 --- a/iOS/Article/ArticleViewController.swift +++ b/iOS/Article/ArticleViewController.swift @@ -293,9 +293,17 @@ class ArticleViewController: UIViewController { return currentWebViewController?.canScrollDown() ?? false } + func canScrollUp() -> Bool { + return currentWebViewController?.canScrollUp() ?? false + } + func scrollPageDown() { currentWebViewController?.scrollPageDown() } + + func scrollPageUp() { + currentWebViewController?.scrollPageUp() + } func stopArticleExtractorIfProcessing() { currentWebViewController?.stopArticleExtractorIfProcessing() diff --git a/iOS/Article/WebViewController.swift b/iOS/Article/WebViewController.swift index 530443e2a..b8dba43e7 100644 --- a/iOS/Article/WebViewController.swift +++ b/iOS/Article/WebViewController.swift @@ -123,24 +123,38 @@ class WebViewController: UIViewController { func canScrollDown() -> Bool { guard let webView = webView else { return false } - return webView.scrollView.contentOffset.y < finalScrollPosition() + return webView.scrollView.contentOffset.y < finalScrollPosition(scrollingUp: false) } - func scrollPageDown() { + func canScrollUp() -> Bool { + guard let webView = webView else { return false } + return webView.scrollView.contentOffset.y > finalScrollPosition(scrollingUp: true) + } + + private func scrollPage(up scrollingUp: Bool) { guard let webView = webView else { return } - + let overlap = 2 * UIFont.systemFont(ofSize: UIFont.systemFontSize).lineHeight * UIScreen.main.scale let scrollToY: CGFloat = { - let fullScroll = webView.scrollView.contentOffset.y + webView.scrollView.layoutMarginsGuide.layoutFrame.height - overlap - let final = finalScrollPosition() - return fullScroll < final ? fullScroll : final + let scrollDistance = webView.scrollView.layoutMarginsGuide.layoutFrame.height - overlap; + let fullScroll = webView.scrollView.contentOffset.y + (scrollingUp ? -scrollDistance : scrollDistance) + let final = finalScrollPosition(scrollingUp: scrollingUp) + return (scrollingUp ? fullScroll > final : fullScroll < final) ? fullScroll : final }() - + let convertedPoint = self.view.convert(CGPoint(x: 0, y: 0), to: webView.scrollView) let scrollToPoint = CGPoint(x: convertedPoint.x, y: scrollToY) webView.scrollView.setContentOffset(scrollToPoint, animated: true) } - + + func scrollPageDown() { + scrollPage(up: false) + } + + func scrollPageUp() { + scrollPage(up: true) + } + func hideClickedImage() { webView?.evaluateJavaScript("hideClickedImage();") } @@ -539,9 +553,14 @@ private extension WebViewController { } - func finalScrollPosition() -> CGFloat { + func finalScrollPosition(scrollingUp: Bool) -> CGFloat { guard let webView = webView else { return 0 } - return webView.scrollView.contentSize.height - webView.scrollView.bounds.height + webView.scrollView.safeAreaInsets.bottom + + if scrollingUp { + return -webView.scrollView.safeAreaInsets.top + } else { + return webView.scrollView.contentSize.height - webView.scrollView.bounds.height + webView.scrollView.safeAreaInsets.bottom + } } func startArticleExtractor() { diff --git a/iOS/RootSplitViewController.swift b/iOS/RootSplitViewController.swift index 248436129..28d9eb885 100644 --- a/iOS/RootSplitViewController.swift +++ b/iOS/RootSplitViewController.swift @@ -35,6 +35,10 @@ class RootSplitViewController: UISplitViewController { @objc func scrollOrGoToNextUnread(_ sender: Any?) { coordinator.scrollOrGoToNextUnread() } + + @objc func scrollUp(_ sender: Any?) { + coordinator.scrollUp() + } @objc func goToPreviousUnread(_ sender: Any?) { coordinator.selectPrevUnread() diff --git a/iOS/SceneCoordinator.swift b/iOS/SceneCoordinator.swift index 6c67bca5d..8522c097c 100644 --- a/iOS/SceneCoordinator.swift +++ b/iOS/SceneCoordinator.swift @@ -990,6 +990,12 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { selectNextUnread() } } + + func scrollUp() { + if articleViewController?.canScrollUp() ?? false { + articleViewController?.scrollPageUp() + } + } func markAllAsRead(_ articles: [Article]) { markArticlesWithUndo(articles, statusKey: .read, flag: true)