fix(dark-mode): WebView folgt System statt eigener localStorage-Toggle
Symptom: in TestFlight-Build wirkte Account-Tab dunkel, aber Lesen + Erkunden hell (oder umgekehrt, je nachdem was im Web- localStorage stand). Inkonsistent, weil: - AccountView (SwiftUI) nutzt ZitareTheme.dynamic() — folgt System - WebView las localStorage['zitare-mode'], das nur über den Theme-Toggle-Button im Web-Header gesetzt wurde — den wir aber nativ ausgeblendet haben → kein User-Steuerpfad Fix: neuer User-Script `syncDarkMode` injiziert at document.start: - liest prefers-color-scheme via matchMedia - schreibt localStorage['zitare-mode'] = 'dark' / removes - togglet die `.dark`-Class auf <html> - bleibt aktiv via matchMedia-change-Listener für Live-Switches Reihenfolge in WebView-Config: syncDarkMode VOR hideWebHeader, damit das Theme richtig ist bevor Header-CSS rendert. Build 3 für nächsten TestFlight-Upload. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f65b949dec
commit
2616c4f440
3 changed files with 43 additions and 1 deletions
|
|
@ -14,6 +14,44 @@ enum WebShellScripts {
|
|||
///
|
||||
/// CSS wird at document.start als `<style>`-Tag injiziert — vor dem
|
||||
/// First Paint, kein Flicker.
|
||||
/// Synct den System-Dark-Mode in den WebView. Zitare-Web liest
|
||||
/// `localStorage['zitare-mode']` beim First Paint (Inline-Script
|
||||
/// in `app.html`) und togglet eine `.dark`-Klasse auf `<html>`.
|
||||
///
|
||||
/// In der nativen App wurde der Theme-Toggle-Button im Web-Header
|
||||
/// ausgeblendet (`hideWebHeader`), deshalb kann der User
|
||||
/// localStorage nicht selber setzen. Statt-dessen lauschen wir auf
|
||||
/// `prefers-color-scheme` und schreiben das passende Value vor
|
||||
/// jeder Page-Load und bei jedem System-Switch.
|
||||
///
|
||||
/// Greift sowohl bei Cold-Load (atDocumentStart, vor app.html-
|
||||
/// Inline-Script) als auch bei nachträglichem System-Wechsel
|
||||
/// (`matchMedia`-Listener auf der selben Page).
|
||||
static let syncDarkMode: WKUserScript = .init(
|
||||
source: """
|
||||
(function() {
|
||||
function apply(isDark) {
|
||||
try {
|
||||
if (isDark) localStorage.setItem('zitare-mode', 'dark');
|
||||
else localStorage.removeItem('zitare-mode');
|
||||
} catch (e) {}
|
||||
var html = document.documentElement;
|
||||
if (!html) return;
|
||||
if (isDark) html.classList.add('dark');
|
||||
else html.classList.remove('dark');
|
||||
}
|
||||
var mq = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
apply(mq.matches);
|
||||
// Listener für Live-Switch während die Page offen ist.
|
||||
if (mq.addEventListener) {
|
||||
mq.addEventListener('change', function(e) { apply(e.matches); });
|
||||
}
|
||||
})();
|
||||
""",
|
||||
injectionTime: .atDocumentStart,
|
||||
forMainFrameOnly: true
|
||||
)
|
||||
|
||||
/// Mehrere Selektor-Strategien stapeln, damit ein Klassen-Rename
|
||||
/// oder Markup-Refactor in zitare-web das Hide nicht still bricht:
|
||||
///
|
||||
|
|
|
|||
|
|
@ -105,6 +105,8 @@ final class WebNavState {
|
|||
let config = WKWebViewConfiguration()
|
||||
config.websiteDataStore = .default()
|
||||
config.applicationNameForUserAgent = "ZitareNative/0.1 (iOS)"
|
||||
// Reihenfolge: erst Theme syncen, dann Header verstecken.
|
||||
config.userContentController.addUserScript(WebShellScripts.syncDarkMode)
|
||||
config.userContentController.addUserScript(WebShellScripts.hideWebHeader)
|
||||
let webView = WKWebView(frame: .zero, configuration: config)
|
||||
webView.navigationDelegate = context.coordinator
|
||||
|
|
@ -153,6 +155,8 @@ final class WebNavState {
|
|||
let config = WKWebViewConfiguration()
|
||||
config.websiteDataStore = .default()
|
||||
config.applicationNameForUserAgent = "ZitareNative/0.1 (macOS)"
|
||||
// Reihenfolge: erst Theme syncen, dann Header verstecken.
|
||||
config.userContentController.addUserScript(WebShellScripts.syncDarkMode)
|
||||
config.userContentController.addUserScript(WebShellScripts.hideWebHeader)
|
||||
let webView = WKWebView(frame: .zero, configuration: config)
|
||||
webView.navigationDelegate = context.coordinator
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ targets:
|
|||
path: Sources/Resources/Info.plist
|
||||
properties:
|
||||
CFBundleShortVersionString: "0.1.0"
|
||||
CFBundleVersion: "2"
|
||||
CFBundleVersion: "3"
|
||||
CFBundleDevelopmentRegion: de
|
||||
CFBundleDisplayName: Zitare
|
||||
# Pflicht-Key für iOS 11+ mit Asset-Catalog-Icons. Xcode setzt
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue