Make sure first webview is fully loaded before callling javascript on it
This commit is contained in:
parent
0c00150849
commit
99be955ede
@ -78,6 +78,7 @@
|
|||||||
5170743A232AABFC00A461A3 /* FlattenedAccountFolderPickerData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C452812265093600C03939 /* FlattenedAccountFolderPickerData.swift */; };
|
5170743A232AABFC00A461A3 /* FlattenedAccountFolderPickerData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C452812265093600C03939 /* FlattenedAccountFolderPickerData.swift */; };
|
||||||
517630042336215100E15FFF /* main.js in Resources */ = {isa = PBXBuildFile; fileRef = 517630032336215100E15FFF /* main.js */; };
|
517630042336215100E15FFF /* main.js in Resources */ = {isa = PBXBuildFile; fileRef = 517630032336215100E15FFF /* main.js */; };
|
||||||
517630052336215100E15FFF /* main.js in Resources */ = {isa = PBXBuildFile; fileRef = 517630032336215100E15FFF /* main.js */; };
|
517630052336215100E15FFF /* main.js in Resources */ = {isa = PBXBuildFile; fileRef = 517630032336215100E15FFF /* main.js */; };
|
||||||
|
517630232336657E00E15FFF /* DetailViewControllerWebViewProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 517630222336657E00E15FFF /* DetailViewControllerWebViewProvider.swift */; };
|
||||||
5183CCD0226E1E880010922C /* NonIntrinsicLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCCF226E1E880010922C /* NonIntrinsicLabel.swift */; };
|
5183CCD0226E1E880010922C /* NonIntrinsicLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCCF226E1E880010922C /* NonIntrinsicLabel.swift */; };
|
||||||
5183CCDA226E31A50010922C /* NonIntrinsicImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCD9226E31A50010922C /* NonIntrinsicImageView.swift */; };
|
5183CCDA226E31A50010922C /* NonIntrinsicImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCD9226E31A50010922C /* NonIntrinsicImageView.swift */; };
|
||||||
5183CCDD226F1F5C0010922C /* NavigationProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCDC226F1F5C0010922C /* NavigationProgressView.swift */; };
|
5183CCDD226F1F5C0010922C /* NavigationProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCDC226F1F5C0010922C /* NavigationProgressView.swift */; };
|
||||||
@ -813,6 +814,7 @@
|
|||||||
515D4FCE2325B3D000EE1167 /* NetNewsWire_iOSshareextension_target.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = NetNewsWire_iOSshareextension_target.xcconfig; sourceTree = "<group>"; };
|
515D4FCE2325B3D000EE1167 /* NetNewsWire_iOSshareextension_target.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = NetNewsWire_iOSshareextension_target.xcconfig; sourceTree = "<group>"; };
|
||||||
51707438232AA97100A461A3 /* ShareFolderPickerController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareFolderPickerController.swift; sourceTree = "<group>"; };
|
51707438232AA97100A461A3 /* ShareFolderPickerController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareFolderPickerController.swift; sourceTree = "<group>"; };
|
||||||
517630032336215100E15FFF /* main.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = main.js; sourceTree = "<group>"; };
|
517630032336215100E15FFF /* main.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = main.js; sourceTree = "<group>"; };
|
||||||
|
517630222336657E00E15FFF /* DetailViewControllerWebViewProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailViewControllerWebViewProvider.swift; sourceTree = "<group>"; };
|
||||||
5183CCCF226E1E880010922C /* NonIntrinsicLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonIntrinsicLabel.swift; sourceTree = "<group>"; };
|
5183CCCF226E1E880010922C /* NonIntrinsicLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonIntrinsicLabel.swift; sourceTree = "<group>"; };
|
||||||
5183CCD9226E31A50010922C /* NonIntrinsicImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonIntrinsicImageView.swift; sourceTree = "<group>"; };
|
5183CCD9226E31A50010922C /* NonIntrinsicImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonIntrinsicImageView.swift; sourceTree = "<group>"; };
|
||||||
5183CCDC226F1F5C0010922C /* NavigationProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationProgressView.swift; sourceTree = "<group>"; };
|
5183CCDC226F1F5C0010922C /* NavigationProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationProgressView.swift; sourceTree = "<group>"; };
|
||||||
@ -1370,6 +1372,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
51C4527E2265092C00C03939 /* DetailViewController.swift */,
|
51C4527E2265092C00C03939 /* DetailViewController.swift */,
|
||||||
|
517630222336657E00E15FFF /* DetailViewControllerWebViewProvider.swift */,
|
||||||
515ADE3F22E11FAE006B2460 /* SystemMessageViewController.swift */,
|
515ADE3F22E11FAE006B2460 /* SystemMessageViewController.swift */,
|
||||||
);
|
);
|
||||||
path = Detail;
|
path = Detail;
|
||||||
@ -2702,6 +2705,7 @@
|
|||||||
51C452A722650A3D00C03939 /* RSImage-Extensions.swift in Sources */,
|
51C452A722650A3D00C03939 /* RSImage-Extensions.swift in Sources */,
|
||||||
51C45269226508F600C03939 /* MasterFeedTableViewCell.swift in Sources */,
|
51C45269226508F600C03939 /* MasterFeedTableViewCell.swift in Sources */,
|
||||||
51F85BFD2275DCA800C787DC /* SingleLineUILabelSizer.swift in Sources */,
|
51F85BFD2275DCA800C787DC /* SingleLineUILabelSizer.swift in Sources */,
|
||||||
|
517630232336657E00E15FFF /* DetailViewControllerWebViewProvider.swift in Sources */,
|
||||||
51C4528F226509BD00C03939 /* UnreadFeed.swift in Sources */,
|
51C4528F226509BD00C03939 /* UnreadFeed.swift in Sources */,
|
||||||
51AF460E232488C6001742EF /* Account-Extensions.swift in Sources */,
|
51AF460E232488C6001742EF /* Account-Extensions.swift in Sources */,
|
||||||
5183CCDD226F1F5C0010922C /* NavigationProgressView.swift in Sources */,
|
5183CCDD226F1F5C0010922C /* NavigationProgressView.swift in Sources */,
|
||||||
|
@ -40,27 +40,21 @@ class DetailViewController: UIViewController {
|
|||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
webView = DetailViewControllerWebViewProvider.shared.dequeueWebView()
|
|
||||||
webView.translatesAutoresizingMaskIntoConstraints = false
|
|
||||||
webView.navigationDelegate = self
|
|
||||||
|
|
||||||
webViewContainer.addSubview(webView)
|
|
||||||
|
|
||||||
let constraints: [NSLayoutConstraint] = [
|
|
||||||
webView.leadingAnchor.constraint(equalTo: webViewContainer.safeAreaLayoutGuide.leadingAnchor),
|
|
||||||
webView.trailingAnchor.constraint(equalTo: webViewContainer.safeAreaLayoutGuide.trailingAnchor),
|
|
||||||
webView.topAnchor.constraint(equalTo: webViewContainer.safeAreaLayoutGuide.topAnchor),
|
|
||||||
webView.bottomAnchor.constraint(equalTo: webViewContainer.safeAreaLayoutGuide.bottomAnchor),
|
|
||||||
]
|
|
||||||
|
|
||||||
NSLayoutConstraint.activate(constraints)
|
|
||||||
|
|
||||||
updateArticleSelection()
|
|
||||||
|
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil)
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(statusesDidChange(_:)), name: .StatusesDidChange, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(statusesDidChange(_:)), name: .StatusesDidChange, object: nil)
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(progressDidChange(_:)), name: .AccountRefreshProgressDidChange, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(progressDidChange(_:)), name: .AccountRefreshProgressDidChange, object: nil)
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(contentSizeCategoryDidChange(_:)), name: UIContentSizeCategory.didChangeNotification, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(contentSizeCategoryDidChange(_:)), name: UIContentSizeCategory.didChangeNotification, object: nil)
|
||||||
|
|
||||||
|
DetailViewControllerWebViewProvider.shared.dequeueWebView() { webView in
|
||||||
|
|
||||||
|
self.webView = webView
|
||||||
|
webView.navigationDelegate = self
|
||||||
|
|
||||||
|
self.webViewContainer.addChildAndPin(webView)
|
||||||
|
self.updateArticleSelection()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewDidAppear(_ animated: Bool) {
|
override func viewDidAppear(_ animated: Bool) {
|
||||||
@ -261,58 +255,3 @@ private struct TemplateData: Codable {
|
|||||||
let style: String
|
let style: String
|
||||||
let body: String
|
let body: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: -
|
|
||||||
|
|
||||||
/// WKWebView has an awful behavior of a flash to white on first load when in dark mode.
|
|
||||||
/// Keep a queue of WebViews where we've already done a trivial load so that by the time we need them in the UI, they're past the flash-to-shite part of their lifecycle.
|
|
||||||
class DetailViewControllerWebViewProvider {
|
|
||||||
|
|
||||||
static var shared = DetailViewControllerWebViewProvider()
|
|
||||||
|
|
||||||
func dequeueWebView() -> WKWebView {
|
|
||||||
if let webView = queue.popLast() {
|
|
||||||
replenishQueueIfNeeded()
|
|
||||||
return webView
|
|
||||||
}
|
|
||||||
|
|
||||||
assertionFailure("Creating WKWebView in \(#function); queue has run dry.")
|
|
||||||
let webView = WKWebView(frame: .zero)
|
|
||||||
return webView
|
|
||||||
}
|
|
||||||
|
|
||||||
func enqueueWebView(_ webView: WKWebView) {
|
|
||||||
guard queue.count < maximumQueueDepth else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
webView.uiDelegate = nil
|
|
||||||
webView.navigationDelegate = nil
|
|
||||||
|
|
||||||
let pageURL = Bundle.main.url(forResource: "page", withExtension: "html")!
|
|
||||||
let page = try! String(contentsOf: pageURL)
|
|
||||||
let baseURL = pageURL.deletingLastPathComponent()
|
|
||||||
|
|
||||||
webView.loadHTMLString(page, baseURL: baseURL)
|
|
||||||
|
|
||||||
queue.insert(webView, at: 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Private
|
|
||||||
|
|
||||||
private let minimumQueueDepth = 3
|
|
||||||
private let maximumQueueDepth = 6
|
|
||||||
private var queue: [WKWebView] = []
|
|
||||||
|
|
||||||
private init() {
|
|
||||||
replenishQueueIfNeeded()
|
|
||||||
}
|
|
||||||
|
|
||||||
private func replenishQueueIfNeeded() {
|
|
||||||
while queue.count < minimumQueueDepth {
|
|
||||||
let webView = WKWebView(frame: .zero)
|
|
||||||
enqueueWebView(webView)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
88
iOS/Detail/DetailViewControllerWebViewProvider.swift
Normal file
88
iOS/Detail/DetailViewControllerWebViewProvider.swift
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
//
|
||||||
|
// DetailViewControllerWebViewProvider.swift
|
||||||
|
// NetNewsWire-iOS
|
||||||
|
//
|
||||||
|
// Created by Maurice Parker on 9/21/19.
|
||||||
|
// Copyright © 2019 Ranchero Software. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import WebKit
|
||||||
|
|
||||||
|
/// WKWebView has an awful behavior of a flash to white on first load when in dark mode.
|
||||||
|
/// Keep a queue of WebViews where we've already done a trivial load so that by the time we need them in the UI, they're past the flash-to-shite part of their lifecycle.
|
||||||
|
class DetailViewControllerWebViewProvider: NSObject, WKNavigationDelegate {
|
||||||
|
|
||||||
|
static let shared = DetailViewControllerWebViewProvider()
|
||||||
|
|
||||||
|
private let minimumQueueDepth = 3
|
||||||
|
private let maximumQueueDepth = 6
|
||||||
|
private var queue: [WKWebView] = []
|
||||||
|
|
||||||
|
private var waitingForFirstLoad = true
|
||||||
|
private var waitingCompletionHandler: ((WKWebView) -> ())?
|
||||||
|
|
||||||
|
func dequeueWebView(completion: @escaping (WKWebView) -> ()) {
|
||||||
|
if waitingForFirstLoad {
|
||||||
|
waitingCompletionHandler = completion
|
||||||
|
} else {
|
||||||
|
completeRequest(completion: completion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func enqueueWebView(_ webView: WKWebView) {
|
||||||
|
guard queue.count < maximumQueueDepth else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
webView.navigationDelegate = self
|
||||||
|
queue.insert(webView, at: 0)
|
||||||
|
|
||||||
|
let pageURL = Bundle.main.url(forResource: "page", withExtension: "html")!
|
||||||
|
let page = try! String(contentsOf: pageURL)
|
||||||
|
let baseURL = pageURL.deletingLastPathComponent()
|
||||||
|
|
||||||
|
webView.loadHTMLString(page, baseURL: baseURL)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: WKNavigationDelegate
|
||||||
|
|
||||||
|
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
||||||
|
if waitingForFirstLoad {
|
||||||
|
waitingForFirstLoad = false
|
||||||
|
if let completion = waitingCompletionHandler {
|
||||||
|
completeRequest(completion: completion)
|
||||||
|
waitingCompletionHandler = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Private
|
||||||
|
|
||||||
|
private override init() {
|
||||||
|
super.init()
|
||||||
|
replenishQueueIfNeeded()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func replenishQueueIfNeeded() {
|
||||||
|
while queue.count < minimumQueueDepth {
|
||||||
|
let webView = WKWebView(frame: .zero)
|
||||||
|
enqueueWebView(webView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func completeRequest(completion: @escaping (WKWebView) -> ()) {
|
||||||
|
if let webView = queue.popLast() {
|
||||||
|
webView.navigationDelegate = nil
|
||||||
|
replenishQueueIfNeeded()
|
||||||
|
completion(webView)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
assertionFailure("Creating WKWebView in \(#function); queue has run dry.")
|
||||||
|
let webView = WKWebView(frame: .zero)
|
||||||
|
completion(webView)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1 +1 @@
|
|||||||
Subproject commit 4dbd31b090ab15c3966e9810a65edbf4abdbdd33
|
Subproject commit fd55bace3c2ef2c9e5af8110c0fd742e2135cad1
|
Loading…
x
Reference in New Issue
Block a user