Change to stop recycling the article view controller when switching panel modes on the iPad. Issue #1570
This commit is contained in:
parent
ed355ad614
commit
deab8f8c6c
|
@ -53,6 +53,7 @@ class ArticleViewController: UIViewController {
|
||||||
updateUI()
|
updateUI()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var restoreWindowScrollY = 0
|
||||||
|
|
||||||
private let keyboardManager = KeyboardManager(type: .detail)
|
private let keyboardManager = KeyboardManager(type: .detail)
|
||||||
override var keyCommands: [UIKeyCommand]? {
|
override var keyCommands: [UIKeyCommand]? {
|
||||||
|
@ -92,6 +93,7 @@ class ArticleViewController: UIViewController {
|
||||||
])
|
])
|
||||||
|
|
||||||
let controller = createWebViewController(article)
|
let controller = createWebViewController(article)
|
||||||
|
controller.restoreWindowScrollY = restoreWindowScrollY
|
||||||
articleExtractorButton.buttonState = controller.articleExtractorButtonState
|
articleExtractorButton.buttonState = controller.articleExtractorButtonState
|
||||||
pageViewController.setViewControllers([controller], direction: .forward, animated: false, completion: nil)
|
pageViewController.setViewControllers([controller], direction: .forward, animated: false, completion: nil)
|
||||||
|
|
||||||
|
@ -246,6 +248,13 @@ class ArticleViewController: UIViewController {
|
||||||
// MARK: WebViewControllerDelegate
|
// MARK: WebViewControllerDelegate
|
||||||
|
|
||||||
extension ArticleViewController: WebViewControllerDelegate {
|
extension ArticleViewController: WebViewControllerDelegate {
|
||||||
|
|
||||||
|
func webViewController(_ webViewController: WebViewController, restoreWindowScrollYDidUpdate restoreWindowScrollY: Int) {
|
||||||
|
if webViewController === currentWebViewController {
|
||||||
|
self.restoreWindowScrollY = restoreWindowScrollY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func webViewController(_ webViewController: WebViewController, articleExtractorButtonStateDidUpdate buttonState: ArticleExtractorButtonState) {
|
func webViewController(_ webViewController: WebViewController, articleExtractorButtonStateDidUpdate buttonState: ArticleExtractorButtonState) {
|
||||||
if webViewController === currentWebViewController {
|
if webViewController === currentWebViewController {
|
||||||
articleExtractorButton.buttonState = buttonState
|
articleExtractorButton.buttonState = buttonState
|
||||||
|
|
|
@ -8,11 +8,13 @@
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
import WebKit
|
import WebKit
|
||||||
|
import RSCore
|
||||||
import Account
|
import Account
|
||||||
import Articles
|
import Articles
|
||||||
import SafariServices
|
import SafariServices
|
||||||
|
|
||||||
protocol WebViewControllerDelegate: class {
|
protocol WebViewControllerDelegate: class {
|
||||||
|
func webViewController(_: WebViewController, restoreWindowScrollYDidUpdate: Int)
|
||||||
func webViewController(_: WebViewController, articleExtractorButtonStateDidUpdate: ArticleExtractorButtonState)
|
func webViewController(_: WebViewController, articleExtractorButtonStateDidUpdate: ArticleExtractorButtonState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +70,12 @@ class WebViewController: UIViewController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var restoreOffset = 0
|
let scrollPositionQueue = CoalescingQueue(name: "Article Scroll Position", interval: 0.3, maxInterval: 1.0)
|
||||||
|
var restoreWindowScrollY = 0 {
|
||||||
|
didSet {
|
||||||
|
delegate?.webViewController(self, restoreWindowScrollYDidUpdate: restoreWindowScrollY)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
if webView != nil {
|
if webView != nil {
|
||||||
|
@ -109,6 +116,7 @@ class WebViewController: UIViewController {
|
||||||
// Configure the webview
|
// Configure the webview
|
||||||
webView.navigationDelegate = self
|
webView.navigationDelegate = self
|
||||||
webView.uiDelegate = self
|
webView.uiDelegate = self
|
||||||
|
webView.scrollView.delegate = self
|
||||||
self.configureContextMenuInteraction()
|
self.configureContextMenuInteraction()
|
||||||
|
|
||||||
webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.imageWasClicked)
|
webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.imageWasClicked)
|
||||||
|
@ -186,10 +194,7 @@ class WebViewController: UIViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
func fullReload() {
|
func fullReload() {
|
||||||
webView?.evaluateJavaScript("window.scrollY") { (scrollY, _) in
|
self.reloadHTML()
|
||||||
self.restoreOffset = scrollY as! Int
|
|
||||||
self.reloadHTML()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func showBars() {
|
func showBars() {
|
||||||
|
@ -408,6 +413,22 @@ extension WebViewController: UIViewControllerTransitioningDelegate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK:
|
||||||
|
|
||||||
|
extension WebViewController: UIScrollViewDelegate {
|
||||||
|
|
||||||
|
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||||
|
scrollPositionQueue.add(self, #selector(scrollPositionDidChange))
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func scrollPositionDidChange() {
|
||||||
|
webView?.evaluateJavaScript("window.scrollY") { (scrollY, _) in
|
||||||
|
self.restoreWindowScrollY = scrollY as! Int
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: JSON
|
// MARK: JSON
|
||||||
|
|
||||||
private struct TemplateData: Codable {
|
private struct TemplateData: Codable {
|
||||||
|
@ -472,10 +493,10 @@ private extension WebViewController {
|
||||||
var render = "error();"
|
var render = "error();"
|
||||||
if let data = try? encoder.encode(templateData) {
|
if let data = try? encoder.encode(templateData) {
|
||||||
let json = String(data: data, encoding: .utf8)!
|
let json = String(data: data, encoding: .utf8)!
|
||||||
render = "render(\(json), \(restoreOffset));"
|
render = "render(\(json), \(restoreWindowScrollY));"
|
||||||
}
|
}
|
||||||
|
|
||||||
restoreOffset = 0
|
restoreWindowScrollY = 0
|
||||||
|
|
||||||
WebViewProvider.shared.articleIconSchemeHandler.currentArticle = article
|
WebViewProvider.shared.articleIconSchemeHandler.currentArticle = article
|
||||||
webView.scrollView.setZoomScale(1.0, animated: false)
|
webView.scrollView.setZoomScale(1.0, animated: false)
|
||||||
|
|
|
@ -28,7 +28,7 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner
|
||||||
|
|
||||||
weak var coordinator: SceneCoordinator!
|
weak var coordinator: SceneCoordinator!
|
||||||
var undoableCommands = [UndoableCommand]()
|
var undoableCommands = [UndoableCommand]()
|
||||||
let scrollPositionQueue = CoalescingQueue(name: "Scroll Position", interval: 0.3, maxInterval: 1.0)
|
let scrollPositionQueue = CoalescingQueue(name: "Timeline Scroll Position", interval: 0.3, maxInterval: 1.0)
|
||||||
|
|
||||||
private let keyboardManager = KeyboardManager(type: .timeline)
|
private let keyboardManager = KeyboardManager(type: .timeline)
|
||||||
override var keyCommands: [UIKeyCommand]? {
|
override var keyCommands: [UIKeyCommand]? {
|
||||||
|
|
|
@ -1677,19 +1677,14 @@ private extension SceneCoordinator {
|
||||||
}
|
}
|
||||||
|
|
||||||
@discardableResult
|
@discardableResult
|
||||||
func installArticleController(_ recycledArticleController: ArticleViewController? = nil, animated: Bool) -> ArticleViewController {
|
func installArticleController(restoreWindowScrollY: Int = 0, animated: Bool) -> ArticleViewController {
|
||||||
|
|
||||||
isArticleViewControllerPending = true
|
isArticleViewControllerPending = true
|
||||||
|
|
||||||
let articleController: ArticleViewController = {
|
let articleController = UIStoryboard.main.instantiateController(ofType: ArticleViewController.self)
|
||||||
if let controller = recycledArticleController {
|
articleController.coordinator = self
|
||||||
return controller
|
articleController.article = currentArticle
|
||||||
} else {
|
articleController.restoreWindowScrollY = restoreWindowScrollY
|
||||||
let controller = UIStoryboard.main.instantiateController(ofType: ArticleViewController.self)
|
|
||||||
controller.coordinator = self
|
|
||||||
return controller
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if let subSplit = subSplitViewController {
|
if let subSplit = subSplitViewController {
|
||||||
let controller = addNavControllerIfNecessary(articleController, showButton: false)
|
let controller = addNavControllerIfNecessary(articleController, showButton: false)
|
||||||
|
@ -1701,12 +1696,6 @@ private extension SceneCoordinator {
|
||||||
rootSplitViewController.showDetailViewController(controller, sender: self)
|
rootSplitViewController.showDetailViewController(controller, sender: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have to do a full reload when installing an article controller. We may have changed color contexts
|
|
||||||
// and need to update the article colors. An example is in dark mode. Split screen doesn't use true black
|
|
||||||
// like darkmode usually does.
|
|
||||||
|
|
||||||
// TODO: This should probably only happen to recycled article controllers
|
|
||||||
articleController.fullReload()
|
|
||||||
return articleController
|
return articleController
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1758,7 +1747,7 @@ private extension SceneCoordinator {
|
||||||
}
|
}
|
||||||
|
|
||||||
func configureThreePanelMode() {
|
func configureThreePanelMode() {
|
||||||
let recycledArticleController = articleViewController
|
let articleRestoreWindowScrollY = articleViewController?.restoreWindowScrollY ?? 0
|
||||||
defer {
|
defer {
|
||||||
masterNavigationController.viewControllers = [masterFeedViewController]
|
masterNavigationController.viewControllers = [masterFeedViewController]
|
||||||
}
|
}
|
||||||
|
@ -1773,14 +1762,14 @@ private extension SceneCoordinator {
|
||||||
masterTimelineViewController?.navigationItem.leftBarButtonItem = rootSplitViewController.displayModeButtonItem
|
masterTimelineViewController?.navigationItem.leftBarButtonItem = rootSplitViewController.displayModeButtonItem
|
||||||
masterTimelineViewController?.navigationItem.leftItemsSupplementBackButton = true
|
masterTimelineViewController?.navigationItem.leftItemsSupplementBackButton = true
|
||||||
|
|
||||||
installArticleController(recycledArticleController, animated: false)
|
installArticleController(restoreWindowScrollY: articleRestoreWindowScrollY, animated: false)
|
||||||
|
|
||||||
masterFeedViewController.restoreSelectionIfNecessary(adjustScroll: true)
|
masterFeedViewController.restoreSelectionIfNecessary(adjustScroll: true)
|
||||||
masterTimelineViewController!.restoreSelectionIfNecessary(adjustScroll: false)
|
masterTimelineViewController!.restoreSelectionIfNecessary(adjustScroll: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func configureStandardPanelMode() {
|
func configureStandardPanelMode() {
|
||||||
let recycledArticleController = articleViewController
|
let articleRestoreWindowScrollY = articleViewController?.restoreWindowScrollY ?? 0
|
||||||
rootSplitViewController.preferredPrimaryColumnWidthFraction = UISplitViewController.automaticDimension
|
rootSplitViewController.preferredPrimaryColumnWidthFraction = UISplitViewController.automaticDimension
|
||||||
|
|
||||||
// Set the is Pending flags early to prevent the navigation controller delegate from thinking that we
|
// Set the is Pending flags early to prevent the navigation controller delegate from thinking that we
|
||||||
|
@ -1800,7 +1789,7 @@ private extension SceneCoordinator {
|
||||||
masterNavigationController.pushViewController(masterTimelineViewController!, animated: false)
|
masterNavigationController.pushViewController(masterTimelineViewController!, animated: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
installArticleController(recycledArticleController, animated: false)
|
installArticleController(restoreWindowScrollY: articleRestoreWindowScrollY, animated: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: NSUserActivity
|
// MARK: NSUserActivity
|
||||||
|
|
Loading…
Reference in New Issue