From 85e0a9739d42e19226033ac1cdff2e9b6662d9cd Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Wed, 20 Dec 2017 13:39:31 -0800 Subject: [PATCH] Implement scrollOrGoToNextUnread. --- .../Detail/DetailViewController.swift | 66 +++++++++++++++++++ .../MainWindow/MainWindowController.swift | 16 ++--- 2 files changed, 73 insertions(+), 9 deletions(-) diff --git a/Evergreen/MainWindow/Detail/DetailViewController.swift b/Evergreen/MainWindow/Detail/DetailViewController.swift index eda8aa6a7..f54dc1ee5 100644 --- a/Evergreen/MainWindow/Detail/DetailViewController.swift +++ b/Evergreen/MainWindow/Detail/DetailViewController.swift @@ -26,6 +26,10 @@ final class DetailViewController: NSViewController, WKNavigationDelegate, WKUIDe } } + private var webviewIsHidden: Bool { + return containerView.contentView !== webview + } + private struct MessageName { static let mouseDidEnter = "mouseDidEnter" static let mouseDidExit = "mouseDidExit" @@ -65,6 +69,28 @@ final class DetailViewController: NSViewController, WKNavigationDelegate, WKUIDe showOrHideWebView() } + // MARK: - Scrolling + + func canScrollDown(_ callback: @escaping (Bool) -> Void) { + + if webviewIsHidden { + callback(false) + return + } + + fetchScrollInfo { (scrollInfo) in + callback(scrollInfo?.canScrollDown ?? false) + } + } + + override func scrollPageDown(_ sender: Any?) { + + guard !webviewIsHidden else { + return + } + webview.scrollPageDown(sender) + } + // MARK: Notifications @objc func timelineSelectionDidChange(_ notification: Notification) { @@ -174,6 +200,28 @@ extension DetailViewController: WKScriptMessageHandler { } } +private extension DetailViewController { + + func fetchScrollInfo(_ callback: @escaping (ScrollInfo?) -> Void) { + + let javascriptString = "var x = {contentHeight: document.body.scrollHeight, offsetY: document.body.scrollTop}; x" + webview.evaluateJavaScript(javascriptString) { (info, error) in + + guard let info = info as? [String: Any] else { + callback(nil) + return + } + guard let contentHeight = info["contentHeight"] as? CGFloat, let offsetY = info["offsetY"] as? CGFloat else { + callback(nil) + return + } + + let scrollInfo = ScrollInfo(contentHeight: contentHeight, viewHeight: self.webview.frame.height, offsetY: offsetY) + callback(scrollInfo) + } + } +} + final class DetailContainerView: NSView { weak var viewController: DetailViewController? = nil @@ -241,3 +289,21 @@ final class NoSelectionView: NSView { } } +private struct ScrollInfo { + + let contentHeight: CGFloat + let viewHeight: CGFloat + let offsetY: CGFloat + let canScrollDown: Bool + let canScrollUp: Bool + + init(contentHeight: CGFloat, viewHeight: CGFloat, offsetY: CGFloat) { + + self.contentHeight = contentHeight + self.viewHeight = viewHeight + self.offsetY = offsetY + + self.canScrollDown = viewHeight + offsetY < contentHeight + self.canScrollUp = offsetY > 0.1 + } +} diff --git a/Evergreen/MainWindow/MainWindowController.swift b/Evergreen/MainWindow/MainWindowController.swift index a6b3ea5b0..512392f86 100644 --- a/Evergreen/MainWindow/MainWindowController.swift +++ b/Evergreen/MainWindow/MainWindowController.swift @@ -122,16 +122,14 @@ class MainWindowController : NSWindowController, NSUserInterfaceValidations { @IBAction func scrollOrGoToNextUnread(_ sender: Any?) { -// guard let detailViewController = detailViewController else { -// return -// } -// -// if detailViewController.canScrollWebView() { -// detailViewController.scrollPageDown(sender) -// return -// } + guard let detailViewController = detailViewController else { + return + } - nextUnread(sender) + detailViewController.canScrollDown { (canScroll) in + + canScroll ? detailViewController.scrollPageDown(sender) : self.nextUnread(sender) + } }