From 82f7f9982711ba6878ba926ae5f69fdd6a216c6a Mon Sep 17 00:00:00 2001 From: Nate Weaver Date: Fri, 10 Jul 2020 13:51:41 -0500 Subject: [PATCH] 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)