Change to stop recycling the article view controller when switching panel modes on the iPad. Issue #1570

This commit is contained in:
Maurice Parker 2020-01-21 11:05:47 -07:00
parent ed355ad614
commit deab8f8c6c
4 changed files with 47 additions and 28 deletions

View File

@ -53,6 +53,7 @@ class ArticleViewController: UIViewController {
updateUI()
}
}
var restoreWindowScrollY = 0
private let keyboardManager = KeyboardManager(type: .detail)
override var keyCommands: [UIKeyCommand]? {
@ -92,6 +93,7 @@ class ArticleViewController: UIViewController {
])
let controller = createWebViewController(article)
controller.restoreWindowScrollY = restoreWindowScrollY
articleExtractorButton.buttonState = controller.articleExtractorButtonState
pageViewController.setViewControllers([controller], direction: .forward, animated: false, completion: nil)
@ -246,6 +248,13 @@ class ArticleViewController: UIViewController {
// MARK: WebViewControllerDelegate
extension ArticleViewController: WebViewControllerDelegate {
func webViewController(_ webViewController: WebViewController, restoreWindowScrollYDidUpdate restoreWindowScrollY: Int) {
if webViewController === currentWebViewController {
self.restoreWindowScrollY = restoreWindowScrollY
}
}
func webViewController(_ webViewController: WebViewController, articleExtractorButtonStateDidUpdate buttonState: ArticleExtractorButtonState) {
if webViewController === currentWebViewController {
articleExtractorButton.buttonState = buttonState

View File

@ -8,11 +8,13 @@
import UIKit
import WebKit
import RSCore
import Account
import Articles
import SafariServices
protocol WebViewControllerDelegate: class {
func webViewController(_: WebViewController, restoreWindowScrollYDidUpdate: Int)
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 {
if webView != nil {
@ -109,6 +116,7 @@ class WebViewController: UIViewController {
// Configure the webview
webView.navigationDelegate = self
webView.uiDelegate = self
webView.scrollView.delegate = self
self.configureContextMenuInteraction()
webView.configuration.userContentController.add(WrapperScriptMessageHandler(self), name: MessageName.imageWasClicked)
@ -186,10 +194,7 @@ class WebViewController: UIViewController {
}
func fullReload() {
webView?.evaluateJavaScript("window.scrollY") { (scrollY, _) in
self.restoreOffset = scrollY as! Int
self.reloadHTML()
}
self.reloadHTML()
}
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
private struct TemplateData: Codable {
@ -472,10 +493,10 @@ private extension WebViewController {
var render = "error();"
if let data = try? encoder.encode(templateData) {
let json = String(data: data, encoding: .utf8)!
render = "render(\(json), \(restoreOffset));"
render = "render(\(json), \(restoreWindowScrollY));"
}
restoreOffset = 0
restoreWindowScrollY = 0
WebViewProvider.shared.articleIconSchemeHandler.currentArticle = article
webView.scrollView.setZoomScale(1.0, animated: false)

View File

@ -28,7 +28,7 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner
weak var coordinator: SceneCoordinator!
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)
override var keyCommands: [UIKeyCommand]? {

View File

@ -1677,19 +1677,14 @@ private extension SceneCoordinator {
}
@discardableResult
func installArticleController(_ recycledArticleController: ArticleViewController? = nil, animated: Bool) -> ArticleViewController {
func installArticleController(restoreWindowScrollY: Int = 0, animated: Bool) -> ArticleViewController {
isArticleViewControllerPending = true
let articleController: ArticleViewController = {
if let controller = recycledArticleController {
return controller
} else {
let controller = UIStoryboard.main.instantiateController(ofType: ArticleViewController.self)
controller.coordinator = self
return controller
}
}()
let articleController = UIStoryboard.main.instantiateController(ofType: ArticleViewController.self)
articleController.coordinator = self
articleController.article = currentArticle
articleController.restoreWindowScrollY = restoreWindowScrollY
if let subSplit = subSplitViewController {
let controller = addNavControllerIfNecessary(articleController, showButton: false)
@ -1701,12 +1696,6 @@ private extension SceneCoordinator {
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
}
@ -1758,7 +1747,7 @@ private extension SceneCoordinator {
}
func configureThreePanelMode() {
let recycledArticleController = articleViewController
let articleRestoreWindowScrollY = articleViewController?.restoreWindowScrollY ?? 0
defer {
masterNavigationController.viewControllers = [masterFeedViewController]
}
@ -1773,14 +1762,14 @@ private extension SceneCoordinator {
masterTimelineViewController?.navigationItem.leftBarButtonItem = rootSplitViewController.displayModeButtonItem
masterTimelineViewController?.navigationItem.leftItemsSupplementBackButton = true
installArticleController(recycledArticleController, animated: false)
installArticleController(restoreWindowScrollY: articleRestoreWindowScrollY, animated: false)
masterFeedViewController.restoreSelectionIfNecessary(adjustScroll: true)
masterTimelineViewController!.restoreSelectionIfNecessary(adjustScroll: false)
}
func configureStandardPanelMode() {
let recycledArticleController = articleViewController
let articleRestoreWindowScrollY = articleViewController?.restoreWindowScrollY ?? 0
rootSplitViewController.preferredPrimaryColumnWidthFraction = UISplitViewController.automaticDimension
// 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)
}
installArticleController(recycledArticleController, animated: false)
installArticleController(restoreWindowScrollY: articleRestoreWindowScrollY, animated: false)
}
// MARK: NSUserActivity