"
html += "\(bookTitle) "
- html += readerConfig.localizedShareBy+" \(authorName) "
-
- if let bookShareLink = readerConfig.localizedShareWebLink {
+ html += self.readerConfig.localizedShareBy+" \(authorName) "
+
+ if let bookShareLink = self.readerConfig.localizedShareWebLink {
html += "\(bookShareLink.absoluteString)"
shareItems.append(bookShareLink as AnyObject)
}
html += "
"
- text = "\(chapterName)\n\n“\(chapterText)” \n\n\(bookTitle) \n\(readerConfig.localizedShareBy) \(authorName)"
+ text = "\(chapterName)\n\n“\(chapterText)” \n\n\(bookTitle) \n\(self.readerConfig.localizedShareBy) \(authorName)"
let act = FolioReaderSharingProvider(subject: subject, text: text, html: html)
shareItems.insert(contentsOf: [act, "" as AnyObject], at: 0)
@@ -1127,7 +1118,7 @@ open class FolioReaderCenter: UIViewController, UICollectionViewDelegate, UIColl
actv.barButtonItem = sender
}
- present(activityViewController, animated: true, completion: nil)
+ self.present(activityViewController, animated: true, completion: nil)
}
}
@@ -1281,7 +1272,7 @@ open class FolioReaderCenter: UIViewController, UICollectionViewDelegate, UIColl
// Perform the page after a short delay as the collection view hasn't completed it's transition if this method is called (the index paths aren't right during fast scrolls).
delay(0.2, closure: { [weak self] in
if (self?.readerConfig.scrollDirection == .horizontalWithVerticalContent),
- let cell = ((scrollView.superview as? UIWebView)?.delegate as? FolioReaderPage) {
+ let cell = ((scrollView.superview as? WKWebView)?.navigationDelegate as? FolioReaderPage) {
let currentIndexPathRow = cell.pageNumber - 1
self?.currentWebViewScrollPositions[currentIndexPathRow] = scrollView.contentOffset
}
diff --git a/Source/FolioReaderPage.swift b/Source/FolioReaderPage.swift
index 5b013a0fd..8ee1e3521 100755
--- a/Source/FolioReaderPage.swift
+++ b/Source/FolioReaderPage.swift
@@ -9,6 +9,7 @@
import UIKit
import SafariServices
import MenuItemKit
+import WebKit
/// Protocol which is used from `FolioReaderPage`s.
@objc public protocol FolioReaderPageDelegate: class {
@@ -35,7 +36,7 @@ import MenuItemKit
@objc optional func pageTap(_ recognizer: UITapGestureRecognizer)
}
-open class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGestureRecognizerDelegate {
+open class FolioReaderPage: UICollectionViewCell, WKNavigationDelegate, UIGestureRecognizerDelegate {
weak var delegate: FolioReaderPageDelegate?
weak var readerContainer: FolioReaderContainer?
@@ -80,13 +81,12 @@ open class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGestureRe
if webView == nil {
webView = FolioReaderWebView(frame: webViewFrame(), readerContainer: readerContainer)
webView?.autoresizingMask = [.flexibleWidth, .flexibleHeight]
- webView?.dataDetectorTypes = .link
webView?.scrollView.showsVerticalScrollIndicator = false
webView?.scrollView.showsHorizontalScrollIndicator = false
webView?.backgroundColor = .clear
self.contentView.addSubview(webView!)
}
- webView?.delegate = self
+ webView?.navigationDelegate = self
if colorView == nil {
colorView = UIView()
@@ -110,7 +110,7 @@ open class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGestureRe
deinit {
webView?.scrollView.delegate = nil
- webView?.delegate = nil
+ webView?.navigationDelegate = nil
NotificationCenter.default.removeObserver(self)
}
@@ -187,14 +187,20 @@ open class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGestureRe
return tempHtmlContent as String
}
- // MARK: - UIWebView Delegate
+ // MARK: - WKNavigation Delegate
- open func webViewDidFinishLoad(_ webView: UIWebView) {
+ open func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
guard let webView = webView as? FolioReaderWebView else {
return
}
delegate?.pageWillLoad?(self)
+ }
+
+ open func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
+ guard let webView = webView as? FolioReaderWebView else {
+ return
+ }
// Add the custom class based onClick listener
self.setupClassBasedOnClickListeners()
@@ -221,11 +227,22 @@ open class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGestureRe
webView.isColors = false
self.webView?.createMenu(options: false)
})
+ webView.js("document.readyState") { _ in
+ self.delegate?.pageDidLoad?(self)
+ }
+ let overlayColor = readerConfig.mediaOverlayColor!
+ let colors = "\"\(overlayColor.hexString(false))\", \"\(overlayColor.highlightColor().hexString(false))\""
+ webView.js("setMediaOverlayStyleColors(\(colors))")
+ }
- delegate?.pageDidLoad?(self)
+ open func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
+ let handledAction = handlePolicy(for: navigationAction)
+ let policy: WKNavigationActionPolicy = handledAction ? .allow : .cancel
+ decisionHandler(policy)
}
- open func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebView.NavigationType) -> Bool {
+ private func handlePolicy(for navigationAction: WKNavigationAction) -> Bool {
+ let request = navigationAction.request
guard
let webView = webView as? FolioReaderWebView,
let scheme = request.url?.scheme else {
@@ -299,7 +316,7 @@ open class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGestureRe
} else if scheme == "mailto" {
print("Email")
return true
- } else if url.absoluteString != "about:blank" && scheme.contains("http") && navigationType == .linkClicked {
+ } else if url.absoluteString != "about:blank" && scheme.contains("http") && navigationAction.navigationType == .linkActivated {
let safariVC = SFSafariViewController(url: request.url!)
safariVC.view.tintColor = self.readerConfig.tintColor
self.folioReader.readerCenter?.present(safariVC, animated: true, completion: nil)
@@ -373,20 +390,20 @@ open class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGestureRe
self.delegate?.pageTap?(recognizer)
if let _navigationController = self.folioReader.readerCenter?.navigationController, (_navigationController.isNavigationBarHidden == true) {
- let selected = webView?.js("getSelectedText()")
+ webView?.js("getSelectedText()") { selected in
+ guard (selected == nil || selected?.isEmpty == true) else {
+ return
+ }
- guard (selected == nil || selected?.isEmpty == true) else {
- return
+ let delay = 0.4 * Double(NSEC_PER_SEC) // 0.4 seconds * nanoseconds per seconds
+ let dispatchTime = (DispatchTime.now() + (Double(Int64(delay)) / Double(NSEC_PER_SEC)))
+
+ DispatchQueue.main.asyncAfter(deadline: dispatchTime, execute: {
+ if (self.shouldShowBar == true && self.menuIsVisible == false) {
+ self.folioReader.readerCenter?.toggleBars()
+ }
+ })
}
-
- let delay = 0.4 * Double(NSEC_PER_SEC) // 0.4 seconds * nanoseconds per seconds
- let dispatchTime = (DispatchTime.now() + (Double(Int64(delay)) / Double(NSEC_PER_SEC)))
-
- DispatchQueue.main.asyncAfter(deadline: dispatchTime, execute: {
- if (self.shouldShowBar == true && self.menuIsVisible == false) {
- self.folioReader.readerCenter?.toggleBars()
- }
- })
} else if (self.readerConfig.shouldHideNavigationOnTap == true) {
self.folioReader.readerCenter?.hideBars()
self.menuIsVisible = false
@@ -433,19 +450,19 @@ open class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGestureRe
*/
open func handleAnchor(_ anchor: String, avoidBeginningAnchors: Bool, animated: Bool) {
if !anchor.isEmpty {
- let offset = getAnchorOffset(anchor)
-
- switch self.readerConfig.scrollDirection {
- case .vertical, .defaultVertical:
- let isBeginning = (offset < frame.forDirection(withConfiguration: self.readerConfig) * 0.5)
-
- if !avoidBeginningAnchors {
- scrollPageToOffset(offset, animated: animated)
- } else if avoidBeginningAnchors && !isBeginning {
- scrollPageToOffset(offset, animated: animated)
+ getAnchorOffset(anchor) { offset in
+ switch self.readerConfig.scrollDirection {
+ case .vertical, .defaultVertical:
+ let isBeginning = (offset < self.frame.forDirection(withConfiguration: self.readerConfig) * 0.5)
+
+ if !avoidBeginningAnchors {
+ self.scrollPageToOffset(offset, animated: animated)
+ } else if avoidBeginningAnchors && !isBeginning {
+ self.scrollPageToOffset(offset, animated: animated)
+ }
+ case .horizontal, .horizontalWithVerticalContent:
+ self.scrollPageToOffset(offset, animated: animated)
}
- case .horizontal, .horizontalWithVerticalContent:
- scrollPageToOffset(offset, animated: animated)
}
}
}
@@ -458,13 +475,15 @@ open class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGestureRe
- parameter anchor: The #anchor id
- returns: The element offset ready to scroll
*/
- func getAnchorOffset(_ anchor: String) -> CGFloat {
+ func getAnchorOffset(_ anchor: String, completion: @escaping ((CGFloat) -> ())) {
let horizontal = self.readerConfig.scrollDirection == .horizontal
- if let strOffset = webView?.js("getAnchorOffset('\(anchor)', \(horizontal.description))") {
- return CGFloat((strOffset as NSString).floatValue)
+ webView?.js("getAnchorOffset('\(anchor)', \(horizontal.description))") { strOffset in
+ guard let strOffset = strOffset else {
+ completion(CGFloat(0))
+ return
+ }
+ completion(CGFloat((strOffset as NSString).floatValue))
}
-
- return CGFloat(0)
}
// MARK: Mark ID
@@ -494,11 +513,13 @@ open class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGestureRe
}
if !webView.isShare && !webView.isColors {
- if let result = webView.js("getSelectedText()") , result.components(separatedBy: " ").count == 1 {
+ webView.js("getSelectedText()") { result in
+ guard let result = result, result.components(separatedBy: " ").count == 1 else {
+ webView.isOneWord = false
+ return
+ }
webView.isOneWord = true
webView.createMenu(options: false)
- } else {
- webView.isOneWord = false
}
}
@@ -511,11 +532,12 @@ open class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGestureRe
if (self.folioReader.nightMode == true) {
// omit create webView and colorView
- let script = "document.documentElement.offsetHeight"
- let contentHeight = webView.stringByEvaluatingJavaScript(from: script)
- let frameHeight = webView.frame.height
- let lastPageHeight = frameHeight * CGFloat(webView.pageCount) - CGFloat(Double(contentHeight!)!)
- colorView.frame = CGRect(x: webView.frame.width * CGFloat(webView.pageCount-1), y: webView.frame.height - lastPageHeight, width: webView.frame.width, height: lastPageHeight)
+ // let script = "document.documentElement.offsetHeight"
+ // let contentHeight = webView.stringByEvaluatingJavaScript(from: script)
+ // let frameHeight = webView.frame.height
+ // let lastPageHeight = frameHeight * CGFloat(webView.pageCount) - CGFloat(Double(contentHeight!)!)
+ // colorView.frame = CGRect(x: webView.frame.width * CGFloat(webView.pageCount-1), y: webView.frame.height - lastPageHeight, width: webView.frame.width, height: lastPageHeight)
+ colorView.frame = CGRect.zero
} else {
colorView.frame = CGRect.zero
}
@@ -525,18 +547,8 @@ open class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGestureRe
fileprivate func setupClassBasedOnClickListeners() {
for listener in self.readerConfig.classBasedOnClickListeners {
- self.webView?.js("addClassBasedOnClickListener(\"\(listener.schemeName)\", \"\(listener.querySelector)\", \"\(listener.attributeName)\", \"\(listener.selectAll)\")");
+ self.webView?.js("addClassBasedOnClickListener(\"\(listener.schemeName)\", \"\(listener.querySelector)\", \"\(listener.attributeName)\", \"\(listener.selectAll)\")")
}
}
- // MARK: - Public Java Script injection
-
- /**
- Runs a JavaScript script and returns it result. The result of running the JavaScript script passed in the script parameter, or nil if the script fails.
-
- - returns: The result of running the JavaScript script passed in the script parameter, or nil if the script fails.
- */
- open func performJavaScript(_ javaScriptCode: String) -> String? {
- return webView?.js(javaScriptCode)
- }
}
diff --git a/Source/FolioReaderPageIndicator.swift b/Source/FolioReaderPageIndicator.swift
index fc1960556..dfa56052c 100644
--- a/Source/FolioReaderPageIndicator.swift
+++ b/Source/FolioReaderPageIndicator.swift
@@ -95,7 +95,12 @@ class FolioReaderPageIndicator: UIView {
pagesLabel.text = " \(pagesRemaining) " + self.readerConfig.localizedReaderManyPagesLeft
}
- let minutesRemaining = Int(ceil(CGFloat((pagesRemaining * totalMinutes)/totalPages)))
+ let minutesRemaining: Int
+ if totalPages == 0 {
+ minutesRemaining = 0
+ } else {
+ minutesRemaining = Int(ceil(CGFloat((pagesRemaining * totalMinutes)/totalPages)))
+ }
if minutesRemaining > 1 {
minutesLabel.text = "\(minutesRemaining) " + self.readerConfig.localizedReaderManyMinutes+" ·"
} else if minutesRemaining == 1 {
diff --git a/Source/FolioReaderScript.swift b/Source/FolioReaderScript.swift
new file mode 100644
index 000000000..1f0140df4
--- /dev/null
+++ b/Source/FolioReaderScript.swift
@@ -0,0 +1,62 @@
+//
+// FolioReaderScript.swift
+// FolioReaderKit
+//
+// Created by Stanislav on 12.06.2020.
+// Copyright (c) 2015 Folio Reader. All rights reserved.
+//
+
+import WebKit
+
+class FolioReaderScript: WKUserScript {
+
+ init(source: String) {
+ super.init(source: source,
+ injectionTime: .atDocumentEnd,
+ forMainFrameOnly: true)
+ }
+
+ static let bridgeJS: FolioReaderScript = {
+ let jsURL = Bundle.frameworkBundle().url(forResource: "Bridge", withExtension: "js")!
+ let jsSource = try! String(contentsOf: jsURL)
+ return FolioReaderScript(source: jsSource)
+ }()
+
+ static let cssInjection: FolioReaderScript = {
+ let cssURL = Bundle.frameworkBundle().url(forResource: "Style", withExtension: "css")!
+ let cssString = try! String(contentsOf: cssURL)
+ return FolioReaderScript(source: cssInjectionSource(for: cssString))
+ }()
+
+ static func cssInjection(overflow: String) -> FolioReaderScript {
+ let cssString = "html{overflow:\(overflow)}"
+ return FolioReaderScript(source: cssInjectionSource(for: cssString))
+ }
+
+ private static func cssInjectionSource(for content: String) -> String {
+ let oneLineContent = content.components(separatedBy: .newlines).joined()
+ let source = """
+ var style = document.createElement('style');
+ style.type = 'text/css'
+ style.innerHTML = '\(oneLineContent)';
+ document.head.appendChild(style);
+ """
+ return source
+ }
+
+}
+
+extension WKUserScript {
+
+ func addIfNeeded(to webView: WKWebView?) {
+ guard let controller = webView?.configuration.userContentController else { return }
+ let alreadyAdded = controller.userScripts.contains { [unowned self] in
+ return $0.source == self.source &&
+ $0.injectionTime == self.injectionTime &&
+ $0.isForMainFrameOnly == self.isForMainFrameOnly
+ }
+ if alreadyAdded { return }
+ controller.addUserScript(self)
+ }
+
+}
diff --git a/Source/FolioReaderWebView.swift b/Source/FolioReaderWebView.swift
index 9c3b7531a..578ddb340 100644
--- a/Source/FolioReaderWebView.swift
+++ b/Source/FolioReaderWebView.swift
@@ -6,13 +6,21 @@
// Copyright (c) 2016 Folio Reader. All rights reserved.
//
-import UIKit
+import WebKit
+
+public typealias JSCallback = (String?) ->()
/// The custom WebView used in each page
-open class FolioReaderWebView: UIWebView {
+open class FolioReaderWebView: WKWebView {
var isColors = false
var isShare = false
var isOneWord = false
+
+ fileprivate(set) var cssOverflowProperty = "scroll" {
+ didSet {
+ FolioReaderScript.cssInjection(overflow: cssOverflowProperty).addIfNeeded(to: self)
+ }
+ }
fileprivate weak var readerContainer: FolioReaderContainer?
@@ -31,14 +39,14 @@ open class FolioReaderWebView: UIWebView {
return readerContainer.folioReader
}
- override init(frame: CGRect) {
- fatalError("use init(frame:readerConfig:book:) instead.")
- }
-
init(frame: CGRect, readerContainer: FolioReaderContainer) {
self.readerContainer = readerContainer
- super.init(frame: frame)
+ let configuration = WKWebViewConfiguration()
+ configuration.dataDetectorTypes = .link
+ super.init(frame: frame, configuration: configuration)
+ FolioReaderScript.cssInjection.addIfNeeded(to: self)
+ FolioReaderScript.bridgeJS.addIfNeeded(to: self)
}
required public init?(coder aDecoder: NSCoder) {
@@ -77,11 +85,13 @@ open class FolioReaderWebView: UIWebView {
let shareImage = UIAlertAction(title: self.readerConfig.localizedShareImageQuote, style: .default, handler: { (action) -> Void in
if self.isShare {
- if let textToShare = self.js("getHighlightContent()") {
+ self.js("getHighlightContent()") { textToShare in
+ guard let textToShare = textToShare else { return }
self.folioReader.readerCenter?.presentQuoteShare(textToShare)
}
} else {
- if let textToShare = self.js("getSelectedText()") {
+ self.js("getSelectedText()") { textToShare in
+ guard let textToShare = textToShare else { return }
self.folioReader.readerCenter?.presentQuoteShare(textToShare)
self.clearTextSelection()
@@ -92,11 +102,13 @@ open class FolioReaderWebView: UIWebView {
let shareText = UIAlertAction(title: self.readerConfig.localizedShareTextQuote, style: .default) { (action) -> Void in
if self.isShare {
- if let textToShare = self.js("getHighlightContent()") {
+ self.js("getHighlightContent()") { textToShare in
+ guard let textToShare = textToShare else { return }
self.folioReader.readerCenter?.shareHighlight(textToShare, rect: sender.menuFrame)
}
} else {
- if let textToShare = self.js("getSelectedText()") {
+ self.js("getSelectedText()") { textToShare in
+ guard let textToShare = textToShare else { return }
self.folioReader.readerCenter?.shareHighlight(textToShare, rect: sender.menuFrame)
}
}
@@ -124,92 +136,103 @@ open class FolioReaderWebView: UIWebView {
}
func remove(_ sender: UIMenuController?) {
- if let removedId = js("removeThisHighlight()") {
+ js("removeThisHighlight()") { removedId in
+ guard let removedId = removedId else { return }
Highlight.removeById(withConfiguration: self.readerConfig, highlightId: removedId)
}
setMenuVisible(false)
}
@objc func highlight(_ sender: UIMenuController?) {
- let highlightAndReturn = js("highlightString('\(HighlightStyle.classForStyle(self.folioReader.currentHighlightStyle))')")
- let jsonData = highlightAndReturn?.data(using: String.Encoding.utf8)
-
- do {
- let json = try JSONSerialization.jsonObject(with: jsonData!, options: []) as! NSArray
- let dic = json.firstObject as! [String: String]
- let rect = NSCoder.cgRect(for: dic["rect"]!)
- guard let startOffset = dic["startOffset"] else {
- return
- }
- guard let endOffset = dic["endOffset"] else {
- return
- }
-
- createMenu(options: true)
- setMenuVisible(true, andRect: rect)
-
- // Persist
- guard
- let html = js("getHTML()"),
- let identifier = dic["id"],
- let bookId = (self.book.name as NSString?)?.deletingPathExtension else {
+ js("highlightString('\(HighlightStyle.classForStyle(self.folioReader.currentHighlightStyle))')") { highlightAndReturn in
+ let jsonData = highlightAndReturn?.data(using: String.Encoding.utf8)
+
+ do {
+ let json = try JSONSerialization.jsonObject(with: jsonData!, options: []) as! NSArray
+ let dic = json.firstObject as! [String: String]
+ let rect = NSCoder.cgRect(for: dic["rect"]!)
+ guard let startOffset = dic["startOffset"] else {
return
- }
-
- let pageNumber = folioReader.readerCenter?.currentPageNumber ?? 0
- let match = Highlight.MatchingHighlight(text: html, id: identifier, startOffset: startOffset, endOffset: endOffset, bookId: bookId, currentPage: pageNumber)
- let highlight = Highlight.matchHighlight(match)
- highlight?.persist(withConfiguration: self.readerConfig)
+ }
+ guard let endOffset = dic["endOffset"] else {
+ return
+ }
- } catch {
- print("Could not receive JSON")
+ self.createMenu(options: true)
+ self.setMenuVisible(true, andRect: rect)
+
+ // Persist
+ self.js("getHTML()") { html in
+
+ guard let html = html, let identifier = dic["id"], let bookId = (self.book.name as NSString?)?.deletingPathExtension
+ else {
+ return
+ }
+ let pageNumber = self.folioReader.readerCenter?.currentPageNumber ?? 0
+ let match = Highlight.MatchingHighlight(text: html, id: identifier, startOffset: startOffset, endOffset: endOffset, bookId: bookId, currentPage: pageNumber)
+ let highlight = Highlight.matchHighlight(match)
+ highlight?.persist(withConfiguration: self.readerConfig)
+ }
+
+ } catch {
+ print("Could not receive JSON:", error)
+ }
}
}
@objc func highlightWithNote(_ sender: UIMenuController?) {
- let highlightAndReturn = js("highlightStringWithNote('\(HighlightStyle.classForStyle(self.folioReader.currentHighlightStyle))')")
- let jsonData = highlightAndReturn?.data(using: String.Encoding.utf8)
+ js("highlightStringWithNote('\(HighlightStyle.classForStyle(self.folioReader.currentHighlightStyle))')") { highlightAndReturn in
+ let jsonData = highlightAndReturn?.data(using: String.Encoding.utf8)
- do {
- let json = try JSONSerialization.jsonObject(with: jsonData!, options: []) as! NSArray
- let dic = json.firstObject as! [String: String]
- guard let startOffset = dic["startOffset"] else { return }
- guard let endOffset = dic["endOffset"] else { return }
-
- self.clearTextSelection()
+ do {
+ let json = try JSONSerialization.jsonObject(with: jsonData!, options: []) as! NSArray
+ let dic = json.firstObject as! [String: String]
+ guard let startOffset = dic["startOffset"] else { return }
+ guard let endOffset = dic["endOffset"] else { return }
- guard let html = js("getHTML()") else { return }
- guard let identifier = dic["id"] else { return }
- guard let bookId = (self.book.name as NSString?)?.deletingPathExtension else { return }
+ self.clearTextSelection()
- let pageNumber = folioReader.readerCenter?.currentPageNumber ?? 0
- let match = Highlight.MatchingHighlight(text: html, id: identifier, startOffset: startOffset, endOffset: endOffset, bookId: bookId, currentPage: pageNumber)
- if let highlight = Highlight.matchHighlight(match) {
- self.folioReader.readerCenter?.presentAddHighlightNote(highlight, edit: false)
+ self.js("getHTML()") { html in
+ guard
+ let html = html, let identifier = dic["id"],
+ let bookId = (self.book.name as NSString?)?.deletingPathExtension else
+ {
+ return
+ }
+
+ let pageNumber = self.folioReader.readerCenter?.currentPageNumber ?? 0
+ let match = Highlight.MatchingHighlight(text: html, id: identifier, startOffset: startOffset, endOffset: endOffset, bookId: bookId, currentPage: pageNumber)
+ if let highlight = Highlight.matchHighlight(match) {
+ self.folioReader.readerCenter?.presentAddHighlightNote(highlight, edit: false)
+ }
+ }
+ } catch {
+ print("Could not receive JSON:", error)
}
- } catch {
- print("Could not receive JSON")
}
}
@objc func updateHighlightNote (_ sender: UIMenuController?) {
- guard let highlightId = js("getHighlightId()") else { return }
- guard let highlightNote = Highlight.getById(withConfiguration: readerConfig, highlightId: highlightId) else { return }
- self.folioReader.readerCenter?.presentAddHighlightNote(highlightNote, edit: true)
+ js("getHighlightId()") { highlightId in
+ guard
+ let highlightId = highlightId,
+ let highlightNote = Highlight.getById(withConfiguration: self.readerConfig, highlightId: highlightId) else { return }
+ self.folioReader.readerCenter?.presentAddHighlightNote(highlightNote, edit: true)
+ }
}
@objc func define(_ sender: UIMenuController?) {
- guard let selectedText = js("getSelectedText()") else {
- return
- }
+ js("getSelectedText()") { selectedText in
+ guard let selectedText = selectedText else { return }
- self.setMenuVisible(false)
- self.clearTextSelection()
+ self.setMenuVisible(false)
+ self.clearTextSelection()
- let vc = UIReferenceLibraryViewController(term: selectedText)
- vc.view.tintColor = self.readerConfig.tintColor
- guard let readerContainer = readerContainer else { return }
- readerContainer.show(vc, sender: nil)
+ let vc = UIReferenceLibraryViewController(term: selectedText)
+ vc.view.tintColor = self.readerConfig.tintColor
+ guard let readerContainer = self.readerContainer else { return }
+ readerContainer.show(vc, sender: nil)
+ }
}
@objc func play(_ sender: UIMenuController?) {
@@ -241,7 +264,8 @@ open class FolioReaderWebView: UIWebView {
func changeHighlightStyle(_ sender: UIMenuController?, style: HighlightStyle) {
self.folioReader.currentHighlightStyle = style.rawValue
- if let updateId = js("setHighlightStyle('\(HighlightStyle.classForStyle(style.rawValue))')") {
+ js("setHighlightStyle('\(HighlightStyle.classForStyle(style.rawValue))')") { updateId in
+ guard let updateId = updateId else { return }
Highlight.updateById(withConfiguration: self.readerConfig, highlightId: updateId, type: style)
}
@@ -346,10 +370,29 @@ open class FolioReaderWebView: UIWebView {
// MARK: - Java Script Bridge
- @discardableResult open func js(_ script: String) -> String? {
- let callback = self.stringByEvaluatingJavaScript(from: script)
- if callback!.isEmpty { return nil }
- return callback
+ open func js(_ script: String, completion: JSCallback? = nil) {
+ evaluateJavaScript(script) { result, error in
+ let output: String?
+ if let result = result {
+ let stringResult = "\(result)"
+ if stringResult.isEmpty {
+ output = nil
+ } else {
+ output = stringResult
+ }
+ } else {
+ output = nil
+ }
+ if let nsError = error as? NSError,
+ let url = nsError.userInfo["WKJavaScriptExceptionSourceURL"] as? NSURL,
+ url.absoluteString == "undefined"
+ {
+ // skip debugPrint - html hasn't loaded yet
+ } else if let error = error {
+ debugPrint("evaluateJavaScript(\(script)) returned an error:", error)
+ }
+ completion?(output)
+ }
}
// MARK: WebView
@@ -366,13 +409,12 @@ open class FolioReaderWebView: UIWebView {
switch self.readerConfig.scrollDirection {
case .vertical, .defaultVertical, .horizontalWithVerticalContent:
scrollView.isPagingEnabled = false
- paginationMode = .unpaginated
+ cssOverflowProperty = "scroll"
scrollView.bounces = true
break
case .horizontal:
scrollView.isPagingEnabled = true
- paginationMode = .leftToRight
- paginationBreakingMode = .page
+ cssOverflowProperty = "-webkit-paged-x"
scrollView.bounces = false
break
}
diff --git a/Source/Models/Highlight+Helper.swift b/Source/Models/Highlight+Helper.swift
index 3d23a4054..537bd0fcf 100644
--- a/Source/Models/Highlight+Helper.swift
+++ b/Source/Models/Highlight+Helper.swift
@@ -288,16 +288,9 @@ extension Highlight {
/// - Parameters:
/// - page: The page containing the HTML.
/// - highlightId: The ID to be removed
- /// - Returns: The removed id
- @discardableResult public static func removeFromHTMLById(withinPage page: FolioReaderPage?, highlightId: String) -> String? {
- guard let currentPage = page else { return nil }
-
- if let removedId = currentPage.webView?.js("removeHighlightById('\(highlightId)')") {
- return removedId
- } else {
- print("Error removing Highlight from page")
- return nil
- }
+ /// - completion: JSCallback with removed id
+ public static func removeFromHTMLById(withinPage page: FolioReaderPage?, highlightId: String, completion: JSCallback? = nil) {
+ page?.webView?.js("removeHighlightById('\(highlightId)')", completion: completion)
}
/**