fix color scheme for custom tabs
This commit is contained in:
+5
-6
@@ -216,12 +216,11 @@ class EngineSettingsReplicationService
|
||||
settings.globalPrivacyControlEnabled,
|
||||
);
|
||||
}
|
||||
if (previous.value?.preferredColorScheme !=
|
||||
settings.preferredColorScheme) {
|
||||
await _service.preferredColorScheme(
|
||||
settings.preferredColorScheme,
|
||||
);
|
||||
}
|
||||
// Note: preferredColorScheme is intentionally NOT replicated from the
|
||||
// engine settings here. The app theme (generalSettings.themeMode) is the
|
||||
// sole source of truth for the color scheme; see the themeMode listener
|
||||
// above. EngineSettings.preferredColorScheme is vestigial and always
|
||||
// `system`, so replicating it would clobber the real theme (issue #436).
|
||||
if (previous.value?.cookieBannerHandlingMode !=
|
||||
settings.cookieBannerHandlingMode) {
|
||||
await _service.cookieBannerHandlingMode(
|
||||
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package eu.weblibre.flutter_mozilla_components
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.core.content.edit
|
||||
import androidx.preference.PreferenceManager
|
||||
import mozilla.components.concept.engine.mediaquery.PreferredColorScheme
|
||||
|
||||
/**
|
||||
* Persists the user's preferred color scheme in the default [SharedPreferences].
|
||||
*
|
||||
* Flutter remains the source of truth for the theme, but Custom Tab / PWA sessions
|
||||
* run in a native, non-Flutter activity ([eu.weblibre.flutter_mozilla_components.activities.ExternalAppBrowserActivity]).
|
||||
* When such a session cold-starts the app, the engine is built before Flutter ever
|
||||
* runs, so it cannot ask Flutter for the scheme. Without a persisted value the engine
|
||||
* falls back to a hardcoded default and reports the wrong `prefers-color-scheme` to
|
||||
* web content (see issue #436). This lets the native side resolve the last known
|
||||
* choice on cold start.
|
||||
*/
|
||||
object ColorSchemePreference {
|
||||
private const val PREF_KEY = "weblibre_preferred_color_scheme"
|
||||
|
||||
private const val VALUE_SYSTEM = "system"
|
||||
private const val VALUE_LIGHT = "light"
|
||||
private const val VALUE_DARK = "dark"
|
||||
|
||||
/**
|
||||
* Fallback used before Flutter has written a value (e.g. the very first
|
||||
* Custom Tab / PWA launch). Must match WebLibre's default app theme
|
||||
* (`ThemeMode.dark`, general_settings.dart) so a direct launch doesn't briefly
|
||||
* disagree with the app's default.
|
||||
*/
|
||||
private val DEFAULT = PreferredColorScheme.Dark
|
||||
|
||||
fun read(prefs: SharedPreferences): PreferredColorScheme =
|
||||
when (prefs.getString(PREF_KEY, null)) {
|
||||
VALUE_SYSTEM -> PreferredColorScheme.System
|
||||
VALUE_LIGHT -> PreferredColorScheme.Light
|
||||
VALUE_DARK -> PreferredColorScheme.Dark
|
||||
else -> DEFAULT
|
||||
}
|
||||
|
||||
fun read(context: Context): PreferredColorScheme =
|
||||
read(PreferenceManager.getDefaultSharedPreferences(context))
|
||||
|
||||
fun write(prefs: SharedPreferences, scheme: PreferredColorScheme) {
|
||||
prefs.edit {
|
||||
putString(
|
||||
PREF_KEY,
|
||||
when (scheme) {
|
||||
PreferredColorScheme.Light -> VALUE_LIGHT
|
||||
PreferredColorScheme.Dark -> VALUE_DARK
|
||||
PreferredColorScheme.System -> VALUE_SYSTEM
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the persisted scheme to an [AppCompatDelegate] night mode so native
|
||||
* activities (Custom Tab / PWA) render their window chrome in the mode the user
|
||||
* selected in WebLibre, instead of always following the system. This avoids the
|
||||
* window flashing dark before the page paints when WebLibre is forced to light.
|
||||
*/
|
||||
fun nightMode(context: Context): Int =
|
||||
when (read(context)) {
|
||||
PreferredColorScheme.Light -> AppCompatDelegate.MODE_NIGHT_NO
|
||||
PreferredColorScheme.Dark -> AppCompatDelegate.MODE_NIGHT_YES
|
||||
PreferredColorScheme.System -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
||||
}
|
||||
}
|
||||
+7
@@ -13,6 +13,7 @@ import android.util.Log
|
||||
import androidx.activity.addCallback
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.WindowCompat
|
||||
import eu.weblibre.flutter_mozilla_components.ColorSchemePreference
|
||||
import eu.weblibre.flutter_mozilla_components.ExternalAppBrowserFragment
|
||||
import eu.weblibre.flutter_mozilla_components.GlobalComponents
|
||||
import eu.weblibre.flutter_mozilla_components.PwaConstants
|
||||
@@ -76,6 +77,12 @@ open class ExternalAppBrowserActivity : AppCompatActivity() {
|
||||
get() = intent?.getStringExtra(EXTRA_WEB_APP_MANIFEST_URL)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
// Match the window chrome (status/nav bar + pre-paint background) to the
|
||||
// user's WebLibre color scheme rather than just the system mode, so a
|
||||
// cold-started Custom Tab / PWA doesn't flash dark when WebLibre is light.
|
||||
// Set before super.onCreate so the correct mode is applied without a recreate.
|
||||
delegate.localNightMode = ColorSchemePreference.nightMode(this)
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
onBackPressedDispatcher.addCallback(this) {
|
||||
|
||||
+8
@@ -8,6 +8,7 @@ package eu.weblibre.flutter_mozilla_components.api
|
||||
|
||||
import androidx.core.content.edit
|
||||
import androidx.preference.PreferenceManager
|
||||
import eu.weblibre.flutter_mozilla_components.ColorSchemePreference
|
||||
import eu.weblibre.flutter_mozilla_components.GlobalComponents
|
||||
import eu.weblibre.flutter_mozilla_components.R
|
||||
import eu.weblibre.flutter_mozilla_components.pigeons.AppLinksMode
|
||||
@@ -336,6 +337,13 @@ class GeckoEngineSettingsApiImpl : GeckoEngineSettingsApi {
|
||||
}
|
||||
if(settings.preferredColorScheme != null) {
|
||||
components.core.engine.settings.preferredColorScheme = components.core.engineSettings.preferredColorScheme
|
||||
// Persist so cold-started Custom Tab / PWA sessions resolve the right
|
||||
// scheme before Flutter runs. Only done here (the runtime path driven by
|
||||
// the app theme), not in setDefaultSettings, so the vestigial engine
|
||||
// settings payload can't clobber the real theme. See issue #436.
|
||||
components.core.engineSettings.preferredColorScheme?.let { scheme ->
|
||||
ColorSchemePreference.write(components.core.prefs, scheme)
|
||||
}
|
||||
reloadSession = true
|
||||
}
|
||||
if(settings.cookieBannerHandlingMode != null) {
|
||||
|
||||
+5
-2
@@ -11,6 +11,7 @@ import android.content.SharedPreferences
|
||||
import android.os.Environment
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.preference.PreferenceManager
|
||||
import eu.weblibre.flutter_mozilla_components.ColorSchemePreference
|
||||
import eu.weblibre.flutter_mozilla_components.Components
|
||||
import eu.weblibre.flutter_mozilla_components.interceptor.AppRequestInterceptor
|
||||
import eu.weblibre.flutter_mozilla_components.services.DownloadService
|
||||
@@ -47,7 +48,6 @@ import mozilla.components.concept.engine.Engine
|
||||
import mozilla.components.concept.engine.EngineSession
|
||||
import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy
|
||||
import mozilla.components.concept.engine.fission.WebContentIsolationStrategy
|
||||
import mozilla.components.concept.engine.mediaquery.PreferredColorScheme
|
||||
import mozilla.components.concept.fetch.Client
|
||||
import mozilla.components.feature.addons.AddonManager
|
||||
import mozilla.components.feature.addons.amo.AMOAddonsProvider
|
||||
@@ -122,7 +122,10 @@ class Core(
|
||||
//fingerprintingProtectionPrivateBrowsing
|
||||
httpsOnlyMode = Engine.HttpsOnlyMode.ENABLED,
|
||||
globalPrivacyControlEnabled = true,
|
||||
preferredColorScheme = PreferredColorScheme.Dark,
|
||||
// Resolve the last persisted choice so cold-started Custom Tab / PWA
|
||||
// sessions report the correct `prefers-color-scheme` before Flutter
|
||||
// (the source of truth) runs. Defaults to System. See issue #436.
|
||||
preferredColorScheme = ColorSchemePreference.read(prefs),
|
||||
cookieBannerHandlingMode = EngineSession.CookieBannerHandlingMode.REJECT_ALL,
|
||||
cookieBannerHandlingModePrivateBrowsing = EngineSession.CookieBannerHandlingMode.REJECT_ALL,
|
||||
cookieBannerHandlingGlobalRules = true,
|
||||
|
||||
Reference in New Issue
Block a user