diff --git a/ios/Platform/Platform/Features/Reader/Views/ArticleWebView.swift b/ios/Platform/Platform/Features/Reader/Views/ArticleWebView.swift index 79da55b..bdde9cf 100644 --- a/ios/Platform/Platform/Features/Reader/Views/ArticleWebView.swift +++ b/ios/Platform/Platform/Features/Reader/Views/ArticleWebView.swift @@ -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 { """ ), 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( + "" + + "

warm

", + baseURL: nil + ) + lastWarmTime = CFAbsoluteTimeGetCurrent() } } diff --git a/ios/Platform/Platform/Features/Reader/Views/ReaderTabView.swift b/ios/Platform/Platform/Features/Reader/Views/ReaderTabView.swift index ca0cf40..848e163 100644 --- a/ios/Platform/Platform/Features/Reader/Views/ReaderTabView.swift +++ b/ios/Platform/Platform/Features/Reader/Views/ReaderTabView.swift @@ -139,6 +139,9 @@ struct ReaderTabView: View { FeedManagementSheet(vm: vm) } } + .onAppear { + ArticleRenderer.shared.reWarmIfNeeded() + } } private var subTabs: [String] { ["Unread", "Starred", "All"] }