perf: re-warm WebKit GPU on Reader tab appear if idle >60s
GPU process can exit due to idle timeout if user waits before opening Reader. reWarmIfNeeded() checks elapsed time since last warm — if >60s, re-attaches WKWebView to window and loads minimal HTML to restart the GPU process. Called on ReaderTabView.onAppear. No timers, no keep-alive loops. Just a timestamp check on tab appear. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ final class ArticleRenderer {
|
||||
static let shared = ArticleRenderer()
|
||||
|
||||
let webView: WKWebView
|
||||
private var lastWarmTime: CFAbsoluteTime = 0
|
||||
|
||||
private init() {
|
||||
let config = WKWebViewConfiguration()
|
||||
@@ -38,11 +39,11 @@ final class ArticleRenderer {
|
||||
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="100" height="60">
|
||||
"""
|
||||
), baseURL: nil)
|
||||
lastWarmTime = CFAbsoluteTimeGetCurrent()
|
||||
}
|
||||
|
||||
/// Attach WKWebView to the app window (invisible) to force GPU process
|
||||
/// launch. Must be called after window is available. Keeps the webview
|
||||
/// attached — it will be moved to the article container on first use.
|
||||
/// launch. Must be called after window is available.
|
||||
func attachToWindow() {
|
||||
guard webView.window == nil,
|
||||
let window = UIApplication.shared.connectedScenes
|
||||
@@ -51,10 +52,22 @@ final class ArticleRenderer {
|
||||
|
||||
webView.alpha = 0
|
||||
window.addSubview(webView)
|
||||
}
|
||||
|
||||
// Keep attached (don't remove) so GPU process stays alive.
|
||||
// The webview will be reparented to the article container
|
||||
// via removeFromSuperview + addSubview in makeUIView.
|
||||
/// Re-warm if the GPU process may have exited due to idle timeout.
|
||||
/// Lightweight: only fires if >60s since last warm, and just reloads
|
||||
/// a tiny HTML page + re-attaches to window if needed.
|
||||
func reWarmIfNeeded() {
|
||||
let elapsed = CFAbsoluteTimeGetCurrent() - lastWarmTime
|
||||
guard elapsed > 60 else { return }
|
||||
|
||||
attachToWindow()
|
||||
webView.loadHTMLString(
|
||||
"<html><head><style>body{font-family:-apple-system;}</style></head>" +
|
||||
"<body><p>warm</p></body></html>",
|
||||
baseURL: nil
|
||||
)
|
||||
lastWarmTime = CFAbsoluteTimeGetCurrent()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -139,6 +139,9 @@ struct ReaderTabView: View {
|
||||
FeedManagementSheet(vm: vm)
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
ArticleRenderer.shared.reWarmIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
private var subTabs: [String] { ["Unread", "Starred", "All"] }
|
||||
|
||||
Reference in New Issue
Block a user