From a63f658b47e447782b8526aa5b10f7e71ad7290a Mon Sep 17 00:00:00 2001 From: Mattias Pfeiffer Date: Fri, 23 Feb 2024 15:02:26 +0100 Subject: [PATCH 1/3] Snapshot and deactivate Visitable during its lifecycle, eg. when dismissing a modal --- Source/Session/Session.swift | 8 ++++++++ Source/Visit/Visit.swift | 4 ++++ Source/Visitable/Visitable.swift | 2 ++ Source/Visitable/VisitableViewController.swift | 10 ++++++++++ Source/WebView/WebViewBridge.swift | 4 ++++ Source/WebView/turbo.js | 6 ++++++ 6 files changed, 34 insertions(+) diff --git a/Source/Session/Session.swift b/Source/Session/Session.swift index bcfdab3..f948350 100644 --- a/Source/Session/Session.swift +++ b/Source/Session/Session.swift @@ -244,6 +244,14 @@ extension Session: VisitableDelegate { } } + public func visitableViewWillDisappear(_ visitable: Visitable) { + topmostVisit?.cacheSnapshot() + } + + public func visitableViewDidDisappear(_ visitable: Visitable) { + deactivateVisitable(visitable) + } + public func visitableDidRequestReload(_ visitable: Visitable) { guard visitable === topmostVisitable else { return } reload() diff --git a/Source/Visit/Visit.swift b/Source/Visit/Visit.swift index 15ed413..7385bc0 100644 --- a/Source/Visit/Visit.swift +++ b/Source/Visit/Visit.swift @@ -68,6 +68,10 @@ class Visit: NSObject { delegate?.visitDidFinish(self) } + func cacheSnapshot() { + bridge.cacheSnapshot() + } + func startVisit() {} func cancelVisit() {} func completeVisit() {} diff --git a/Source/Visitable/Visitable.swift b/Source/Visitable/Visitable.swift index 6f51247..079c48b 100644 --- a/Source/Visitable/Visitable.swift +++ b/Source/Visitable/Visitable.swift @@ -4,6 +4,8 @@ import WebKit public protocol VisitableDelegate: AnyObject { func visitableViewWillAppear(_ visitable: Visitable) func visitableViewDidAppear(_ visitable: Visitable) + func visitableViewWillDisappear(_ visitable: Visitable) + func visitableViewDidDisappear(_ visitable: Visitable) func visitableDidRequestReload(_ visitable: Visitable) func visitableDidRequestRefresh(_ visitable: Visitable) } diff --git a/Source/Visitable/VisitableViewController.swift b/Source/Visitable/VisitableViewController.swift index b245952..47433ab 100644 --- a/Source/Visitable/VisitableViewController.swift +++ b/Source/Visitable/VisitableViewController.swift @@ -28,6 +28,16 @@ open class VisitableViewController: UIViewController, Visitable { visitableDelegate?.visitableViewDidAppear(self) } + open override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + visitableDelegate?.visitableViewWillDisappear(self) + } + + open override func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + visitableDelegate?.visitableViewDidDisappear(self) + } + // MARK: Visitable open func visitableDidRender() { diff --git a/Source/WebView/WebViewBridge.swift b/Source/WebView/WebViewBridge.swift index a7bdc73..74c23fb 100644 --- a/Source/WebView/WebViewBridge.swift +++ b/Source/WebView/WebViewBridge.swift @@ -76,6 +76,10 @@ final class WebViewBridge { callJavaScript(function: "window.turboNative.clearSnapshotCache") } + func cacheSnapshot() { + callJavaScript(function: "window.turboNative.cacheSnapshot") + } + func cancelVisit(withIdentifier identifier: String) { callJavaScript(function: "window.turboNative.cancelVisitWithIdentifier", arguments: [identifier]) } diff --git a/Source/WebView/turbo.js b/Source/WebView/turbo.js index 329c90c..b9299bd 100644 --- a/Source/WebView/turbo.js +++ b/Source/WebView/turbo.js @@ -64,6 +64,12 @@ } } + cacheSnapshot() { + if (window.Turbo) { + Turbo.session.view.cacheSnapshot() + } + } + // Current visit issueRequestForVisitWithIdentifier(identifier) { From 1390d047f37221976307258a4fcd8963120e317f Mon Sep 17 00:00:00 2001 From: Mattias Pfeiffer Date: Tue, 27 Feb 2024 06:25:05 +0100 Subject: [PATCH 2/3] Session: Only cache snapshot from native side if no other Visitable will appear to avoid double snapshots --- Source/Session/Session.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Source/Session/Session.swift b/Source/Session/Session.swift index f948350..c0a26c5 100644 --- a/Source/Session/Session.swift +++ b/Source/Session/Session.swift @@ -35,6 +35,7 @@ public class Session: NSObject { private var currentVisit: Visit? private var topmostVisit: Visit? + private var disappearingVisitForSnapshotting: Visit? /// The topmost visitable is the visitable that has most recently completed a visit public var topmostVisitable: Visitable? { @@ -213,6 +214,8 @@ extension Session: VisitDelegate { extension Session: VisitableDelegate { public func visitableViewWillAppear(_ visitable: Visitable) { + self.disappearingVisitForSnapshotting = nil + guard let topmostVisit = self.topmostVisit, let currentVisit = self.currentVisit else { return } if visitable === topmostVisit.visitable && visitable.visitableViewController.isMovingToParent { @@ -245,10 +248,11 @@ extension Session: VisitableDelegate { } public func visitableViewWillDisappear(_ visitable: Visitable) { - topmostVisit?.cacheSnapshot() + self.disappearingVisitForSnapshotting = topmostVisit } public func visitableViewDidDisappear(_ visitable: Visitable) { + disappearingVisitForSnapshotting?.cacheSnapshot() deactivateVisitable(visitable) } From 661b3a92c4bb2b59bea46f853959d743793b52b9 Mon Sep 17 00:00:00 2001 From: Mattias Pfeiffer Date: Tue, 27 Feb 2024 06:46:06 +0100 Subject: [PATCH 3/3] Detect restore visit in viewWillAppear when navigating from a native screen --- Source/Session/Session.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Session/Session.swift b/Source/Session/Session.swift index c0a26c5..a1a0991 100644 --- a/Source/Session/Session.swift +++ b/Source/Session/Session.swift @@ -214,6 +214,7 @@ extension Session: VisitDelegate { extension Session: VisitableDelegate { public func visitableViewWillAppear(_ visitable: Visitable) { + let lastDisappearingVisit = self.disappearingVisitForSnapshotting self.disappearingVisitForSnapshotting = nil guard let topmostVisit = self.topmostVisit, let currentVisit = self.currentVisit else { return } @@ -228,7 +229,7 @@ extension Session: VisitableDelegate { } else if visitable === currentVisit.visitable && currentVisit.state == .started { // Navigating forward - complete navigation early completeNavigationForCurrentVisit() - } else if visitable !== topmostVisit.visitable { + } else if visitable !== topmostVisit.visitable || visitable === lastDisappearingVisit?.visitable { // Navigating backward visit(visitable, action: .restore) }