From f7d524eafa970143575cfabe280ea472e799d947 Mon Sep 17 00:00:00 2001 From: iaomw Date: Thu, 9 Aug 2018 18:16:20 +0200 Subject: [PATCH 01/23] Fix a crash issue for over-released --- r2-navigator-swift/TriptychView.swift | 3 +-- r2-navigator-swift/WebView.swift | 27 +++++++++++---------------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/r2-navigator-swift/TriptychView.swift b/r2-navigator-swift/TriptychView.swift index dc2eb7b7..4da754e8 100644 --- a/r2-navigator-swift/TriptychView.swift +++ b/r2-navigator-swift/TriptychView.swift @@ -253,7 +253,6 @@ final class TriptychView: UIView { views = Views.two(firstView: firstView, secondView: secondView) } default: - let currentView = viewForIndex(index, location: leading) if index == 0 { self.views = Views.many( currentView: viewForIndex(index, location: leading), @@ -266,7 +265,7 @@ final class TriptychView: UIView { viewForIndex(index - 1, location: leading))) } else { views = Views.many( - currentView: currentView, + currentView: viewForIndex(index, location: leading), otherViews: Disjunction.both( first: viewForIndex(index - 1, location: trailing), second: viewForIndex(index + 1, location: leading))) diff --git a/r2-navigator-swift/WebView.swift b/r2-navigator-swift/WebView.swift index a34cd1fc..fc3215f7 100644 --- a/r2-navigator-swift/WebView.swift +++ b/r2-navigator-swift/WebView.swift @@ -81,6 +81,8 @@ final class WebView: WKWebView { } } } + + var sizeObservation: NSKeyValueObservation? init(frame: CGRect, initialLocation: BinaryLocation) { self.initialLocation = initialLocation @@ -96,22 +98,15 @@ final class WebView: WKWebView { scrollView.showsVerticalScrollIndicator = false navigationDelegate = self - scrollView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil) - } - - deinit { - scrollView.removeObserver(self, forKeyPath: "contentSize", context: nil) - } - - override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { - if keyPath == "contentSize" { - if let value = change?[NSKeyValueChangeKey.newKey] as? CGSize { - // update total pages - let pageCount = Int(value.width / scrollView.frame.size.width); - if totalPages != pageCount { - totalPages = pageCount - viewDelegate?.documentPageDidChanged(webview: self, currentPage: currentPage(), totalPage: pageCount) - } + sizeObservation = scrollView.observe(\.contentSize, options: .new) { (thisScrollView, thisValue) in + // update total pages + guard let newWidth = thisValue.newValue?.width else {return} + let pageWidth = self.scrollView.frame.size.width + if pageWidth == 0.0 {return} // Possible zero value + let pageCount = Int(newWidth / self.scrollView.frame.size.width); + if self.totalPages != pageCount { + self.totalPages = pageCount + self.viewDelegate?.documentPageDidChanged(webview: self, currentPage: self.currentPage(), totalPage: pageCount) } } } From 218aff232a86639d79898c58150997c7d6333a84 Mon Sep 17 00:00:00 2001 From: iaomw Date: Tue, 21 Aug 2018 10:28:12 +0200 Subject: [PATCH 02/23] Remove unused property --- r2-navigator-swift/NavigatorViewController.swift | 1 - r2-navigator-swift/UserSettings.swift | 1 - 2 files changed, 2 deletions(-) diff --git a/r2-navigator-swift/NavigatorViewController.swift b/r2-navigator-swift/NavigatorViewController.swift index ff3878c1..1aba7c46 100644 --- a/r2-navigator-swift/NavigatorViewController.swift +++ b/r2-navigator-swift/NavigatorViewController.swift @@ -49,7 +49,6 @@ open class NavigatorViewController: UIViewController { self.initialProgression = initialProgression userSettings = UserSettings() publication.userProperties.properties = userSettings.userProperties.properties - userSettings.userSettingsUIPreset = publication.userSettingsUIPreset delegatee = Delegatee() var index = initialIndex diff --git a/r2-navigator-swift/UserSettings.swift b/r2-navigator-swift/UserSettings.swift index aac20014..9735b86d 100644 --- a/r2-navigator-swift/UserSettings.swift +++ b/r2-navigator-swift/UserSettings.swift @@ -35,7 +35,6 @@ public class UserSettings { private var pageMargins: Float = 1 private var lineHeight: Float = 1 - public var userSettingsUIPreset: [ReadiumCSSName: Bool]? public let userProperties = UserProperties() private let userDefaults = UserDefaults.standard From 485adca7426b536520fdfb33d552eb5856707a78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ullstro=CC=88m?= Date: Thu, 27 Sep 2018 15:19:55 +0200 Subject: [PATCH 03/23] Add fadeIn on document load, fade animation when tapping between documents, and scroll animation for tap paging inside document --- .../NavigatorViewController.swift | 27 +++++++++++-- r2-navigator-swift/WebView.swift | 39 +++++++++++++++++++ 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/r2-navigator-swift/NavigatorViewController.swift b/r2-navigator-swift/NavigatorViewController.swift index 1aba7c46..42fbc056 100644 --- a/r2-navigator-swift/NavigatorViewController.swift +++ b/r2-navigator-swift/NavigatorViewController.swift @@ -105,7 +105,9 @@ extension NavigatorViewController { guard publication.spine.indices.contains(index) else { return } - triptychView.moveTo(index: index) + fadeInOutTriptychView { + self.triptychView.moveTo(index: index) + } } /// Display the spine item at `index` with scroll `progression` @@ -135,7 +137,9 @@ extension NavigatorViewController { let id = (components.count > 1 ? components.last : "") // Jumping set to true to avoid clamping. - triptychView.moveTo(index: index, id: id) + fadeInOutTriptychView { + self.triptychView.moveTo(index: index, id: id) + } } public func getSpine() -> [Link] { @@ -168,13 +172,13 @@ extension NavigatorViewController: ViewDelegate { /// Display next spine item (spine item). public func displayRightDocument() { let delta = triptychView.direction == .rtl ? -1:1 - displaySpineItem(at: triptychView.index + delta) + self.displaySpineItem(at: self.triptychView.index + delta) } /// Display previous document (spine item). public func displayLeftDocument() { let delta = triptychView.direction == .rtl ? -1:1 - displaySpineItem(at: triptychView.index - delta) + self.displaySpineItem(at: self.triptychView.index - delta) } /// Returns the currently presented Publication's identifier. @@ -248,3 +252,18 @@ extension Delegatee: TriptychViewDelegate { } } + +extension NavigatorViewController { + + func fadeInOutTriptychView(becameHidden: @escaping () -> ()) { + UIView.animate(withDuration: 0.3, animations: { + self.triptychView.alpha = 0 + }) { (_) in + becameHidden() + UIView.animate(withDuration: 0.3, animations: { + self.triptychView.alpha = 1 + }) + } + } +} + diff --git a/r2-navigator-swift/WebView.swift b/r2-navigator-swift/WebView.swift index fc3215f7..94d7f059 100644 --- a/r2-navigator-swift/WebView.swift +++ b/r2-navigator-swift/WebView.swift @@ -63,6 +63,18 @@ final class WebView: WKWebView { case right func proceed(on target: WebView) { + let scrollView = target.scrollView + if scrollView.isPagingEnabled { + switch self { + case .left: + let isAtFirstPageInDocument = scrollView.contentOffset.x == 0 + if !isAtFirstPageInDocument { return scrollView.scrollToPreviousPage() } + case .right: + let isAtLastPageInDocument = scrollView.contentOffset.x == scrollView.contentSize.width - scrollView.frame.size.width + if !isAtLastPageInDocument { return scrollView.scrollToNextPage() } + } + } + let dir = target.direction?.rawValue ?? PageProgressionDirection.ltr.rawValue switch self { @@ -109,6 +121,8 @@ final class WebView: WKWebView { self.viewDelegate?.documentPageDidChanged(webview: self, currentPage: self.currentPage(), totalPage: pageCount) } } + + self.alpha = 0 } @available(*, unavailable) @@ -172,6 +186,9 @@ extension WebView { /// - Parameter body: Unused. internal func documentDidLoad(body: String) { documentLoaded = true + UIView.animate(withDuration: 0.3, animations: { + self.alpha = 1 + }) applyUserSettingsStyle() scrollToInitialPosition() } @@ -332,3 +349,25 @@ extension WebView: UIScrollViewDelegate { } } + +extension UIScrollView { + + func scrollToNextPage() { + //FIXME: Fix bug with getting stuck between two pages + var newOffset = contentOffset + let incr = bounds.size.width + newOffset.x += incr + let area = CGRect.init(origin: newOffset, size: bounds.size) + scrollRectToVisible(area, animated: true) + } + + func scrollToPreviousPage() { + //FIXME: Fix bug with getting stuck between two pages + var newOffset = contentOffset + let incr = bounds.size.width + newOffset.x -= incr + let area = CGRect.init(origin: newOffset, size: bounds.size) + scrollRectToVisible(area, animated: true) + } +} + From e5daa86f219bdc2d23f539f5f7f678834ee9442b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ullstro=CC=88m?= Date: Thu, 27 Sep 2018 16:02:40 +0200 Subject: [PATCH 04/23] Fix paging bug --- r2-navigator-swift/WebView.swift | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/r2-navigator-swift/WebView.swift b/r2-navigator-swift/WebView.swift index 94d7f059..75d6806e 100644 --- a/r2-navigator-swift/WebView.swift +++ b/r2-navigator-swift/WebView.swift @@ -353,19 +353,18 @@ extension WebView: UIScrollViewDelegate { extension UIScrollView { func scrollToNextPage() { - //FIXME: Fix bug with getting stuck between two pages - var newOffset = contentOffset - let incr = bounds.size.width - newOffset.x += incr - let area = CGRect.init(origin: newOffset, size: bounds.size) - scrollRectToVisible(area, animated: true) + moveHorizontalContent(with: bounds.size.width) } func scrollToPreviousPage() { - //FIXME: Fix bug with getting stuck between two pages + moveHorizontalContent(with: -bounds.size.width) + } + + private func moveHorizontalContent(with offsetX: CGFloat) { var newOffset = contentOffset - let incr = bounds.size.width - newOffset.x -= incr + newOffset.x += offsetX + let rounded = round(newOffset.x / offsetX) * offsetX + newOffset.x = rounded let area = CGRect.init(origin: newOffset, size: bounds.size) scrollRectToVisible(area, animated: true) } From f510e88dc64a8a517a99e47c0972727d0e23fa2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ullstro=CC=88m?= Date: Thu, 27 Sep 2018 16:51:03 +0200 Subject: [PATCH 05/23] Fix bug with not always getting document load-callback from javascript --- r2-navigator-swift/TriptychView.swift | 8 +++++--- r2-navigator-swift/WebView.swift | 24 ++++++++++++++++++++---- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/r2-navigator-swift/TriptychView.swift b/r2-navigator-swift/TriptychView.swift index 4da754e8..6b65dee5 100644 --- a/r2-navigator-swift/TriptychView.swift +++ b/r2-navigator-swift/TriptychView.swift @@ -279,10 +279,8 @@ final class TriptychView: UIView { } private func syncSubviews() { + let webViewsBefore = scrollView.subviews.compactMap { $0 as? WebView } scrollView.subviews.forEach({ - if let webview = ($0 as? WebView) { - webview.removeMessageHandlers() - } $0.removeFromSuperview() }) @@ -294,6 +292,10 @@ final class TriptychView: UIView { self.scrollView.addSubview($0) }) } + + webViewsBefore.forEach { + if $0.superview == nil { $0.removeMessageHandlers() } + } } } diff --git a/r2-navigator-swift/WebView.swift b/r2-navigator-swift/WebView.swift index 75d6806e..5b7df0c9 100644 --- a/r2-navigator-swift/WebView.swift +++ b/r2-navigator-swift/WebView.swift @@ -48,6 +48,7 @@ final class WebView: WKWebView { public var presentingFixedLayoutContent = false // TMP fix for fxl. + var hasLoadedJsEvents = false let jsEvents = ["leftTap": leftTapped, "centerTap": centerTapped, "rightTap": rightTapped, @@ -186,9 +187,9 @@ extension WebView { /// - Parameter body: Unused. internal func documentDidLoad(body: String) { documentLoaded = true - UIView.animate(withDuration: 0.3, animations: { - self.alpha = 1 - }) + + fadeInWithDelay() + applyUserSettingsStyle() scrollToInitialPosition() } @@ -288,10 +289,12 @@ extension WebView: WKScriptMessageHandler { /// Add a message handler for incoming javascript events. internal func addMessageHandlers() { + if hasLoadedJsEvents { return } // Add the message handlers. for eventName in jsEvents.keys { configuration.userContentController.add(self, name: eventName) } + hasLoadedJsEvents = true } // Deinit message handlers (preventing strong reference cycle). @@ -299,6 +302,7 @@ extension WebView: WKScriptMessageHandler { for eventName in jsEvents.keys { configuration.userContentController.removeScriptMessageHandler(forName: eventName) } + hasLoadedJsEvents = false } } @@ -350,7 +354,7 @@ extension WebView: UIScrollViewDelegate { } -extension UIScrollView { +private extension UIScrollView { func scrollToNextPage() { moveHorizontalContent(with: bounds.size.width) @@ -370,3 +374,15 @@ extension UIScrollView { } } +private extension UIView { + + func fadeInWithDelay() { + //We need to give the CSS and webview time to layout correctly. :( 0.2 seconds seems like a good value for it to work on an iPhone 5s. + DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { + UIView.animate(withDuration: 0.3, animations: { + self.alpha = 1 + }) + } + } +} + From 07a39fc0ad060dde26c2e7d2cef6985057b8e567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ullstro=CC=88m?= Date: Mon, 1 Oct 2018 10:31:07 +0200 Subject: [PATCH 06/23] Tweak fade time in Navigator --- Cartfile.resolved | 4 ++-- r2-navigator-swift/NavigatorViewController.swift | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cartfile.resolved b/Cartfile.resolved index d1d15042..4f6279cb 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,2 +1,2 @@ -github "Hearst-DD/ObjectMapper" "2.2.0" -github "Readium/r2-shared-swift" "07f5fe26381e0980925f7a16e8c05a1c7455ea45" +github "BookBeat/r2-shared-swift" "54bea7b9da2980da197b1b9208a0ef2f7c46c606" +github "Hearst-DD/ObjectMapper" "3.3.0" diff --git a/r2-navigator-swift/NavigatorViewController.swift b/r2-navigator-swift/NavigatorViewController.swift index 42fbc056..35bd80d3 100644 --- a/r2-navigator-swift/NavigatorViewController.swift +++ b/r2-navigator-swift/NavigatorViewController.swift @@ -256,11 +256,11 @@ extension Delegatee: TriptychViewDelegate { extension NavigatorViewController { func fadeInOutTriptychView(becameHidden: @escaping () -> ()) { - UIView.animate(withDuration: 0.3, animations: { + UIView.animate(withDuration: 0.15, animations: { self.triptychView.alpha = 0 }) { (_) in becameHidden() - UIView.animate(withDuration: 0.3, animations: { + UIView.animate(withDuration: 0.15, animations: { self.triptychView.alpha = 1 }) } From 3d015a594cfd0ea922d210dcd8a6e54ed89c25e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ullstro=CC=88m?= Date: Fri, 5 Oct 2018 15:19:44 +0200 Subject: [PATCH 07/23] Use clear background color as standard for TriptychView and NavigatorViewController --- r2-navigator-swift/NavigatorViewController.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/r2-navigator-swift/NavigatorViewController.swift b/r2-navigator-swift/NavigatorViewController.swift index 35bd80d3..7ee04a6b 100644 --- a/r2-navigator-swift/NavigatorViewController.swift +++ b/r2-navigator-swift/NavigatorViewController.swift @@ -71,6 +71,8 @@ open class NavigatorViewController: UIViewController { open override func viewDidLoad() { super.viewDidLoad() delegatee.parent = self + view.backgroundColor = .clear + triptychView.backgroundColor = .clear triptychView.delegate = delegatee triptychView.frame = view.bounds triptychView.autoresizingMask = [.flexibleHeight, .flexibleWidth] From fe7f1d1eb5fbbc2768948bb0e77edd04904d0792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ullstro=CC=88m?= Date: Mon, 8 Oct 2018 17:11:22 +0200 Subject: [PATCH 08/23] Fix bug with emitting page changes while the WebView is loading the document --- r2-navigator-swift/WebView.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/r2-navigator-swift/WebView.swift b/r2-navigator-swift/WebView.swift index 5b7df0c9..8187c7df 100644 --- a/r2-navigator-swift/WebView.swift +++ b/r2-navigator-swift/WebView.swift @@ -113,6 +113,7 @@ final class WebView: WKWebView { sizeObservation = scrollView.observe(\.contentSize, options: .new) { (thisScrollView, thisValue) in // update total pages + guard self.documentLoaded else { return } guard let newWidth = thisValue.newValue?.width else {return} let pageWidth = self.scrollView.frame.size.width if pageWidth == 0.0 {return} // Possible zero value From 1eebefc561d0084c17e1c528752e4d413281b6b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ullstro=CC=88m?= Date: Mon, 15 Oct 2018 16:50:05 +0200 Subject: [PATCH 09/23] Fix bug with not jumping to progression in webview if it was not loaded into the triptych-view --- r2-navigator-swift/NavigatorViewController.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/r2-navigator-swift/NavigatorViewController.swift b/r2-navigator-swift/NavigatorViewController.swift index 7ee04a6b..648aa659 100644 --- a/r2-navigator-swift/NavigatorViewController.swift +++ b/r2-navigator-swift/NavigatorViewController.swift @@ -116,6 +116,7 @@ extension NavigatorViewController { /// /// - Parameter index: The index of the spine item to display. public func displaySpineItem(at index: Int, progression: Double) { + self.initialProgression = progression //This is so the webview will move to it's correct progression displaySpineItem(at: index) if let webView = triptychView.currentView as? WebView { webView.scrollAt(position: progression) From 867acc18350f3f705da4ee7408d6a940791f06a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ullstro=CC=88m?= Date: Tue, 16 Oct 2018 08:49:30 +0200 Subject: [PATCH 10/23] Fix animation bug when changing spine item with progression --- r2-navigator-swift/NavigatorViewController.swift | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/r2-navigator-swift/NavigatorViewController.swift b/r2-navigator-swift/NavigatorViewController.swift index 648aa659..9783bccf 100644 --- a/r2-navigator-swift/NavigatorViewController.swift +++ b/r2-navigator-swift/NavigatorViewController.swift @@ -116,10 +116,16 @@ extension NavigatorViewController { /// /// - Parameter index: The index of the spine item to display. public func displaySpineItem(at index: Int, progression: Double) { - self.initialProgression = progression //This is so the webview will move to it's correct progression - displaySpineItem(at: index) - if let webView = triptychView.currentView as? WebView { - webView.scrollAt(position: progression) + guard publication.spine.indices.contains(index) else { + return + } + + fadeInOutTriptychView { + self.initialProgression = progression //This is so the webview will move to it's correct progression if it's not loaded into the triptych view + self.triptychView.moveTo(index: index) + if let webView = self.triptychView.currentView as? WebView { + webView.scrollAt(position: progression) + } } } From a52e27b7a40108e70fa31ebb8dac4822c50bd61b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ullstro=CC=88m?= Date: Tue, 16 Oct 2018 10:40:39 +0200 Subject: [PATCH 11/23] Tweak fading for triptych view --- .../NavigatorViewController.swift | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/r2-navigator-swift/NavigatorViewController.swift b/r2-navigator-swift/NavigatorViewController.swift index 9783bccf..b5a53acb 100644 --- a/r2-navigator-swift/NavigatorViewController.swift +++ b/r2-navigator-swift/NavigatorViewController.swift @@ -107,7 +107,7 @@ extension NavigatorViewController { guard publication.spine.indices.contains(index) else { return } - fadeInOutTriptychView { + fadeTriptychView { self.triptychView.moveTo(index: index) } } @@ -120,7 +120,7 @@ extension NavigatorViewController { return } - fadeInOutTriptychView { + fadeTriptychViewDelayed { self.initialProgression = progression //This is so the webview will move to it's correct progression if it's not loaded into the triptych view self.triptychView.moveTo(index: index) if let webView = self.triptychView.currentView as? WebView { @@ -146,7 +146,7 @@ extension NavigatorViewController { let id = (components.count > 1 ? components.last : "") // Jumping set to true to avoid clamping. - fadeInOutTriptychView { + fadeTriptychView { self.triptychView.moveTo(index: index, id: id) } } @@ -264,15 +264,31 @@ extension Delegatee: TriptychViewDelegate { extension NavigatorViewController { - func fadeInOutTriptychView(becameHidden: @escaping () -> ()) { - UIView.animate(withDuration: 0.15, animations: { - self.triptychView.alpha = 0 - }) { (_) in + func fadeTriptychView(becameHidden: @escaping () -> ()) { + fadeTriptychView(alpha: 0) { + becameHidden() + self.fadeTriptychView(alpha: 1, completion: { }) + } + } + + /* + This is used when we want to jump to a document with proression. The rendering is sometimes very slow in this case so we have a generous delay before we show the view again. + */ + func fadeTriptychViewDelayed(becameHidden: @escaping () -> ()) { + fadeTriptychView(alpha: 0) { becameHidden() - UIView.animate(withDuration: 0.15, animations: { - self.triptychView.alpha = 1 + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: { + self.fadeTriptychView(alpha: 1, completion: { }) }) } } + + private func fadeTriptychView(alpha: CGFloat, completion: @escaping () -> ()) { + UIView.animate(withDuration: 0.15, animations: { + self.triptychView.alpha = alpha + }) { _ in + completion() + } + } } From 63a132393c85f9169a6df0de91f17cfa26492c59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ullstro=CC=88m?= Date: Thu, 18 Oct 2018 14:54:20 +0200 Subject: [PATCH 12/23] Add support for feeding the navigator delegate with information when navigating via internal links in the html --- r2-navigator-swift/NavigatorViewController.swift | 16 ++++++++++++++++ r2-navigator-swift/WebView.swift | 4 ++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/r2-navigator-swift/NavigatorViewController.swift b/r2-navigator-swift/NavigatorViewController.swift index b5a53acb..b9d7cc63 100644 --- a/r2-navigator-swift/NavigatorViewController.swift +++ b/r2-navigator-swift/NavigatorViewController.swift @@ -20,6 +20,7 @@ public protocol NavigatorDelegate: class { /// It changes when html file resource changed func didChangedDocumentPage(currentDocumentIndex: Int) func didChangedPaginatedDocumentPage(currentPage: Int, documentTotalPage: Int) + func didNavigateViaInternalLinkTap(to link: Link) } public extension NavigatorDelegate { @@ -172,6 +173,21 @@ extension NavigatorViewController { } extension NavigatorViewController: ViewDelegate { + + func handleTapOnInternalLink(with href: String) { + displaySpineItem(with: href) + + //I'd like to refactor the displaySpineItem to use a link instead of a string href, but I don't want to restructure the navigator too much. This therefore more or less copied from the displaySpineItem-function. + let components = href.components(separatedBy: "#") + guard let href = components.first else { + return + } + guard let link = publication.spine.first(where: { $0.href?.contains(href) ?? false }) else { + return + } + delegate?.didNavigateViaInternalLinkTap(to: link) + } + func documentPageDidChanged(webview: WebView, currentPage: Int, totalPage: Int) { if triptychView.currentView == webview { delegate?.didChangedPaginatedDocumentPage(currentPage: currentPage, documentTotalPage: totalPage) diff --git a/r2-navigator-swift/WebView.swift b/r2-navigator-swift/WebView.swift index 8187c7df..c1896335 100644 --- a/r2-navigator-swift/WebView.swift +++ b/r2-navigator-swift/WebView.swift @@ -20,7 +20,7 @@ protocol ViewDelegate: class { func handleCenterTap() func publicationIdentifier() -> String? func publicationBaseUrl() -> URL? - func displaySpineItem(with href: String) + func handleTapOnInternalLink(with href: String) func documentPageDidChanged(webview: WebView, currentPage: Int ,totalPage: Int) } @@ -324,7 +324,7 @@ extension WebView: WKNavigationDelegate { // Internal link. let href = url.absoluteString.replacingOccurrences(of: baseUrlString, with: "") - viewDelegate?.displaySpineItem(with: href) + viewDelegate?.handleTapOnInternalLink(with: href) } else if url.absoluteString.contains("http") { // TEMPORARY, better checks coming. // External Link. let view = SFSafariViewController(url: url) From eeb1db805b4dc058ec19c5be0683506e2d6c78fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ullstro=CC=88m?= Date: Mon, 22 Oct 2018 17:02:59 +0200 Subject: [PATCH 13/23] Add document index return to displaySpineItem(with href) and adjust NavigatorDelegate accordingly --- .../NavigatorViewController.swift | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/r2-navigator-swift/NavigatorViewController.swift b/r2-navigator-swift/NavigatorViewController.swift index b9d7cc63..691f05d2 100644 --- a/r2-navigator-swift/NavigatorViewController.swift +++ b/r2-navigator-swift/NavigatorViewController.swift @@ -20,7 +20,7 @@ public protocol NavigatorDelegate: class { /// It changes when html file resource changed func didChangedDocumentPage(currentDocumentIndex: Int) func didChangedPaginatedDocumentPage(currentPage: Int, documentTotalPage: Int) - func didNavigateViaInternalLinkTap(to link: Link) + func didNavigateViaInternalLinkTap(to documentIndex: Int) } public extension NavigatorDelegate { @@ -133,14 +133,15 @@ extension NavigatorViewController { /// Load resource with the corresponding href. /// /// - Parameter href: The href of the resource to load. Can contain a tag id. - public func displaySpineItem(with href: String) { + /// - Return: The document index for the link + public func displaySpineItem(with href: String) -> Int? { // remove id if any let components = href.components(separatedBy: "#") guard let href = components.first else { - return + return nil } guard let index = publication.spine.index(where: { $0.href?.contains(href) ?? false }) else { - return + return nil } // If any id found, set the scroll position to it, else to the // beggining of the document. @@ -150,6 +151,7 @@ extension NavigatorViewController { fadeTriptychView { self.triptychView.moveTo(index: index, id: id) } + return index } public func getSpine() -> [Link] { @@ -175,17 +177,8 @@ extension NavigatorViewController { extension NavigatorViewController: ViewDelegate { func handleTapOnInternalLink(with href: String) { - displaySpineItem(with: href) - - //I'd like to refactor the displaySpineItem to use a link instead of a string href, but I don't want to restructure the navigator too much. This therefore more or less copied from the displaySpineItem-function. - let components = href.components(separatedBy: "#") - guard let href = components.first else { - return - } - guard let link = publication.spine.first(where: { $0.href?.contains(href) ?? false }) else { - return - } - delegate?.didNavigateViaInternalLinkTap(to: link) + guard let index = displaySpineItem(with: href) else { return } + delegate?.didNavigateViaInternalLinkTap(to: index) } func documentPageDidChanged(webview: WebView, currentPage: Int, totalPage: Int) { From 1708321e5b6caf5527181731e7ed6be2176d7591 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ullstro=CC=88m?= Date: Thu, 25 Oct 2018 17:23:08 +0200 Subject: [PATCH 14/23] Add external tap url as delegate method. Prevent peek'n'pop for localhost links. --- .../NavigatorViewController.swift | 5 ++++ r2-navigator-swift/WebView.swift | 27 ++++++++++++------- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/r2-navigator-swift/NavigatorViewController.swift b/r2-navigator-swift/NavigatorViewController.swift index 691f05d2..449d4feb 100644 --- a/r2-navigator-swift/NavigatorViewController.swift +++ b/r2-navigator-swift/NavigatorViewController.swift @@ -21,6 +21,7 @@ public protocol NavigatorDelegate: class { func didChangedDocumentPage(currentDocumentIndex: Int) func didChangedPaginatedDocumentPage(currentPage: Int, documentTotalPage: Int) func didNavigateViaInternalLinkTap(to documentIndex: Int) + func didTapExternalUrl(_ : URL) } public extension NavigatorDelegate { @@ -176,6 +177,10 @@ extension NavigatorViewController { extension NavigatorViewController: ViewDelegate { + func handleTapOnLink(with url: URL) { + delegate?.didTapExternalUrl(url) + } + func handleTapOnInternalLink(with href: String) { guard let index = displaySpineItem(with: href) else { return } delegate?.didNavigateViaInternalLinkTap(to: index) diff --git a/r2-navigator-swift/WebView.swift b/r2-navigator-swift/WebView.swift index c1896335..40d36a72 100644 --- a/r2-navigator-swift/WebView.swift +++ b/r2-navigator-swift/WebView.swift @@ -10,7 +10,6 @@ // import WebKit -import SafariServices import R2Shared @@ -20,6 +19,7 @@ protocol ViewDelegate: class { func handleCenterTap() func publicationIdentifier() -> String? func publicationBaseUrl() -> URL? + func handleTapOnLink(with url: URL) func handleTapOnInternalLink(with href: String) func documentPageDidChanged(webview: WebView, currentPage: Int ,totalPage: Int) } @@ -110,6 +110,7 @@ final class WebView: WKWebView { scrollView.showsHorizontalScrollIndicator = false scrollView.showsVerticalScrollIndicator = false navigationDelegate = self + uiDelegate = self sizeObservation = scrollView.observe(\.contentSize, options: .new) { (thisScrollView, thisValue) in // update total pages @@ -323,15 +324,9 @@ extension WebView: WKNavigationDelegate { let baseUrlString = publicationBaseUrl?.absoluteString { // Internal link. let href = url.absoluteString.replacingOccurrences(of: baseUrlString, with: "") - viewDelegate?.handleTapOnInternalLink(with: href) - } else if url.absoluteString.contains("http") { // TEMPORARY, better checks coming. - // External Link. - let view = SFSafariViewController(url: url) - - UIApplication.shared.keyWindow?.rootViewController?.present(view, - animated: true, - completion: nil) + } else { + viewDelegate?.handleTapOnLink(with: url) } } } @@ -354,6 +349,20 @@ extension WebView: UIScrollViewDelegate { } } +extension WebView: WKUIDelegate { + + + @available(iOS 10.0, *) //the property allowsLinkPreview is default false in iOS9, so this should be safe + func webView(_ webView: WKWebView, shouldPreviewElement elementInfo: WKPreviewElementInfo) -> Bool { + let publicationBaseUrl = viewDelegate?.publicationBaseUrl() + let url = elementInfo.linkURL + if url?.host == publicationBaseUrl?.host { + return false + } + return true + } +} + private extension UIScrollView { From 87ee821519e94629215c017cdbde7f004fe5aef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ullstro=CC=88m?= Date: Fri, 26 Oct 2018 12:07:30 +0200 Subject: [PATCH 15/23] Disable user interaction when animating page change --- r2-navigator-swift/WebView.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/r2-navigator-swift/WebView.swift b/r2-navigator-swift/WebView.swift index 40d36a72..84a36f81 100644 --- a/r2-navigator-swift/WebView.swift +++ b/r2-navigator-swift/WebView.swift @@ -347,6 +347,10 @@ extension WebView: UIScrollViewDelegate { } return nil } + + func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { + scrollView.isUserInteractionEnabled = true + } } extension WebView: WKUIDelegate { @@ -375,6 +379,8 @@ private extension UIScrollView { } private func moveHorizontalContent(with offsetX: CGFloat) { + isUserInteractionEnabled = false + var newOffset = contentOffset newOffset.x += offsetX let rounded = round(newOffset.x / offsetX) * offsetX From 5921c4e6c5b7283f956e6c0e2c26ce521058bc63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ullstro=CC=88m?= Date: Tue, 30 Oct 2018 13:17:54 +0100 Subject: [PATCH 16/23] Add contentView as a public property. Add viewWillDisappear super-call. --- r2-navigator-swift/NavigatorViewController.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/r2-navigator-swift/NavigatorViewController.swift b/r2-navigator-swift/NavigatorViewController.swift index 449d4feb..bdb189ed 100644 --- a/r2-navigator-swift/NavigatorViewController.swift +++ b/r2-navigator-swift/NavigatorViewController.swift @@ -90,6 +90,7 @@ open class NavigatorViewController: UIViewController { } open override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) // Save the currently opened document index and progression. if navigationController == nil { let progression = triptychView.getCurrentDocumentProgression() @@ -278,6 +279,10 @@ extension Delegatee: TriptychViewDelegate { extension NavigatorViewController { + public var contentView: UIView { + return triptychView + } + func fadeTriptychView(becameHidden: @escaping () -> ()) { fadeTriptychView(alpha: 0) { becameHidden() From bc2e72c810544445d4f3c9f5dcbe2fa644255832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ullstro=CC=88m?= Date: Wed, 31 Oct 2018 08:46:45 +0100 Subject: [PATCH 17/23] Use readium shared repo --- Cartfile.resolved | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cartfile.resolved b/Cartfile.resolved index 4f6279cb..11fe8e89 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,2 +1,2 @@ -github "BookBeat/r2-shared-swift" "54bea7b9da2980da197b1b9208a0ef2f7c46c606" -github "Hearst-DD/ObjectMapper" "3.3.0" +github "Hearst-DD/ObjectMapper" "2.2.0" +github "Readium/r2-shared-swift" "3dd222c34fcf658afd6bc4fd3e06218d773421bb" From 5944fa3445bee9e4d7940c79a883ece8231c50c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ullstro=CC=88m?= Date: Wed, 31 Oct 2018 12:12:35 +0100 Subject: [PATCH 18/23] Fix documentation for func in NavigatorViewController --- r2-navigator-swift/NavigatorViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r2-navigator-swift/NavigatorViewController.swift b/r2-navigator-swift/NavigatorViewController.swift index bdb189ed..aca711b5 100644 --- a/r2-navigator-swift/NavigatorViewController.swift +++ b/r2-navigator-swift/NavigatorViewController.swift @@ -135,7 +135,7 @@ extension NavigatorViewController { /// Load resource with the corresponding href. /// /// - Parameter href: The href of the resource to load. Can contain a tag id. - /// - Return: The document index for the link + /// - Returns: The spine index for the link public func displaySpineItem(with href: String) -> Int? { // remove id if any let components = href.components(separatedBy: "#") From 338a21826f2f4329fa755a977226933d48e6e925 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ullstro=CC=88m?= Date: Fri, 2 Nov 2018 14:39:02 +0100 Subject: [PATCH 19/23] Add option to choose PageTransition-style --- r2-navigator-swift.xcodeproj/project.pbxproj | 4 ++ .../NavigatorViewController.swift | 47 ++++++++++------ r2-navigator-swift/PageTransition.swift | 17 ++++++ r2-navigator-swift/WebView.swift | 56 +++++++++++++------ 4 files changed, 91 insertions(+), 33 deletions(-) create mode 100644 r2-navigator-swift/PageTransition.swift diff --git a/r2-navigator-swift.xcodeproj/project.pbxproj b/r2-navigator-swift.xcodeproj/project.pbxproj index 6a1a77e9..36b28f7f 100644 --- a/r2-navigator-swift.xcodeproj/project.pbxproj +++ b/r2-navigator-swift.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 1D3A2F56218C85A100108B31 /* PageTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D3A2F55218C85A100108B31 /* PageTransition.swift */; }; F341C2711F506ED5005E6758 /* UserSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = F341C2701F506ED5005E6758 /* UserSettings.swift */; }; F3E7D3D41F4D83B000DF166D /* r2-navigator-swift.h in Headers */ = {isa = PBXBuildFile; fileRef = F3E7D3C61F4D83B000DF166D /* r2-navigator-swift.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3E7D3DE1F4D845B00DF166D /* BinaryLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E7D3DD1F4D845B00DF166D /* BinaryLocation.swift */; }; @@ -19,6 +20,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 1D3A2F55218C85A100108B31 /* PageTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageTransition.swift; sourceTree = ""; }; F341C2701F506ED5005E6758 /* UserSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserSettings.swift; sourceTree = ""; }; F3B2C86C1F603E79007601E4 /* SwiftyJSON.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftyJSON.framework; path = Carthage/Build/iOS/SwiftyJSON.framework; sourceTree = ""; }; F3E7D3C31F4D83B000DF166D /* R2Navigator.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = R2Navigator.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -103,6 +105,7 @@ F3E7D3DD1F4D845B00DF166D /* BinaryLocation.swift */, F3E7D3DF1F4D847E00DF166D /* Disjunction.swift */, F341C2701F506ED5005E6758 /* UserSettings.swift */, + 1D3A2F55218C85A100108B31 /* PageTransition.swift */, ); name = EPUB; sourceTree = ""; @@ -203,6 +206,7 @@ F341C2711F506ED5005E6758 /* UserSettings.swift in Sources */, F3E7D3DE1F4D845B00DF166D /* BinaryLocation.swift in Sources */, F3E7D3E41F4D84DC00DF166D /* TriptychView.swift in Sources */, + 1D3A2F56218C85A100108B31 /* PageTransition.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/r2-navigator-swift/NavigatorViewController.swift b/r2-navigator-swift/NavigatorViewController.swift index aca711b5..232e864d 100644 --- a/r2-navigator-swift/NavigatorViewController.swift +++ b/r2-navigator-swift/NavigatorViewController.swift @@ -43,12 +43,15 @@ open class NavigatorViewController: UIViewController { public let publication: Publication public weak var delegate: NavigatorDelegate? + public let pageTransition: PageTransition + /// - Parameters: /// - publication: The publication. /// - initialIndex: Inital index of -1 will open the publication's at the end. - public init(for publication: Publication, initialIndex: Int, initialProgression: Double?) { + public init(for publication: Publication, initialIndex: Int, initialProgression: Double?, pageTransition: PageTransition = .none) { self.publication = publication self.initialProgression = initialProgression + self.pageTransition = pageTransition userSettings = UserSettings() publication.userProperties.properties = userSettings.userProperties.properties delegatee = Delegatee() @@ -110,7 +113,7 @@ extension NavigatorViewController { guard publication.spine.indices.contains(index) else { return } - fadeTriptychView { + performTriptychViewTransition { self.triptychView.moveTo(index: index) } } @@ -123,10 +126,12 @@ extension NavigatorViewController { return } - fadeTriptychViewDelayed { - self.initialProgression = progression //This is so the webview will move to it's correct progression if it's not loaded into the triptych view + performTriptychViewTransitionDelayed { + // This is so the webview will move to it's correct progression if it's not loaded into the triptych view + self.initialProgression = progression self.triptychView.moveTo(index: index) if let webView = self.triptychView.currentView as? WebView { + // This is needed for when the webView is loaded into the triptychView webView.scrollAt(position: progression) } } @@ -150,7 +155,7 @@ extension NavigatorViewController { let id = (components.count > 1 ? components.last : "") // Jumping set to true to avoid clamping. - fadeTriptychView { + performTriptychViewTransition { self.triptychView.moveTo(index: index, id: id) } return index @@ -233,7 +238,7 @@ extension Delegatee: TriptychViewDelegate { public func triptychView(_ view: TriptychView, viewForIndex index: Int, location: BinaryLocation) -> UIView { - let webView = WebView(frame: view.bounds, initialLocation: location) + let webView = WebView(frame: view.bounds, initialLocation: location, pageTransition: parent.pageTransition) webView.direction = view.direction let link = parent.publication.spine[index] @@ -283,22 +288,32 @@ extension NavigatorViewController { return triptychView } - func fadeTriptychView(becameHidden: @escaping () -> ()) { - fadeTriptychView(alpha: 0) { - becameHidden() - self.fadeTriptychView(alpha: 1, completion: { }) + func performTriptychViewTransition(commitTransition: @escaping () -> ()) { + switch pageTransition { + case .none: + commitTransition() + case .animated: + fadeTriptychView(alpha: 0) { + commitTransition() + self.fadeTriptychView(alpha: 1, completion: { }) + } } } /* This is used when we want to jump to a document with proression. The rendering is sometimes very slow in this case so we have a generous delay before we show the view again. */ - func fadeTriptychViewDelayed(becameHidden: @escaping () -> ()) { - fadeTriptychView(alpha: 0) { - becameHidden() - DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: { - self.fadeTriptychView(alpha: 1, completion: { }) - }) + func performTriptychViewTransitionDelayed(commitTransition: @escaping () -> ()) { + switch pageTransition { + case .none: + commitTransition() + case .animated: + fadeTriptychView(alpha: 0) { + commitTransition() + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: { + self.fadeTriptychView(alpha: 1, completion: { }) + }) + } } } diff --git a/r2-navigator-swift/PageTransition.swift b/r2-navigator-swift/PageTransition.swift new file mode 100644 index 00000000..db42a2ab --- /dev/null +++ b/r2-navigator-swift/PageTransition.swift @@ -0,0 +1,17 @@ +// +// PageTransition.swift +// r2-navigator-swift +// +// Created by Jonas Ullström on 2018-11-02. +// +// Copyright 2018 Readium Foundation. All rights reserved. +// Use of this source code is governed by a BSD-style license which is detailed +// in the LICENSE file present in the project repository where this source code is maintained. +// + +import Foundation + +public enum PageTransition { + case none + case animated +} diff --git a/r2-navigator-swift/WebView.swift b/r2-navigator-swift/WebView.swift index 84a36f81..e3d68b9b 100644 --- a/r2-navigator-swift/WebView.swift +++ b/r2-navigator-swift/WebView.swift @@ -31,6 +31,8 @@ final class WebView: WKWebView { var direction: PageProgressionDirection? + var pageTransition: PageTransition + public var initialId: String? // progression and totalPages only work on 'readium-scroll-off' mode public var progression: Double? @@ -62,20 +64,17 @@ final class WebView: WKWebView { internal enum Scroll { case left case right + func proceed(on target: WebView) { - - let scrollView = target.scrollView - if scrollView.isPagingEnabled { - switch self { - case .left: - let isAtFirstPageInDocument = scrollView.contentOffset.x == 0 - if !isAtFirstPageInDocument { return scrollView.scrollToPreviousPage() } - case .right: - let isAtLastPageInDocument = scrollView.contentOffset.x == scrollView.contentSize.width - scrollView.frame.size.width - if !isAtLastPageInDocument { return scrollView.scrollToNextPage() } - } + switch target.pageTransition { + case .none: + evaluateJavascriptForScroll(on: target) + case .animated: + performSwipeTransition(on: target) } - + } + + private func evaluateJavascriptForScroll(on target: WebView) { let dir = target.direction?.rawValue ?? PageProgressionDirection.ltr.rawValue switch self { @@ -93,12 +92,30 @@ final class WebView: WKWebView { }) } } + + private func performSwipeTransition(on target: WebView) { + let scrollView = target.scrollView + switch self { + case .left: + let isAtFirstPageInDocument = scrollView.contentOffset.x == 0 + if !isAtFirstPageInDocument { + return scrollView.scrollToPreviousPage() + } + case .right: + let isAtLastPageInDocument = scrollView.contentOffset.x == scrollView.contentSize.width - scrollView.frame.size.width + if !isAtLastPageInDocument { + return scrollView.scrollToNextPage() + } + } + evaluateJavascriptForScroll(on: target) + } } var sizeObservation: NSKeyValueObservation? - init(frame: CGRect, initialLocation: BinaryLocation) { + init(frame: CGRect, initialLocation: BinaryLocation, pageTransition: PageTransition = .none) { self.initialLocation = initialLocation + self.pageTransition = pageTransition super.init(frame: frame, configuration: .init()) isOpaque = false @@ -190,7 +207,12 @@ extension WebView { internal func documentDidLoad(body: String) { documentLoaded = true - fadeInWithDelay() + switch pageTransition { + case .none: + alpha = 1 + case .animated: + fadeInWithDelay() + } applyUserSettingsStyle() scrollToInitialPosition() @@ -355,8 +377,8 @@ extension WebView: UIScrollViewDelegate { extension WebView: WKUIDelegate { - - @available(iOS 10.0, *) //the property allowsLinkPreview is default false in iOS9, so this should be safe + // The property allowsLinkPreview is default false in iOS9, so it should be safe to use @available(iOS 10.0, *) + @available(iOS 10.0, *) func webView(_ webView: WKWebView, shouldPreviewElement elementInfo: WKPreviewElementInfo) -> Bool { let publicationBaseUrl = viewDelegate?.publicationBaseUrl() let url = elementInfo.linkURL @@ -393,7 +415,7 @@ private extension UIScrollView { private extension UIView { func fadeInWithDelay() { - //We need to give the CSS and webview time to layout correctly. :( 0.2 seconds seems like a good value for it to work on an iPhone 5s. + //TODO: We need to give the CSS and webview time to layout correctly. 0.2 seconds seems like a good value for it to work on an iPhone 5s. Look into solving this better DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { UIView.animate(withDuration: 0.3, animations: { self.alpha = 1 From c6809daf9486e19e568d29015f2b2e8f02b7c3ea Mon Sep 17 00:00:00 2001 From: Aferdita Muriqi Date: Wed, 7 Nov 2018 08:41:50 -0500 Subject: [PATCH 20/23] made new delegate methods optional --- r2-navigator-swift/NavigatorViewController.swift | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/r2-navigator-swift/NavigatorViewController.swift b/r2-navigator-swift/NavigatorViewController.swift index 232e864d..4b935e63 100644 --- a/r2-navigator-swift/NavigatorViewController.swift +++ b/r2-navigator-swift/NavigatorViewController.swift @@ -32,6 +32,13 @@ public extension NavigatorDelegate { func didChangedPaginatedDocumentPage(currentPage: Int, documentTotalPage: Int) { // optional } + func didNavigateViaInternalLinkTap(to documentIndex: Int) { + // optional + } + + func didTapExternalUrl(_: URL) { + // optional + } } open class NavigatorViewController: UIViewController { From 7aa981fa21fb6bb5164682646903d8003fde3225 Mon Sep 17 00:00:00 2001 From: Aferdita Muriqi Date: Wed, 7 Nov 2018 09:09:42 -0500 Subject: [PATCH 21/23] re-added default implementation of handling external urls --- r2-navigator-swift/NavigatorViewController.swift | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/r2-navigator-swift/NavigatorViewController.swift b/r2-navigator-swift/NavigatorViewController.swift index 4b935e63..39ed2305 100644 --- a/r2-navigator-swift/NavigatorViewController.swift +++ b/r2-navigator-swift/NavigatorViewController.swift @@ -12,6 +12,7 @@ import UIKit import R2Shared import WebKit +import SafariServices public protocol NavigatorDelegate: class { func middleTapHandler() @@ -35,9 +36,15 @@ public extension NavigatorDelegate { func didNavigateViaInternalLinkTap(to documentIndex: Int) { // optional } - - func didTapExternalUrl(_: URL) { + + func didTapExternalUrl(_ url: URL) { // optional + // TODO following lines have been moved from the original implementation and might need to be revisited at some point + let view = SFSafariViewController(url: url) + + UIApplication.shared.keyWindow?.rootViewController?.present(view, + animated: true, + completion: nil) } } From 2793026f4b9710c5abcd44460ffcfb734dbb870e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ullstro=CC=88m?= Date: Fri, 9 Nov 2018 14:19:06 +0100 Subject: [PATCH 22/23] Set clamping to none in scrollViewDidEndScrollingAnimation --- r2-navigator-swift/TriptychView.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/r2-navigator-swift/TriptychView.swift b/r2-navigator-swift/TriptychView.swift index 6b65dee5..c90f040e 100644 --- a/r2-navigator-swift/TriptychView.swift +++ b/r2-navigator-swift/TriptychView.swift @@ -399,6 +399,14 @@ extension TriptychView: UIScrollViewDelegate { } } } + func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { + // Set the clamping to .none here to prevent the bug introduced by + // the workaround in scrollViewDidEndDecelerating where the + // scrollview contentOffset is animated. + // When animating the contentOffset, scrollViewDidScroll is called + // without calling scrollViewDidEndDecelerating afterwards. + clamping = .none + } public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { From 85428ecf548184a3b0c40476bb51e3b80167112b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ullstro=CC=88m?= Date: Fri, 9 Nov 2018 15:08:05 +0100 Subject: [PATCH 23/23] Set clamping to none in scrollViewdidEndDragging if decelerate is false --- r2-navigator-swift/TriptychView.swift | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/r2-navigator-swift/TriptychView.swift b/r2-navigator-swift/TriptychView.swift index c90f040e..7fd1f0bf 100644 --- a/r2-navigator-swift/TriptychView.swift +++ b/r2-navigator-swift/TriptychView.swift @@ -399,12 +399,19 @@ extension TriptychView: UIScrollViewDelegate { } } } + + // Set the clamping to .none in scrollViewDidEndScrollingAnimation + // and scrollViewDidEndDragging with decelerate == false, + // to prevent the bug introduced by the workaround in + // scrollViewDidEndDecelerating where the scrollview contentOffset + // is animated. When animating the contentOffset, scrollViewDidScroll + // is called without calling scrollViewDidEndDecelerating afterwards. func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { - // Set the clamping to .none here to prevent the bug introduced by - // the workaround in scrollViewDidEndDecelerating where the - // scrollview contentOffset is animated. - // When animating the contentOffset, scrollViewDidScroll is called - // without calling scrollViewDidEndDecelerating afterwards. + clamping = .none + } + + func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { + if decelerate { return } clamping = .none }