Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto-scrolling for wide HTML content #571

Merged
merged 2 commits into from
Nov 25, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -3,6 +3,8 @@ import SnapKit
import UIKit
import WebKit

// MARK: ProcessedContentTextViewDelegate: class -

protocol ProcessedContentTextViewDelegate: class {
func processedContentTextViewDidLoadContent(_ view: ProcessedContentTextView)
func processedContentTextView(_ view: ProcessedContentTextView, didReportNewHeight height: Int)
@@ -14,13 +16,17 @@ extension ProcessedContentTextViewDelegate {
func processedContentTextView(_ view: ProcessedContentTextView, didReportNewHeight height: Int) { }
}

// MARK: - Appearance -

extension ProcessedContentTextView {
struct Appearance {
var insets = LayoutInsets(top: 10, left: 16, bottom: 4, right: 16)
var backgroundColor = UIColor.white
}
}

// MARK: - ProcessedContentTextView: UIView -

final class ProcessedContentTextView: UIView {
private static let reloadTimeStandardInterval: TimeInterval = 0.5
private static let reloadTimeout: TimeInterval = 10.0
@@ -90,6 +96,12 @@ final class ProcessedContentTextView: UIView {
)
}

/// A Boolean value that determines whether auto-scrolling is enabled.
///
/// If the value of this property is `true`, auto-scrolling is enabled and view will enable scrolling for wider content than webView's size,
/// and if it is `false`, auto-scrolling is disabled.
var isAutoScrollingEnabled = true

var isScrollEnabled: Bool {
get {
return self.webView.scrollView.isScrollEnabled
@@ -211,8 +223,42 @@ final class ProcessedContentTextView: UIView {
self?.fetchHeightWithInterval(count + 1)
}
}

private func getContentWidth() -> Guarantee<Int> {
return Guarantee { seal in
self.webView.evaluateJavaScript("document.body.scrollWidth;") { res, _ in
if let width = res as? Int {
seal(width)
return
}
seal(0)
}
}
}

private func fetchWidthWithInterval(_ count: Int = 0) {
let currentTime = TimeInterval(count) * ProcessedContentTextView.reloadTimeStandardInterval
guard currentTime <= ProcessedContentTextView.reloadTimeout else {
return
}

DispatchQueue.main.asyncAfter(deadline: .now() + currentTime) { [weak self] in
guard let strongSelf = self else {
return
}

strongSelf.getContentWidth().done { width in
if strongSelf.isAutoScrollingEnabled {
strongSelf.isScrollEnabled = CGFloat(width) > strongSelf.webView.bounds.size.width
}
}
strongSelf.fetchWidthWithInterval(count + 1)
}
}
}

// MARK: - ProcessedContentTextView: ProgrammaticallyInitializableViewProtocol -

extension ProcessedContentTextView: ProgrammaticallyInitializableViewProtocol {
func addSubviews() {
self.addSubview(self.webView)
@@ -230,6 +276,8 @@ extension ProcessedContentTextView: ProgrammaticallyInitializableViewProtocol {
}
}

// MARK: - ProcessedContentTextView: WKNavigationDelegate -

extension ProcessedContentTextView: WKNavigationDelegate {
// swiftlint:disable:next implicitly_unwrapped_optional
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
@@ -252,6 +300,7 @@ extension ProcessedContentTextView: WKNavigationDelegate {
}

self.fetchHeightWithInterval()
self.fetchWidthWithInterval()
}
}

@@ -288,6 +337,8 @@ extension ProcessedContentTextView: WKNavigationDelegate {
}
}

// MARK: - ProcessedContentTextView: UIScrollViewDelegate -

extension ProcessedContentTextView: UIScrollViewDelegate {
// swiftlint:disable:next identifier_name
func viewForZooming(in: UIScrollView) -> UIView? {